4 * Copyright (C) 1995-1998 by Paal-Kr. Engstad and Volker Lendecke
5 * extensively modified by Tridge
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #define SMBMOUNT_MALLOC 1
27 #include <sys/utsname.h>
29 #include <asm/types.h>
30 #include <asm/posix_types.h>
31 #include <linux/smb.h>
32 #include <linux/smb_mount.h>
33 #include <asm/unistd.h>
36 /* This may look strange but MS_MGC_VAL is what we are looking for and
37 is what we need from <linux/fs.h> under libc systems and is
38 provided in standard includes on glibc systems. So... We
39 switch on what we need... */
43 static uid_t mount_uid;
44 static gid_t mount_gid;
46 static unsigned mount_fmask;
47 static unsigned mount_dmask;
48 static int user_mount;
55 printf("Usage: smbmnt mount-point [options]\n");
56 printf("Version %s\n\n",SAMBA_VERSION_STRING);
57 printf("-s share share name on server\n"
58 "-r mount read-only\n"
59 "-u uid mount as uid\n"
60 "-g gid mount as gid\n"
61 "-f mask permission mask for files\n"
62 "-d mask permission mask for directories\n"
63 "-o options name=value, list of options\n"
64 "-h print this help text\n");
68 parse_args(int argc, char *argv[], struct smb_mount_data *data, char **share)
72 while ((opt = getopt (argc, argv, "s:u:g:rf:d:o:")) != EOF)
81 mount_uid = strtol(optarg, NULL, 0);
86 mount_gid = strtol(optarg, NULL, 0);
93 mount_fmask = strtol(optarg, NULL, 8);
96 mount_dmask = strtol(optarg, NULL, 8);
110 fullpath(const char *p)
112 char path[PATH_MAX+1];
114 if (strlen(p) > PATH_MAX) {
118 if (realpath(p, path) == NULL) {
119 fprintf(stderr,"Failed to find real path for mount point %s: %s\n",
126 /* Check whether user is allowed to mount on the specified mount point. If it's
127 OK then we change into that directory - this prevents race conditions */
128 static int mount_ok(char *mount_point)
132 if (chdir(mount_point) != 0) {
136 if (stat(".", &st) != 0) {
140 if (!S_ISDIR(st.st_mode)) {
145 if ((getuid() != 0) &&
146 ((getuid() != st.st_uid) ||
147 ((st.st_mode & S_IRWXU) != S_IRWXU))) {
155 /* Tries to mount using the appropriate format. For 2.2 the struct,
156 for 2.4 the ascii version. */
158 do_mount(char *share_name, unsigned int flags, struct smb_mount_data *data)
162 char *release, *major, *minor;
166 release = uts.release;
167 major = strtok(release, ".");
168 minor = strtok(NULL, ".");
169 if (major && minor && atoi(major) == 2 && atoi(minor) < 4) {
170 /* < 2.4, assume struct */
171 data1 = (char *) data;
174 /* >= 2.4, assume ascii but fall back on struct */
176 data2 = (char *) data;
179 slprintf(opts, sizeof(opts)-1,
180 "version=7,uid=%d,gid=%d,file_mode=0%o,dir_mode=0%o,%s",
181 mount_uid, mount_gid, data->file_mode, data->dir_mode,options);
182 if (mount(share_name, ".", "smbfs", flags, data1) == 0)
184 return mount(share_name, ".", "smbfs", flags, data2);
187 int main(int argc, char *argv[])
189 char *mount_point, *share_name = NULL;
193 struct smb_mount_data data;
196 memset(&data, 0, sizeof(struct smb_mount_data));
203 if (argv[1][0] == '-') {
212 if (geteuid() != 0) {
213 fprintf(stderr, "smbmnt must be installed suid root for direct user mounts (%d,%d)\n", getuid(), geteuid());
217 mount_uid = getuid();
218 mount_gid = getgid();
219 mount_fmask = umask(0);
221 mount_fmask = ~mount_fmask;
223 mount_point = fullpath(argv[1]);
228 if (mount_ok(mount_point) != 0) {
229 fprintf(stderr, "cannot mount on %s: %s\n",
230 mount_point, strerror(errno));
234 data.version = SMB_MOUNT_VERSION;
236 /* getuid() gives us the real uid, who may umount the fs */
237 data.mounted_uid = getuid();
239 if (parse_args(argc, argv, &data, &share_name) != 0) {
244 data.uid = mount_uid; // truncates to 16-bits here!!!
245 data.gid = mount_gid;
246 data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & mount_fmask;
247 data.dir_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & mount_dmask;
249 if (mount_dmask == 0) {
250 data.dir_mode = data.file_mode;
251 if ((data.dir_mode & S_IRUSR) != 0)
252 data.dir_mode |= S_IXUSR;
253 if ((data.dir_mode & S_IRGRP) != 0)
254 data.dir_mode |= S_IXGRP;
255 if ((data.dir_mode & S_IROTH) != 0)
256 data.dir_mode |= S_IXOTH;
259 flags = MS_MGC_VAL | MS_NOSUID | MS_NODEV;
261 if (mount_ro) flags |= MS_RDONLY;
263 if (do_mount(share_name, flags, &data) < 0) {
266 fprintf(stderr, "ERROR: smbfs filesystem not supported by the kernel\n");
269 perror("mount error");
271 fprintf(stderr, "Please refer to the smbmnt(8) manual page\n");
275 ment.mnt_fsname = share_name ? share_name : "none";
276 ment.mnt_dir = mount_point;
277 ment.mnt_type = "smbfs";
282 mount_point = ment.mnt_dir;
284 if (mount_point == NULL)
286 fprintf(stderr, "Mount point too long\n");
290 if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
292 fprintf(stderr, "Can't get "MOUNTED"~ lock file");
297 if ((mtab = setmntent(MOUNTED, "a+")) == NULL)
299 fprintf(stderr, "Can't open " MOUNTED);
303 if (addmntent(mtab, &ment) == 1)
305 fprintf(stderr, "Can't write mount entry");
308 if (fchmod(fileno(mtab), 0644) == -1)
310 fprintf(stderr, "Can't set perms on "MOUNTED);
315 if (unlink(MOUNTED"~") == -1)
317 fprintf(stderr, "Can't remove "MOUNTED"~");