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