]> git.ipfire.org Git - thirdparty/util-linux.git/blame - shlibs/mount/samples/mount.c
colrm: manual update
[thirdparty/util-linux.git] / shlibs / mount / samples / mount.c
CommitLineData
97073441
KZ
1/*
2 * mount(8) -- mount a filesystem
3 *
4 * Copyright (C) 2011 Red Hat, Inc. All rights reserved.
5 * Written by Karel Zak <kzak@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it would be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <errno.h>
25#include <string.h>
26#include <getopt.h>
97073441
KZ
27#include <unistd.h>
28#include <sys/types.h>
29
2a1f429a
KZ
30#include <libmount.h>
31
97073441
KZ
32#include "nls.h"
33#include "c.h"
34
35/*** TODO: DOCS:
36 *
37 * -p, --pass-fd is unsupported
38 * --guess-fstype is unsupported
39 * -c = --no-canonicalize
40 */
41
42/* exit status */
43#define EX_SUCCESS 0
44#define EX_USAGE 1 /* incorrect invocation or permission */
45#define EX_SYSERR 2 /* out of memory, cannot fork, ... */
46#define EX_SOFTWARE 4 /* internal mount bug or wrong version */
47#define EX_USER 8 /* user interrupt */
48#define EX_FILEIO 16 /* problems writing, locking, ... mtab/fstab */
49#define EX_FAIL 32 /* mount failure */
50#define EX_SOMEOK 64 /* some mount succeeded */
51
68164f6c 52static struct libmnt_lock *lock;
97073441
KZ
53
54static void lock_atexit_cleanup(void)
55{
56 if (lock)
57 mnt_unlock_file(lock);
58}
59
60static void __attribute__((__noreturn__)) exit_non_root(const char *option)
61{
62 const uid_t ruid = getuid();
63 const uid_t euid = geteuid();
64
65 if (ruid == 0 && euid != 0) {
66 /* user is root, but setuid to non-root */
67 if (option)
68 errx(EX_USAGE, _("only root can use \"--%s\" option "
69 "(effective UID is %u)"),
70 option, euid);
71 errx(EX_USAGE, _("only root can do that "
72 "(effective UID is %u)"), euid);
73 }
74 if (option)
75 errx(EX_USAGE, _("only root can use \"--%s\" option"), option);
76 errx(EX_USAGE, _("only root can do that"));
77}
78
79static void __attribute__((__noreturn__)) print_version(void)
80{
81 const char *ver = NULL;
82
83 mnt_get_library_version(&ver);
84
85 printf("%s from %s (libmount %s)\n",
86 program_invocation_short_name, PACKAGE_STRING, ver);
87 exit(EX_SUCCESS);
88}
89
90static const char *opt_to_longopt(int c, const struct option *opts)
91{
92 const struct option *o;
93
94 for (o = opts; o->name; o++)
95 if (o->val == c)
96 return o->name;
97 return NULL;
98}
99
68164f6c 100static int print_all(struct libmnt_context *cxt, char *pattern, int show_label)
97073441
KZ
101{
102 int rc = 0;
68164f6c
KZ
103 struct libmnt_table *tb;
104 struct libmnt_iter *itr;
105 struct libmnt_fs *fs;
106 struct libmnt_cache *cache = NULL;
97073441
KZ
107
108 rc = mnt_context_get_mtab(cxt, &tb);
109 if (rc)
110 goto done;
111
112 itr = mnt_new_iter(MNT_ITER_FORWARD);
113 if (!itr)
114 goto done;
115
116 if (show_label)
117 cache = mnt_new_cache();
118
68164f6c 119 while(mnt_table_next_fs(tb, itr, &fs) == 0) {
97073441
KZ
120 const char *type = mnt_fs_get_fstype(fs);
121 const char *src = mnt_fs_get_source(fs);
7cf389f7 122 const char *optstr = mnt_fs_get_options(fs);
97073441
KZ
123
124 if (type && pattern && !mnt_match_fstype(type, pattern))
125 continue;
126
127 /* TODO: print loop backing file instead of device name */
128
129 printf ("%s on %s", src ? : "none", mnt_fs_get_target(fs));
130 if (type)
131 printf (" type %s", type);
132 if (optstr)
133 printf (" (%s)", optstr);
134 if (show_label && src) {
135 char *lb = mnt_cache_find_tag_value(cache, src, "LABEL");
136 if (lb)
137 printf (" [%s]", lb);
138 }
139 fputc('\n', stdout);
140 }
141done:
142 mnt_free_cache(cache);
b192b7b9 143 mnt_free_iter(itr);
97073441
KZ
144 return rc;
145}
146
147static void __attribute__((__noreturn__)) usage(FILE *out)
148{
149 fprintf(out, _("Usage:\n"
150 " %1$s [-lhV]\n"
151 " %1$s -a [options]\n"
152 " %1$s [options] <source> | <directory>\n"
153 " %1$s [options] <source> <directory>\n"
154 " %1$s <operation> <mountpoint> [<target>]\n"),
155 program_invocation_short_name);
156
157 fprintf(out, _(
158 "\nOptions:\n"
159 " -a, --all mount all filesystems mentioned in fstab\n"
160 " -f, --fake dry run, skip mount(2) syscall\n"
161 " -F, --fork fork off for each device (use with -a)\n"
162 " -h, --help this help\n"
163 " -n, --no-mtab don't write to /etc/mtab\n"
164 " -r, --read-only mount the filesystem read-only (same as -o ro)\n"
165 " -v, --verbose verbose mode\n"
166 " -V, --version print version string\n"
167 " -w, --read-write mount the filesystem read-write (default)\n"
168 " -o, --options <list> comma separated string of mount options\n"
169 " -O, --test-opts <list> limit the set of filesystems (use with -a)\n"
170 " -t, --types <list> indicate the filesystem type\n"
171 " -c, --no-canonicalize don't canonicalize paths\n"
172 " -i, --internal-only don't call the mount.<type> helpers\n"
173 " -l, --show-labels lists all mounts with LABELs\n"
174
175 "\nSource:\n"
176 " -L, --label <label> synonym for LABEL=<label>\n"
177 " -U, --uuid <uuid> synonym for UUID=<uuid>\n"
178 " LABEL=<label> specifies device by filesystem label\n"
179 " UUID=<uuid> specifies device by filesystem UUID\n"
180 " <device> specifies device by path\n"
181 " <directory> mountpoint for bind mounts (see --bind/rbind)\n"
182 " <file> regular file for loopdev setup\n"
183
184 "\nOperations:\n"
185 " -B, --bind mount a subtree somewhere else (same as -o bind)\n"
186 " -M, --move move a subtree to some other place\n"
187 " -R, --rbind mount a subtree and all submounts somewhere else\n"
188 " --make-shared mark a subtree as shared\n"
189 " --make-slave mark a subtree as slave\n"
190 " --make-private mark a subtree as private\n"
191 " --make-unbindable mark a subtree as unbindable\n"
192 " --make-rshared recursively mark a whole subtree as shared\n"
193 " --make-rslave recursively mark a whole subtree as slave\n"
194 " --make-rprivate recursively mark a whole subtree as private\n"
195 " --make-runbindable recursively mark a whole subtree as unbindable\n"
196 ));
197
198 fprintf(out, _("\nFor more information see mount(8).\n"));
199
200 exit(out == stderr ? EX_USAGE : EX_SUCCESS);
201}
202
203int main(int argc, char **argv)
204{
205 int c, rc = EXIT_FAILURE, all = 0, show_labels = 0;
68164f6c 206 struct libmnt_context *cxt;
97073441
KZ
207 char *source = NULL, *srcbuf = NULL;
208 char *types = NULL;
209 unsigned long oper = 0;
210
6c7d5ae9 211 static const struct option longopts[] = {
97073441
KZ
212 { "all", 0, 0, 'a' },
213 { "fake", 0, 0, 'f' },
214 { "fork", 0, 0, 'F' },
215 { "help", 0, 0, 'h' },
216 { "no-mtab", 0, 0, 'n' },
217 { "read-only", 0, 0, 'r' },
218 { "ro", 0, 0, 'r' },
219 { "verbose", 0, 0, 'v' },
220 { "version", 0, 0, 'V' },
221 { "read-write", 0, 0, 'w' },
222 { "rw", 0, 0, 'w' },
223 { "options", 1, 0, 'o' },
224 { "test-opts", 1, 0, 'O' },
225 { "types", 1, 0, 't' },
226 { "uuid", 1, 0, 'U' },
227 { "label", 1, 0, 'L'},
228 { "bind", 0, 0, 'B' },
229 { "move", 0, 0, 'M' },
230 { "rbind", 0, 0, 'R' },
231 { "make-shared", 0, 0, 136 },
232 { "make-slave", 0, 0, 137 },
233 { "make-private", 0, 0, 138 },
234 { "make-unbindable", 0, 0, 139 },
235 { "make-rshared", 0, 0, 140 },
236 { "make-rslave", 0, 0, 141 },
237 { "make-rprivate", 0, 0, 142 },
238 { "make-runbindable", 0, 0, 143 },
239 { "no-canonicalize", 0, 0, 'c' },
240 { "internal-only", 0, 0, 'i' },
241 { "show-labels", 0, 0, 'l' },
242 { NULL, 0, 0, 0 }
243 };
244
245 setlocale(LC_ALL, "");
246 bindtextdomain(PACKAGE, LOCALEDIR);
247 textdomain(PACKAGE);
248
249 mnt_init_debug(0);
250 cxt = mnt_new_context();
251 if (!cxt)
252 err(EX_SYSERR, _("libmount context allocation failed"));
253
254 while ((c = getopt_long(argc, argv, "aBcfFhilL:Mno:O:rRsU:vVwt:",
255 longopts, NULL)) != -1) {
256
257 /* only few options are allowed for non-root users */
258 if (mnt_context_is_restricted(cxt) && !strchr("hlLUVv", c))
259 exit_non_root(opt_to_longopt(c, longopts));
260
261 switch(c) {
262 case 'a':
263 all = 1;
264 err(EX_FAIL, "-a not implemented yet"); /* TODO */
265 break;
266 case 'c':
267 mnt_context_disable_canonicalize(cxt, TRUE);
268 break;
269 case 'f':
270 mnt_context_enable_fake(cxt, TRUE);
271 break;
272 case 'F':
273 err(EX_FAIL, "-F not implemented yet"); /* TODO */
274 break;
275 case 'h':
276 usage(stdout);
277 break;
278 case 'i':
279 mnt_context_disable_helpers(cxt, TRUE);
280 break;
281 case 'n':
282 mnt_context_disable_mtab(cxt, TRUE);
283 break;
284 case 'r':
285 if (mnt_context_append_options(cxt, "ro"))
286 err(EX_SYSERR, _("failed to append options"));
287 break;
288 case 'v':
289 mnt_context_enable_verbose(cxt, TRUE);
290 break;
291 case 'V':
292 print_version();
293 break;
294 case 'w':
295 if (mnt_context_append_options(cxt, "rw"))
296 err(EX_SYSERR, _("failed to append options"));
297 break;
298 case 'o':
299 if (mnt_context_append_options(cxt, optarg))
300 err(EX_SYSERR, _("failed to append options"));
301 break;
302 case 'O':
303 if (mnt_context_set_options_pattern(cxt, optarg))
304 err(EX_SYSERR, _("failed to set options pattern"));
305 break;
306 case 'L':
307 case 'U':
308 if (source)
e8ab5ce3 309 errx(EX_USAGE, _("only one <source> may be specified"));
97073441
KZ
310 if (asprintf(&srcbuf, "%s=\"%s\"",
311 c == 'L' ? "LABEL" : "UUID", optarg) <= 0)
312 err(EX_SYSERR, _("failed to allocate source buffer"));
313 source = srcbuf;
314 break;
315 case 'l':
316 show_labels = 1;
317 break;
318 case 't':
319 types = optarg;
320 break;
321 case 's':
322 mnt_context_enable_sloppy(cxt, TRUE);
323 break;
324 case 'B':
325 oper = MS_BIND;
326 break;
327 case 'M':
328 oper = MS_MOVE;
329 break;
330 case 'R':
331 oper = (MS_BIND | MS_REC);
332 break;
333 case 136:
334 oper = MS_SHARED;
335 break;
336 case 137:
337 oper = MS_SLAVE;
338 break;
339 case 138:
340 oper = MS_PRIVATE;
341 break;
342 case 139:
343 oper = MS_UNBINDABLE;
344 break;
345 case 140:
346 oper = (MS_SHARED | MS_REC);
347 break;
348 case 141:
349 oper = (MS_SLAVE | MS_REC);
350 break;
351 case 142:
352 oper = (MS_PRIVATE | MS_REC);
353 break;
354 case 143:
355 oper = (MS_UNBINDABLE | MS_REC);
356 break;
357 default:
358 usage(stderr);
359 break;
360 }
361 }
362
363 argc -= optind;
364 argv += optind;
365
366 if (!source && !argc && !all) {
367 if (oper)
368 usage(stderr);
369 if (!print_all(cxt, types, show_labels))
370 rc = EX_SUCCESS;
371 goto done;
372 }
373
374 if (oper && (types || all || source))
375 usage(stderr);
376
377 if (types && (strchr(types, ',') || strncmp(types, "no", 2) == 0))
378 mnt_context_set_fstype_pattern(cxt, types);
379 else if (types)
380 mnt_context_set_fstype(cxt, types);
381
382 if (argc == 0 && source) {
383 /* mount -L|-U */
384 mnt_context_set_source(cxt, source);
385
386 } else if (argc == 1) {
387 /* mount [-L|-U] <target>
388 * mount <source|target> */
389 if (source) {
390 if (mnt_context_is_restricted(cxt))
391 exit_non_root(NULL);
392 mnt_context_set_source(cxt, source);
393 }
394 mnt_context_set_target(cxt, argv[0]);
395
396 } else if (argc == 2 && !source) {
397 /* mount <source> <target> */
398 if (mnt_context_is_restricted(cxt))
399 exit_non_root(NULL);
400 mnt_context_set_source(cxt, argv[0]);
401 mnt_context_set_target(cxt, argv[1]);
402 } else
403 usage(stderr);
404
405 if (oper)
68164f6c 406 mnt_context_set_mflags(cxt, oper);
97073441
KZ
407
408 lock = mnt_context_get_lock(cxt);
409 if (lock)
410 atexit(lock_atexit_cleanup);
411
cfb9db30 412 rc = mnt_context_mount(cxt);
97073441
KZ
413 if (rc) {
414 /* TODO: call mnt_context_strerror() */
415 rc = EX_FAIL;
416 } else
417 rc = EX_SUCCESS;
418done:
419 free(srcbuf);
420 mnt_free_context(cxt);
421 return rc;
422}
423