]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/swapoff.c
Use fputs instead of fprintf if possible
[thirdparty/util-linux.git] / sys-utils / swapoff.c
CommitLineData
6cf8d46c 1#include <stdio.h>
6cf8d46c 2#include <errno.h>
7cf6a654 3#include <getopt.h>
6cf8d46c
KZ
4
5#ifdef HAVE_SYS_SWAP_H
6# include <sys/swap.h>
7#endif
8
9#include "nls.h"
10#include "c.h"
52f2fd9b 11#include "xalloc.h"
6cf8d46c
KZ
12#include "closestream.h"
13
52f2fd9b 14#include "swapprober.h"
6cf8d46c
KZ
15#include "swapon-common.h"
16
cf9b16f1 17#if !defined(HAVE_SWAPOFF) && defined(SYS_swapoff)
6cf8d46c
KZ
18# include <sys/syscall.h>
19# define swapoff(path) syscall(SYS_swapoff, path)
20#endif
21
22static int verbose;
23static int all;
24
25#define QUIET 1
26#define CANONIC 1
27
ecfa4dad 28#define SWAPOFF_EX_OK 0 /* no errors */
e4253d3c
KZ
29#define SWAPOFF_EX_ENOMEM 2 /* swapoff(2) failed due to OOM */
30#define SWAPOFF_EX_FAILURE 4 /* swapoff(2) failed due to another reason */
31#define SWAPOFF_EX_SYSERR 8 /* non-swaoff() errors */
ecfa4dad
KZ
32#define SWAPOFF_EX_USAGE 16 /* usage, permissions or syntax error */
33#define SWAPOFF_EX_ALLERR 32 /* --all all failed */
34#define SWAPOFF_EX_SOMEOK 64 /* --all some failed some OK */
35
52f2fd9b 36/*
9e930041 37 * This function works like mnt_resolve_tag(), but it's able to read UUID/LABEL
52f2fd9b
KZ
38 * from regular swap files too (according to entries in /proc/swaps). Note that
39 * mnt_resolve_tag() and mnt_resolve_spec() works with system visible block
40 * devices only.
41 */
42static char *swapoff_resolve_tag(const char *name, const char *value,
43 struct libmnt_cache *cache)
44{
45 char *path;
46 struct libmnt_table *tb;
47 struct libmnt_iter *itr;
48 struct libmnt_fs *fs;
49
50 /* this is usual case for block devices (and it's really fast as it uses
51 * udev /dev/disk/by-* symlinks by default */
52 path = mnt_resolve_tag(name, value, cache);
53 if (path)
54 return path;
55
56 /* try regular files from /proc/swaps */
57 tb = get_swaps();
58 if (!tb)
59 return NULL;
60
61 itr = mnt_new_iter(MNT_ITER_BACKWARD);
62 if (!itr)
ecfa4dad 63 err(SWAPOFF_EX_SYSERR, _("failed to initialize libmount iterator"));
52f2fd9b
KZ
64
65 while (tb && mnt_table_next_fs(tb, itr, &fs) == 0) {
66 blkid_probe pr = NULL;
67 const char *src = mnt_fs_get_source(fs);
68 const char *type = mnt_fs_get_swaptype(fs);
69 const char *data = NULL;
70
71 if (!src || !type || strcmp(type, "file") != 0)
72 continue;
73 pr = get_swap_prober(src);
74 if (!pr)
75 continue;
76 blkid_probe_lookup_value(pr, name, &data, NULL);
77 if (data && strcmp(data, value) == 0)
78 path = xstrdup(src);
79 blkid_free_probe(pr);
80 if (path)
81 break;
82 }
83
84 mnt_free_iter(itr);
85 return path;
86}
87
6cf8d46c
KZ
88static int do_swapoff(const char *orig_special, int quiet, int canonic)
89{
90 const char *special = orig_special;
ecfa4dad 91 int rc = SWAPOFF_EX_OK;
6cf8d46c
KZ
92
93 if (verbose)
e7b63bea 94 printf(_("swapoff %s\n"), orig_special);
6cf8d46c
KZ
95
96 if (!canonic) {
52f2fd9b
KZ
97 char *n, *v;
98
6cf8d46c 99 special = mnt_resolve_spec(orig_special, mntcache);
eeea7ef5 100 if (!special && blkid_parse_tag_string(orig_special, &n, &v) == 0) {
52f2fd9b 101 special = swapoff_resolve_tag(n, v, mntcache);
eeea7ef5
KZ
102 free(n);
103 free(v);
104 }
6cf8d46c
KZ
105 if (!special)
106 return cannot_find(orig_special);
107 }
108
109 if (swapoff(special) == 0)
ecfa4dad
KZ
110 rc = SWAPOFF_EX_OK; /* success */
111 else {
112 switch (errno) {
113 case EPERM:
114 errx(SWAPOFF_EX_USAGE, _("Not superuser."));
115 break;
116 case ENOMEM:
117 warn(_("%s: swapoff failed"), orig_special);
118 rc = SWAPOFF_EX_ENOMEM;
119 break;
120 default:
121 if (!quiet)
122 warn(_("%s: swapoff failed"), orig_special);
123 rc = SWAPOFF_EX_FAILURE;
124 break;
125 }
126 }
6cf8d46c 127
ecfa4dad 128 return rc;
6cf8d46c
KZ
129}
130
52f2fd9b 131static int swapoff_by(const char *name, const char *value, int quiet)
6cf8d46c 132{
52f2fd9b
KZ
133 const char *special = swapoff_resolve_tag(name, value, mntcache);
134 return special ? do_swapoff(special, quiet, CANONIC) : cannot_find(value);
6cf8d46c
KZ
135}
136
6e1eda6f 137static void __attribute__((__noreturn__)) usage(void)
6cf8d46c 138{
6e1eda6f 139 FILE *out = stdout;
7cf6a654 140 fputs(USAGE_HEADER, out);
6cf8d46c
KZ
141 fprintf(out, _(" %s [options] [<spec>]\n"), program_invocation_short_name);
142
451dbcfa
BS
143 fputs(USAGE_SEPARATOR, out);
144 fputs(_("Disable devices and files for paging and swapping.\n"), out);
145
7cf6a654 146 fputs(USAGE_OPTIONS, out);
6cf8d46c 147 fputs(_(" -a, --all disable all swaps from /proc/swaps\n"
7cf6a654
KZ
148 " -v, --verbose verbose mode\n"), out);
149
150 fputs(USAGE_SEPARATOR, out);
f45f3ec3 151 printf(USAGE_HELP_OPTIONS(24));
6cf8d46c
KZ
152
153 fputs(_("\nThe <spec> parameter:\n" \
154 " -L <label> LABEL of device to be used\n" \
155 " -U <uuid> UUID of device to be used\n" \
156 " LABEL=<label> LABEL of device to be used\n" \
157 " UUID=<uuid> UUID of device to be used\n" \
158 " <device> name of device to be used\n" \
7cf6a654
KZ
159 " <file> name of file to be used\n"), out);
160
f45f3ec3 161 printf(USAGE_MAN_TAIL("swapoff(8)"));
ecfa4dad 162 exit(SWAPOFF_EX_OK);
6cf8d46c
KZ
163}
164
e7b63bea
KZ
165static int swapoff_all(void)
166{
ecfa4dad 167 int nerrs = 0, nsucc = 0;
e7b63bea
KZ
168 struct libmnt_table *tb;
169 struct libmnt_fs *fs;
170 struct libmnt_iter *itr = mnt_new_iter(MNT_ITER_BACKWARD);
171
172 if (!itr)
ecfa4dad 173 err(SWAPOFF_EX_SYSERR, _("failed to initialize libmount iterator"));
e7b63bea
KZ
174
175 /*
176 * In case /proc/swaps exists, unswap stuff listed there. We are quiet
177 * but report errors in status. Errors might mean that /proc/swaps
178 * exists as ordinary file, not in procfs. do_swapoff() exits
179 * immediately on EPERM.
180 */
181 tb = get_swaps();
182
ecfa4dad
KZ
183 while (tb && mnt_table_find_next_fs(tb, itr, match_swap, NULL, &fs) == 0) {
184 if (do_swapoff(mnt_fs_get_source(fs), QUIET, CANONIC) == SWAPOFF_EX_OK)
185 nsucc++;
186 else
187 nerrs++;
188 }
e7b63bea
KZ
189
190 /*
191 * Unswap stuff mentioned in /etc/fstab. Probably it was unmounted
192 * already, so errors are not bad. Doing swapoff -a twice should not
193 * give error messages.
194 */
a5a9b544 195 tb = get_fstab(NULL);
e7b63bea
KZ
196 mnt_reset_iter(itr, MNT_ITER_FORWARD);
197
198 while (tb && mnt_table_find_next_fs(tb, itr, match_swap, NULL, &fs) == 0) {
199 if (!is_active_swap(mnt_fs_get_source(fs)))
200 do_swapoff(mnt_fs_get_source(fs), QUIET, !CANONIC);
201 }
202
203 mnt_free_iter(itr);
ecfa4dad
KZ
204
205 if (nerrs == 0)
206 return SWAPOFF_EX_OK; /* all success */
207 else if (nsucc == 0)
208 return SWAPOFF_EX_ALLERR; /* all failed */
209
210 return SWAPOFF_EX_SOMEOK; /* some success, some failed */
e7b63bea 211}
6cf8d46c
KZ
212
213int main(int argc, char *argv[])
214{
6cf8d46c
KZ
215 int status = 0, c;
216 size_t i;
217
218 static const struct option long_opts[] = {
87918040
SK
219 { "all", no_argument, NULL, 'a' },
220 { "help", no_argument, NULL, 'h' },
221 { "verbose", no_argument, NULL, 'v' },
222 { "version", no_argument, NULL, 'V' },
223 { NULL, 0, NULL, 0 }
6cf8d46c
KZ
224 };
225
226 setlocale(LC_ALL, "");
227 bindtextdomain(PACKAGE, LOCALEDIR);
228 textdomain(PACKAGE);
2c308875 229 close_stdout_atexit();
6cf8d46c
KZ
230
231 while ((c = getopt_long(argc, argv, "ahvVL:U:",
232 long_opts, NULL)) != -1) {
233 switch (c) {
234 case 'a': /* all */
235 ++all;
236 break;
6cf8d46c
KZ
237 case 'v': /* be chatty */
238 ++verbose;
239 break;
6cf8d46c
KZ
240 case 'L':
241 add_label(optarg);
242 break;
243 case 'U':
244 add_uuid(optarg);
245 break;
2c308875
KZ
246
247 case 'h': /* help */
248 usage();
249 case 'V': /* version */
ecfa4dad 250 print_version(SWAPOFF_EX_OK);
6cf8d46c 251 default:
ecfa4dad 252 errtryhelp(SWAPOFF_EX_USAGE);
6cf8d46c
KZ
253 }
254 }
255 argv += optind;
256
6e1eda6f
RM
257 if (!all && !numof_labels() && !numof_uuids() && *argv == NULL) {
258 warnx(_("bad usage"));
ecfa4dad 259 errtryhelp(SWAPOFF_EX_USAGE);
6e1eda6f 260 }
6cf8d46c
KZ
261
262 mnt_init_debug(0);
263 mntcache = mnt_new_cache();
264
6cf8d46c 265 for (i = 0; i < numof_labels(); i++)
52f2fd9b 266 status |= swapoff_by("LABEL", get_label(i), !QUIET);
6cf8d46c
KZ
267
268 for (i = 0; i < numof_uuids(); i++)
52f2fd9b 269 status |= swapoff_by("UUID", get_uuid(i), !QUIET);
6cf8d46c
KZ
270
271 while (*argv != NULL)
272 status |= do_swapoff(*argv++, !QUIET, !CANONIC);
273
e7b63bea
KZ
274 if (all)
275 status |= swapoff_all();
6cf8d46c
KZ
276
277 free_tables();
6195f9e6 278 mnt_unref_cache(mntcache);
6cf8d46c
KZ
279
280 return status;
281}