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