~ubuntu-branches/ubuntu/lucid/loop-aes-utils/lucid-security

« back to all changes in this revision

Viewing changes to mount/mount.c

  • Committer: Bazaar Package Importer
  • Author(s): Max Vozeler
  • Date: 2008-08-22 11:57:17 UTC
  • mfrom: (8.1.3 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080822115717-v8wfa8pxwlfvyje0
Tags: 2.13.1-4
* patches/losetup_add_option_f.dpatch: 
  - Added to support "find next free loop" in losetup.
    (closes: #495682)

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
#include <sys/wait.h>
22
22
#include <sys/mount.h>
23
23
 
24
 
#include "mount_blkid.h"
 
24
#include <mntent.h>
 
25
#include <paths.h>
 
26
 
 
27
#ifdef HAVE_LIBSELINUX
 
28
#include <selinux/selinux.h>
 
29
#include <selinux/context.h>
 
30
#endif
 
31
 
 
32
#include "fsprobe.h"
25
33
#include "mount_constants.h"
26
34
#include "sundries.h"
27
35
#include "xmalloc.h"
28
 
#include "mntent.h"
 
36
#include "mount_mntent.h"
29
37
#include "fstab.h"
30
38
#include "lomount.h"
31
39
#include "loop.h"
32
40
#include "linux_fs.h"           /* for BLKGETSIZE */
33
 
#include "mount_guess_rootdev.h"
34
 
#include "mount_guess_fstype.h"
35
 
#include "mount_by_label.h"
36
41
#include "getusername.h"
37
 
#include "paths.h"
 
42
#include "mount_paths.h"
38
43
#include "env.h"
39
44
#include "nls.h"
40
45
 
44
49
#include "setproctitle.h"
45
50
#endif
46
51
 
 
52
/* Quiet mode */
 
53
int mount_quiet = 0;
 
54
 
47
55
/* True for fake mount (-f).  */
48
56
static int fake = 0;
49
57
 
74
82
/* Add volumelabel in a listing of mounted devices (-l). */
75
83
static int list_with_volumelabel = 0;
76
84
 
77
 
/* Nonzero for mount {--bind|--replace|--before|--after|--over|--move} */
 
85
/* Nonzero for mount {--bind|--replace|--before|--after|--over|--move|
 
86
 *                     make-shared|make-private|make-unbindable|make-slave}
 
87
 */
78
88
static int mounttype = 0;
79
89
 
80
90
/* True if ruid != euid.  */
98
108
#define MS_USER         0x20000000
99
109
#define MS_OWNER        0x10000000
100
110
#define MS_GROUP        0x08000000
101
 
#define MS_COMMENT      0x00020000
 
111
#define MS_COMMENT      0x02000000
102
112
#define MS_LOOP         0x00010000
103
113
 
104
114
/* Options that we keep the mount system call from seeing.  */
107
117
/* Options that we keep from appearing in the options field in the mtab.  */
108
118
#define MS_NOMTAB       (MS_REMOUNT|MS_NOAUTO|MS_USERS|MS_USER)
109
119
 
 
120
#define MS_PROPAGATION  (MS_SHARED|MS_SLAVE|MS_UNBINDABLE|MS_PRIVATE)
 
121
 
110
122
/* Options that we make ordinary users have by default.  */
111
123
#define MS_SECURE       (MS_NOEXEC|MS_NOSUID|MS_NODEV)
112
124
 
164
176
  { "diratime", 0, 1, MS_NODIRATIME },  /* Update dir access times */
165
177
  { "nodiratime", 0, 0, MS_NODIRATIME },/* Do not update dir access times */
166
178
#endif
 
179
#ifdef MS_RELATIME
 
180
  { "relatime", 0, 0, MS_RELATIME },   /* Update access times relative to
 
181
                                          mtime/ctime */
 
182
  { "norelatime", 0, 1, MS_RELATIME }, /* Update access time without regard
 
183
                                          to mtime/ctime */
 
184
#endif
167
185
  { NULL,       0, 0, 0         }
168
186
};
169
187
 
170
188
static const char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption,
171
 
        *opt_speed, *opt_comment;
 
189
        *opt_speed, *opt_comment, *opt_uhelper;
 
190
 
 
191
static int mounted (const char *spec0, const char *node0);
 
192
static int check_special_mountprog(const char *spec, const char *node,
 
193
                const char *type, int flags, char *extra_opts, int *status);
172
194
 
173
195
static struct string_opt_map {
174
196
  char *tag;
181
203
  { "encryption=", 0, &opt_encryption },
182
204
  { "speed=", 0, &opt_speed },
183
205
  { "comment=", 1, &opt_comment },
 
206
  { "uhelper=", 0, &opt_uhelper },
184
207
  { NULL, 0, NULL }
185
208
};
186
209
 
207
230
        return 0;
208
231
}
209
232
 
210
 
int mount_quiet=0;
 
233
static void
 
234
my_free(const void *s) {
 
235
        if (s)
 
236
                free((void *) s);
 
237
}
211
238
 
212
239
/* Report on a single mount.  */
213
240
static void
220
247
        if (me->mnt_opts != NULL)
221
248
                printf (" (%s)", me->mnt_opts);
222
249
        if (list_with_volumelabel) {
223
 
                const char *label;
224
 
                label = mount_get_volume_label_by_spec(me->mnt_fsname);
225
 
                if (label) {
226
 
                        printf (" [%s]", label);
227
 
                        /* free(label); */
 
250
                const char *devname = fsprobe_get_devname(me->mnt_fsname);
 
251
 
 
252
                if (devname) {
 
253
                        const char *label;
 
254
 
 
255
                        label = fsprobe_get_label_by_devname(devname);
 
256
                        my_free(devname);
 
257
 
 
258
                        if (label) {
 
259
                                printf (" [%s]", label);
 
260
                                my_free(label);
 
261
                        }
228
262
                }
229
263
        }
230
264
        printf ("\n");
243
277
     exit (0);
244
278
}
245
279
 
246
 
static void
247
 
my_free(const void *s) {
248
 
        if (s)
249
 
                free((void *) s);
250
 
}
 
280
/* reallocates its first arg */
 
281
static char *
 
282
append_opt(char *s, const char *opt, const char *val)
 
283
{
 
284
        if (!opt)
 
285
                return s;
 
286
        if (!s) {
 
287
                if (!val)
 
288
                       return xstrdup(opt);             /* opt */
 
289
 
 
290
                return xstrconcat3(NULL, opt, val);     /* opt=val */
 
291
        }
 
292
        if (!val)
 
293
                return xstrconcat3(s, ",", opt);        /* s,opt */
 
294
 
 
295
        return xstrconcat4(s, ",", opt, val);           /* s,opt=val */
 
296
}
 
297
 
 
298
static char *
 
299
append_numopt(char *s, const char *opt, long num)
 
300
{
 
301
        char buf[32];
 
302
 
 
303
        snprintf(buf, sizeof(buf), "%ld", num);
 
304
        return append_opt(s, opt, buf);
 
305
}
 
306
 
 
307
#ifdef HAVE_LIBSELINUX
 
308
/* strip quotes from a "string"
 
309
 * Warning: This function modify the "str" argument.
 
310
 */
 
311
static char *
 
312
strip_quotes(char *str)
 
