~barry/ubuntu/maverick/fuse/bug-697792-m

« back to all changes in this revision

Viewing changes to util/fusermount.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2007-08-04 08:09:00 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20070804080900-m1e9xpk5eitzmelg
Tags: 2.7.0-1ubuntu1
* Resynchronise with Debian (LP: #128292). Remaining changes:
  - Don't install the init script; install the udev rule and the module
    configuration file instead.
  - debian/45-fuse.rules: set /dev/fuse group to fuse.
  - debian/fuse-utils.modprobe: module configuration file that mounts the
    control filesystem when fuse is loaded and unmounts it when fuse is
    unloaded, along with checking that the control FS is mounting before
    unmounting it.
  - debian/fuse-utils.install: add the udev rule, the module configuration
    file, and ulockmgr_server.
  - Load fuse on install, and set it so it gets loaded on reboot.
  - Move fusermount and ulockmgr_server to /bin and associated libraries
    to /lib.
* Use dpkg-query to fetch conffile md5sums rather than parsing
  /var/lib/dpkg/status directly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
    FUSE: Filesystem in Userspace
3
 
    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
3
    Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
4
4
 
5
5
    This program can be distributed under the terms of the GNU GPL.
6
6
    See the file COPYING.
7
7
*/
8
8
/* This program does the mounting and unmounting of FUSE filesystems */
9
9
 
10
 
/*
11
 
 * NOTE: This program should be part of (or be called from) /bin/mount
12
 
 *
13
 
 * Unless that is done, operations on /etc/mtab are not under lock, and so
14
 
 * data in this file may be lost. (I will _not_ reimplement that locking,
15
 
 * and anyway that should be done in libc, if possible.  But probably it
16
 
 * isn't).
17
 
 */
18
 
 
19
10
#include <config.h>
20
11
 
 
12
#include "mount_util.h"
21
13
#include <stdio.h>
22
14
#include <stdlib.h>
23
15
#include <string.h>
28
20
#include <fcntl.h>
29
21
#include <pwd.h>
30
22
#include <mntent.h>
31
 
#include <dirent.h>
32
 
#include <sys/param.h>
33
23
#include <sys/wait.h>
34
24
#include <sys/stat.h>
35
25
#include <sys/mount.h>
36
26
#include <sys/fsuid.h>
37
27
#include <sys/socket.h>
38
 
#include <sys/un.h>
39
28
#include <sys/utsname.h>
40
 
#include <sys/sysmacros.h>
41
 
 
42
 
#ifdef HAVE_SELINUX_SELINUX_H
43
 
#include <selinux/selinux.h>
44
 
#endif
45
29
 
46
30
#define FUSE_COMMFD_ENV         "_FUSE_COMMFD"
47
31
 
89
73
    }
90
74
}
91
75
 
92
 
static int do_unmount(const char *mnt, int quiet, int lazy)
93
 
{
94
 
    int res = umount2(mnt, lazy ? 2 : 0);
95
 
    if (res == -1) {
96
 
        if (!quiet)
97
 
            fprintf(stderr, "%s: failed to unmount %s: %s\n",
98
 
                    progname, mnt, strerror(errno));
99
 
    }
100
 
    return res;
101
 
}
102
 
 
103
76
#ifndef IGNORE_MTAB
104
 
/* use a lock file so that multiple fusermount processes don't try and
105
 
   modify the mtab file at once! */
106
 
static int lock_mtab(void)
107
 
{
108
 
    const char *mtab_lock = _PATH_MOUNTED ".fuselock";
109
 
    int mtablock;
110
 
    int res;
111
 
    struct stat mtab_stat;
112
 
 
113
 
    /* /etc/mtab could be a symlink to /proc/mounts */
114
 
    if (!lstat(_PATH_MOUNTED, &mtab_stat)) {
115
 
        if (S_ISLNK(mtab_stat.st_mode))
116
 
            return -1;
117
 
    }
118
 
 
119
 
    mtablock = open(mtab_lock, O_RDWR | O_CREAT, 0600);
120
 
    if (mtablock >= 0) {
121
 
        res = lockf(mtablock, F_LOCK, 0);
122
 
        if (res < 0)
123
 
            fprintf(stderr, "%s: error getting lock", progname);
124
 
    } else
125
 
        fprintf(stderr, "%s: unable to open fuse lock file\n", progname);
126
 
 
127
 
    return mtablock;
128
 
}
129
 
 
130
 
