source: MondoRescue/branches/3.3/mindi-busybox/util-linux/swaponoff.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 7.1 KB
Line 
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] [-e]" IF_FEATURE_SWAPON_DISCARD(" [-d[POL]]") 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_DISCARD(
16//usage: "\n -d[POL] Discard blocks at swapon (POL=once),"
17//usage: "\n as freed (POL=pages), or both (POL omitted)"
18//usage: )
19//usage: "\n -e Silently skip devices that do not exist"
20//usage: IF_FEATURE_SWAPON_PRI(
21//usage: "\n -p PRI Set swap device priority"
22//usage: )
23//usage:
24//usage:#define swapoff_trivial_usage
25//usage: "[-a] [DEVICE]"
26//usage:#define swapoff_full_usage "\n\n"
27//usage: "Stop swapping on DEVICE\n"
28//usage: "\n -a Stop swapping on all swap devices"
29
30#include "libbb.h"
31#include "common_bufsiz.h"
32#include <mntent.h>
33#ifndef __BIONIC__
34# include <sys/swap.h>
35#endif
36
37#if ENABLE_FEATURE_MOUNT_LABEL
38# include "volume_id.h"
39#else
40# define resolve_mount_spec(fsname) ((void)0)
41#endif
42
43#ifndef MNTTYPE_SWAP
44# define MNTTYPE_SWAP "swap"
45#endif
46
47#if ENABLE_FEATURE_SWAPON_DISCARD
48#ifndef SWAP_FLAG_DISCARD
49#define SWAP_FLAG_DISCARD 0x10000
50#endif
51#ifndef SWAP_FLAG_DISCARD_ONCE
52#define SWAP_FLAG_DISCARD_ONCE 0x20000
53#endif
54#ifndef SWAP_FLAG_DISCARD_PAGES
55#define SWAP_FLAG_DISCARD_PAGES 0x40000
56#endif
57#define SWAP_FLAG_DISCARD_MASK \
58 (SWAP_FLAG_DISCARD | SWAP_FLAG_DISCARD_ONCE | SWAP_FLAG_DISCARD_PAGES)
59#endif
60
61
62#if ENABLE_FEATURE_SWAPON_DISCARD || ENABLE_FEATURE_SWAPON_PRI
63struct globals {
64 int flags;
65} FIX_ALIASING;
66#define G (*(struct globals*)bb_common_bufsiz1)
67#define g_flags (G.flags)
68#define save_g_flags() int save_g_flags = g_flags
69#define restore_g_flags() g_flags = save_g_flags
70#else
71#define g_flags 0
72#define save_g_flags() ((void)0)
73#define restore_g_flags() ((void)0)
74#endif
75#define INIT_G() do { setup_common_bufsiz(); } while (0)
76
77#define do_swapoff (applet_name[5] == 'f')
78
79/* Command line options */
80enum {
81 OPTBIT_a, /* -a all */
82 OPTBIT_e, /* -e ifexists */
83 IF_FEATURE_SWAPON_DISCARD( OPTBIT_d ,) /* -d discard */
84 IF_FEATURE_SWAPON_PRI ( OPTBIT_p ,) /* -p priority */
85 OPT_a = 1 << OPTBIT_a,
86 OPT_e = 1 << OPTBIT_e,
87 OPT_d = IF_FEATURE_SWAPON_DISCARD((1 << OPTBIT_d)) + 0,
88 OPT_p = IF_FEATURE_SWAPON_PRI ((1 << OPTBIT_p)) + 0,
89};
90
91#define OPT_ALL (option_mask32 & OPT_a)
92#define OPT_DISCARD (option_mask32 & OPT_d)
93#define OPT_IFEXISTS (option_mask32 & OPT_e)
94#define OPT_PRIO (option_mask32 & OPT_p)
95
96static int swap_enable_disable(char *device)
97{
98 int err = 0;
99 int quiet = 0;
100
101 resolve_mount_spec(&device);
102
103 if (do_swapoff) {
104 err = swapoff(device);
105 /* Don't complain on OPT_ALL if not a swap device or if it doesn't exist */
106 quiet = (OPT_ALL && (errno == EINVAL || errno == ENOENT));
107 } else {
108 /* swapon */
109 struct stat st;
110 err = stat(device, &st);
111 if (!err) {
112 if (ENABLE_DESKTOP && S_ISREG(st.st_mode)) {
113 if (st.st_blocks * (off_t)512 < st.st_size) {
114 bb_error_msg("%s: file has holes", device);
115 return 1;
116 }
117 }
118 err = swapon(device, g_flags);
119 /* Don't complain on swapon -a if device is already in use */
120 quiet = (OPT_ALL && errno == EBUSY);
121 }
122 /* Don't complain if file does not exist with -e option */
123 if (err && OPT_IFEXISTS && errno == ENOENT)
124 err = 0;
125 }
126
127 if (err && !quiet) {
128 bb_simple_perror_msg(device);
129 return 1;
130 }
131 return 0;
132}
133
134#if ENABLE_FEATURE_SWAPON_DISCARD
135static void set_discard_flag(char *s)
136{
137 /* Unset the flag first to allow fstab options to override */
138 /* options set on the command line */
139 g_flags = (g_flags & ~SWAP_FLAG_DISCARD_MASK) | SWAP_FLAG_DISCARD;
140
141 if (!s) /* No optional policy value on the commandline */
142 return;
143 /* Skip prepended '=' */
144 if (*s == '=')
145 s++;
146 /* For fstab parsing: remove other appended options */
147 *strchrnul(s, ',') = '\0';
148
149 if (strcmp(s, "once") == 0)
150 g_flags |= SWAP_FLAG_DISCARD_ONCE;
151 if (strcmp(s, "pages") == 0)
152 g_flags |= SWAP_FLAG_DISCARD_PAGES;
153}
154#else
155#define set_discard_flag(s) ((void)0)
156#endif
157
158#if ENABLE_FEATURE_SWAPON_PRI
159static void set_priority_flag(char *s)
160{
161 unsigned prio;
162
163 /* For fstab parsing: remove other appended options */
164 *strchrnul(s, ',') = '\0';
165 /* Max allowed 32767 (== SWAP_FLAG_PRIO_MASK) */
166 prio = bb_strtou(s, NULL, 10);
167 if (!errno) {
168 /* Unset the flag first to allow fstab options to override */
169 /* options set on the command line */
170 g_flags = (g_flags & ~SWAP_FLAG_PRIO_MASK) | SWAP_FLAG_PREFER |
171 MIN(prio, SWAP_FLAG_PRIO_MASK);
172 }
173}
174#else
175#define set_priority_flag(s) ((void)0)
176#endif
177
178static int do_em_all_in_fstab(void)
179{
180 struct mntent *m;
181 int err = 0;
182 FILE *f = xfopen_for_read("/etc/fstab");
183
184 while ((m = getmntent(f)) != NULL) {
185 if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0) {
186 /* swapon -a should ignore entries with noauto,
187 * but swapoff -a should process them
188 */
189 if (do_swapoff || hasmntopt(m, MNTOPT_NOAUTO) == NULL) {
190 /* each swap space might have different flags */
191 /* save global flags for the next round */
192 save_g_flags();
193 if (ENABLE_FEATURE_SWAPON_DISCARD) {
194 char *p = hasmntopt(m, "discard");
195 if (p) {
196 /* move to '=' or to end of string */
197 p += 7;
198 set_discard_flag(p);
199 }
200 }
201 if (ENABLE_FEATURE_SWAPON_PRI) {
202 char *p = hasmntopt(m, "pri");
203 if (p) {
204 set_priority_flag(p + 4);
205 }
206 }
207 err |= swap_enable_disable(m->mnt_fsname);
208 restore_g_flags();
209 }
210 }
211 }
212
213 if (ENABLE_FEATURE_CLEAN_UP)
214 endmntent(f);
215
216 return err;
217}
218
219static int do_all_in_proc_swaps(void)
220{
221 char *line;
222 int err = 0;
223 FILE *f = fopen_for_read("/proc/swaps");
224 /* Don't complain if missing */
225 if (f) {
226 while ((line = xmalloc_fgetline(f)) != NULL) {
227 if (line[0] == '/') {
228 *strchrnul(line, ' ') = '\0';
229 err |= swap_enable_disable(line);
230 }
231 free(line);
232 }
233 if (ENABLE_FEATURE_CLEAN_UP)
234 fclose(f);
235 }
236
237 return err;
238}
239
240#define OPTSTR_SWAPON "ae" \
241 IF_FEATURE_SWAPON_DISCARD("d::") \
242 IF_FEATURE_SWAPON_PRI("p:")
243
244int swap_on_off_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
245int swap_on_off_main(int argc UNUSED_PARAM, char **argv)
246{
247 IF_FEATURE_SWAPON_PRI(char *prio;)
248 IF_FEATURE_SWAPON_DISCARD(char *discard = NULL;)
249 int ret = 0;
250
251 INIT_G();
252
253 getopt32(argv, do_swapoff ? "ae" : OPTSTR_SWAPON
254 IF_FEATURE_SWAPON_DISCARD(, &discard)
255 IF_FEATURE_SWAPON_PRI(, &prio)
256 );
257
258 argv += optind;
259
260 if (OPT_DISCARD) {
261 set_discard_flag(discard);
262 }
263 if (OPT_PRIO) {
264 set_priority_flag(prio);
265 }
266
267 if (OPT_ALL) {
268 /* swapoff -a does also /proc/swaps */
269 if (do_swapoff)
270 ret = do_all_in_proc_swaps();
271 ret |= do_em_all_in_fstab();
272 } else if (!*argv) {
273 /* if not -a we need at least one arg */
274 bb_show_usage();
275 }
276 /* Unset -a now to allow for more messages in swap_enable_disable */
277 option_mask32 = option_mask32 & ~OPT_a;
278 /* Now process devices on the commandline if any */
279 while (*argv) {
280 ret |= swap_enable_disable(*argv++);
281 }
282 return ret;
283}
Note: See TracBrowser for help on using the repository browser.