313
{
 
314
        char *end = NULL;
 
315
 
 
316
        if (*str != '"')
 
317
                return str;
 
318
 
 
319
        end = strrchr(str, '"');
 
320
        if (end == NULL || end == str)
 
321
                die (EX_USAGE, _("mount: improperly quoted option string '%s'"), str);
 
322
 
 
323
        *end = '\0';
 
324
        return str+1;
 
325
}
 
326
 
 
327
/* translates SELinux context from human to raw format and
 
328
 * appends it to the mount extra options.
 
329
 *
 
330
 * returns -1 on error and 0 on success
 
331
 */
 
332
static int
 
333
append_context(const char *optname, char *optdata, char **extra_opts)
 
334
{
 
335
        security_context_t raw = NULL;
 
336
        char *data = NULL;
 
337
 
 
338
        if (!is_selinux_enabled())
 
339
                /* ignore the option if we running without selinux */
 
340
                return 0;
 
341
 
 
342
        if (optdata==NULL || *optdata=='\0' || optname==NULL)
 
343
                return -1;
 
344
 
 
345
        /* TODO: use strip_quotes() for all mount options? */
 
346
        data = *optdata =='"' ? strip_quotes(optdata) : optdata;
 
347
 
 
348
        if (selinux_trans_to_raw_context(
 
349
                        (security_context_t) data, &raw)==-1 ||
 
350
                        raw==NULL)
 
351
                return -1;
 
352
 
 
353
        if (verbose)
 
354
                printf(_("mount: translated %s '%s' to '%s'\n"),
 
355
                                optname, data, (char *) raw);
 
356
 
 
357
        *extra_opts = append_opt(*extra_opts, optname, NULL);
 
358
        *extra_opts = xstrconcat4(*extra_opts, "\"", (char *) raw, "\"");
 
359
 
 
360
        freecon(raw);
 
361
        return 0;
 
362
}
 
363
#endif
251
364
 
252
365
/*
253
366
 * Look for OPT in opt_map table and return mask value.
255
368
 * For the options uid= and gid= replace user or group name by its value.
256
369
 */
257
370
static inline void
258
 
parse_opt(const char *opt, int *mask, char *extra_opts, int len) {
 
371
parse_opt(char *opt, int *mask, char **extra_opts) {
259
372
        const struct opt_map *om;
260
373
 
261
374
        for (om = opt_map; om->opt != NULL; om++)
279
392
                        return;
280
393
                }
281
394
 
282
 
        len -= strlen(extra_opts);
283
 
 
284
 
        if (*extra_opts && --len > 0)
285
 
                strcat(extra_opts, ",");
286
 
 
287
395
        /* convert nonnumeric ids to numeric */
288
396
        if (!strncmp(opt, "uid=", 4) && !isdigit(opt[4])) {
289
397
                struct passwd *pw = getpwnam(opt+4);
290
 
                char uidbuf[20];
291
398
 
292
399
                if (pw) {
293
 
                        sprintf(uidbuf, "uid=%d", pw->pw_uid);
294
 
                        if ((len -= strlen(uidbuf)) > 0)
295
 
                                strcat(extra_opts, uidbuf);
 
400
                        *extra_opts = append_numopt(*extra_opts,
 
401
                                                "uid=", pw->pw_uid);
296
402
                        return;
297
403
                }
298
404
        }
299
405
        if (!strncmp(opt, "gid=", 4) && !isdigit(opt[4])) {
300
406
                struct group *gr = getgrnam(opt+4);
301
 
                char gidbuf[20];
302
407
 
303
408
                if (gr) {
304
 
                        sprintf(gidbuf, "gid=%d", gr->gr_gid);
305
 
                        if ((len -= strlen(gidbuf)) > 0)
306
 
                                strcat(extra_opts, gidbuf);
 
409
                        *extra_opts = append_numopt(*extra_opts,
 
410
                                                "gid=", gr->gr_gid);
307
411
                        return;
308
412
                }
309
413
        }
310
414
 
311
 
        if ((len -= strlen(opt)) > 0)
312
 
                strcat(extra_opts, opt);
 
415
#ifdef HAVE_LIBSELINUX
 
416
        if (strncmp(opt, "context=", 8) == 0 && *(opt+8)) {
 
417
                if (append_context("context=", opt+8, extra_opts) == 0)
 
418
                        return;
 
419
        }
 
420
        if (strncmp(opt, "fscontext=", 10) == 0 && *(opt+10)) {
 
421
                if (append_context("fscontext=", opt+10, extra_opts) == 0)
 
422
                        return;
 
423
        }
 
424
        if (strncmp(opt, "defcontext=", 11) == 0 && *(opt+11)) {
 
425
                if (append_context("defcontext=", opt+11, extra_opts) == 0)
 
426
                        return;
 
427
        }
 
428
#endif
 
429
        *extra_opts = append_opt(*extra_opts, opt, NULL);
313
430
}
314
 
  
 
431
 
315
432
/* Take -o options list and compute 4th and 5th args to mount(2).  flags
316
433
   gets the standard options (indicated by bits) and extra_opts all the rest */
317
434
static void
323
440
 
324
441
        if (options != NULL) {
325
442
                char *opts = xstrdup(options);
326
 
                char *opt;
327
 
                int len = strlen(opts) + 20;
328
 
 
329
 
                *extra_opts = xmalloc(len); 
330
 
                **extra_opts = '\0';
331
 
 
332
 
                for (opt = strtok(opts, ","); opt; opt = strtok(NULL, ","))
333
 
                        if (!parse_string_opt(opt))
334
 
                                parse_opt(opt, flags, *extra_opts, len);
335
 
 
 
443
                int open_quote = 0;
 
444
                char *opt, *p;
 
445
 
 
446
                for (p=opts, opt=NULL; p && *p; p++) {
 
447
                        if (!opt)
 
448
                                opt = p;                /* begin of the option item */
 
449
                        if (*p == '"')
 
450
                                open_quote ^= 1;        /* reverse the status */
 
451
                        if (open_quote)
 
452
                                continue;               /* still in quoted block */
 
453
                        if (*p == ',')
 
454
                                *p = '\0';              /* terminate the option item */
 
455
                        /* end of option item or last item */
 
456
                        if (*p == '\0' || *(p+1) == '\0') {
 
457
                                if (!parse_string_opt(opt))
 
458
                                        parse_opt(opt, flags, extra_opts);
 
459
                                opt = NULL;
 
460
                        }
 
461
                }
336
462
                free(opts);
337
463
        }
338
464
 
340
466
                *flags |= MS_RDONLY;
341
467
        if (readwrite)
342
468
                *flags &= ~MS_RDONLY;
 
469
 
 
470
        if (mounttype & MS_PROPAGATION)
 
471
                *flags &= ~MS_BIND;
343
472
        *flags |= mounttype;
344
473
}
345
474
 
350
479
        const struct string_opt_map *m;
351
480
        char *new_opts;
352
481
 
353
 
        new_opts = xstrdup((flags & MS_RDONLY) ? "ro" : "rw");
 
482
        new_opts = append_opt(NULL, (flags & MS_RDONLY) ? "ro" : "rw", NULL);
354
483
        for (om = opt_map; om->opt != NULL; om++) {
355
484
                if (om->skip)
356
485
                        continue;
357
486
                if (om->inv || !om->mask || (flags & om->mask) != om->mask)
358
487
                        continue;
359
 
                new_opts = xstrconcat3(new_opts, ",", om->opt);
 
488
                new_opts = append_opt(new_opts, om->opt, NULL);
360
489
                flags &= ~om->mask;
361
490
        }