static void unlock_mtab(int mtablock)
131
 
{
132
 
    if (mtablock >= 0) {
133
 
        lockf(mtablock, F_ULOCK, 0);
134
 
        close(mtablock);
135
 
    }
136
 
}
137
 
 
138
 
/* Glibc addmntent() doesn't encode '\n', misencodes '\t' as '\n'
139
 
   (version 2.3.2), and encodes '\\' differently as mount(8).  So
140
 
   let's not allow those characters, they are not all that usual in
141
 
   filenames. */
142
 
static int check_name(const char *name)
143
 
{
144
 
    const char *s;
145
 
    for (s = "\n\t\\"; *s; s++) {
146
 
        if (strchr(name, *s)) {
147
 
            fprintf(stderr, "%s: illegal character 0x%02x in mount entry\n",
148
 
                    progname, *s);
149
 
            return -1;
150
 
        }
151
 
    }
152
 
    return 0;
153
 
}
154
 
 
155
 
static int add_mount(const char *fsname, const char *mnt, const char *type,
 
77
static int add_mount(const char *source, const char *mnt, const char *type,
156
78
                     const char *opts)
157
79
{
158
 
    int res;
159
 
    const char *mtab = _PATH_MOUNTED;
160
 
    struct mntent ent;
161
 
    FILE *fp;
162
 
 
163
 
    if (check_name(fsname) == -1 || check_name(mnt) == -1 ||
164
 
        check_name(type) == -1 || check_name(opts) == -1)
165
 
        return -1;
166
 
 
167
 
    fp = setmntent(mtab, "a");
168
 
    if (fp == NULL) {
169
 
        fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab,
170
 
                strerror(errno));
171
 
        return -1;
172
 
    }
173
 
 
174
 
    ent.mnt_fsname = (char *) fsname;
175
 
    ent.mnt_dir = (char *) mnt;
176
 
    ent.mnt_type = (char *) type;
177
 
    ent.mnt_opts = (char *) opts;
178
 
    ent.mnt_freq = 0;
179
 
    ent.mnt_passno = 0;
180
 
    res = addmntent(fp, &ent);
181
 
    if (res != 0) {
182
 
        fprintf(stderr, "%s: failed to add entry to %s: %s\n", progname,
183
 
                mtab, strerror(errno));
184
 
        return -1;
185
 
    }
186
 
 
187
 
    endmntent(fp);
188
 
    return 0;
189
 
}
190
 
 
191
 
static int unmount_rename(const char *mtab, const char *mtab_new)
192
 
{
193
 
    int res;
194
 
    struct stat sbuf;
195
 
 
196
 
    if (stat(mtab, &sbuf) == 0)
197
 
        chown(mtab_new, sbuf.st_uid, sbuf.st_gid);
198
 
 
199
 
#ifdef HAVE_LIBSELINUX
200
 
    {
201
 
        security_context_t filecon;
202
 
 
203
 
        if (getfilecon(mtab, &filecon) > 0) {
204
 
            setfilecon(mtab_new, filecon);
205
 
            if (filecon != NULL)
206
 
                freecon(filecon);
207
 
        }
208
 
    }
209
 
#endif
210
 
 
211
 
    res = rename(mtab_new, mtab);
212
 
    if (res == -1) {
213
 
        fprintf(stderr, "%s: failed to rename %s to %s: %s\n", progname,
214
 
                mtab_new, mtab, strerror(errno));
215
 
        return -1;
216
 
    }
217
 
    return 0;
 
80
    return fuse_mnt_add_mount(progname, source, mnt, type, opts);
218
81
}
219
82
 
