]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/swapoff.c
swapoff: use libmount to parse fstab
[thirdparty/util-linux.git] / sys-utils / swapoff.c
CommitLineData
6cf8d46c
KZ
1#include <stdlib.h>
2#include <stdio.h>
3#include <getopt.h>
4#include <string.h>
5#include <mntent.h>
6#include <errno.h>
7#include <sys/stat.h>
8#include <unistd.h>
9#include <sys/types.h>
10#include <sys/wait.h>
11#include <fcntl.h>
12#include <stdint.h>
13#include <ctype.h>
14
15#ifdef HAVE_SYS_SWAP_H
16# include <sys/swap.h>
17#endif
18
19#include "nls.h"
20#include "c.h"
21#include "closestream.h"
22
23#include "swapon-common.h"
24
25#ifndef SWAPON_HAS_TWO_ARGS
26/* libc is insane, let's call the kernel */
27# include <sys/syscall.h>
28# define swapoff(path) syscall(SYS_swapoff, path)
29#endif
30
31static int verbose;
32static int all;
33
34#define QUIET 1
35#define CANONIC 1
36
37static int do_swapoff(const char *orig_special, int quiet, int canonic)
38{
39 const char *special = orig_special;
40
41 if (verbose)
e7b63bea 42 printf(_("swapoff %s\n"), orig_special);
6cf8d46c
KZ
43
44 if (!canonic) {
45 special = mnt_resolve_spec(orig_special, mntcache);
46 if (!special)
47 return cannot_find(orig_special);
48 }
49
50 if (swapoff(special) == 0)
51 return 0; /* success */
52
53 if (errno == EPERM)
54 errx(EXIT_FAILURE, _("Not superuser."));
55
56 if (!quiet || errno == ENOMEM)
57 warn(_("%s: swapoff failed"), orig_special);
58
59 return -1;
60}
61
62static int swapoff_by_label(const char *label, int quiet)
63{
64 const char *special = mnt_resolve_tag("LABEL", label, mntcache);
65 return special ? do_swapoff(special, quiet, CANONIC) : cannot_find(label);
66}
67
68static int swapoff_by_uuid(const char *uuid, int quiet)
69{
70 const char *special = mnt_resolve_tag("UUID", uuid, mntcache);
71 return special ? do_swapoff(special, quiet, CANONIC) : cannot_find(uuid);
72}
73
74static void usage(FILE *out, int n)
75{
76 fputs(_("\nUsage:\n"), out);
77 fprintf(out, _(" %s [options] [<spec>]\n"), program_invocation_short_name);
78
79 fputs(_("\nOptions:\n"), out);
80 fputs(_(" -a, --all disable all swaps from /proc/swaps\n"
81 " -h, --help display help and exit\n"
82 " -v, --verbose verbose mode\n"
83 " -V, --version display version and exit\n"), out);
84
85 fputs(_("\nThe <spec> parameter:\n" \
86 " -L <label> LABEL of device to be used\n" \
87 " -U <uuid> UUID of device to be used\n" \
88 " LABEL=<label> LABEL of device to be used\n" \
89 " UUID=<uuid> UUID of device to be used\n" \
90 " <device> name of device to be used\n" \
91 " <file> name of file to be used\n\n"), out);
92 exit(n);
93}
94
e7b63bea
KZ
95static int swapoff_all(void)
96{
97 int status = 0;
98 struct libmnt_table *tb;
99 struct libmnt_fs *fs;
100 struct libmnt_iter *itr = mnt_new_iter(MNT_ITER_BACKWARD);
101
102 if (!itr)
103 err(EXIT_FAILURE, _("failed to initialize libmount iterator"));
104
105 /*
106 * In case /proc/swaps exists, unswap stuff listed there. We are quiet
107 * but report errors in status. Errors might mean that /proc/swaps
108 * exists as ordinary file, not in procfs. do_swapoff() exits
109 * immediately on EPERM.
110 */
111 tb = get_swaps();
112
113 while (tb && mnt_table_find_next_fs(tb, itr, match_swap, NULL, &fs) == 0)
114 status |= do_swapoff(mnt_fs_get_source(fs), QUIET, CANONIC);
115
116 /*
117 * Unswap stuff mentioned in /etc/fstab. Probably it was unmounted
118 * already, so errors are not bad. Doing swapoff -a twice should not
119 * give error messages.
120 */
121 tb = get_fstab();
122 mnt_reset_iter(itr, MNT_ITER_FORWARD);
123
124 while (tb && mnt_table_find_next_fs(tb, itr, match_swap, NULL, &fs) == 0) {
125 if (!is_active_swap(mnt_fs_get_source(fs)))
126 do_swapoff(mnt_fs_get_source(fs), QUIET, !CANONIC);
127 }
128
129 mnt_free_iter(itr);
130 return status;
131}
6cf8d46c
KZ
132
133int main(int argc, char *argv[])
134{
6cf8d46c
KZ
135 int status = 0, c;
136 size_t i;
137
138 static const struct option long_opts[] = {
139 { "all", 0, 0, 'a' },
140 { "help", 0, 0, 'h' },
141 { "verbose", 0, 0, 'v' },
142 { "version", 0, 0, 'V' },
143 { NULL, 0, 0, 0 }
144 };
145
146 setlocale(LC_ALL, "");
147 bindtextdomain(PACKAGE, LOCALEDIR);
148 textdomain(PACKAGE);
149 atexit(close_stdout);
150
151 while ((c = getopt_long(argc, argv, "ahvVL:U:",
152 long_opts, NULL)) != -1) {
153 switch (c) {
154 case 'a': /* all */
155 ++all;
156 break;
157 case 'h': /* help */
158 usage(stdout, 0);
159 break;
160 case 'v': /* be chatty */
161 ++verbose;
162 break;
163 case 'V': /* version */
164 printf(UTIL_LINUX_VERSION);
165 return EXIT_SUCCESS;
166 case 'L':
167 add_label(optarg);
168 break;
169 case 'U':
170 add_uuid(optarg);
171 break;
172 case 0:
173 break;
174 case '?':
175 default:
176 usage(stderr, 1);
177 }
178 }
179 argv += optind;
180
181 if (!all && !numof_labels() && !numof_uuids() && *argv == NULL)
182 usage(stderr, 2);
183
184 mnt_init_debug(0);
185 mntcache = mnt_new_cache();
186
6cf8d46c
KZ
187 for (i = 0; i < numof_labels(); i++)
188 status |= swapoff_by_label(get_label(i), !QUIET);
189
190 for (i = 0; i < numof_uuids(); i++)
191 status |= swapoff_by_uuid(get_uuid(i), !QUIET);
192
193 while (*argv != NULL)
194 status |= do_swapoff(*argv++, !QUIET, !CANONIC);
195
e7b63bea
KZ
196 if (all)
197 status |= swapoff_all();
6cf8d46c
KZ
198
199 free_tables();
200 mnt_free_cache(mntcache);
201
202 return status;
203}