362
491
        for (m = &string_opt_map[0]; m->tag; m++) {
363
492
                if (!m->skip && *(m->valptr))
364
 
                        new_opts = xstrconcat4(new_opts, ",",
365
 
                                               m->tag, *(m->valptr));
366
 
        }
367
 
        if (extra_opts && *extra_opts) {
368
 
                new_opts = xstrconcat3(new_opts, ",", extra_opts);
369
 
        }
370
 
        if (user) {
371
 
                new_opts = xstrconcat3(new_opts, ",user=", user);
372
 
        }
 
493
                        new_opts = append_opt(new_opts, m->tag, *(m->valptr));
 
494
        }
 
495
        if (extra_opts && *extra_opts)
 
496
                new_opts = append_opt(new_opts, extra_opts, NULL);
 
497
 
 
498
        if (user)
 
499
                new_opts = append_opt(new_opts, "user=", user);
 
500
 
373
501
        return new_opts;
374
502
}
375
503
 
409
537
        }
410
538
 
411
539
        /* Find the root entry by looking it up in fstab */
412
 
        if ((fstab = getfsfile ("/")) || (fstab = getfsfile ("root"))) {
 
540
        if ((fstab = getfs_by_dir ("/")) || (fstab = getfs_by_dir ("root"))) {
413
541
                char *extra_opts;
414
542
                parse_opts (fstab->m.mnt_opts, &flags, &extra_opts);
415
543
                mnt.mnt_dir = "/";
416
 
                mnt.mnt_fsname = canonicalize (fstab->m.mnt_fsname);
 
544
                mnt.mnt_fsname = fsprobe_get_devname(fstab->m.mnt_fsname);
417
545
                mnt.mnt_type = fstab->m.mnt_type;
418
546
                mnt.mnt_opts = fix_opts_string (flags, extra_opts, NULL);
419
547
                mnt.mnt_freq = mnt.mnt_passno = 0;
448
576
static int
449
577
do_mount_syscall (struct mountargs *args) {
450
578
        int flags = args->flags;
451
 
        int ret;
452
579
 
453
580
        if ((flags & MS_MGC_MSK) == 0)
454
581
                flags |= MS_MGC_VAL;
455
582
 
456
 
        ret = mount (args->spec, args->node, args->type, flags, args->data);
 
583
        if (verbose > 2)
 
584
                printf("mount: mount(2) syscall: source: \"%s\", target: \"%s\", "
 
585
                        "filesystemtype: \"%s\", mountflags: %d, data: %s\n",
 
586
                        args->spec, args->node, args->type, flags, (char *) args->data);
 
587
 
 
588
        return mount (args->spec, args->node, args->type, flags, args->data);
 
589
}
 
590
 
 
591
/*
 
592
 * do_mount()
 
593
 *      Mount a single file system, possibly invoking an external handler to
 
594
 *      do so. Keep track of successes.
 
595
 * returns: 0: OK, -1: error in errno
 
596
 */
 
597
static int
 
598
do_mount (struct mountargs *args, int *special, int *status) {
 
599
        int ret;
 
600
        if (check_special_mountprog(args->spec, args->node, args->type,
 
601
                                    args->flags, args->data, status)) {
 
602
                *special = 1;
 
603
                ret = 0;
 
604
        } else
 
605
                ret = do_mount_syscall(args);
 
606
 
457
607
        if (ret == 0)
458
608
                mountcount++;
459
609
        return ret;
460
610
}
461
611
 
462
612
/*
 
613
 * check_special_mountprog()
 
614
 *      If there is a special mount program for this type, exec it.
 
615
 * returns: 0: no exec was done, 1: exec was done, status has result
 
616
 */
 
617
static int
 
618
check_special_mountprog(const char *spec, const char *node, const char *type, int flags,
 
619
                        char *extra_opts, int *status) {
 
620
  char mountprog[120];
 
621
  struct stat statbuf;
 
622
  int res;
 
623
 
 
624
  if (!external_allowed)
 
625
      return 0;
 
626
 
 
627
  if (type && strlen(type) < 100) {
 
628
       sprintf(mountprog, "/sbin/mount.%s", type);
 
629
       if (stat(mountprog, &statbuf) == 0) {
 
630
            if (verbose)
 
631
                 fflush(stdout);
 
632
            res = fork();
 
633
            if (res == 0) {
 
634
                 char *oo, *mountargs[10];
 
635
                 int i = 0;
 
636
 
 
637
                 if(setgid(getgid()) < 0)
 
638
                         die(EX_FAIL, _("mount: cannot set group id: %s"), strerror(errno));
 
639
 
 
640
                 if(setuid(getuid()) < 0)
 
641
                         die(EX_FAIL, _("mount: cannot set user id: %s"), strerror(errno));
 
642
 
 
643
                 oo = fix_opts_string (flags, extra_opts, NULL);
 
644
                 mountargs[i++] = mountprog;                            /* 1 */
 
645
                 mountargs[i++] = (char *) spec;                        /* 2 */
 
646
                 mountargs[i++] = (char *) node;                        /* 3 */
 
647
                 if (sloppy && strncmp(type, "nfs", 3) == 0)
 
648
                      mountargs[i++] = "-s";                            /* 4 */
 
649
                 if (fake)
 
650
                      mountargs[i++] = "-f";                            /* 5 */
 
651
                 if (nomtab)
 
652
                      mountargs[i++] = "-n";                            /* 6 */
 
653
                 if (verbose)
 
654
                      mountargs[i++] = "-v";                            /* 7 */
 
655
                 if (oo && *oo) {
 
656
                      mountargs[i++] = "-o";                            /* 8 */
 
657
                      mountargs[i++] = oo;                              /* 9 */
 
658
                 }
 
659
                 mountargs[i] = NULL;                                   /* 10 */
 
660
 
 
661
                 if (verbose > 2) {
 
662
                        i = 0;
 
663
                        while(verbose > 2 && mountargs[i]) {
 
664
                                printf("mount: external mount: argv[%d] = \"%s\"\n",
 
665
                                        i, mountargs[i]);
 
666
                                i++;
 
667
                        }
 
668
                        fflush(stdout);
 
669
                 }
 
670
 
 
671
                 execv(mountprog, mountargs);
 
672
                 exit(1);       /* exec failed */
 
673
            } else if (res != -1) {
 
674
                 int st;
 
675
                 wait(&st);
 
676
                 *status = (WIFEXITED(st) ? WEXITSTATUS(st) : EX_SYSERR);
 
677
                 return 1;
 
678
            } else {
 
679
                 int errsv = errno;
 
680
                 error(_("mount: cannot fork: %s"), strerror(errsv));
 
681
            }
 
682
       }
 
683
  }
 
684
  return 0;
 
685
}
 
686
 
 
687
 
 
688
static const char *
 
689
guess_fstype_by_devname(const char *devname)
 
690
{
 
691
   const char *type = fsprobe_get_fstype_by_devname(devname);
 
692
 
 
693
   if (verbose) {
 
694
      printf (_("mount: you didn't specify a filesystem type for %s\n"), devname);
 
695
 
 
696
      if (!type)
 
697
         printf (_("       I will try all types mentioned in %s or %s\n"),
 
698
                      ETC_FILESYSTEMS, PROC_FILESYSTEMS);
 
699
      else if (!strcmp(type, "swap"))
 
700
         printf (_("       and it looks like this is swapspace\n"));
 
701
      else
 
702
         printf (_("       I will try type %s\n"), type);
 
703
   }
 
704
   return type;
 
705
}
 
706
 
 
707
/*
463
708
 * guess_fstype_and_mount()
464
709
 *      Mount a single file system. Guess the type when unknown.
465
710
 * returns: 0: OK, -1: error in errno, 1: other error
468
713
 */
469
714
static int
470
715
guess_fstype_and_mount(const char *spec, const char *node, const char **types,
471
 
                       int flags, char *mount_opts) {
 
716
                       int flags, char *mount_opts, int *special, int *status) {
472
717
   struct mountargs args = { spec, node, NULL, flags & ~MS_NOSYS, mount_opts };
473
 
   
 
718
 
474
719
   if (*types && strcasecmp (*types, "auto") == 0)
475
720
      *types = NULL;
476
721
 
478
723
      *types = "none";          /* random, but not "bind" */
479
724
 
480
725
   if (!*types && !(flags & MS_REMOUNT)) {
481
 
      *types = guess_fstype(spec);
482
 
      if (*types && !strcmp(*types, "swap")) {
483
 
          error(_("%s looks like swapspace - not mounted"), spec);
484
 
          *types = NULL;
485
 
          return 1;
 
726
      *types = guess_fstype_by_devname(spec);
 
727
      if (*types) {
 
728
          if (!strcmp(*types, "swap")) {
 
729
              error(_("%s looks like swapspace - not mounted"), spec);
 
730
              *types = NULL;
 
731
              return 1;
 
732
          } else {
 
733
              args.type = *types;
 
734
              return do_mount (&args, special, status);
 
735
          }
486
736
      }
487
737
   }
488
738
 
495
745
      while((p = index(t,',')) != NULL) {
496
746
         *p = 0;
497
747
         args.type = *types = t;
498
 
         if(do_mount_syscall (&args) == 0)
 
748
         if (do_mount (&args, special, status) == 0)
499
749
            return 0;
500
750
         t = p+1;
501
751
      }
505
755
 
506
756
   if (*types || (flags & MS_REMOUNT)) {
507
757
      args.type = *types;
508
 
      return do_mount_syscall (&args);
 
758
      return do_mount (&args, special, status);
509
759
   }
510
760
 
511
 
   return procfsloop(do_mount_syscall, &args, types);
 
761
   return fsprobe_procfsloop_mount(do_mount, &args, types, special, status);
512
762
}
513
763
 
514
764
/*
617
867
        printf(_("mount: skipping the setup of a loop device\n"));
618
868
    } else {
619
869
      int loopro = (*flags & MS_RDONLY);
 
870
      int res;
620
871
 
621
 
      if (!*loopdev || !**loopdev)
622
 
        *loopdev = find_unused_loop_device();
623
 
      if (!*loopdev)
624
 
        return EX_SYSERR;       /* no more loop devices */
625
 
      if (verbose)
626
 
        printf(_("mount: going to use the loop device %s\n"), *loopdev);
627
872
      offset = opt_offset ? strtoull(opt_offset, NULL, 0) : 0;
628
 
      if (set_loop(*loopdev, *loopfile, offset,
629
 
                   opt_encryption, pfd, &loopro)) {
 
873
 
 
874
      do {
 
875
        if (!*loopdev || !**loopdev)
 
876
          *loopdev = find_unused_loop_device();
 
877
        if (!*loopdev)
 
878
          return EX_SYSERR;     /* no more loop devices */
630
879
        if (verbose)
631
 
          printf(_("mount: failed setting up loop device\n"));
632
 
        return EX_FAIL;
633
 
      }
 
880
          printf(_("mount: going to use the loop device %s\n"), *loopdev);
 
881
 
 
882
        if ((res = set_loop(*loopdev, *loopfile, offset,
 
883
                            opt_encryption, pfd, &loopro))) {
 
884
          if (res == 2) {
 
885
             /* loop dev has been grabbed by some other process,
 
886
                try again, if not given explicitly */
 
887
             if (!opt_loopdev) {
 
888
               if (verbose)
 
889
                 printf(_("mount: stolen loop=%s ...trying again\n"), *loopdev);
 
890
               my_free(*loopdev);
 
891
               *loopdev = NULL;
 
892
               continue;
 
893
             }
 
894
             error(_("mount: stolen loop=%s"), *loopdev);
 
895
             return EX_FAIL;
 
896
 
 
897
          } else {
 
898
             if (verbose)
 
899
               printf(_("mount: failed setting up loop device\n"));
 
900
             if (!opt_loopdev) {
 
901
               my_free(*loopdev);
 
902
               *loopdev = NULL;
 
903
             }
 
904
             return EX_FAIL;
 
905
          }
 
906
        }
 
907
      } while (!*loopdev);
 
908
 
634
909
      if (verbose > 1)
635
910
        printf(_("mount: setup loop device successfully\n"));
636
911
      *spec = *loopdev;
653
928
        mnt.mnt_opts = opts;
654
929
        mnt.mnt_freq = freq;
655
930
        mnt.mnt_passno = pass;
656
 
      
 
931
 
657
932
        /* We get chatty now rather than after the update to mtab since the
658
933
           mount succeeded, even if the write to /etc/mtab should fail.  */
659
934
        if (verbose)
662
937
        if (!nomtab && mtab_is_writable()) {
663
938
                if (flags & MS_REMOUNT)
664
939
                        update_mtab (mnt.mnt_dir, &mnt);
 
940
                else if (flags & MS_MOVE)
 
941
                        update_mtab(mnt.mnt_fsname, &mnt);
665
942
                else {
666
943
                        mntFILE *mfp;
667
944
 
713
990
}
714
991
 
715
992
/*
716
 
 * check_special_mountprog()
717
 
 *      If there is a special mount program for this type, exec it.
718
 
 * returns: 0: no exec was done, 1: exec was done, status has result
719
 
 */
720
 
 
721
 
static int
722
 
check_special_mountprog(const char *spec, const char *node, const char *type,
723
 
                        int flags, char *extra_opts, int *status) {
724
 
  char mountprog[120];
725
 
  struct stat statbuf;
726
 
  int res;
727
 
 
728
 
  if (!external_allowed)
729
 
      return 0;
730
 
 
731
 
  if (type && strlen(type) < 100) {
732
 
       sprintf(mountprog, "/sbin/mount.%s", type);
733
 
       if (stat(mountprog, &statbuf) == 0) {
734
 
            res = fork();
735
 
            if (res == 0) {
736
 
                 const char *oo, *mountargs[10];
737
 
                 int i = 0;
738
 
 
739
 
                 setuid(getuid());
740
 
                 setgid(getgid());
741
 
                 oo = fix_opts_string (flags, extra_opts, NULL);
742
 
                 mountargs[i++] = mountprog;
743
 
                 mountargs[i++] = spec;
744
 
                 mountargs[i++] = node;
745
 
                 if (nomtab)
746
 
                      mountargs[i++] = "-n";
747
 
                 if (verbose)
748
 
                      mountargs[i++] = "-v";
749
 
                 if (oo && *oo) {
750
 
                      mountargs[i++] = "-o";
751
 
                      mountargs[i++] = oo;
752
 
                 }
753
 
                 mountargs[i] = NULL;
754
 
                 execv(mountprog, (char **) mountargs);
755
 
                 exit(1);       /* exec failed */
756
 
            } else if (res != -1) {
757
 
                 int st;
758
 
                 wait(&st);
759
 
                 *status = (WIFEXITED(st) ? WEXITSTATUS(st) : EX_SYSERR);
760
 
                 return 1;
761
 
            } else {
762
 
                 int errsv = errno;
763
 
                 error(_("mount: cannot fork: %s"), strerror(errsv));
764
 
            }
765
 
       }
766
 
  }
767
 
  return 0;
768
 
}
769
 
 
770
 
/*
771
993
 * try_mount_one()
772
994
 *      Try to mount one file system. When "bg" is 1, this is a retry
773
995
 *      in the background. One additional exit code EX_BG is used here.
779
1001
static int
780
1002
try_mount_one (const char *spec0, const char *node0, const char *types0,
781
1003
               const char *opts0, int freq, int pass, int bg, int ro) {
782
 
  int res = 0, status;
 
1004
  int res = 0, status = 0, special = 0;
783
1005
  int mnt5_res = 0;             /* only for gcc */
784
1006
  int mnt_err;
785
1007
  int flags;
790
1012
  int loop = 0;
791
1013
  const char *loopdev = 0, *loopfile = 0;
792
1014
  struct stat statbuf;
793
 
  int nfs_mount_version = 0;    /* any version */
794
1015
 
795
1016
  /* copies for freeing on exit */
796
1017
  const char *opts1, *spec1, *node1, *types1, *extra_opts1;
797
1018
 
 
1019
  if (verbose > 2) {
 
1020
          printf("mount: spec:  \"%s\"\n", spec0);
 
1021
          printf("mount: node:  \"%s\"\n", node0);
 
1022
          printf("mount: types: \"%s\"\n", types0);
 
1023
          printf("mount: opts:  \"%s\"\n", opts0);
 
1024
  }
 
1025
 
798
1026
  spec = spec1 = xstrdup(spec0);
799
1027
  node = node1 = xstrdup(node0);
800
1028
  types = types1 = xstrdup(types0);
809
1037
 
810
1038
  suid_check(spec, node, &flags, &user);
811
1039
 
 
1040
  /* The "mount -f" checks for for existing record in /etc/mtab (with
 
1041
   * regular non-fake mount this is usually done by kernel)
 
1042
   */
 
1043
  if (!(flags & MS_REMOUNT) && fake && mounted (spec, node))
 
1044
      die(EX_USAGE, _("mount: according to mtab, "
 
1045
                      "%s is already mounted on %s\n"),
 
1046
                      spec, node);
 
1047
 
812
1048
  mount_opts = extra_opts;
813
1049
 
814
1050
  if (opt_speed)
825
1061
          goto out;
826
1062
  }
827
1063
 
 
1064
  if (loop)
 
1065
      opt_loopdev = loopdev;
 
1066
 
828
1067
  /*
829
1068
   * Call mount.TYPE for types that require a separate mount program.
830
1069
   * For the moment these types are ncpfs and smbfs. Maybe also vxfs.
835
1074
      goto out;
836
1075
  }
837
1076
 
838
 
  /*
839
 
   * Also nfs requires a separate program, but it is built in.
840
 
   */
841
 
  if (!fake && types && streq (types, "nfs")) {
842
 
#ifdef HAVE_NFS
843
 
retry_nfs:
844
 
    mnt_err = nfsmount (spec, node, &flags, &extra_opts, &mount_opts,
845
 
                        &nfs_mount_version, bg);
846
 
    if (mnt_err) {
847
 
        res = mnt_err;
848
 
        goto out;
849
 
    }
850
 
#else
851
 
    die (EX_SOFTWARE, _("mount: this version was compiled "
852
 
                      "without support for the type `nfs'"));
853
 
#endif
854
 
  }
855
 
 
856
1077
  block_signals (SIG_BLOCK);
857
1078
 
858
 
  if (!fake)
 
1079
  if (!fake) {
859
1080
    mnt5_res = guess_fstype_and_mount (spec, node, &types, flags & ~MS_NOSYS,
860
 
                                       mount_opts);
 
1081
                                       mount_opts, &special, &status);
 
1082
 
 
1083
    if (special) {
 
1084
      block_signals (SIG_UNBLOCK);
 
1085
      res = status;
 
1086
      goto out;
 
1087
    }
 
1088
  }
861
1089
 
862
1090
  if (fake || mnt5_res == 0) {
863
1091
      /* Mount succeeded, report this (if verbose) and write mtab entry.  */
864
 
      if (loop)
865
 
          opt_loopdev = loopdev;
866
1092
 
867
 
      update_mtab_entry(loop ? loopfile : spec,
 
1093
      if (!(mounttype & MS_PROPAGATION)) {
 
1094
              update_mtab_entry(loop ? loopfile : spec,
868
1095
                        node,
869
1096
                        types ? types : "unknown",
870
1097
                        fix_opts_string (flags & ~MS_NOMTAB, extra_opts, user),
871
1098
                        flags,
872
1099
                        freq,
873
1100
                        pass);
 
1101
      }
874
1102
 
875
1103
      block_signals (SIG_UNBLOCK);
876
1104
      res = 0;
884
1112
 
885
1113
  block_signals (SIG_UNBLOCK);
886
1114
 
887
 
#ifdef HAVE_NFS
888
 
  if (mnt_err && types && streq (types, "nfs")) {
889
 
      if (nfs_mount_version == 4 && mnt_err != EBUSY && mnt_err != ENOENT) {
890
 
          if (verbose)
891
 
            printf(_("mount: failed with nfs mount version 4, trying 3..\n"));
892
 
          nfs_mount_version = 3;
893
 
          goto retry_nfs;
894
 
      }
895
 
  }
896
 
#endif
897
 
 
898
1115
  /* Mount failed, complain, but don't die.  */
899
1116
 
900
1117
  if (types == 0) {
964
1181
        error (_("mount: %s not mounted already, or bad option"), node);
965
1182
      } else {
966
1183
        error (_("mount: wrong fs type, bad option, bad superblock on %s,\n"
967
 
               "       missing codepage or other error"),
 
1184
               "       missing codepage or helper program, or other error"),
968
1185
               spec);
969
1186
 
970
1187
        if (stat(spec, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)
1006
1223
    case EIO:
1007
1224
      error (_("mount: %s: can't read superblock"), spec); break;
1008
1225
    case ENODEV:
1009
 
    { int pfs;
1010
 
      if ((pfs = is_in_procfs(types)) == 1 || !strcmp(types, "guess"))
 
1226
    {
 
1227
      int pfs = fsprobe_known_fstype_in_procfs(types);
 
1228
 
 
1229
      if (pfs == 1 || !strcmp(types, "guess"))
1011
1230
        error(_("mount: %s: unknown device"), spec);
1012
1231
      else if (pfs == 0) {
1013
1232
        char *lowtype, *p;
1024
1243
            u++;
1025
1244
          }
1026
1245
        }
1027
 
        if (u && is_in_procfs(lowtype) == 1)
 
1246
        if (u && fsprobe_known_fstype_in_procfs(lowtype) == 1)
1028
1247
          error (_("mount: probably you meant %s"), lowtype);
1029
 
        else if (!strncmp(lowtype, "iso", 3) && is_in_procfs("iso9660") == 1)
 
1248
        else if (!strncmp(lowtype, "iso", 3) &&
 
1249
                        fsprobe_known_fstype_in_procfs("iso9660") == 1)
1030
1250
          error (_("mount: maybe you meant 'iso9660'?"));
1031
 
        else if (!strncmp(lowtype, "fat", 3) && is_in_procfs("vfat") == 1)
 
1251
        else if (!strncmp(lowtype, "fat", 3) &&
 
1252
                        fsprobe_known_fstype_in_procfs("vfat") == 1)
1032
1253
          error (_("mount: maybe you meant 'vfat'?"));
1033
1254
        free(lowtype);
1034
1255
      } else
1062
1283
                 bd, spec);
1063
1284
          break;
1064
1285
      } else {
1065
 
         if (loop) {
1066
 
             opts = opts0;
1067
 
             types = types0;
1068
 
         }
 
1286
         opts = opts0;
 
1287
         types = types0;
 
1288
 
1069
1289
         if (opts) {
1070
 
             char *opts2 = xrealloc(xstrdup(opts), strlen(opts)+4);
1071
 
             strcat(opts2, ",ro");
 
1290
             char *opts2 = append_opt(xstrdup(opts), "ro", NULL);
1072
1291
             my_free(opts1);
1073
1292
             opts = opts1 = opts2;
1074
1293
         } else
1122
1341
        return n;
1123
1342
}
1124
1343
 
1125
 
static const char *
 
1344
static char *
1126
1345
usersubst(const char *opts) {
1127
1346
        char *s, *w;
1128
1347
        char id[40];
1129
1348
 
 
1349
        if (!opts)
 
1350
                return NULL;
 
1351
 
1130
1352
        s = "uid=useruid";
1131
1353
        if (opts && (w = strstr(opts, s)) != NULL) {
1132
1354
                sprintf(id, "uid=%d", getuid());
1137
1359
                sprintf(id, "gid=%d", getgid());
1138
1360
                opts = subst_string(opts, w, strlen(s), id);
1139
1361
        }
1140
 
        return opts;
 
1362
        return xstrdup(opts);
1141
1363
}
1142
1364
 
1143
1365
static int
1152
1374
 */
1153
1375
static int
1154
1376
mount_one (const char *spec, const char *node, const char *types,
1155
 
           const char *opts, char *cmdlineopts, int freq, int pass) {
 
1377
           const char *fstabopts, char *cmdlineopts, int freq, int pass) {
1156
1378
        int status, status2;
1157
1379
        const char *nspec;
 
1380
        char *opts;
1158
1381
 
1159
1382
        /* Substitute values in opts, if required */
1160
 
        opts = usersubst(opts);
 
1383
        opts = usersubst(fstabopts);
1161
1384
 
1162
1385
        /* Merge the fstab and command line options.  */
1163
 
        if (opts == NULL)
1164
 
                opts = cmdlineopts;
1165
 
        else if (cmdlineopts != NULL)
1166
 
                opts = xstrconcat3(opts, ",", cmdlineopts);
1167
 
 
1168
 
        /* Handle possible LABEL= and UUID= forms of spec */
1169
 
        nspec = mount_get_devname_for_mounting(spec);
1170
 
        if (nspec)
1171
 
                spec = nspec;
 
1386
        opts = append_opt(opts, cmdlineopts, NULL);
1172
1387
 
1173
1388
        if (types == NULL && !mounttype && !is_existing_file(spec)) {
1174
1389
                if (strchr (spec, ':') != NULL) {
1178
1393
                                         "I'll assume nfs because of "
1179
1394
                                         "the colon\n"));
1180
1395
                } else if(!strncmp(spec, "//", 2)) {
1181
 
                        types = "smbfs";
 
1396
                        types = "cifs";
1182
1397
                        if (verbose)
1183
1398
                                printf(_("mount: no type was given - "
1184
 
                                         "I'll assume smbfs because of "
 
1399
                                         "I'll assume cifs because of "
1185
1400
                                         "the // prefix\n"));
1186
1401
                }
1187
1402
        }
1188
1403
 
 
1404
        /* Handle possible LABEL= and UUID= forms of spec */
 
1405
        if (types == NULL || (strncmp(types, "nfs", 3) &&
 
1406
                              strncmp(types, "cifs", 4) &&
 
1407
                              strncmp(types, "smbfs", 5))) {
 
1408
                nspec = fsprobe_get_devname_for_mounting(spec);
 
1409
                if (nspec)
 
1410
                        spec = nspec;
 
1411
        }
 
1412
 
1189
1413
        /*
1190
1414
         * Try to mount the file system. When the exit status is EX_BG,
1191
1415
         * we will retry in the background. Otherwise, we're done.
1204
1428
        spec = xstrdup(spec);           /* arguments will be destroyed */
1205
1429
        node = xstrdup(node);           /* by set_proc_name()          */
1206
1430
        types = xstrdup(types);
1207
 
        opts = xstrdup(opts);
1208
1431
        set_proc_name (spec);           /* make a nice "ps" listing */
1209
1432
        status2 = try_mount_one (spec, node, types, opts, freq, pass, 1, 0);
1210
1433
        if (verbose && status2)
1211
1434
                printf (_("mount: giving up \"%s\"\n"), spec);
 
1435
 
 
1436
        my_free(opts);
 
1437
        my_free(node);
 
1438
        my_free(types);
1212
1439
        exit (0);                       /* child stops here */
1213
1440
}
1214
1441
 
1216
1443
static int
1217
1444
mounted (const char *spec0, const char *node0) {
1218
1445
        struct mntentchn *mc, *mc0;
1219
 
        char *spec, *node;
 
1446
        const char *spec, *node;
1220
1447
        int ret = 0;
1221
1448
 
1222
1449
        /* Handle possible UUID= and LABEL= in spec */
1223
 
        spec0 = mount_get_devname(spec0);
1224
 
        if (!spec0)
 
1450
        spec = fsprobe_get_devname(spec0);
 
1451
        if (!spec)
1225
1452
                return ret;
1226
1453
 
1227
 
        spec = canonicalize(spec0);
1228
1454
        node = canonicalize(node0);
1229
1455
 
1230
1456
        mc0 = mtab_head();
1308
1534
                                                DISKMAJOR(statbuf.st_rdev));
1309
1535
                                        g = major;
1310
1536
                                }
