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

« back to all changes in this revision

Viewing changes to lib/mount_util.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
/*
 
2
    FUSE: Filesystem in Userspace
 
3
    Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
 
4
 
 
5
    This program can be distributed under the terms of the GNU LGPL.
 
6
    See the file COPYING.LIB.
 
7
*/
 
8
 
 
9
#include "mount_util.h"
 
10
#include <stdio.h>
 
11
#include <unistd.h>
 
12
#include <stdlib.h>
 
13
#include <string.h>
 
14
#include <dirent.h>
 
15
#include <errno.h>
 
16
#include <limits.h>
 
17
#include <sys/stat.h>
 
18
#include <sys/wait.h>
 
19
 
 
20
int fuse_mnt_add_mount(const char *progname, const char *fsname,
 
21
                       const char *mnt, const char *type, const char *opts)
 
22
{
 
23
    int res;
 
24
    int status;
 
25
 
 
26
    res = fork();
 
27
    if (res == -1) {
 
28
        fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
 
29
        return -1;
 
30
    }
 
31
    if (res == 0) {
 
32
        char templ[] = "/tmp/fusermountXXXXXX";
 
33
        char *tmp;
 
34
 
 
35
        setuid(geteuid());
 
36
 
 
37
        /* 
 
38
         * hide in a directory, where mount isn't able to resolve
 
39
         * fsname as a valid path
 
40
         */
 
41
        tmp = mkdtemp(templ);
 
42
        if (!tmp) {
 
43
            fprintf(stderr, "%s: failed to create temporary directory\n",
 
44
                    progname);
 
45
            exit(1);
 
46
        }
 
47
        if (chdir(tmp)) {
 
48
            fprintf(stderr, "%s: failed to chdir to %s: %s\n",
 
49
                    progname, tmp, strerror(errno));
 
50
            exit(1);
 
51
        }
 
52
        rmdir(tmp);
 
53
        execl("/bin/mount", "/bin/mount", "-i", "-f", "-t", type, "-o", opts,
 
54
              fsname, mnt, NULL);
 
55
        fprintf(stderr, "%s: failed to execute /bin/mount: %s\n", progname,
 
56
                strerror(errno));
 
57
        exit(1);
 
58
    }
 
59
    res = waitpid(res, &status, 0);
 
60
    if (res == -1) {
 
61
        fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
 
62
        return -1;
 
63
    }
 
64
    if (status != 0)
 
65
        return -1;
 
66
 
 
67
    return 0;
 
68
}
 
69
 
 
70
int fuse_mnt_umount(const char *progname, const char *mnt, int lazy)
 
71
{
 
72
    int res;
 
73
    int status;
 
74
 
 
75
    res = fork();
 
76
    if (res == -1) {
 
77
        fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
 
78
        return -1;
 
79
    }
 
80
    if (res == 0) {
 
81
        setuid(geteuid());
 
82
        execl("/bin/umount", "/bin/umount", "-i", mnt, lazy ? "-l" : NULL,
 
83
              NULL);
 
84
        fprintf(stderr, "%s: failed to execute /bin/umount: %s\n", progname,
 
85
                strerror(errno));
 
86
        exit(1);
 
87
    }
 
88
    res = waitpid(res, &status, 0);
 
89
    if (res == -1) {
 
90
        fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
 
91
        return -1;
 
92
    }
 
93
    if (status != 0)
 
94
        return -1;
 
95
 
 
96
    return 0;
 
97
}
 
98
 
 
99
char *fuse_mnt_resolve_path(const char *progname, const char *orig)
 
100
{
 
101
    char buf[PATH_MAX];
 
102
    char *copy;
 
103
    char *dst;
 
104
    char *end;
 
105
    char *lastcomp;
 
106
    const char *toresolv;
 
107
 
 
108
    if (!orig[0]) {
 
109
        fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname, orig);
 
110
        return NULL;
 
111
    }
 
112
 
 
113
    copy = strdup(orig);
 
114
    if (copy == NULL) {
 
115
        fprintf(stderr, "%s: failed to allocate memory\n", progname);
 
116
        return NULL;
 
117
    }
 
118
 
 
119
    toresolv = copy;
 
120
    lastcomp = NULL;
 
121
    for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
 
122
    if (end[0] != '/') {
 
123
        char *tmp;
 
124
        end[1] = '\0';
 
125
        tmp = strrchr(copy, '/');
 
126
        if (tmp == NULL) {
 
127
            lastcomp = copy;
 
128
            toresolv = ".";
 
129
        } else {
 
130
            lastcomp = tmp + 1;
 
131
            if (tmp == copy)
 
132
                toresolv = "/";
 
133
        }
 
134
        if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
 
135
            lastcomp = NULL;
 
136
            toresolv = copy;
 
137
        }
 
138
        else if (tmp)
 
139
            tmp[0] = '\0';
 
140
    }
 
141
    if (realpath(toresolv, buf) == NULL) {
 
142
        fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
 
143
                strerror(errno));
 
144
        free(copy);
 
145
        return NULL;
 
146
    }
 
147
    if (lastcomp == NULL)
 
148
        dst = strdup(buf);
 
149
    else {
 
150
        dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
 
151
        if (dst) {
 
152
            unsigned buflen = strlen(buf);
 
153
            if (buflen && buf[buflen-1] == '/')
 
154
                sprintf(dst, "%s%s", buf, lastcomp);
 
155
            else
 
156
                sprintf(dst, "%s/%s", buf, lastcomp);
 
157
        }
 
158
    }
 
159
    free(copy);
 
160
    if (dst == NULL)
 
161
        fprintf(stderr, "%s: failed to allocate memory\n", progname);
 
162
    return dst;
 
163
}
 
164
 
 
165
int fuse_mnt_check_empty(const char *progname, const char *mnt,
 
166
                         mode_t rootmode, off_t rootsize)
 
167
{
 
168
    int isempty = 1;
 
169
 
 
170
    if (S_ISDIR(rootmode)) {
 
171
        struct dirent *ent;
 
172
        DIR *dp = opendir(mnt);
 
173
        if (dp == NULL) {
 
174
            fprintf(stderr, "%s: failed to open mountpoint for reading: %s\n",
 
175
                    progname, strerror(errno));
 
176
            return -1;
 
177
        }
 
178
        while ((ent = readdir(dp)) != NULL) {
 
179
            if (strcmp(ent->d_name, ".") != 0 &&
 
180
                strcmp(ent->d_name, "..") != 0) {
 
181
                isempty = 0;
 
182
                break;
 
183
            }
 
184
        }
 
185
        closedir(dp);
 
186
    } else if (rootsize)
 
187
        isempty = 0;
 
188
 
 
189
    if (!isempty) {
 
190
        fprintf(stderr, "%s: mountpoint is not empty\n", progname);
 
191
        fprintf(stderr, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname);
 
192
        return -1;
 
193
    }
 
194
    return 0;
 
195
}
 
196
 
 
197
int fuse_mnt_check_fuseblk(void)
 
198
{
 
199
    char buf[256];
 
200
    FILE *f = fopen("/proc/filesystems", "r");
 
201
    if (!f)
 
202
        return 1;
 
203
 
 
204
    while (fgets(buf, sizeof(buf), f))
 
205
        if (strstr(buf, "fuseblk\n")) {
 
206
            fclose(f);
 
207
            return 1;
 
208
        }
 
209
 
 
210
    fclose(f);
 
211
    return 0;
 
212
}