client/smbmnt.c

説明を見る。
00001 /*
00002  *  smbmnt.c
00003  *
00004  *  Copyright (C) 1995-1998 by Paal-Kr. Engstad and Volker Lendecke
00005  *  extensively modified by Tridge
00006  *
00007  *  This program is free software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation; either version 2 of the License, or
00010  *  (at your option) any later version.
00011  *  
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *  
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020  *
00021  */
00022 
00023 #define SMBMOUNT_MALLOC 1
00024 
00025 #include "includes.h"
00026 
00027 #include <mntent.h>
00028 #include <sys/utsname.h>
00029 
00030 #include <asm/types.h>
00031 #include <asm/posix_types.h>
00032 #include <linux/smb.h>
00033 #include <linux/smb_mount.h>
00034 #include <asm/unistd.h>
00035 
00036 #ifndef MS_MGC_VAL
00037 /* This may look strange but MS_MGC_VAL is what we are looking for and
00038         is what we need from <linux/fs.h> under libc systems and is
00039         provided in standard includes on glibc systems.  So...  We
00040         switch on what we need...  */
00041 #include <linux/fs.h>
00042 #endif
00043 
00044 static uid_t mount_uid;
00045 static gid_t mount_gid;
00046 static int mount_ro;
00047 static unsigned mount_fmask;
00048 static unsigned mount_dmask;
00049 static int user_mount;
00050 static char *options;
00051 
00052 static void
00053 help(void)
00054 {
00055         printf("\n");
00056         printf("Usage: smbmnt mount-point [options]\n");
00057         printf("Version %s\n\n",SAMBA_VERSION_STRING);
00058         printf("-s share       share name on server\n"
00059                "-r             mount read-only\n"
00060                "-u uid         mount as uid\n"
00061                "-g gid         mount as gid\n"
00062                "-f mask        permission mask for files\n"
00063                "-d mask        permission mask for directories\n"
00064                "-o options     name=value, list of options\n"
00065                "-h             print this help text\n");
00066 }
00067 
00068 static int
00069 parse_args(int argc, char *argv[], struct smb_mount_data *data, char **share)
00070 {
00071         int opt;
00072 
00073         while ((opt = getopt (argc, argv, "s:u:g:rf:d:o:")) != EOF)
00074         {
00075                 switch (opt)
00076                 {
00077                 case 's':
00078                         *share = optarg;
00079                         break;
00080                 case 'u':
00081                         if (!user_mount) {
00082                                 mount_uid = strtol(optarg, NULL, 0);
00083                         }
00084                         break;
00085                 case 'g':
00086                         if (!user_mount) {
00087                                 mount_gid = strtol(optarg, NULL, 0);
00088                         }
00089                         break;
00090                 case 'r':
00091                         mount_ro = 1;
00092                         break;
00093                 case 'f':
00094                         mount_fmask = strtol(optarg, NULL, 8);
00095                         break;
00096                 case 'd':
00097                         mount_dmask = strtol(optarg, NULL, 8);
00098                         break;
00099                 case 'o':
00100                         options = optarg;
00101                         break;
00102                 default:
00103                         return -1;
00104                 }
00105         }
00106         return 0;
00107         
00108 }
00109 
00110 static char *
00111 fullpath(const char *p)
00112 {
00113         char path[PATH_MAX+1];
00114 
00115         if (strlen(p) > PATH_MAX) {
00116                 return NULL;
00117         }
00118 
00119         if (realpath(p, path) == NULL) {
00120                 fprintf(stderr,"Failed to find real path for mount point %s: %s\n",
00121                         p, strerror(errno));
00122                 exit(1);
00123         }
00124         return strdup(path);
00125 }
00126 
00127 /* Check whether user is allowed to mount on the specified mount point. If it's
00128    OK then we change into that directory - this prevents race conditions */
00129 static int mount_ok(char *mount_point)
00130 {
00131         struct stat st;
00132 
00133         if (chdir(mount_point) != 0) {
00134                 return -1;
00135         }
00136 
00137         if (stat(".", &st) != 0) {
00138                 return -1;
00139         }
00140 
00141         if (!S_ISDIR(st.st_mode)) {
00142                 errno = ENOTDIR;
00143                 return -1;
00144         }
00145 
00146         if ((getuid() != 0) && 
00147             ((getuid() != st.st_uid) || 
00148              ((st.st_mode & S_IRWXU) != S_IRWXU))) {
00149                 errno = EPERM;
00150                 return -1;
00151         }
00152 
00153         return 0;
00154 }
00155 
00156 /* Tries to mount using the appropriate format. For 2.2 the struct,
00157    for 2.4 the ascii version. */
00158 static int
00159 do_mount(char *share_name, unsigned int flags, struct smb_mount_data *data)
00160 {
00161         pstring opts;
00162         struct utsname uts;
00163         char *release, *major, *minor;
00164         char *data1, *data2;
00165 
00166         uname(&uts);
00167         release = uts.release;
00168         major = strtok(release, ".");
00169         minor = strtok(NULL, ".");
00170         if (major && minor && atoi(major) == 2 && atoi(minor) < 4) {
00171                 /* < 2.4, assume struct */
00172                 data1 = (char *) data;
00173                 data2 = opts;
00174         } else {
00175                 /* >= 2.4, assume ascii but fall back on struct */
00176                 data1 = opts;
00177                 data2 = (char *) data;
00178         }
00179 
00180         slprintf(opts, sizeof(opts)-1,
00181                  "version=7,uid=%d,gid=%d,file_mode=0%o,dir_mode=0%o,%s",
00182                  mount_uid, mount_gid, data->file_mode, data->dir_mode,options);
00183         if (mount(share_name, ".", "smbfs", flags, data1) == 0)
00184                 return 0;
00185         return mount(share_name, ".", "smbfs", flags, data2);
00186 }
00187 
00188  int main(int argc, char *argv[])
00189 {
00190         char *mount_point, *share_name = NULL;
00191         FILE *mtab;
00192         int fd;
00193         unsigned int flags;
00194         struct smb_mount_data data;
00195         struct mntent ment;
00196 
00197         memset(&data, 0, sizeof(struct smb_mount_data));
00198 
00199         if (argc < 2) {
00200                 help();
00201                 exit(1);
00202         }
00203 
00204         if (argv[1][0] == '-') {
00205                 help();
00206                 exit(1);
00207         }
00208 
00209         if (getuid() != 0) {
00210                 user_mount = 1;
00211         }
00212 
00213         if (geteuid() != 0) {
00214                 fprintf(stderr, "smbmnt must be installed suid root for direct user mounts (%d,%d)\n", getuid(), geteuid());
00215                 exit(1);
00216         }
00217 
00218         mount_uid = getuid();
00219         mount_gid = getgid();
00220         mount_fmask = umask(0);
00221         umask(mount_fmask);
00222         mount_fmask = ~mount_fmask;
00223 
00224         mount_point = fullpath(argv[1]);
00225 
00226         argv += 1;
00227         argc -= 1;
00228 
00229         if (mount_ok(mount_point) != 0) {
00230                 fprintf(stderr, "cannot mount on %s: %s\n",
00231                         mount_point, strerror(errno));
00232                 exit(1);
00233         }
00234 
00235         data.version = SMB_MOUNT_VERSION;
00236 
00237         /* getuid() gives us the real uid, who may umount the fs */
00238         data.mounted_uid = getuid();
00239 
00240         if (parse_args(argc, argv, &data, &share_name) != 0) {
00241                 help();
00242                 return -1;
00243         }
00244 
00245         data.uid = mount_uid;    // truncates to 16-bits here!!!
00246         data.gid = mount_gid;
00247         data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & mount_fmask;
00248         data.dir_mode  = (S_IRWXU|S_IRWXG|S_IRWXO) & mount_dmask;
00249 
00250         if (mount_dmask == 0) {
00251                 data.dir_mode = data.file_mode;
00252                 if ((data.dir_mode & S_IRUSR) != 0)
00253                         data.dir_mode |= S_IXUSR;
00254                 if ((data.dir_mode & S_IRGRP) != 0)
00255                         data.dir_mode |= S_IXGRP;
00256                 if ((data.dir_mode & S_IROTH) != 0)
00257                         data.dir_mode |= S_IXOTH;
00258         }
00259 
00260         flags = MS_MGC_VAL | MS_NOSUID | MS_NODEV;
00261 
00262         if (mount_ro) flags |= MS_RDONLY;
00263 
00264         if (do_mount(share_name, flags, &data) < 0) {
00265                 switch (errno) {
00266                 case ENODEV:
00267                         fprintf(stderr, "ERROR: smbfs filesystem not supported by the kernel\n");
00268                         break;
00269                 default:
00270                         perror("mount error");
00271                 }
00272                 fprintf(stderr, "Please refer to the smbmnt(8) manual page\n");
00273                 return -1;
00274         }
00275 
00276         ment.mnt_fsname = share_name ? share_name : "none";
00277         ment.mnt_dir = mount_point;
00278         ment.mnt_type = "smbfs";
00279         ment.mnt_opts = "";
00280         ment.mnt_freq = 0;
00281         ment.mnt_passno= 0;
00282 
00283         mount_point = ment.mnt_dir;
00284 
00285         if (mount_point == NULL)
00286         {
00287                 fprintf(stderr, "Mount point too long\n");
00288                 return -1;
00289         }
00290         
00291         if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
00292         {
00293                 fprintf(stderr, "Can't get "MOUNTED"~ lock file");
00294                 return 1;
00295         }
00296         close(fd);
00297         
00298         if ((mtab = setmntent(MOUNTED, "a+")) == NULL)
00299         {
00300                 fprintf(stderr, "Can't open " MOUNTED);
00301                 return 1;
00302         }
00303 
00304         if (addmntent(mtab, &ment) == 1)
00305         {
00306                 fprintf(stderr, "Can't write mount entry");
00307                 return 1;
00308         }
00309         if (fchmod(fileno(mtab), 0644) == -1)
00310         {
00311                 fprintf(stderr, "Can't set perms on "MOUNTED);
00312                 return 1;
00313         }
00314         endmntent(mtab);
00315 
00316         if (unlink(MOUNTED"~") == -1)
00317         {
00318                 fprintf(stderr, "Can't remove "MOUNTED"~");
00319                 return 1;
00320         }
00321 
00322         return 0;
00323 }       

Sambaに対してSat Aug 29 21:22:53 2009に生成されました。  doxygen 1.4.7