1311
 
#ifdef HAVE_NFS
1312
1537
                                if (strcmp(mc->m.mnt_type, "nfs") == 0) {
1313
1538
                                        g = xstrdup(mc->m.mnt_fsname);
1314
1539
                                        colon = strchr(g, ':');
1315
1540
                                        if (colon)
1316
1541
                                                *colon = '\0';
1317
1542
                                }
1318
 
#endif
1319
1543
                        }
1320
1544
                        if (g) {
1321
1545
                                for (cp = childhead.nxt; cp; cp = cp->nxt)
1389
1613
        return status;
1390
1614
}
1391
1615
 
1392
 
extern char version[];
1393
1616
static struct option longopts[] = {
1394
1617
        { "all", 0, 0, 'a' },
1395
1618
        { "fake", 0, 0, 'f' },
1414
1637
        { "move", 0, 0, 133 },
1415
1638
        { "guess-fstype", 1, 0, 134 },
1416
1639
        { "rbind", 0, 0, 135 },
 
1640
        { "make-shared", 0, 0, 136 },
 
1641
        { "make-slave", 0, 0, 137 },
 
1642
        { "make-private", 0, 0, 138 },
 
1643
        { "make-unbindable", 0, 0, 139 },
 
1644
        { "make-rshared", 0, 0, 140 },
 
1645
        { "make-rslave", 0, 0, 141 },
 
1646
        { "make-rprivate", 0, 0, 142 },
 
1647
        { "make-runbindable", 0, 0, 143 },
1417
1648
        { "internal-only", 0, 0, 'i' },
1418
1649
        { NULL, 0, 0, 0 }
1419
1650
};
1440
1671
          "       mount --bind olddir newdir\n"
