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