| lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 1 | /* vi: set sw=4 ts=4: */ | 
|  | 2 | /* | 
|  | 3 | * Mini swapon/swapoff implementation for busybox | 
|  | 4 | * | 
|  | 5 | * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> | 
|  | 6 | * | 
|  | 7 | * Licensed under GPLv2, see file LICENSE in this source tree. | 
|  | 8 | */ | 
|  | 9 |  | 
|  | 10 | //usage:#define swapon_trivial_usage | 
|  | 11 | //usage:       "[-a]" IF_FEATURE_SWAPON_PRI(" [-p PRI]") " [DEVICE]" | 
|  | 12 | //usage:#define swapon_full_usage "\n\n" | 
|  | 13 | //usage:       "Start swapping on DEVICE\n" | 
|  | 14 | //usage:     "\n	-a	Start swapping on all swap devices" | 
|  | 15 | //usage:	IF_FEATURE_SWAPON_PRI( | 
|  | 16 | //usage:     "\n	-p PRI	Set swap device priority" | 
|  | 17 | //usage:	) | 
|  | 18 | //usage: | 
|  | 19 | //usage:#define swapoff_trivial_usage | 
|  | 20 | //usage:       "[-a] [DEVICE]" | 
|  | 21 | //usage:#define swapoff_full_usage "\n\n" | 
|  | 22 | //usage:       "Stop swapping on DEVICE\n" | 
|  | 23 | //usage:     "\n	-a	Stop swapping on all swap devices" | 
|  | 24 |  | 
|  | 25 | #include "libbb.h" | 
|  | 26 | #include <mntent.h> | 
|  | 27 | #ifndef __BIONIC__ | 
|  | 28 | # include <sys/swap.h> | 
|  | 29 | #endif | 
|  | 30 |  | 
|  | 31 | #if ENABLE_FEATURE_MOUNT_LABEL | 
|  | 32 | # include "volume_id.h" | 
|  | 33 | #else | 
|  | 34 | # define resolve_mount_spec(fsname) ((void)0) | 
|  | 35 | #endif | 
|  | 36 |  | 
|  | 37 | #ifndef MNTTYPE_SWAP | 
|  | 38 | # define MNTTYPE_SWAP "swap" | 
|  | 39 | #endif | 
|  | 40 |  | 
|  | 41 | #if ENABLE_FEATURE_SWAPON_PRI | 
|  | 42 | struct globals { | 
|  | 43 | int flags; | 
|  | 44 | } FIX_ALIASING; | 
|  | 45 | #define G (*(struct globals*)&bb_common_bufsiz1) | 
|  | 46 | #define g_flags (G.flags) | 
|  | 47 | #else | 
|  | 48 | #define g_flags 0 | 
|  | 49 | #endif | 
|  | 50 | #define INIT_G() do { } while (0) | 
|  | 51 |  | 
|  | 52 | static int swap_enable_disable(char *device) | 
|  | 53 | { | 
|  | 54 | int status; | 
|  | 55 | struct stat st; | 
|  | 56 |  | 
|  | 57 | resolve_mount_spec(&device); | 
|  | 58 | xstat(device, &st); | 
|  | 59 |  | 
|  | 60 | #if ENABLE_DESKTOP | 
|  | 61 | /* test for holes */ | 
|  | 62 | if (S_ISREG(st.st_mode)) | 
|  | 63 | if (st.st_blocks * (off_t)512 < st.st_size) | 
|  | 64 | bb_error_msg("warning: swap file has holes"); | 
|  | 65 | #endif | 
|  | 66 |  | 
|  | 67 | if (applet_name[5] == 'n') | 
|  | 68 | status = swapon(device, g_flags); | 
|  | 69 | else | 
|  | 70 | status = swapoff(device); | 
|  | 71 |  | 
|  | 72 | if (status != 0) { | 
|  | 73 | bb_simple_perror_msg(device); | 
|  | 74 | return 1; | 
|  | 75 | } | 
|  | 76 |  | 
|  | 77 | return 0; | 
|  | 78 | } | 
|  | 79 |  | 
|  | 80 | static int do_em_all(void) | 
|  | 81 | { | 
|  | 82 | struct mntent *m; | 
|  | 83 | FILE *f; | 
|  | 84 | int err; | 
|  | 85 |  | 
|  | 86 | f = setmntent("/etc/fstab", "r"); | 
|  | 87 | if (f == NULL) | 
|  | 88 | bb_perror_msg_and_die("/etc/fstab"); | 
|  | 89 |  | 
|  | 90 | err = 0; | 
|  | 91 | while ((m = getmntent(f)) != NULL) { | 
|  | 92 | if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0) { | 
|  | 93 | /* swapon -a should ignore entries with noauto, | 
|  | 94 | * but swapoff -a should process them */ | 
|  | 95 | if (applet_name[5] != 'n' | 
|  | 96 | || hasmntopt(m, MNTOPT_NOAUTO) == NULL | 
|  | 97 | ) { | 
|  | 98 | err += swap_enable_disable(m->mnt_fsname); | 
|  | 99 | } | 
|  | 100 | } | 
|  | 101 | } | 
|  | 102 |  | 
|  | 103 | if (ENABLE_FEATURE_CLEAN_UP) | 
|  | 104 | endmntent(f); | 
|  | 105 |  | 
|  | 106 | return err; | 
|  | 107 | } | 
|  | 108 |  | 
|  | 109 | int swap_on_off_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 
|  | 110 | int swap_on_off_main(int argc UNUSED_PARAM, char **argv) | 
|  | 111 | { | 
|  | 112 | int ret; | 
|  | 113 |  | 
|  | 114 | INIT_G(); | 
|  | 115 |  | 
|  | 116 | #if !ENABLE_FEATURE_SWAPON_PRI | 
|  | 117 | ret = getopt32(argv, "a"); | 
|  | 118 | #else | 
|  | 119 | if (applet_name[5] == 'n') | 
|  | 120 | opt_complementary = "p+"; | 
|  | 121 | ret = getopt32(argv, (applet_name[5] == 'n') ? "ap:" : "a", &g_flags); | 
|  | 122 |  | 
|  | 123 | if (ret & 2) { // -p | 
|  | 124 | g_flags = SWAP_FLAG_PREFER | | 
|  | 125 | ((g_flags & SWAP_FLAG_PRIO_MASK) << SWAP_FLAG_PRIO_SHIFT); | 
|  | 126 | ret &= 1; | 
|  | 127 | } | 
|  | 128 | #endif | 
|  | 129 |  | 
|  | 130 | if (ret /* & 1: not needed */) // -a | 
|  | 131 | return do_em_all(); | 
|  | 132 |  | 
|  | 133 | argv += optind; | 
|  | 134 | if (!*argv) | 
|  | 135 | bb_show_usage(); | 
|  | 136 |  | 
|  | 137 | /* ret = 0; redundant */ | 
|  | 138 | do { | 
|  | 139 | ret += swap_enable_disable(*argv); | 
|  | 140 | } while (*++argv); | 
|  | 141 |  | 
|  | 142 | return ret; | 
|  | 143 | } |