Makefile.in: Added maintainer mode fixes.
[samba.git] / source3 / client / smbmnt.c
1 /*
2  *  smbmount.c
3  *
4  *  Copyright (C) 1995-1998 by Paal-Kr. Engstad and 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 <asm/unistd.h>
17
18 #ifndef MS_MGC_VAL
19 /* This may look strange but MS_MGC_VAL is what we are looking for and
20         is what we need from <linux/fs.h> under libc systems and is
21         provided in standard includes on glibc systems.  So...  We
22         switch on what we need...  */
23 #include <linux/fs.h>
24 #endif
25
26 static char *progname;
27
28
29 static void
30 usage(void)
31 {
32         printf("usage: %s mount-point [options]\n", progname);
33         printf("Try `%s -h' for more information\n", progname);
34 }
35
36 static void
37 help(void)
38 {
39         printf("\n");
40         printf("usage: %s mount-point [options]\n", progname);
41         printf("-u uid         uid the mounted files get\n"
42                "-g gid         gid the mounted files get\n"
43                "-f mode        permission the files get (octal notation)\n"
44                "-d mode        permission the dirs get (octal notation)\n"
45                "-P pid         connection handler's pid\n\n"
46                "-s share       share name on server\n\n"
47                "-h             print this help text\n");
48 }
49
50 static int
51 parse_args(int argc, char *argv[], struct smb_mount_data *data, char **share)
52 {
53         int opt;
54         struct passwd *pwd;
55         struct group  *grp;
56
57         while ((opt = getopt (argc, argv, "u:g:f:d:s:")) != EOF)
58         {
59                 switch (opt)
60                 {
61                 case 'u':
62                         if (isdigit(optarg[0]))
63                         {
64                                 data->uid = atoi(optarg);
65                         }
66                         else
67                         {
68                                 pwd = getpwnam(optarg);
69                                 if (pwd == NULL)
70                                 {
71                                         fprintf(stderr, "Unknown user: %s\n",
72                                                 optarg);
73                                         return 1;
74                                 }
75                                 data->uid = pwd->pw_uid;
76                         }
77                         break;
78                 case 'g':
79                         if (isdigit(optarg[0]))
80                         {
81                                 data->gid = atoi(optarg);
82                         }
83                         else
84                         {
85                                 grp = getgrnam(optarg);
86                                 if (grp == NULL)
87                                 {
88                                         fprintf(stderr, "Unknown group: %s\n",
89                                                 optarg);
90                                         return 1;
91                                 }
92                                 data->gid = grp->gr_gid;
93                         }
94                         break;
95                 case 'f':
96                         data->file_mode = strtol(optarg, NULL, 8);
97                         break;
98                 case 'd':
99                         data->dir_mode = strtol(optarg, NULL, 8);
100                         break;
101                 case 's':
102                         *share = optarg;
103                         break;
104                 default:
105                         return -1;
106                 }
107         }
108         return 0;
109         
110 }
111
112 static char *
113 fullpath(const char *p)
114 {
115         char path[MAXPATHLEN];
116
117         if (strlen(p) > MAXPATHLEN-1)
118         {
119                 return NULL;
120         }
121
122         if (realpath(p, path) == NULL)
123         {
124                 return strdup(p);
125         }
126         return strdup(path);
127 }
128
129 /* Check whether user is allowed to mount on the specified mount point */
130 static int
131 mount_ok(SMB_STRUCT_STAT *st)
132 {
133         if (!S_ISDIR(st->st_mode))
134         {
135                 errno = ENOTDIR;
136                 return -1;
137         }
138         
139         if (   (getuid() != 0)
140             && (   (getuid() != st->st_uid)
141                 || ((st->st_mode & S_IRWXU) != S_IRWXU)))
142         {
143                 errno = EPERM;
144                 return -1;
145         }
146
147         return 0;
148 }
149
150 int 
151 main(int argc, char *argv[])
152 {
153         char *mount_point, *share_name = NULL;
154         FILE *mtab;
155         int fd, um;
156         unsigned int flags;
157         struct smb_mount_data data;
158         SMB_STRUCT_STAT st;
159         struct mntent ment;
160
161         progname = argv[0];
162
163         memset(&data, 0, sizeof(struct smb_mount_data));
164
165         if (   (argc == 2)
166                && (argv[1][0] == '-')
167                && (argv[1][1] == 'h')
168                && (argv[1][2] == '\0'))
169         {
170                 help();
171                 return 0;
172         }
173
174         if (geteuid() != 0) {
175                 fprintf(stderr, "%s must be installed suid root\n", progname);
176                 exit(1);
177         }
178
179         if (argc < 2)
180         {
181                 usage();
182                 return 1;
183         }
184
185         mount_point = argv[1];
186
187         argv += 1;
188         argc -= 1;
189
190         if (sys_stat(mount_point, &st) == -1) {
191                 fprintf(stderr, "could not find mount point %s: %s\n",
192                         mount_point, strerror(errno));
193                 exit(1);
194         }
195
196         if (mount_ok(&st) != 0) {
197                 fprintf(stderr, "cannot mount on %s: %s\n",
198                         mount_point, strerror(errno));
199                 exit(1);
200         }
201
202         data.version = SMB_MOUNT_VERSION;
203
204         /* getuid() gives us the real uid, who may umount the fs */
205         data.mounted_uid = getuid();
206
207         data.uid = getuid();
208         data.gid = getgid();
209         um = umask(0);
210         umask(um);
211         data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & ~um;
212         data.dir_mode  = 0;
213
214         if (parse_args(argc, argv, &data, &share_name) != 0) {
215                 usage();
216                 return -1;
217         }
218
219         if (data.dir_mode == 0) {
220                 data.dir_mode = data.file_mode;
221                 if ((data.dir_mode & S_IRUSR) != 0)
222                         data.dir_mode |= S_IXUSR;
223                 if ((data.dir_mode & S_IRGRP) != 0)
224                         data.dir_mode |= S_IXGRP;
225                 if ((data.dir_mode & S_IROTH) != 0)
226                         data.dir_mode |= S_IXOTH;
227         }
228
229         flags = MS_MGC_VAL;
230
231         if (mount(share_name, mount_point, "smbfs", flags, (char *)&data) < 0)
232         {
233                 perror("mount error");
234                 printf("Please refer to the smbmnt(8) manual page\n");
235                 return -1;
236         }
237
238         ment.mnt_fsname = share_name ? share_name : "none";
239         ment.mnt_dir = fullpath(mount_point);
240         ment.mnt_type = "smbfs";
241         ment.mnt_opts = "";
242         ment.mnt_freq = 0;
243         ment.mnt_passno= 0;
244
245         mount_point = ment.mnt_dir;
246
247         if (mount_point == NULL)
248         {
249                 fprintf(stderr, "Mount point too long\n");
250                 return -1;
251         }
252         
253         if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
254         {
255                 fprintf(stderr, "Can't get "MOUNTED"~ lock file");
256                 return 1;
257         }
258         close(fd);
259         
260         if ((mtab = setmntent(MOUNTED, "a+")) == NULL)
261         {
262                 fprintf(stderr, "Can't open " MOUNTED);
263                 return 1;
264         }
265
266         if (addmntent(mtab, &ment) == 1)
267         {
268                 fprintf(stderr, "Can't write mount entry");
269                 return 1;
270         }
271         if (fchmod(fileno(mtab), 0644) == -1)
272         {
273                 fprintf(stderr, "Can't set perms on "MOUNTED);
274                 return 1;
275         }
276         endmntent(mtab);
277
278         if (unlink(MOUNTED"~") == -1)
279         {
280                 fprintf(stderr, "Can't remove "MOUNTED"~");
281                 return 1;
282         }
283
284         return 0;
285 }