#include #include #include #ifdef HAVE_SYS_SWAP_H # include #endif #include "nls.h" #include "c.h" #include "xalloc.h" #include "closestream.h" #include "swapprober.h" #include "swapon-common.h" #if !defined(HAVE_SWAPOFF) && defined(SYS_swapoff) # include # define swapoff(path) syscall(SYS_swapoff, path) #endif static int verbose; static int all; #define QUIET 1 #define CANONIC 1 #define SWAPOFF_EX_OK 0 /* no errors */ #define SWAPOFF_EX_ENOMEM 2 /* swapoff(2) failed due to OOM */ #define SWAPOFF_EX_FAILURE 4 /* swapoff(2) failed due to another reason */ #define SWAPOFF_EX_SYSERR 8 /* non-swaoff() errors */ #define SWAPOFF_EX_USAGE 16 /* usage, permissions or syntax error */ #define SWAPOFF_EX_ALLERR 32 /* --all all failed */ #define SWAPOFF_EX_SOMEOK 64 /* --all some failed some OK */ /* * This function works like mnt_resolve_tag(), but it's able to read UUID/LABEL * from regular swap files too (according to entries in /proc/swaps). Note that * mnt_resolve_tag() and mnt_resolve_spec() works with system visible block * devices only. */ static char *swapoff_resolve_tag(const char *name, const char *value, struct libmnt_cache *cache) { char *path; struct libmnt_table *tb; struct libmnt_iter *itr; struct libmnt_fs *fs; /* this is usual case for block devices (and it's really fast as it uses * udev /dev/disk/by-* symlinks by default */ path = mnt_resolve_tag(name, value, cache); if (path) return path; /* try regular files from /proc/swaps */ tb = get_swaps(); if (!tb) return NULL; itr = mnt_new_iter(MNT_ITER_BACKWARD); if (!itr) err(SWAPOFF_EX_SYSERR, _("failed to initialize libmount iterator")); while (tb && mnt_table_next_fs(tb, itr, &fs) == 0) { blkid_probe pr = NULL; const char *src = mnt_fs_get_source(fs); const char *type = mnt_fs_get_swaptype(fs); const char *data = NULL; if (!src || !type || strcmp(type, "file") != 0) continue; pr = get_swap_prober(src); if (!pr) continue; blkid_probe_lookup_value(pr, name, &data, NULL); if (data && strcmp(data, value) == 0) path = xstrdup(src); blkid_free_probe(pr); if (path) break; } mnt_free_iter(itr); return path; } static int do_swapoff(const char *orig_special, int quiet, int canonic) { const char *special = orig_special; int rc = SWAPOFF_EX_OK; if (verbose) printf(_("swapoff %s\n"), orig_special); if (!canonic) { char *n, *v; special = mnt_resolve_spec(orig_special, mntcache); if (!special && blkid_parse_tag_string(orig_special, &n, &v) == 0) { special = swapoff_resolve_tag(n, v, mntcache); free(n); free(v); } if (!special) return cannot_find(orig_special); } if (swapoff(special) == 0) rc = SWAPOFF_EX_OK; /* success */ else { switch (errno) { case EPERM: errx(SWAPOFF_EX_USAGE, _("Not superuser.")); break; case ENOMEM: warn(_("%s: swapoff failed"), orig_special); rc = SWAPOFF_EX_ENOMEM; break; default: if (!quiet) warn(_("%s: swapoff failed"), orig_special); rc = SWAPOFF_EX_FAILURE; break; } } return rc; } static int swapoff_by(const char *name, const char *value, int quiet) { const char *special = swapoff_resolve_tag(name, value, mntcache); return special ? do_swapoff(special, quiet, CANONIC) : cannot_find(value); } static void __attribute__((__noreturn__)) usage(void) { FILE *out = stdout; fputs(USAGE_HEADER, out); fprintf(out, _(" %s [options] []\n"), program_invocation_short_name); fputs(USAGE_SEPARATOR, out); fputs(_("Disable devices and files for paging and swapping.\n"), out); fputs(USAGE_OPTIONS, out); fputs(_(" -a, --all disable all swaps from /proc/swaps\n" " -v, --verbose verbose mode\n"), out); fputs(USAGE_SEPARATOR, out); printf(USAGE_HELP_OPTIONS(24)); fputs(_("\nThe parameter:\n" \ " -L