1441
1672
          "or move a subtree:\n"
1442
1673
          "       mount --move olddir newdir\n"
 
1674
          "One can change the type of mount containing the directory dir:\n"
 
1675
          "       mount --make-shared dir\n"
 
1676
          "       mount --make-slave dir\n"
 
1677
          "       mount --make-private dir\n"
 
1678
          "       mount --make-unbindable dir\n"
 
1679
          "One can change the type of all the mounts in a mount subtree\n"
 
1680
          "containing the directory dir:\n"
 
1681
          "       mount --make-rshared dir\n"
 
1682
          "       mount --make-rslave dir\n"
 
1683
          "       mount --make-rprivate dir\n"
 
1684
          "       mount --make-runbindable dir\n"
1443
1685
          "A device can be given by name, say /dev/hda1 or /dev/cdrom,\n"
1444
1686
          "or by label, using  -L label  or by uuid, using  -U uuid .\n"
1445
1687
          "Other options: [-nfFrsvw] [-o options] [-p passwdfd].\n"
1453
1695
        exit (n);
1454
1696
}
1455
1697
 
 
1698
/* returns mount entry from fstab */
 
1699
static struct mntentchn *
 
1700
getfs(const char *spec, const char *uuid, const char *label)
 
1701
{
 
1702
        struct mntentchn *mc = NULL;
 
1703
        const char *devname = NULL;
 
1704
 
 
1705
        if (!spec && !uuid && !label)
 
1706
                return NULL;
 
1707
 
 
1708
        /*
 
1709
         * A) 99% of all cases, the spec on cmdline matches
 
1710
         *    with spec in fstab
 
1711
         */
 
1712
        if (uuid)
 
1713
                mc = getfs_by_uuid(uuid);
 
1714
        else if (label)
 
1715
                mc = getfs_by_label(label);
 
1716
        else {
 
1717
                mc = getfs_by_spec(spec);
 
1718
 
 
1719
                if (!mc)
 
1720
                        mc = getfs_by_dir(spec);
 
1721
        }
 
1722
        if (mc)
 
1723
                return mc;
 
1724
 
 
1725
        /*
 
1726
         * B) UUID or LABEL on cmdline, but devname in fstab
 
1727
         */
 
1728
        if (uuid)
 
1729
                devname = fsprobe_get_devname_by_uuid(uuid);
 
1730
        else if (label)
 
1731
                devname = fsprobe_get_devname_by_label(label);
 
1732
        else
 
1733
                devname = fsprobe_get_devname(spec);
 
1734
 
 
1735
        if (devname)
 
1736
                mc = getfs_by_devname(devname);
 
1737
 
 
1738
        /*
 
1739
         * C) mixed
 
1740
         */
 
1741
        if (!mc && devname) {
 
1742
                const char *id = NULL;
 
1743
 
 
1744
                if (!label && (!spec || strncmp(spec, "LABEL=", 6))) {
 
1745
                        id = fsprobe_get_label_by_devname(devname);
 
1746
                        if (id)
 
1747
                                mc = getfs_by_label(id);
 
1748
                }
 
1749
                if (!mc && !uuid && (!spec || strncmp(spec, "UUID=", 5))) {
 
1750
                        id = fsprobe_get_uuid_by_devname(devname);
 
1751
                        if (id)
 
1752
                                mc = getfs_by_uuid(id);
 
1753
                }
 
1754
                my_free(id);
 
1755
 
 
1756
                if (mc) {
 
1757
                        /* use real device name to avoid repetitional
 
1758
                         * conversion from LABEL/UUID to devname
 
1759
                         */
 
1760
                        my_free(mc->m.mnt_fsname);
 
1761
                        mc->m.mnt_fsname = xstrdup(devname);
 
1762
                }
 
1763
        }
 
1764
 
 
1765
        /*
 
1766
         * D) remount -- try /etc/mtab
 
1767
         *    Earlier mtab was tried first, but this would sometimes try the
 
1768
         *    wrong mount in case mtab had the root device entry wrong.
 
1769
         */
 
1770
        if (!mc && (devname || spec))
 
1771
                mc = getmntfile (devname ? devname : spec);
 
1772
 
 
1773
        if (devname)
 
1774
                my_free(devname);
 
1775
        return mc;
 
1776
}
 
