r5208: pull one last change from 3.0
[Samba.git] / source / client / smbumount.c
blob29a7b5dafc13786f5a40afd42300e894e7655e91
1 /*
2 * smbumount.c
4 * Copyright (C) 1995-1998 by Volker Lendecke
6 */
8 #include "includes.h"
10 #include <mntent.h>
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>
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.
23 #undef SMB_IOC_GETMOUNTUID
24 #define SMB_IOC_GETMOUNTUID _IOR('u', 1, __kernel_uid_t)
26 #ifndef O_NOFOLLOW
27 #define O_NOFOLLOW 0400000
28 #endif
30 static void
31 usage(void)
33 printf("usage: smbumount mountpoint\n");
36 static int
37 umount_ok(const char *mount_point)
39 /* we set O_NOFOLLOW to prevent users playing games with symlinks to
40 umount filesystems they don't own */
41 int fid = open(mount_point, O_RDONLY|O_NOFOLLOW, 0);
42 __kernel_uid32_t mount_uid;
44 if (fid == -1) {
45 fprintf(stderr, "Could not open %s: %s\n",
46 mount_point, strerror(errno));
47 return -1;
50 if (ioctl(fid, SMB_IOC_GETMOUNTUID32, &mount_uid) != 0) {
51 __kernel_uid_t mount_uid16;
52 if (ioctl(fid, SMB_IOC_GETMOUNTUID, &mount_uid16) != 0) {
53 fprintf(stderr, "%s probably not smb-filesystem\n",
54 mount_point);
55 return -1;
57 mount_uid = mount_uid16;
60 if ((getuid() != 0)
61 && (mount_uid != getuid())) {
62 fprintf(stderr, "You are not allowed to umount %s\n",
63 mount_point);
64 return -1;
67 close(fid);
68 return 0;
71 /* Make a canonical pathname from PATH. Returns a freshly malloced string.
72 It is up the *caller* to ensure that the PATH is sensible. i.e.
73 canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.''
74 is not a legal pathname for ``/dev/fd0'' Anything we cannot parse
75 we return unmodified. */
76 static char *
77 canonicalize (char *path)
79 char *canonical = malloc (PATH_MAX + 1);
81 if (!canonical) {
82 fprintf(stderr, "Error! Not enough memory!\n");
83 return NULL;
86 if (strlen(path) > PATH_MAX) {
87 fprintf(stderr, "Mount point string too long\n");
88 return NULL;
91 if (path == NULL)
92 return NULL;
94 if (realpath (path, canonical))
95 return canonical;
97 strncpy (canonical, path, PATH_MAX);
98 canonical[PATH_MAX] = '\0';
99 return canonical;
103 int
104 main(int argc, char *argv[])
106 int fd;
107 char* mount_point;
108 struct mntent *mnt;
109 FILE* mtab;
110 FILE* new_mtab;
112 if (argc != 2) {
113 usage();
114 exit(1);
117 if (geteuid() != 0) {
118 fprintf(stderr, "smbumount must be installed suid root\n");
119 exit(1);
122 mount_point = canonicalize(argv[1]);
124 if (mount_point == NULL)
126 exit(1);
129 if (umount_ok(mount_point) != 0) {
130 exit(1);
133 if (umount(mount_point) != 0) {
134 fprintf(stderr, "Could not umount %s: %s\n",
135 mount_point, strerror(errno));
136 exit(1);
139 if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
141 fprintf(stderr, "Can't get "MOUNTED"~ lock file");
142 return 1;
144 close(fd);
146 if ((mtab = setmntent(MOUNTED, "r")) == NULL) {
147 fprintf(stderr, "Can't open " MOUNTED ": %s\n",
148 strerror(errno));
149 return 1;
152 #define MOUNTED_TMP MOUNTED".tmp"
154 if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) {
155 fprintf(stderr, "Can't open " MOUNTED_TMP ": %s\n",
156 strerror(errno));
157 endmntent(mtab);
158 return 1;
161 while ((mnt = getmntent(mtab)) != NULL) {
162 if (strcmp(mnt->mnt_dir, mount_point) != 0) {
163 addmntent(new_mtab, mnt);
167 endmntent(mtab);
169 if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
170 fprintf(stderr, "Error changing mode of %s: %s\n",
171 MOUNTED_TMP, strerror(errno));
172 exit(1);
175 endmntent(new_mtab);
177 if (rename(MOUNTED_TMP, MOUNTED) < 0) {
178 fprintf(stderr, "Cannot rename %s to %s: %s\n",
179 MOUNTED, MOUNTED_TMP, strerror(errno));
180 exit(1);
183 if (unlink(MOUNTED"~") == -1)
185 fprintf(stderr, "Can't remove "MOUNTED"~");
186 return 1;
189 return 0;