~ubuntu-branches/ubuntu/trusty/util-linux/trusty-proposed

« back to all changes in this revision

Viewing changes to shlibs/mount/samples/mount.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2011-11-03 15:38:23 UTC
  • mto: (4.5.5 sid) (1.6.4)
  • mto: This revision was merged to the branch mainline in revision 85.
  • Revision ID: package-import@ubuntu.com-20111103153823-10sx16jprzxlhkqf
ImportĀ upstreamĀ versionĀ 2.20.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
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>
27
 
#include <err.h>
28
 
#include <unistd.h>
29
 
#include <sys/types.h>
30
 
 
31
 
#include <libmount.h>
32
 
 
33
 
#include "nls.h"
34
 
#include "c.h"
35
 
 
36
 
/*** TODO: DOCS:
37
 
 *
38
 
 *  -p, --pass-fd       is unsupported
39
 
 *  --guess-fstype      is unsupported
40
 
 *  -c =                --no-canonicalize
41
 
 */
42
 
 
43
 
/* exit status */
44
 
#define EX_SUCCESS      0
45
 
#define EX_USAGE        1       /* incorrect invocation or permission */
46
 
#define EX_SYSERR       2       /* out of memory, cannot fork, ... */
47
 
#define EX_SOFTWARE     4       /* internal mount bug or wrong version */
48
 
#define EX_USER         8       /* user interrupt */
49
 
#define EX_FILEIO      16       /* problems writing, locking, ... mtab/fstab */
50
 
#define EX_FAIL        32       /* mount failure */
51
 
#define EX_SOMEOK      64       /* some mount succeeded */
52
 
 
53
 
static struct libmnt_lock *lock;
54
 
 
55
 
static void lock_atexit_cleanup(void)
56
 
{
57
 
        if (lock)
58
 
                mnt_unlock_file(lock);
59
 
}
60
 
 
61
 
static void __attribute__((__noreturn__)) exit_non_root(const char *option)
62
 
{
63
 
        const uid_t ruid = getuid();
64
 
        const uid_t euid = geteuid();
65
 
 
66
 
        if (ruid == 0 && euid != 0) {
67
 
                /* user is root, but setuid to non-root */
68
 
                if (option)
69
 
                        errx(EX_USAGE, _("only root can use \"--%s\" option "
70
 
                                         "(effective UID is %u)"),
71
 
                                        option, euid);
72
 
                errx(EX_USAGE, _("only root can do that "
73
 
                                 "(effective UID is %u)"), euid);
74
 
        }
75
 
        if (option)
76
 
                errx(EX_USAGE, _("only root can use \"--%s\" option"), option);
77
 
        errx(EX_USAGE, _("only root can do that"));
78
 
}
79
 
 
80
 
static void __attribute__((__noreturn__)) print_version(void)
81
 
{
82
 
        const char *ver = NULL;
83
 
 
84
 
        mnt_get_library_version(&ver);
85
 
 
86
 
        printf("%s from %s (libmount %s)\n",
87
 
                        program_invocation_short_name, PACKAGE_STRING, ver);
88
 
        exit(EX_SUCCESS);
89
 
}
90
 
 
91
 
static const char *opt_to_longopt(int c, const struct option *opts)
92
 
{
93
 
        const struct option *o;
94
 
 
95
 
        for (o = opts; o->name; o++)
96
 
                if (o->val == c)
97
 
                        return o->name;
98
 
        return NULL;
99
 
}
100
 
 
101
 
static int print_all(struct libmnt_context *cxt, char *pattern, int show_label)
102
 
{
103
 
        int rc = 0;
104
 
        struct libmnt_table *tb;
105
 
        struct libmnt_iter *itr;
106
 
        struct libmnt_fs *fs;
107
 
        struct libmnt_cache *cache = NULL;
108
 
 
109
 
        rc = mnt_context_get_mtab(cxt, &tb);
110
 
        if (rc)
111
 
                goto done;
112
 
 
113
 
        itr = mnt_new_iter(MNT_ITER_FORWARD);
114
 
        if (!itr)
115
 
                goto done;
116
 
 
117
 
        if (show_label)
118
 
                cache = mnt_new_cache();
119
 
 
120
 
        while(mnt_table_next_fs(tb, itr, &fs) == 0) {
121
 
                const char *type = mnt_fs_get_fstype(fs);
122
 
                const char *src = mnt_fs_get_source(fs);
123
 
                char *optstr = mnt_fs_strdup_options(fs);
124
 
 
125
 
                if (type && pattern && !mnt_match_fstype(type, pattern))
126
 
                        continue;
127
 
 
128
 
                /* TODO: print loop backing file instead of device name */
129
 
 
130
 
                printf ("%s on %s", src ? : "none", mnt_fs_get_target(fs));
131
 
                if (type)
132
 
                        printf (" type %s", type);
133
 
                if (optstr)
134
 
                        printf (" (%s)", optstr);
135
 
                if (show_label && src) {
136
 
                        char *lb = mnt_cache_find_tag_value(cache, src, "LABEL");
137
 
                        if (lb)
138
 
                                printf (" [%s]", lb);
139
 
                }
140
 
                fputc('\n', stdout);
141
 
        }
142
 
done:
143
 
        mnt_free_cache(cache);
144
 
        return rc;
145
 
}
146
 
 
147
 
static 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
 
 
203
 
int main(int argc, char **argv)
204
 
{
205
 
        int c, rc = EXIT_FAILURE, all = 0, show_labels = 0;
206
 
        struct libmnt_context *cxt;
207
 
        char *source = NULL, *srcbuf = NULL;
208
 
        char *types = NULL;
209
 
        unsigned long oper = 0;
210
 
 
211
 
        struct option longopts[] = {
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)
309
 
                                errx(EX_USAGE, _("only one <source> could be specified"));
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)
406
 
                mnt_context_set_mflags(cxt, oper);
407
 
 
408
 
        lock = mnt_context_get_lock(cxt);
409
 
        if (lock)
410
 
                atexit(lock_atexit_cleanup);
411
 
 
412
 
        rc = mnt_context_mount(cxt);
413
 
        if (rc) {
414
 
                /* TODO: call mnt_context_strerror() */
415
 
                rc = EX_FAIL;
416
 
        } else
417
 
                rc = EX_SUCCESS;
418
 
done:
419
 
        free(srcbuf);
420
 
        mnt_free_context(cxt);
421
 
        return rc;
422
 
}
423