12 #include "closestream.h"
14 #include "swapprober.h"
15 #include "swapon-common.h"
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)
30 * This function works like mnt_resolve_tag(), but it's able to read UUID/LABEL
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
35 static char *swapoff_resolve_tag(const char *name
, const char *value
,
36 struct libmnt_cache
*cache
)
39 struct libmnt_table
*tb
;
40 struct libmnt_iter
*itr
;
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
);
49 /* try regular files from /proc/swaps */
54 itr
= mnt_new_iter(MNT_ITER_BACKWARD
);
56 err(EXIT_FAILURE
, _("failed to initialize libmount iterator"));
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
;
64 if (!src
|| !type
|| strcmp(type
, "file") != 0)
66 pr
= get_swap_prober(src
);
69 blkid_probe_lookup_value(pr
, name
, &data
, NULL
);
70 if (data
&& strcmp(data
, value
) == 0)
81 static int do_swapoff(const char *orig_special
, int quiet
, int canonic
)
83 const char *special
= orig_special
;
86 printf(_("swapoff %s\n"), orig_special
);
91 special
= mnt_resolve_spec(orig_special
, mntcache
);
92 if (!special
&& blkid_parse_tag_string(orig_special
, &n
, &v
) == 0) {
93 special
= swapoff_resolve_tag(n
, v
, mntcache
);
98 return cannot_find(orig_special
);
101 if (swapoff(special
) == 0)
102 return 0; /* success */
105 errx(EXIT_FAILURE
, _("Not superuser."));
107 if (!quiet
|| errno
== ENOMEM
)
108 warn(_("%s: swapoff failed"), orig_special
);
113 static int swapoff_by(const char *name
, const char *value
, int quiet
)
115 const char *special
= swapoff_resolve_tag(name
, value
, mntcache
);
116 return special
? do_swapoff(special
, quiet
, CANONIC
) : cannot_find(value
);
119 static void __attribute__((__noreturn__
)) usage(void)
122 fputs(USAGE_HEADER
, out
);
123 fprintf(out
, _(" %s [options] [<spec>]\n"), program_invocation_short_name
);
125 fputs(USAGE_SEPARATOR
, out
);
126 fputs(_("Disable devices and files for paging and swapping.\n"), out
);
128 fputs(USAGE_OPTIONS
, out
);
129 fputs(_(" -a, --all disable all swaps from /proc/swaps\n"
130 " -v, --verbose verbose mode\n"), out
);
132 fputs(USAGE_SEPARATOR
, out
);
133 fputs(USAGE_HELP
, out
);
134 fputs(USAGE_VERSION
, out
);
136 fputs(_("\nThe <spec> parameter:\n" \
137 " -L <label> LABEL of device to be used\n" \
138 " -U <uuid> UUID of device to be used\n" \
139 " LABEL=<label> LABEL of device to be used\n" \
140 " UUID=<uuid> UUID of device to be used\n" \
141 " <device> name of device to be used\n" \
142 " <file> name of file to be used\n"), out
);
144 fprintf(out
, USAGE_MAN_TAIL("swapoff(8)"));
148 static int swapoff_all(void)
151 struct libmnt_table
*tb
;
152 struct libmnt_fs
*fs
;
153 struct libmnt_iter
*itr
= mnt_new_iter(MNT_ITER_BACKWARD
);
156 err(EXIT_FAILURE
, _("failed to initialize libmount iterator"));
159 * In case /proc/swaps exists, unswap stuff listed there. We are quiet
160 * but report errors in status. Errors might mean that /proc/swaps
161 * exists as ordinary file, not in procfs. do_swapoff() exits
162 * immediately on EPERM.
166 while (tb
&& mnt_table_find_next_fs(tb
, itr
, match_swap
, NULL
, &fs
) == 0)
167 status
|= do_swapoff(mnt_fs_get_source(fs
), QUIET
, CANONIC
);
170 * Unswap stuff mentioned in /etc/fstab. Probably it was unmounted
171 * already, so errors are not bad. Doing swapoff -a twice should not
172 * give error messages.
175 mnt_reset_iter(itr
, MNT_ITER_FORWARD
);
177 while (tb
&& mnt_table_find_next_fs(tb
, itr
, match_swap
, NULL
, &fs
) == 0) {
178 if (!is_active_swap(mnt_fs_get_source(fs
)))
179 do_swapoff(mnt_fs_get_source(fs
), QUIET
, !CANONIC
);
186 int main(int argc
, char *argv
[])
191 static const struct option long_opts
[] = {
192 { "all", no_argument
, NULL
, 'a' },
193 { "help", no_argument
, NULL
, 'h' },
194 { "verbose", no_argument
, NULL
, 'v' },
195 { "version", no_argument
, NULL
, 'V' },
199 setlocale(LC_ALL
, "");
200 bindtextdomain(PACKAGE
, LOCALEDIR
);
202 atexit(close_stdout
);
204 while ((c
= getopt_long(argc
, argv
, "ahvVL:U:",
205 long_opts
, NULL
)) != -1) {
213 case 'v': /* be chatty */
216 case 'V': /* version */
217 printf(UTIL_LINUX_VERSION
);
226 errtryhelp(EXIT_FAILURE
);
231 if (!all
&& !numof_labels() && !numof_uuids() && *argv
== NULL
) {
232 warnx(_("bad usage"));
233 errtryhelp(EXIT_FAILURE
);
237 mntcache
= mnt_new_cache();
239 for (i
= 0; i
< numof_labels(); i
++)
240 status
|= swapoff_by("LABEL", get_label(i
), !QUIET
);
242 for (i
= 0; i
< numof_uuids(); i
++)
243 status
|= swapoff_by("UUID", get_uuid(i
), !QUIET
);
245 while (*argv
!= NULL
)
246 status
|= do_swapoff(*argv
++, !QUIET
, !CANONIC
);
249 status
|= swapoff_all();
252 mnt_unref_cache(mntcache
);