1777
 
1456
1778
char *progname;
1457
1779
 
1458
1780
int
1459
1781
main(int argc, char *argv[]) {
1460
1782
        int c, result = 0, specseen;
1461
1783
        char *options = NULL, *test_opts = NULL, *node;
1462
 
        const char *spec;
1463
 
        char *volumelabel = NULL;
 
1784
        const char *spec = NULL;
 
1785
        char *label = NULL;
1464
1786
        char *uuid = NULL;
1465
1787
        char *types = NULL;
1466
1788
        char *p;
1485
1807
        if (fd > 2)
1486
1808
                close(fd);
1487
1809
 
1488
 
        mount_blkid_get_cache();
 
1810
        fsprobe_init();
1489
1811
 
1490
1812
#ifdef DO_PS_FIDDLING
1491
1813
        initproctitle(argc, argv);
1513
1835
                        list_with_volumelabel = 1;
1514
1836
                        break;
1515
1837
                case 'L':
1516
 
                        volumelabel = optarg;
 
1838
                        label = optarg;
1517
1839
                        break;
1518
1840
                case 'n':               /* do not write /etc/mtab */
1519
1841
                        ++nomtab;
1520
1842
                        break;
1521
1843
                case 'o':               /* specify mount options */
1522
 
                        if (options)
1523
 
                                options = xstrconcat3(options, ",", optarg);
1524
 
                        else
1525
 
                                options = xstrdup(optarg);
 
1844
                        options = append_opt(options, optarg, NULL);
1526
1845
                        break;
1527
1846
                case 'O':               /* with -t: mount only if (not) opt */
1528
 
                        if (test_opts)
1529
 
                                test_opts = xstrconcat3(test_opts, ",", optarg);
1530
 
                        else
1531
 
                                test_opts = xstrdup(optarg);
 
1847
                        test_opts = append_opt(test_opts, optarg, NULL);
1532
1848
                        break;
1533
1849
                case 'p':               /* fd on which to read passwd */
1534
1850
                        set_pfd(optarg);
1550
1866
                        ++verbose;
1551
1867
                        break;
1552
1868
                case 'V':               /* version */
1553
 
                        printf ("mount: %s\n", version);
 
1869
                        printf ("mount (%s)\n", PACKAGE_STRING);
1554
1870
                        exit (0);
1555
1871
                case 'w':               /* mount read/write */
1556
1872
                        readwrite = 1;
1583
1899
                           use only for testing purposes -
1584
1900
                           the guessing is not reliable at all */
1585
1901
                    {
1586
 
                        char *fstype;
1587
 
                        fstype = do_guess_fstype(optarg);
 
1902
                        const char *fstype;
 
1903
                        fstype = fsprobe_get_fstype_by_devname(optarg);
1588
1904
                        printf("%s\n", fstype ? fstype : "unknown");
1589
1905
                        exit(fstype ? 0 : EX_FAIL);
1590
1906
                    }
1591
1907
                case 135:
1592
1908
                        mounttype = (MS_BIND | MS_REC);
1593
1909
                        break;
 
1910
 
 
1911
                case 136:
 
1912
                        mounttype = MS_SHARED;
 
1913
                        break;
 
1914
 
 
1915
                case 137:
 
1916
                        mounttype = MS_SLAVE;
 
1917
                        break;
 
1918
 
 
1919
                case 138:
 
1920
                        mounttype = MS_PRIVATE;
 
1921
                        break;
 
1922
 
 
1923
                case 139:
 
1924
                        mounttype = MS_UNBINDABLE;
 
1925
                        break;
 
1926
 
 
1927
                case 140:
 
1928
                        mounttype = (MS_SHARED | MS_REC);
 
1929
                        break;
 
1930
 
 
1931
                case 141:
 
1932
                        mounttype = (MS_SLAVE | MS_REC);
 
1933
                        break;
 
1934
 
 
1935
                case 142:
 
1936
                        mounttype = (MS_PRIVATE | MS_REC);
 
1937
                        break;
 
1938
 
 
1939
                case 143:
 
1940
                        mounttype = (MS_UNBINDABLE | MS_REC);
 
1941
                        break;
 
1942
 
1594
1943
                case '?':
1595
1944
                default:
1596
1945
                        usage (stderr, EX_USAGE);
1597
1946
                }
