~james-w/+junk/fuse-ubuntu-upstream

« back to all changes in this revision

Viewing changes to lib/mount_util.c

  • Committer: James Westby
  • Date: 2008-05-16 12:58:53 UTC
  • Revision ID: jw+debian@jameswestby.net-20080516125853-8ixljpt4yia8mkt9
Tags: upstream-debian-2.7.0, upstream-ubuntu-2.7.0
Import upstream from fuse_2.7.0.orig.tar.gz

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
}