220
83
static int unmount_fuse(const char *mnt, int quiet, int lazy)
221
84
{
222
 
    int res;
223
 
    struct mntent *entp;
224
 
    FILE *fp;
225
 
    FILE *newfp = NULL;
226
 
    const char *user = NULL;
227
 
    char uidstr[32];
228
 
    unsigned uidlen = 0;
229
 
    int found;
230
 
    int issymlink = 0;
231
 
    struct stat stbuf;
232
 
    const char *mtab = _PATH_MOUNTED;
233
 
    const char *mtab_new = _PATH_MOUNTED "~fuse~";
234
 
 
235
 
    if (lstat(mtab, &stbuf) != -1 && S_ISLNK(stbuf.st_mode))
236
 
        issymlink = 1;
237
 
 
238
 
    fp = setmntent(mtab, "r");
239
 
    if (fp == NULL) {
240
 
        fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab,
241
 
                strerror(errno));
242
 
        return -1;
243
 
    }
244
 
 
245
 
    if (!issymlink) {
246
 
        newfp = setmntent(mtab_new, "w");
247
 
        if (newfp == NULL) {
248
 
            fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab_new,
249
 
                    strerror(errno));
250
 
            endmntent(fp);
251
 
            return -1;
252
 
        }
253
 
    }
254
 
 
255
85
    if (getuid() != 0) {
 
86
        struct mntent *entp;
 
87
        FILE *fp;
 
88
        const char *user = NULL;
 
89
        char uidstr[32];
 
90
        unsigned uidlen = 0;
 
91
        int found;
 
92
        const char *mtab = _PATH_MOUNTED;
 
93
 
256
94
        user = get_user_name();
257
95
        if (user == NULL)
258
 
            goto err_endmntent;
 
96
            return -1;
 
97
 
 
98
        fp = setmntent(mtab, "r");
 
99
        if (fp == NULL) {
 
100
            fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab,
 
101
                    strerror(errno));
 
102
            return -1;
 
103
        }
259
104
 
260
105
        uidlen = sprintf(uidstr, "%u", getuid());
261
 
    }
262
106
 
263
 
    found = 0;
264
 
    while ((entp = getmntent(fp)) != NULL) {
265
 
        int removed = 0;
266
 
        if (!found && strcmp(entp->mnt_dir, mnt) == 0 &&
267
 
            (strcmp(entp->mnt_type, "fuse") == 0 ||
268
 
             strcmp(entp->mnt_type, "fuseblk") == 0)) {
269
 
            if (user == NULL)
270
 
                removed = 1;
271
 
            else {
 
107
        found = 0;
 
108
        while ((entp = getmntent(fp)) != NULL) {
 
109
            if (!found && strcmp(entp->mnt_dir, mnt) == 0 &&
 
110
                (strcmp(entp->mnt_type, "fuse") == 0 ||
 
111
                 strcmp(entp->mnt_type, "fuseblk") == 0 ||
 
112
                 strncmp(entp->mnt_type, "fuse.", 5) == 0 ||
 
113
                 strncmp(entp->mnt_type, "fuseblk.", 8) == 0)) {
272
114
                char *p = strstr(entp->mnt_opts, "user=");
273
115
                if (p && (p == entp->mnt_opts || *(p-1) == ',') &&
274
 
                    strcmp(p + 5, user) == 0)
275
 
                    removed = 1;
 
116
                    strcmp(p + 5, user) == 0) {
 
117
                    found = 1;
 
118
                    break;
 
119
                }
276
120
                /* /etc/mtab is a link pointing to /proc/mounts: */
277
121
                else if ((p = strstr(entp->mnt_opts, "user_id=")) &&
278
122
                         (p == entp->mnt_opts || *(p-1) == ',') &&
279
123
                         strncmp(p + 8, uidstr, uidlen) == 0 &&
280
 
                         (*(p+8+uidlen) == ',' || *(p+8+uidlen) == '\0'))
281
 
                    removed = 1;
282
 
            }
283
 
        }
284
 
        if (removed)
285
 
            found = 1;
286
 
        else if (!issymlink) {
287
 
            res = addmntent(newfp, entp);
288
 
            if (res != 0) {
289
 
                fprintf(stderr, "%s: failed to add entry to %s: %s\n",
290
 
                        progname, mtab_new, strerror(errno));
291
 
            }
292
 
        }
293
 
    }
294
 
 
295
 
    endmntent(fp);
296
 
    if (!issymlink)
297
 
        endmntent(newfp);
298
 
 
299
 
    if (!found) {
300
 
        if (!quiet)
301
 
            fprintf(stderr, "%s: entry for %s not found in %s\n", progname,
302
 
                    mnt, mtab);
303
 
        goto err;
304
 
    }
305
 
 
306
 
    drop_privs();
307
 
    res = do_unmount(mnt, quiet, lazy);
308
 
    restore_privs();
309
 
    if (res == -1)
310
 
        goto err;
311
 
 
312
 
    if (!issymlink) {
313
 
        res = unmount_rename(mtab, mtab_new);
314
 
        if (res == -1)
315
 
            goto err;
316
 
    }
317
 
    return 0;
318
 
 
319
 
 err_endmntent:
320
 
    if (!issymlink)
321
 
        endmntent(newfp);
322
 
    endmntent(fp);
323
 
 err:
324
 
    if (!issymlink)
325
 
        unlink(mtab_new);
326
 
    return -1;
 
124
                         (*(p+8+uidlen) == ',' || *(p+8+uidlen) == '\0')) {
 
125
                    found = 1;
 
126
                    break;
 
127
                }
 
