304da24ff6cf28078830f0f108aeead33755cd6a
[samba.git] / source / client / smbumount.c
1 /*
2  *  smbumount.c
3  *
4  *  Copyright (C) 1995 by Volker Lendecke
5  *
6  */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <signal.h>
11 #include <pwd.h>
12 #include <grp.h>
13 #include <sys/socket.h>
14 #include <sys/param.h>
15 #include <netinet/in.h>
16 #include <netdb.h>
17 #include <sys/stat.h>
18 #include <sys/types.h>
19 /* #include <sys/wait.h> */  /* generates a warning here */
20 extern pid_t waitpid(pid_t, int *, int);
21 #include <sys/errno.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <ctype.h>
26 #include <stdlib.h>
27 #include <sys/mount.h>
28 #include <mntent.h>
29
30 #include <sys/ioctl.h>
31 #include <linux/fs.h>
32 #include <linux/smb.h>
33 #include <linux/smb_mount.h>
34 #include <linux/smb_fs.h>
35
36 static char *progname;
37
38 static void
39 usage(void)
40 {
41         printf("usage: %s mount-point\n", progname);
42 }
43
44 static int
45 umount_ok(const char *mount_point)
46 {
47         int fid = open(mount_point, O_RDONLY, 0);
48         uid_t mount_uid;
49
50         if (fid == -1) {
51                 fprintf(stderr, "Could not open %s: %s\n",
52                         mount_point, strerror(errno));
53                 return -1;
54         }
55         
56         if (ioctl(fid, SMB_IOC_GETMOUNTUID, &mount_uid) != 0) {
57                 fprintf(stderr, "%s probably not smb-filesystem\n",
58                         mount_point);
59                 return -1;
60         }
61
62         if (   (getuid() != 0)
63             && (mount_uid != getuid())) {
64                 fprintf(stderr, "You are not allowed to umount %s\n",
65                         mount_point);
66                 return -1;
67         }
68
69         close(fid);
70         return 0;
71 }
72
73 /* Make a canonical pathname from PATH.  Returns a freshly malloced string.
74    It is up the *caller* to ensure that the PATH is sensible.  i.e.
75    canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.''
76    is not a legal pathname for ``/dev/fd0.''  Anything we cannot parse
77    we return unmodified.   */
78 char *
79 canonicalize (const char *path)
80 {
81         char *canonical = malloc (PATH_MAX + 1);
82
83         if (strlen(path) > PATH_MAX)
84         {
85                 fprintf(stderr, "Mount point string too long\n");
86                 return NULL;
87         }
88
89         if (path == NULL)
90                 return NULL;
91   
92         if (realpath (path, canonical))
93                 return canonical;
94
95         strcpy (canonical, path);
96         return canonical;
97 }
98
99
100 int 
101 main(int argc, char *argv[])
102 {
103         int fd;
104
105         char* mount_point;
106
107         struct mntent *mnt;
108         FILE* mtab;
109         FILE* new_mtab;
110
111         progname = argv[0];
112
113         if (argc != 2) {
114                 usage();
115                 exit(1);
116         }
117
118         if (geteuid() != 0) {
119                 fprintf(stderr, "%s must be installed suid root\n", progname);
120                 exit(1);
121         }
122
123         mount_point = canonicalize(argv[1]);
124
125         if (mount_point == NULL)
126         {
127                 exit(1);
128         }
129
130         if (umount_ok(mount_point) != 0) {
131                 exit(1);
132         }
133
134         if (umount(mount_point) != 0) {
135                 fprintf(stderr, "Could not umount %s: %s\n",
136                         mount_point, strerror(errno));
137                 exit(1);
138         }
139
140         if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
141         {
142                 fprintf(stderr, "Can't get "MOUNTED"~ lock file");
143                 return 1;
144         }
145         close(fd);
146         
147         if ((mtab = setmntent(MOUNTED, "r")) == NULL) {
148                 fprintf(stderr, "Can't open " MOUNTED ": %s\n",
149                         strerror(errno));
150                 return 1;
151         }
152
153 #define MOUNTED_TMP MOUNTED".tmp"
154
155         if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) {
156                 fprintf(stderr, "Can't open " MOUNTED_TMP ": %s\n",
157                         strerror(errno));
158                 endmntent(mtab);
159                 return 1;
160         }
161
162         while ((mnt = getmntent(mtab)) != NULL) {
163                 if (strcmp(mnt->mnt_dir, mount_point) != 0) {
164                         addmntent(new_mtab, mnt);
165                 }
166         }
167
168         endmntent(mtab);
169
170         if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
171                 fprintf(stderr, "Error changing mode of %s: %s\n",
172                         MOUNTED_TMP, strerror(errno));
173                 exit(1);
174         }
175
176         endmntent(new_mtab);
177
178         if (rename(MOUNTED_TMP, MOUNTED) < 0) {
179                 fprintf(stderr, "Cannot rename %s to %s: %s\n",
180                         MOUNTED, MOUNTED_TMP, strerror(errno));
181                 exit(1);
182         }
183
184         if (unlink(MOUNTED"~") == -1)
185         {
186                 fprintf(stderr, "Can't remove "MOUNTED"~");
187                 return 1;
188         }
189
190         return 0;
191 }