1598
1947
        }
1599
1948
 
 
1949
        if (verbose > 2) {
 
1950
                printf("mount: fstab path: \"%s\"\n", _PATH_FSTAB);
 
1951
                printf("mount: lock path:  \"%s\"\n", MOUNTED_LOCK);
 
1952
                printf("mount: temp path:  \"%s\"\n", MOUNTED_TEMP);
 
1953
        }
 
1954
 
1600
1955
        argc -= optind;
1601
1956
        argv += optind;
1602
1957
 
1603
 
        specseen = (uuid || volumelabel) ? 1 : 0;       /* yes, .. i know */
 
1958
        specseen = (uuid || label) ? 1 : 0;     /* yes, .. i know */
1604
1959
 
1605
1960
        if (argc+specseen == 0 && !mount_all) {
1606
1961
                if (options || mounttype)
1622
1977
                create_mtab ();
1623
1978
        }
1624
1979
 
1625
 
        if (specseen) {
1626
 
                if (uuid)
1627
 
                        spec = mount_get_devname_by_uuid(uuid);
1628
 
                else
1629
 
                        spec = mount_get_devname_by_label(volumelabel);
1630
 
 
1631
 
                if (!spec)
1632
 
                        die (EX_USAGE, _("mount: no such partition found"));
1633
 
                if (verbose)
1634
 
                        printf(_("mount: mounting %s\n"), spec);
1635
 
        } else