128
            }
 
129
        }
 
130
        endmntent(fp);
 
131
 
 
132
        if (!found) {
 
133
            if (!quiet)
 
134
                fprintf(stderr, "%s: entry for %s not found in %s\n", progname,
 
135
                        mnt, mtab);
 
136
            return -1;
 
137
        }
 
138
    }
 
139
 
 
140
    return fuse_mnt_umount(progname, mnt, lazy);
327
141
}
328
142
 
329
143
static int count_fuse_fs(void)
338
152
        return -1;
339
153
    }
340
154
    while ((entp = getmntent(fp)) != NULL) {
341
 
        if (strcmp(entp->mnt_type, "fuse") == 0)
 
155
        if (strcmp(entp->mnt_type, "fuse") == 0 ||
 
156
            strncmp(entp->mnt_type, "fuse.", 5) == 0)
342
157
            count ++;
343
158
    }
344
159
    endmntent(fp);
347
162
 
348
163
 
349
164
#else /* IGNORE_MTAB */
350
 
static int lock_mtab()
351
 
{
352
 
    return 0;
353
 
}
354
 
 
355
 
static void unlock_mtab(int mtablock)
356
 
{
357
 
    (void) mtablock;
358
 
}
359
 
 
360
165
static int count_fuse_fs()
361
166
{
362
167
    return 0;
363
168
}
364
169
 
365
 
