+'mntent.mnt_fsname' and 'mntent.mnt_type' mntent overriding options.
[lufs.git] / util / lufsmnt.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <limits.h>
6 #include <errno.h>
7 #include <mntent.h>
8 #include <paths.h>
9 #include <fcntl.h>
10 #include <string.h>
11
12 #include <sys/types.h>
13 #include <sys/mount.h>
14 #include <sys/stat.h>
15
16 #define ERROR(x...)     fprintf(stderr, x)
17
18 static void
19 help(){
20     printf("\n");
21     printf("Usage: lufsmnt mount-point [options]\n");
22     printf("This is a suid wrapper called by lufsd.\n");
23
24 }
25
26 static int
27 fullpath(char *path, char *full){
28     
29     full[0] = 0;
30     
31     if(strlen(path) >= PATH_MAX - 1)
32         return -1;
33
34     if(!realpath(path, full))
35         return -1;
36     else 
37         return 0;
38 }
39
40 static int
41 mount_ok(char *mp){
42     struct stat st;
43     
44     if(chdir(mp)){
45         ERROR("cannot chdir %s\n", mp);
46         return -1;
47     }
48         
49     if(stat(".", &st)){
50         ERROR("cannot stat %s\n", mp);
51         return -1;
52     }
53         
54     if(!S_ISDIR(st.st_mode)){
55         ERROR("%s is not a directory\n", mp);
56         return -1;
57     }
58
59     if((getuid()) && ((getuid() != st.st_uid) || ((st.st_mode & S_IRWXU) != S_IRWXU))){
60         ERROR("you don't have proper permissions to mount on %s\n", mp);
61         return -1;
62     }
63
64     return 0;
65 }
66
67 void
68 hide_pass(char *opts){
69     char *c;
70
71     if((c = strstr(opts, "password="))){
72         for(c = c + 9; (*c != 0) && (*c != ','); c++)
73             *c = '*';
74     }
75 }
76
77 int
78 get_opt(char *opts, const char *optname, char *buf, int buflen){
79     char *begin, *end;
80
81     for(begin = opts; (begin = strstr(begin, optname)); begin++){
82         if (begin > opts && begin[-1] != ',')
83             continue;
84         if (begin[strlen(optname)] != '=')
85             continue;
86         begin += strlen(optname) + 1;
87
88         if(!(end = strchr(begin, ','))){
89             end = begin + strlen(begin);
90         }
91         
92         if( end - begin >= buflen)
93             end = begin + buflen - 1;
94
95         memcpy(buf, begin, end - begin);
96         buf[end - begin] = 0;
97         return 1;
98     }
99     return 0;
100 }
101
102 int
103 main(int argc, char **argv){
104     char *mountpoint, *opts;
105     static char fpath[PATH_MAX];
106     static char mfs[PATH_MAX];
107     static char mopts[PATH_MAX];
108     static char mntent_mnt_type[PATH_MAX];
109     struct mntent ment;
110     int fd;
111     FILE *mtab;
112     
113     if(argc != 3){
114         help();
115         exit(1);
116     }
117
118     if(geteuid()){
119         ERROR("%s needs to be installed suid root in order to be used by unprivileged users\n", argv[0]);
120         exit(1);
121     }
122     
123     mountpoint = argv[1];
124     opts = argv[2];
125
126     fullpath(mountpoint, fpath);
127     
128     if(mount_ok(fpath)){
129         exit(1);
130     }
131         
132     if (mount("none", fpath, "lufs", MS_NOSUID | MS_NODEV, opts) < 0){
133         ERROR("mount failed: %s\n", strerror(errno));
134         switch(errno){
135         case ENODEV:
136             ERROR("you don't have kernel lufs support (check whether the lufs module is available/loaded)\n");
137             break;
138         }
139         return errno;
140     }
141
142     sprintf(mopts, "owner=%d,", getuid());
143     hide_pass(opts);
144     if(strlen(mopts) + strlen(opts) < PATH_MAX)
145         strcat(mopts, opts);
146     mfs[0] = 0;
147     get_opt(opts, "fs", mfs, PATH_MAX);
148     get_opt(opts, "mntent.mnt_fsname", mfs, PATH_MAX);
149
150     ment.mnt_fsname = mfs;
151     ment.mnt_dir = fpath;
152     strcpy(mntent_mnt_type, "lufs");
153     get_opt(opts, "mntent.mnt_type", mntent_mnt_type, sizeof(mntent_mnt_type));
154     ment.mnt_type = mntent_mnt_type;
155     ment.mnt_opts = mopts;
156     ment.mnt_freq = 0;
157     ment.mnt_passno = 0;
158
159     if((fd = open(_PATH_MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) < 0){
160         ERROR("can't get "_PATH_MOUNTED"~ lock file\n");
161         return 1;
162     }
163     close(fd);
164     
165     if((mtab = setmntent(_PATH_MOUNTED, "a+")) == NULL){
166         ERROR("can't open "_PATH_MOUNTED"\n");
167         return 1;
168     }
169     
170     if(addmntent(mtab, &ment)){
171         ERROR("can't write mount entry\n");
172         return 1;
173     }
174     
175     if(fchmod(fileno(mtab), 0644) < 0){
176         ERROR("can't set [erms on "_PATH_MOUNTED"\n");
177         return 1;
178     }
179     
180     endmntent(mtab);
181     
182     if(unlink(_PATH_MOUNTED"~") < 0){
183         ERROR("can't remove "_PATH_MOUNTED"~\n");
184         return 1;
185     }
186     
187     return 0;
188 }
189