1636
 
                spec = NULL;            /* just for gcc */
1637
 
 
1638
1980
        switch (argc+specseen) {
1639
1981
        case 0:
1640
1982
                /* mount -a */
1641
1983
                result = do_mount_all (types, options, test_opts);
1642
 
                if (result == 0 && verbose)
 
1984
                if (result == 0 && verbose && !fake)
1643
1985
                        error(_("nothing was mounted"));
1644
1986
                break;
1645
1987
 
1646
1988
        case 1:
1647
 
                /* mount [-nfrvw] [-o options] special | node */
 
1989
                /* mount [-nfrvw] [-o options] special | node
 
1990
                 * mount -L label  (or -U uuid)
 
1991
                 * (/etc/fstab is necessary)
 
1992
                 */
1648
1993
                if (types != NULL)
1649
1994
                        usage (stderr, EX_USAGE);
1650
 
                if (specseen) {
1651
 
                        /* We know the device. Where shall we mount it? */
1652
 
                        mc = (uuid ? getfsuuidspec (uuid)
1653
 
                                   : getfsvolspec (volumelabel));
1654
 
                        if (mc == NULL)
1655
 
                                mc = getfsspec (spec);
1656
 
                        if (mc == NULL)
1657
 
                                die (EX_USAGE,
1658
 
                                     _("mount: cannot find %s in %s"),
1659
 
                                     spec, _PATH_FSTAB);
1660
 
                        mc->m.mnt_fsname = spec;
1661
 
                } else {
1662
 
                        /* Try to find the other pathname in fstab.  */
1663
 
                        spec = canonicalize (*argv);
1664
 
                        if ((mc = getfsspec (spec)) == NULL &&
1665
 
                            (mc = getfsfile (spec)) == NULL &&
1666
 
                            /* Try noncanonical name in fstab
1667
 
                               perhaps /dev/cdrom or /dos is a symlink */
1668
 
                            (mc = getfsspec (*argv)) == NULL &&
1669
 
                            (mc = getfsfile (*argv)) == NULL &&
1670
 
                            /* Try mtab - maybe this was a remount */
1671
 
                            (mc = getmntfile (spec)) == NULL)
1672
 
                                die (EX_USAGE,
1673
 
                                     _("mount: can't find %s in %s or %s"),
1674
 
                                     spec, _PATH_FSTAB, MOUNTED);
1675
 
                        /* Earlier mtab was tried first, but this would
1676
 
                           sometimes try the wrong mount in case mtab had
1677
 
                           the root device entry wrong. */
1678
 
 
1679
 
                        my_free(spec);
 
1995
 
 
1996
                if (uuid || label)
 
1997
                        mc = getfs(NULL, uuid, label);
 
1998
                else
 
1999
                        mc = getfs(*argv, NULL, NULL);
 
2000
 
 
2001
                if (!mc) {
 
2002
                        if (uuid || label)
 
2003
                                die (EX_USAGE, _("mount: no such partition found"));
 
2004
 
 
2005
                        die (EX_USAGE,
 
2006
                             _("mount: can't find %s in %s or %s"),
 
2007
                             *argv, _PATH_FSTAB, MOUNTED);
1680
2008
                }
1681
2009
 
1682
2010
                result = mount_one (xstrdup (mc->m.mnt_fsname),
1686
2014
                break;
1687
2015
 
1688
2016
        case 2:
1689
 
                /* mount [-nfrvw] [-t vfstype] [-o options] special node */
 
2017
                /* mount special node  (/etc/fstab is not necessary) */
1690
2018
                if (specseen) {
1691
 
                        /* we have spec already */
 
2019
                        /* mount -L label node   (or -U uuid) */
 
2020
                        spec = uuid ?   fsprobe_get_devname_by_uuid(uuid) :
 
2021
                                        fsprobe_get_devname_by_label(label);
1692
2022
                        node = argv[0];
1693
2023
                } else {
 
2024
                        /* mount special node */
1694
2025
                        spec = argv[0];
1695
2026
                        node = argv[1];
1696
2027
                }
 
2028
                if (!spec)
 
2029
                        die (EX_USAGE, _("mount: no such partition found"));
 
2030
 
1697
2031
                result = mount_one (spec, node, types, NULL, options, 0, 0);
1698
2032
                break;
1699
 
      
 
2033
 
1700
2034
        default:
1701
2035
                usage (stderr, EX_USAGE);
1702
2036
        }
1704
2038
        if (result == EX_SOMEOK)
1705
2039
                result = 0;
1706
2040
 
1707
 
        mount_blkid_put_cache();
 
2041
        fsprobe_exit();
1708
2042
 
1709
2043
        exit (result);
1710
2044
}