static int add_mount(const char *fsname, const char *mnt, const char *type,
 
170
static int add_mount(const char *source, const char *mnt, const char *type,
366
171
                     const char *opts)
367
172
{
368
 
    (void) fsname;
 
173
    (void) source;
369
174
    (void) mnt;
370
175
    (void) type;
371
176
    (void) opts;
374
179
 
375
180
static int unmount_fuse(const char *mnt, int quiet, int lazy)
376
181
{
377
 
    return do_unmount(mnt, quiet, lazy);
 
182
    return fuse_mnt_umount(progname, mnt, lazy);
378
183
}
379
184
#endif /* IGNORE_MTAB */
380
185
 
543
348
        return 0;
544
349
}
545
350
 
546
 
static int check_mountpoint_empty(const char *mnt, mode_t rootmode,
547
 
                                  off_t rootsize)
 
351
static int get_string_opt(const char *s, unsigned len, const char *opt,
 
352
                          char **val)
548
353
{
549
 
    int isempty = 1;
550
 
 
551
 
    if (S_ISDIR(rootmode)) {
552
 
        struct dirent *ent;
553
 
        DIR *dp = opendir(mnt);
554
 
        if (dp == NULL) {
555
 
            fprintf(stderr, "%s: failed to open mountpoint for reading: %s\n",
556
 
                    progname, strerror(errno));
557
 
            return -1;
558
 
        }
559
 
        while ((ent = readdir(dp)) != NULL) {
560
 
            if (strcmp(ent->d_name, ".") != 0 &&
561
 
                strcmp(ent->d_name, "..") != 0) {
562
 
                isempty = 0;
563
 
                break;
564
 
            }
565
 
        }
566
 
        closedir(dp);
567
 
    } else if (rootsize)
568
 
        isempty = 0;
569
 
 
570
 
    if (!isempty) {
571
 
        fprintf(stderr, "%s: mountpoint is not empty\n", progname);
572
 
        fprintf(stderr, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname);
573
 
        return -1;
 
354
    unsigned opt_len = strlen(opt);
 
355
 
 
356
    if (*val)
 
357
        free(*val);
 
358
    *val = (char *) malloc(len - opt_len + 1);
 
359
    if (!*val) {
 
360
        fprintf(stderr, "%s: failed to allocate memory\n", progname);
 
361
        return 0;
574
362
    }
575
 
    return 0;
576
 
}
577
 
 
578
 
static int has_fuseblk(void)
579
 
{
580
 
    char buf[256];
581
 
    FILE *f = fopen("/proc/filesystems", "r");
582
 
    if (!f)
583
 
        return 1;
584
 
 
585
 
    while (fgets(buf, sizeof(buf), f))
586
 
        if (strstr(buf, "fuseblk\n")) {
587
 
            fclose(f);
588
 
            return 1;
589
 
        }
590
 
 
591
 
    fclose(f);
592
 
    return 0;
593
 
}
594
 
 
595
 
static int do_mount(const char *mnt, const char **type, mode_t rootmode,
596
 
                    int fd, const char *opts, const char *dev, char **fsnamep,
 
363
 
 
364
    memcpy(*val, s + opt_len, len - opt_len);
 
365
    (*val)[len - opt_len] = '\0';
 
366
    return 1;
 
367
}
 
368
 
 
369
static int do_mount(const char *mnt, char **typep, mode_t rootmode,
 
370
                    int fd, const char *opts, const char *dev, char **sourcep,
597
371
                    char **mnt_optsp, off_t rootsize)
598
372
{
599
373
    int res;
603
377
    const char *s;
604
378
    char *d;
605
379
    char *fsname = NULL;
 
380
    char *subtype = NULL;
 
381
    char *source = NULL;
 
382
    char *type = NULL;
606
383
    int check_empty = 1;
607
384
    int blkdev = 0;
608
385
 
615
392
    for (s = opts, d = optbuf; *s;) {
616
393
        unsigned len;
617
394
        const char *fsname_str = "fsname=";
 
395
        const char *subtype_str = "subtype=";
618
396
        for (len = 0; s[len] && s[len] != ','; len++);
619
397
        if (begins_with(s, fsname_str)) {
620
 
            unsigned fsname_str_len = strlen(fsname_str);
621
 
            if (fsname)
622
 
                free(fsname);
623
 
            fsname = (char *) malloc(len - fsname_str_len + 1);
624
 
            if (!fsname) {
625
 
                fprintf(stderr, "%s: failed to allocate memory\n", progname);
626
 
                goto err;
627
 
            }
628
 
            memcpy(fsname, s + fsname_str_len, len - fsname_str_len);
629
 
            fsname[len - fsname_str_len] = '\0';
 
398
            if (!get_string_opt(s, len, fsname_str, &fsname))
 
399
                goto err;
 
400
        } else if (begins_with(s, subtype_str)) {
 
401
            if (!get_string_opt(s, len, subtype_str, &subtype))
 
402
                goto err;
630
403
        } else if (opt_eq(s, len, "blkdev")) {
631
404
            if (getuid() != 0) {
632
405
                fprintf(stderr, "%s: option blkdev is privileged\n", progname);
683
456
 
684
457
    sprintf(d, "fd=%i,rootmode=%o,user_id=%i,group_id=%i",
685
458
            fd, rootmode, getuid(), getgid());
686
 
    if (fsname == NULL) {
687
 
        fsname = strdup(dev);
688
 
        if (!fsname) {
689
 
            fprintf(stderr, "%s: failed to allocate memory\n", progname);
690
 
            goto err;
 
459
 
 
460
    if (check_empty &&
 
461
        fuse_mnt_check_empty(progname, mnt, rootmode, rootsize) == -1)
 
462
        goto err;
 
463
 
 
464
    source = malloc((fsname ? strlen(fsname) : 0) +
 
465
                    (subtype ? strlen(subtype) : 0) + strlen(dev) + 32);
 
466
 
 
467
    type = malloc((subtype ? strlen(subtype) : 0) + 32);
 
468
    if (!type || !source) {
 
469
        fprintf(stderr, "%s: failed to allocate memory\n", progname);
 
470
        goto err;
 
471
    }
 
472
 
 
473
    if (subtype)
 
474
        sprintf(type, "%s.%s", blkdev ? "fuseblk" : "fuse", subtype);
 
475
    else
 
476
        strcpy(type, blkdev ? "fuseblk" : "fuse");
 
477
 
 
478
    if (fsname)
 
479
        strcpy(source, fsname);
 
480
    else
 
481
        strcpy(source, subtype ? subtype : dev);
 
482
 
 
483
    res = mount(source, mnt, type, flags, optbuf);
 
484
    if (res == -1 && errno == ENODEV && subtype) {
 
485
        /* Probably missing subtype support */
 
486
        strcpy(type, blkdev ? "fuseblk" : "fuse");
 
487
        if (fsname) {
 
488
            if (!blkdev)
 
489
                sprintf(source, "%s#%s", subtype, fsname);
 
490
        } else {
 
491
            strcpy(source, type);
691
492
        }
 
493
 
 
494
        res = mount(source, mnt, type, flags, optbuf);
692
495
    }
693
 
 
694
 
    if (check_empty && check_mountpoint_empty(mnt, rootmode, rootsize) == -1)
695
 
        goto err;
696
 
 
697
 
    if (blkdev)
698
 
        *type = "fuseblk";
699
 
    res = mount(fsname, mnt, *type, flags, optbuf);
700
496
    if (res == -1 && errno == EINVAL) {
701
497
        /* It could be an old version not supporting group_id */
702
498
        sprintf(d, "fd=%i,rootmode=%o,user_id=%i", fd, rootmode, getuid());
703
 
        res = mount(fsname, mnt, *type, flags, optbuf);
 
499
        res = mount(source, mnt, type, flags, optbuf);
704
500
    }
705
501
    if (res == -1) {
706
502
        int errno_save = errno;
707
 
        if (blkdev && errno == ENODEV && !has_fuseblk())
708
 
            fprintf(stderr, "%s: 'fuseblk' support missing; try the kernel module from fuse-2.6.0 or later\n", progname);
 
503
        if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk())
 
504
            fprintf(stderr, "%s: 'fuseblk' support missing\n", progname);
709
505
        else
710
506
            fprintf(stderr, "%s: mount failed: %s\n", progname, strerror(errno_save));
711
507
        goto err;
712
508
    } else {
713
 
        *fsnamep = fsname;
 
509
        *sourcep = source;
 
510
        *typep = type;
714
511
        *mnt_optsp = mnt_opts;
715
512
    }
716
513
    free(optbuf);
719
516
 
720
517
 err:
721
518
    free(fsname);
 
519
    free(subtype);
 
520
    free(source);
 
521
    free(type);
722
522
    free(mnt_opts);
723
523
    free(optbuf);
724
524
    return -1;
895
695
    int res;
896
696
    int fd;
897
697
    char *dev;
898
 
    const char *type = "fuse";
899
698
    struct stat stbuf;
900
 
    char *fsname = NULL;
 
699
    char *type = NULL;
 
700
    char *source = NULL;
901
701
    char *mnt_opts = NULL;
902
702
    const char *real_mnt = mnt;
903
703
    int currdir_fd = -1;
904
704
    int mountpoint_fd = -1;
905
 
    int mtablock = -1;
906
705
 
907
706
    fd = open_fuse_device(&dev);
908
707
    if (fd == -1)
909
708
        return -1;
910
709
 
911
 
    if (geteuid() == 0)
912
 
        mtablock = lock_mtab();
913
 
 
914
710
    drop_privs();
915
711
    read_conf();
916
712
 
919
715
        if (mount_count >= mount_max) {
920
716
            fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in /etc/fuse.conf\n", progname);
921
717
            close(fd);
922
 
            unlock_mtab(mtablock);
923
718
            return -1;
924
719
        }
925
720
    }
930
725
        restore_privs();
931
726
        if (res != -1)
932
727
            res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT, fd, opts,
933
 
                           dev, &fsname, &mnt_opts, stbuf.st_size);
 
728
                           dev, &source, &mnt_opts, stbuf.st_size);
934
729
    } else
935
730
        restore_privs();
936
731
 
943
738
 
944
739
    if (res == -1) {
945
740
        close(fd);
946
 
        unlock_mtab(mtablock);
947
741
        return -1;
948
742
    }
949
743
 
950
744
    if (geteuid() == 0) {
951
 
        res = add_mount(fsname, mnt, type, mnt_opts);
952
 
        unlock_mtab(mtablock);
 
745
        res = add_mount(source, mnt, type, mnt_opts);
953
746
        if (res == -1) {
954
747
            umount2(mnt, 2); /* lazy umount */
955
748
            close(fd);
957
750
        }
958
751
    }
959
752
 
960
 
    free(fsname);
 
753
    free(source);
 
754
    free(type);
961
755
    free(mnt_opts);
962
756
    free(dev);
963
757
 
964
758
    return fd;
965
759
}
966
760
 
967
 
static char *resolve_path(const char *orig)
968
 
{
969
 
    char buf[PATH_MAX];
970
 
    char *copy;
971
 
    char *dst;
972
 
    char *end;
973
 
    char *lastcomp;
974
 
    const char *toresolv;
975
 
 
976
 
    if (!orig[0]) {
977
 
        fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname, orig);
978
 
        return NULL;
979
 
    }
980
 
 
981
 
    copy = strdup(orig);
982
 
    if (copy == NULL) {
983
 
        fprintf(stderr, "%s: failed to allocate memory\n", progname);
984
 
        return NULL;
985
 
    }
986
 
 
987
 
    toresolv = copy;
988
 
    lastcomp = NULL;
989
 
    for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
990
 
    if (end[0] != '/') {
991
 
        char *tmp;
992
 
        end[1] = '\0';
993
 
        tmp = strrchr(copy, '/');
994
 
        if (tmp == NULL) {
995
 
            lastcomp = copy;
996
 
            toresolv = ".";
997
 
        } else {
998
 
            lastcomp = tmp + 1;
999
 
            if (tmp == copy)
1000
 
                toresolv = "/";
1001
 
        }
1002
 
        if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
1003
 
            lastcomp = NULL;
1004
 
            toresolv = copy;
1005
 
        }
1006
 
        else if (tmp)
1007
 
            tmp[0] = '\0';
1008
 
    }
1009
 
    if (realpath(toresolv, buf) == NULL) {
1010
 
        fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
1011
 
                strerror(errno));
1012
 
        free(copy);
1013
 
        return NULL;
1014
 
    }
