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