]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/swapoff.c
swapoff: move code from swapon.c to swapoff.c
[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)
42 printf(_("swapoff %s\n"), orig_special);
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
95
96int main(int argc, char *argv[])
97{
98 FILE *fp;
99 struct mntent *fstab;
100 int status = 0, c;
101 size_t i;
102
103 static const struct option long_opts[] = {
104 { "all", 0, 0, 'a' },
105 { "help", 0, 0, 'h' },
106 { "verbose", 0, 0, 'v' },
107 { "version", 0, 0, 'V' },
108 { NULL, 0, 0, 0 }
109 };
110
111 setlocale(LC_ALL, "");
112 bindtextdomain(PACKAGE, LOCALEDIR);
113 textdomain(PACKAGE);
114 atexit(close_stdout);
115
116 while ((c = getopt_long(argc, argv, "ahvVL:U:",
117 long_opts, NULL)) != -1) {
118 switch (c) {
119 case 'a': /* all */
120 ++all;
121 break;
122 case 'h': /* help */
123 usage(stdout, 0);
124 break;
125 case 'v': /* be chatty */
126 ++verbose;
127 break;
128 case 'V': /* version */
129 printf(UTIL_LINUX_VERSION);
130 return EXIT_SUCCESS;
131 case 'L':
132 add_label(optarg);
133 break;
134 case 'U':
135 add_uuid(optarg);
136 break;
137 case 0:
138 break;
139 case '?':
140 default:
141 usage(stderr, 1);
142 }
143 }
144 argv += optind;
145
146 if (!all && !numof_labels() && !numof_uuids() && *argv == NULL)
147 usage(stderr, 2);
148
149 mnt_init_debug(0);
150 mntcache = mnt_new_cache();
151
152 /*
153 * swapoff any explicitly given arguments.
154 * Complain in case the swapoff call fails.
155 */
156 for (i = 0; i < numof_labels(); i++)
157 status |= swapoff_by_label(get_label(i), !QUIET);
158
159 for (i = 0; i < numof_uuids(); i++)
160 status |= swapoff_by_uuid(get_uuid(i), !QUIET);
161
162 while (*argv != NULL)
163 status |= do_swapoff(*argv++, !QUIET, !CANONIC);
164
165 if (all) {
166 /*
167 * In case /proc/swaps exists, unswap stuff listed there.
168 * We are quiet but report errors in status.
169 * Errors might mean that /proc/swaps
170 * exists as ordinary file, not in procfs.
171 * do_swapoff() exits immediately on EPERM.
172 */
173 struct libmnt_table *st = get_swaps();
174
175 if (st && mnt_table_get_nents(st) > 0) {
176 struct libmnt_iter *itr = mnt_new_iter(MNT_ITER_BACKWARD);
177 struct libmnt_fs *fs;
178
179 while (itr && mnt_table_next_fs(st, itr, &fs) == 0)
180 status |= do_swapoff(mnt_fs_get_source(fs),
181 QUIET, CANONIC);
182
183 mnt_free_iter(itr);
184 }
185
186 /*
187 * Unswap stuff mentioned in /etc/fstab.
188 * Probably it was unmounted already, so errors are not bad.
189 * Doing swapoff -a twice should not give error messages.
190 */
191 fp = setmntent(_PATH_MNTTAB, "r");
192 if (fp == NULL)
193 err(2, _("%s: open failed"), _PATH_MNTTAB);
194
195 while ((fstab = getmntent(fp)) != NULL) {
196 const char *special;
197
198 if (strcmp(fstab->mnt_type, MNTTYPE_SWAP) != 0)
199 continue;
200
201 special = mnt_resolve_spec(fstab->mnt_fsname, mntcache);
202 if (!special)
203 continue;
204
205 if (!is_active_swap(special))
206 do_swapoff(special, QUIET, CANONIC);
207 }
208 fclose(fp);
209 }
210
211 free_tables();
212 mnt_free_cache(mntcache);
213
214 return status;
215}