1015
 
    if (lastcomp == NULL)
1016
 
        dst = strdup(buf);
1017
 
    else {
1018
 
        dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
1019
 
        if (dst) {
1020
 
            unsigned buflen = strlen(buf);
1021
 
            if (buflen && buf[buflen-1] == '/')
1022
 
                sprintf(dst, "%s%s", buf, lastcomp);
1023
 
            else
1024
 
                sprintf(dst, "%s/%s", buf, lastcomp);
1025
 
        }
1026
 
    }
1027
 
    free(copy);
1028
 
    if (dst == NULL)
1029
 
        fprintf(stderr, "%s: failed to allocate memory\n", progname);
1030
 
    return dst;
1031
 
}
1032
 
 
1033
761
static int send_fd(int sock_fd, int fd)
1034
762
{
1035
763
    int retval;
1159
887
    origmnt = argv[optind];
1160
888
 
1161
889
    drop_privs();
1162
 
    mnt = resolve_path(origmnt);
 
890
    mnt = fuse_mnt_resolve_path(progname, origmnt);
1163
891
    restore_privs();
1164
892
    if (mnt == NULL)
1165
893
        exit(1);
1166
894
 
1167
895
    umask(033);
1168
896
    if (unmount) {
1169
 
        if (geteuid() == 0) {
1170
 
            int mtablock = lock_mtab();
 
897
        if (geteuid() == 0)
1171
898
            res = unmount_fuse(mnt, quiet, lazy);
1172
 
            unlock_mtab(mtablock);
1173
 
        } else
1174
 
            res = do_unmount(mnt, quiet, lazy);
 
899
        else {
 
900
            res = umount2(mnt, lazy ? 2 : 0);
 
901
            if (res == -1 && !quiet)
 
902
                fprintf(stderr, "%s: failed to unmount %s: %s\n", progname,
 
903
                        mnt, strerror(errno));
 
904
        }
1175
905
        if (res == -1)
1176
906
            exit(1);
1177
907
        return 0;