client/mount.cifs.c

説明を見る。
00001 /* 
00002    Mount helper utility for Linux CIFS VFS (virtual filesystem) client
00003    Copyright (C) 2003,2008 Steve French  (sfrench@us.ibm.com)
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 2 of the License, or
00008    (at your option) any later version.
00009    
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014    
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software
00017    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
00018 
00019 #ifndef _GNU_SOURCE
00020 #define _GNU_SOURCE
00021 #endif
00022 
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <unistd.h>
00026 #include <pwd.h>
00027 #include <grp.h>
00028 #include <ctype.h>
00029 #include <sys/types.h>
00030 #include <sys/mount.h>
00031 #include <sys/stat.h>
00032 #include <sys/utsname.h>
00033 #include <sys/socket.h>
00034 #include <arpa/inet.h>
00035 #include <getopt.h>
00036 #include <errno.h>
00037 #include <netdb.h>
00038 #include <string.h>
00039 #include <mntent.h>
00040 #include <fcntl.h>
00041 #include <limits.h>
00042 
00043 #define MOUNT_CIFS_VERSION_MAJOR "1"
00044 #define MOUNT_CIFS_VERSION_MINOR "10"
00045 
00046 #ifndef MOUNT_CIFS_VENDOR_SUFFIX
00047  #ifdef _SAMBA_BUILD_
00048   #include "include/version.h"
00049   #ifdef SAMBA_VERSION_VENDOR_SUFFIX
00050    #define MOUNT_CIFS_VENDOR_SUFFIX "-"SAMBA_VERSION_OFFICIAL_STRING"-"SAMBA_VERSION_VENDOR_SUFFIX
00051   #else
00052    #define MOUNT_CIFS_VENDOR_SUFFIX "-"SAMBA_VERSION_OFFICIAL_STRING
00053   #endif /* SAMBA_VERSION_OFFICIAL_STRING and SAMBA_VERSION_VENDOR_SUFFIX */
00054  #else
00055    #define MOUNT_CIFS_VENDOR_SUFFIX ""
00056  #endif /* _SAMBA_BUILD_ */
00057 #endif /* MOUNT_CIFS_VENDOR_SUFFIX */
00058 
00059 #ifndef MS_MOVE 
00060 #define MS_MOVE 8192 
00061 #endif 
00062 
00063 #ifndef MS_BIND
00064 #define MS_BIND 4096
00065 #endif
00066 
00067 #define MAX_UNC_LEN 1024
00068 
00069 #define CONST_DISCARD(type, ptr)      ((type) ((void *) (ptr)))
00070 
00071 const char *thisprogram;
00072 int verboseflag = 0;
00073 static int got_password = 0;
00074 static int got_user = 0;
00075 static int got_domain = 0;
00076 static int got_ip = 0;
00077 static int got_unc = 0;
00078 static int got_uid = 0;
00079 static int got_gid = 0;
00080 static char * user_name = NULL;
00081 static char * mountpassword = NULL;
00082 char * domain_name = NULL;
00083 char * prefixpath = NULL;
00084 
00085 /* glibc doesn't have strlcpy, strlcat. Ensure we do. JRA. We
00086  * don't link to libreplace so need them here. */
00087 
00088 /* like strncpy but does not 0 fill the buffer and always null
00089  *    terminates. bufsize is the size of the destination buffer */
00090 size_t strlcpy(char *d, const char *s, size_t bufsize)
00091 {
00092         size_t len = strlen(s);
00093         size_t ret = len;
00094         if (bufsize <= 0) return 0;
00095         if (len >= bufsize) len = bufsize-1;
00096         memcpy(d, s, len);
00097         d[len] = 0;
00098         return ret;
00099 }
00100 
00101 /* like strncat but does not 0 fill the buffer and always null
00102  *    terminates. bufsize is the length of the buffer, which should
00103  *       be one more than the maximum resulting string length */
00104 size_t strlcat(char *d, const char *s, size_t bufsize)
00105 {
00106         size_t len1 = strlen(d);
00107         size_t len2 = strlen(s);
00108         size_t ret = len1 + len2;
00109 
00110         if (len1+len2 >= bufsize) {
00111                 if (bufsize < (len1+1)) {
00112                         return ret;
00113                 }
00114                 len2 = bufsize - (len1+1);
00115         }
00116         if (len2 > 0) {
00117                 memcpy(d+len1, s, len2);
00118                 d[len1+len2] = 0;
00119         }
00120         return ret;
00121 }
00122 
00123 /* BB finish BB
00124 
00125         cifs_umount
00126         open nofollow - avoid symlink exposure? 
00127         get owner of dir see if matches self or if root
00128         call system(umount argv) etc.
00129                 
00130 BB end finish BB */
00131 
00132 static char * check_for_domain(char **);
00133 
00134 
00135 static void mount_cifs_usage(void)
00136 {
00137         printf("\nUsage:  %s <remotetarget> <dir> -o <options>\n", thisprogram);
00138         printf("\nMount the remote target, specified as a UNC name,");
00139         printf(" to a local directory.\n\nOptions:\n");
00140         printf("\tuser=<arg>\n\tpass=<arg>\n\tdom=<arg>\n");
00141         printf("\nLess commonly used options:");
00142         printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,rw,ro,");
00143         printf("\n\tsep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,serverino,");
00144         printf("\n\tdirectio,mapchars,nomapchars,nolock,servernetbiosname=<SRV_RFC1001NAME>");
00145         printf("\n\nOptions not needed for servers supporting CIFS Unix extensions");
00146         printf("\n\t(e.g. unneeded for mounts to most Samba versions):");
00147         printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>,sfu");
00148         printf("\n\nRarely used options:");
00149         printf("\n\tport=<tcpport>,rsize=<size>,wsize=<size>,unc=<unc_name>,ip=<ip_address>,");
00150         printf("\n\tdev,nodev,nouser_xattr,netbiosname=<OUR_RFC1001NAME>,hard,soft,intr,");
00151         printf("\n\tnointr,ignorecase,noposixpaths,noacl");
00152         printf("\n\nOptions are described in more detail in the manual page");
00153         printf("\n\tman 8 mount.cifs\n");
00154         printf("\nTo display the version number of the mount helper:");
00155         printf("\n\t%s -V\n",thisprogram);
00156 
00157         if(mountpassword) {
00158                 memset(mountpassword,0,64);
00159                 free(mountpassword);
00160                 mountpassword = NULL;
00161         }
00162         exit(1);
00163 }
00164 
00165 /* caller frees username if necessary */
00166 static char * getusername(void) {
00167         char *username = NULL;
00168         struct passwd *password = getpwuid(getuid());
00169 
00170         if (password) {
00171                 username = password->pw_name;
00172         }
00173         return username;
00174 }
00175 
00176 static char * parse_cifs_url(char * unc_name)
00177 {
00178         printf("\nMounting cifs URL not implemented yet. Attempt to mount %s\n",unc_name);
00179         return NULL;
00180 }
00181 
00182 static int open_cred_file(char * file_name)
00183 {
00184         char * line_buf;
00185         char * temp_val;
00186         FILE * fs;
00187         int i, length;
00188         fs = fopen(file_name,"r");
00189         if(fs == NULL)
00190                 return errno;
00191         line_buf = (char *)malloc(4096);
00192         if(line_buf == NULL) {
00193                 fclose(fs);
00194                 return -ENOMEM;
00195         }
00196 
00197         while(fgets(line_buf,4096,fs)) {
00198                 /* parse line from credential file */
00199 
00200                 /* eat leading white space */
00201                 for(i=0;i<4086;i++) {
00202                         if((line_buf[i] != ' ') && (line_buf[i] != '\t'))
00203                                 break;
00204                         /* if whitespace - skip past it */
00205                 }
00206                 if (strncasecmp("username",line_buf+i,8) == 0) {
00207                         temp_val = strchr(line_buf + i,'=');
00208                         if(temp_val) {
00209                                 /* go past equals sign */
00210                                 temp_val++;
00211                                 for(length = 0;length<4087;length++) {
00212                                         if ((temp_val[length] == '\n')
00213                                             || (temp_val[length] == '\0')) {
00214                                                 break;
00215                                         }
00216                                 }
00217                                 if(length > 4086) {
00218                                         printf("mount.cifs failed due to malformed username in credentials file");
00219                                         memset(line_buf,0,4096);
00220                                         if(mountpassword) {
00221                                                 memset(mountpassword,0,64);
00222                                         }
00223                                         exit(1);
00224                                 } else {
00225                                         got_user = 1;
00226                                         user_name = (char *)calloc(1 + length,1);
00227                                         /* BB adding free of user_name string before exit,
00228                                                 not really necessary but would be cleaner */
00229                                         strncpy(user_name,temp_val, length);
00230                                 }
00231                         }
00232                 } else if (strncasecmp("password",line_buf+i,8) == 0) {
00233                         temp_val = strchr(line_buf+i,'=');
00234                         if(temp_val) {
00235                                 /* go past equals sign */
00236                                 temp_val++;
00237                                 for(length = 0;length<65;length++) {
00238                                         if ((temp_val[length] == '\n')
00239                                             || (temp_val[length] == '\0')) {
00240                                                 break;
00241                                         }
00242                                 }
00243                                 if(length > 64) {
00244                                         printf("mount.cifs failed: password in credentials file too long\n");
00245                                         memset(line_buf,0, 4096);
00246                                         if(mountpassword) {
00247                                                 memset(mountpassword,0,64);
00248                                         }
00249                                         exit(1);
00250                                 } else {
00251                                         if(mountpassword == NULL) {
00252                                                 mountpassword = (char *)calloc(65,1);
00253                                         } else
00254                                                 memset(mountpassword,0,64);
00255                                         if(mountpassword) {
00256                                                 strncpy(mountpassword,temp_val,length);
00257                                                 got_password = 1;
00258                                         }
00259                                 }
00260                         }
00261                 } else if (strncasecmp("domain",line_buf+i,6) == 0) {
00262                         temp_val = strchr(line_buf+i,'=');
00263                         if(temp_val) {
00264                                 /* go past equals sign */
00265                                 temp_val++;
00266                                 if(verboseflag)
00267                                         printf("\nDomain %s\n",temp_val);
00268                                 for(length = 0;length<65;length++) {
00269                                         if ((temp_val[length] == '\n')
00270                                             || (temp_val[length] == '\0')) {
00271                                                 break;
00272                                         }
00273                                 }
00274                                 if(length > 64) {
00275                                         printf("mount.cifs failed: domain in credentials file too long\n");
00276                                         if(mountpassword) {
00277                                                 memset(mountpassword,0,64);
00278                                         }
00279                                         exit(1);
00280                                 } else {
00281                                         if(domain_name == NULL) {
00282                                                 domain_name = (char *)calloc(65,1);
00283                                         } else
00284                                                 memset(domain_name,0,64);
00285                                         if(domain_name) {
00286                                                 strncpy(domain_name,temp_val,length);
00287                                                 got_domain = 1;
00288                                         }
00289                                 }
00290                         }
00291                 }
00292 
00293         }
00294         fclose(fs);
00295         if(line_buf) {
00296                 memset(line_buf,0,4096);
00297                 free(line_buf);
00298                 line_buf = NULL;
00299         }
00300         return 0;
00301 }
00302 
00303 static int get_password_from_file(int file_descript, char * filename)
00304 {
00305         int rc = 0;
00306         int i;
00307         char c;
00308 
00309         if(mountpassword == NULL)
00310                 mountpassword = (char *)calloc(65,1);
00311         else 
00312                 memset(mountpassword, 0, 64);
00313 
00314         if (mountpassword == NULL) {
00315                 printf("malloc failed\n");
00316                 exit(1);
00317         }
00318 
00319         if(filename != NULL) {
00320                 file_descript = open(filename, O_RDONLY);
00321                 if(file_descript < 0) {
00322                         printf("mount.cifs failed. %s attempting to open password file %s\n",
00323                                    strerror(errno),filename);
00324                         exit(1);
00325                 }
00326         }
00327         /* else file already open and fd provided */
00328 
00329         for(i=0;i<64;i++) {
00330                 rc = read(file_descript,&c,1);
00331                 if(rc < 0) {
00332                         printf("mount.cifs failed. Error %s reading password file\n",strerror(errno));
00333                         memset(mountpassword,0,64);
00334                         if(filename != NULL)
00335                                 close(file_descript);
00336                         exit(1);
00337                 } else if(rc == 0) {
00338                         if(mountpassword[0] == 0) {
00339                                 if(verboseflag)
00340                                         printf("\nWarning: null password used since cifs password file empty");
00341                         }
00342                         break;
00343                 } else /* read valid character */ {
00344                         if((c == 0) || (c == '\n')) {
00345                                 break;
00346                         } else 
00347                                 mountpassword[i] = c;
00348                 }
00349         }
00350         if((i == 64) && (verboseflag)) {
00351                 printf("\nWarning: password longer than 64 characters specified in cifs password file");
00352         }
00353         got_password = 1;
00354         if(filename != NULL) {
00355                 close(file_descript);
00356         }
00357 
00358         return rc;
00359 }
00360 
00361 static int parse_options(char ** optionsp, int * filesys_flags)
00362 {
00363         const char * data;
00364         char * percent_char = NULL;
00365         char * value = NULL;
00366         char * next_keyword = NULL;
00367         char * out = NULL;
00368         int out_len = 0;
00369         int word_len;
00370         int rc = 0;
00371         char user[32];
00372         char group[32];
00373 
00374         if (!optionsp || !*optionsp)
00375                 return 1;
00376         data = *optionsp;
00377 
00378         if(verboseflag)
00379                 printf("parsing options: %s\n", data);
00380 
00381         /* BB fixme check for separator override BB */
00382 
00383         if (getuid()) {
00384                 got_uid = 1;
00385                 snprintf(user,sizeof(user),"%u",getuid());
00386                 got_gid = 1;
00387                 snprintf(group,sizeof(group),"%u",getgid());
00388         }
00389 
00390 /* while ((data = strsep(&options, ",")) != NULL) { */
00391         while(data != NULL) {
00392                 /*  check if ends with trailing comma */
00393                 if(*data == 0)
00394                         break;
00395 
00396                 /* format is keyword=value,keyword2=value2,keyword3=value3 etc.) */
00397                 /* data  = next keyword */
00398                 /* value = next value ie stuff after equal sign */
00399 
00400                 next_keyword = strchr(data,','); /* BB handle sep= */
00401         
00402                 /* temporarily null terminate end of keyword=value pair */
00403                 if(next_keyword)
00404                         *next_keyword++ = 0;
00405 
00406                 /* temporarily null terminate keyword to make keyword and value distinct */
00407                 if ((value = strchr(data, '=')) != NULL) {
00408                         *value = '\0';
00409                         value++;
00410                 }
00411 
00412                 if (strncmp(data, "users",5) == 0) {
00413                         if(!value || !*value) {
00414                                 goto nocopy;
00415                         }
00416                 } else if (strncmp(data, "user_xattr",10) == 0) {
00417                    /* do nothing - need to skip so not parsed as user name */
00418                 } else if (strncmp(data, "user", 4) == 0) {
00419 
00420                         if (!value || !*value) {
00421                                 if(data[4] == '\0') {
00422                                         if(verboseflag)
00423                                                 printf("\nskipping empty user mount parameter\n");
00424                                         /* remove the parm since it would otherwise be confusing
00425                                         to the kernel code which would think it was a real username */
00426                                         goto nocopy;
00427                                 } else {
00428                                         printf("username specified with no parameter\n");
00429                                         return 1;       /* needs_arg; */
00430                                 }
00431                         } else {
00432                                 if (strnlen(value, 260) < 260) {
00433                                         got_user=1;
00434                                         percent_char = strchr(value,'%');
00435                                         if(percent_char) {
00436                                                 *percent_char = ',';
00437                                                 if(mountpassword == NULL)
00438                                                         mountpassword = (char *)calloc(65,1);
00439                                                 if(mountpassword) {
00440                                                         if(got_password)
00441                                                                 printf("\nmount.cifs warning - password specified twice\n");
00442                                                         got_password = 1;
00443                                                         percent_char++;
00444                                                         strncpy(mountpassword, percent_char,64);
00445                                                 /*  remove password from username */
00446                                                         while(*percent_char != 0) {
00447                                                                 *percent_char = ',';
00448                                                                 percent_char++;
00449                                                         }
00450                                                 }
00451                                         }
00452                                         /* this is only case in which the user
00453                                         name buf is not malloc - so we have to
00454                                         check for domain name embedded within
00455                                         the user name here since the later
00456                                         call to check_for_domain will not be
00457                                         invoked */
00458                                         domain_name = check_for_domain(&value);
00459                                 } else {
00460                                         printf("username too long\n");
00461                                         return 1;
00462                                 }
00463                         }
00464                 } else if (strncmp(data, "pass", 4) == 0) {
00465                         if (!value || !*value) {
00466                                 if(got_password) {
00467                                         printf("\npassword specified twice, ignoring second\n");
00468                                 } else
00469                                         got_password = 1;
00470                         } else if (strnlen(value, 17) < 17) {
00471                                 if(got_password)
00472                                         printf("\nmount.cifs warning - password specified twice\n");
00473                                 got_password = 1;
00474                         } else {
00475                                 printf("password too long\n");
00476                                 return 1;
00477                         }
00478                 } else if (strncmp(data, "sec", 3) == 0) {
00479                         if (value) {
00480                                 if (!strncmp(value, "none", 4) ||
00481                                     !strncmp(value, "krb5", 4))
00482                                         got_password = 1;
00483                         }
00484                 } else if (strncmp(data, "ip", 2) == 0) {
00485                         if (!value || !*value) {
00486                                 printf("target ip address argument missing");
00487                         } else if (strnlen(value, 35) < 35) {
00488                                 if(verboseflag)
00489                                         printf("ip address %s override specified\n",value);
00490                                 got_ip = 1;
00491                         } else {
00492                                 printf("ip address too long\n");
00493                                 return 1;
00494                         }
00495                 } else if ((strncmp(data, "unc", 3) == 0)
00496                    || (strncmp(data, "target", 6) == 0)
00497                    || (strncmp(data, "path", 4) == 0)) {
00498                         if (!value || !*value) {
00499                                 printf("invalid path to network resource\n");
00500                                 return 1;  /* needs_arg; */
00501                         } else if(strnlen(value,5) < 5) {
00502                                 printf("UNC name too short");
00503                         }
00504 
00505                         if (strnlen(value, 300) < 300) {
00506                                 got_unc = 1;
00507                                 if (strncmp(value, "//", 2) == 0) {
00508                                         if(got_unc)
00509                                                 printf("unc name specified twice, ignoring second\n");
00510                                         else
00511                                                 got_unc = 1;
00512                                 } else if (strncmp(value, "\\\\", 2) != 0) {                       
00513                                         printf("UNC Path does not begin with // or \\\\ \n");
00514                                         return 1;
00515                                 } else {
00516                                         if(got_unc)
00517                                                 printf("unc name specified twice, ignoring second\n");
00518                                         else
00519                                                 got_unc = 1;
00520                                 }
00521                         } else {
00522                                 printf("CIFS: UNC name too long\n");
00523                                 return 1;
00524                         }
00525                 } else if ((strncmp(data, "domain", 3) == 0)
00526                            || (strncmp(data, "workgroup", 5) == 0)) {
00527                         if (!value || !*value) {
00528                                 printf("CIFS: invalid domain name\n");
00529                                 return 1;       /* needs_arg; */
00530                         }
00531                         if (strnlen(value, 65) < 65) {
00532                                 got_domain = 1;
00533                         } else {
00534                                 printf("domain name too long\n");
00535                                 return 1;
00536                         }
00537                 } else if (strncmp(data, "cred", 4) == 0) {
00538                         if (value && *value) {
00539                                 rc = open_cred_file(value);
00540                                 if(rc) {
00541                                         printf("error %d opening credential file %s\n",rc, value);
00542                                         return 1;
00543                                 }
00544                         } else {
00545                                 printf("invalid credential file name specified\n");
00546                                 return 1;
00547                         }
00548                 } else if (strncmp(data, "uid", 3) == 0) {
00549                         if (value && *value) {
00550                                 got_uid = 1;
00551                                 if (!isdigit(*value)) {
00552                                         struct passwd *pw;
00553 
00554                                         if (!(pw = getpwnam(value))) {
00555                                                 printf("bad user name \"%s\"\n", value);
00556                                                 exit(1);
00557                                         }
00558                                         snprintf(user, sizeof(user), "%u", pw->pw_uid);
00559                                 } else {
00560                                         strlcpy(user,value,sizeof(user));
00561                                 }
00562                         }
00563                         goto nocopy;
00564                 } else if (strncmp(data, "gid", 3) == 0) {
00565                         if (value && *value) {
00566                                 got_gid = 1;
00567                                 if (!isdigit(*value)) {
00568                                         struct group *gr;
00569 
00570                                         if (!(gr = getgrnam(value))) {
00571                                                 printf("bad group name \"%s\"\n", value);
00572                                                 exit(1);
00573                                         }
00574                                         snprintf(group, sizeof(group), "%u", gr->gr_gid);
00575                                 } else {
00576                                         strlcpy(group,value,sizeof(group));
00577                                 }
00578                         }
00579                         goto nocopy;
00580        /* fmask and dmask synonyms for people used to smbfs syntax */
00581                 } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) {
00582                         if (!value || !*value) {
00583                                 printf ("Option '%s' requires a numerical argument\n", data);
00584                                 return 1;
00585                         }
00586 
00587                         if (value[0] != '0') {
00588                                 printf ("WARNING: '%s' not expressed in octal.\n", data);
00589                         }
00590 
00591                         if (strcmp (data, "fmask") == 0) {
00592                                 printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
00593                                 data = "file_mode"; /* BB fix this */
00594                         }
00595                 } else if (strcmp(data, "dir_mode") == 0 || strcmp(data, "dmask")==0) {
00596                         if (!value || !*value) {
00597                                 printf ("Option '%s' requires a numerical argument\n", data);
00598                                 return 1;
00599                         }
00600 
00601                         if (value[0] != '0') {
00602                                 printf ("WARNING: '%s' not expressed in octal.\n", data);
00603                         }
00604 
00605                         if (strcmp (data, "dmask") == 0) {
00606                                 printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
00607                                 data = "dir_mode";
00608                         }
00609                         /* the following eight mount options should be
00610                         stripped out from what is passed into the kernel
00611                         since these eight options are best passed as the
00612                         mount flags rather than redundantly to the kernel 
00613                         and could generate spurious warnings depending on the
00614                         level of the corresponding cifs vfs kernel code */
00615                 } else if (strncmp(data, "nosuid", 6) == 0) {
00616                         *filesys_flags |= MS_NOSUID;
00617                 } else if (strncmp(data, "suid", 4) == 0) {
00618                         *filesys_flags &= ~MS_NOSUID;
00619                 } else if (strncmp(data, "nodev", 5) == 0) {
00620                         *filesys_flags |= MS_NODEV;
00621                 } else if ((strncmp(data, "nobrl", 5) == 0) || 
00622                            (strncmp(data, "nolock", 6) == 0)) {
00623                         *filesys_flags &= ~MS_MANDLOCK;
00624                 } else if (strncmp(data, "dev", 3) == 0) {
00625                         *filesys_flags &= ~MS_NODEV;
00626                 } else if (strncmp(data, "noexec", 6) == 0) {
00627                         *filesys_flags |= MS_NOEXEC;
00628                 } else if (strncmp(data, "exec", 4) == 0) {
00629                         *filesys_flags &= ~MS_NOEXEC;
00630                 } else if (strncmp(data, "guest", 5) == 0) {
00631                         got_password=1;
00632                 } else if (strncmp(data, "ro", 2) == 0) {
00633                         *filesys_flags |= MS_RDONLY;
00634                 } else if (strncmp(data, "rw", 2) == 0) {
00635                         *filesys_flags &= ~MS_RDONLY;
00636                 } else if (strncmp(data, "remount", 7) == 0) {
00637                         *filesys_flags |= MS_REMOUNT;
00638                 } /* else if (strnicmp(data, "port", 4) == 0) {
00639                         if (value && *value) {
00640                                 vol->port =
00641                                         simple_strtoul(value, &value, 0);
00642                         }
00643                 } else if (strnicmp(data, "rsize", 5) == 0) {
00644                         if (value && *value) {
00645                                 vol->rsize =
00646                                         simple_strtoul(value, &value, 0);
00647                         }
00648                 } else if (strnicmp(data, "wsize", 5) == 0) {
00649                         if (value && *value) {
00650                                 vol->wsize =
00651                                         simple_strtoul(value, &value, 0);
00652                         }
00653                 } else if (strnicmp(data, "version", 3) == 0) {
00654                 } else {
00655                         printf("CIFS: Unknown mount option %s\n",data);
00656                 } */ /* nothing to do on those four mount options above.
00657                         Just pass to kernel and ignore them here */
00658 
00659                 /* Copy (possibly modified) option to out */
00660                 word_len = strlen(data);
00661                 if (value)
00662                         word_len += 1 + strlen(value);
00663 
00664                 out = (char *)realloc(out, out_len + word_len + 2);
00665                 if (out == NULL) {
00666                         perror("malloc");
00667                         exit(1);
00668                 }
00669 
00670                 if (out_len) {
00671                         strlcat(out, ",", out_len + word_len + 2);
00672                         out_len++;
00673                 }
00674 
00675                 if (value)
00676                         snprintf(out + out_len, word_len + 1, "%s=%s", data, value);
00677                 else
00678                         snprintf(out + out_len, word_len + 1, "%s", data);
00679                 out_len = strlen(out);
00680 
00681 nocopy:
00682                 data = next_keyword;
00683         }
00684 
00685         /* special-case the uid and gid */
00686         if (got_uid) {
00687                 word_len = strlen(user);
00688 
00689                 out = (char *)realloc(out, out_len + word_len + 6);
00690                 if (out == NULL) {
00691                         perror("malloc");
00692                         exit(1);
00693                 }
00694 
00695                 if (out_len) {
00696                         strlcat(out, ",", out_len + word_len + 6);
00697                         out_len++;
00698                 }
00699                 snprintf(out + out_len, word_len + 5, "uid=%s", user);
00700                 out_len = strlen(out);
00701         }
00702         if (got_gid) {
00703                 word_len = strlen(group);
00704 
00705                 out = (char *)realloc(out, out_len + 1 + word_len + 6);
00706                 if (out == NULL) {
00707                 perror("malloc");
00708                         exit(1);
00709                 }
00710 
00711                 if (out_len) {
00712                         strlcat(out, ",", out_len + word_len + 6);
00713                         out_len++;
00714                 }
00715                 snprintf(out + out_len, word_len + 5, "gid=%s", group);
00716                 out_len = strlen(out);
00717         }
00718 
00719         free(*optionsp);
00720         *optionsp = out;
00721         return 0;
00722 }
00723 
00724 /* replace all (one or more) commas with double commas */
00725 static void check_for_comma(char ** ppasswrd)
00726 {
00727         char *new_pass_buf;
00728         char *pass;
00729         int i,j;
00730         int number_of_commas = 0;
00731         int len;
00732 
00733         if(ppasswrd == NULL)
00734                 return;
00735         else 
00736                 (pass = *ppasswrd);
00737 
00738         len = strlen(pass);
00739 
00740         for(i=0;i<len;i++)  {
00741                 if(pass[i] == ',')
00742                         number_of_commas++;
00743         }
00744 
00745         if(number_of_commas == 0)
00746                 return;
00747         if(number_of_commas > 64) {
00748                 /* would otherwise overflow the mount options buffer */
00749                 printf("\nInvalid password. Password contains too many commas.\n");
00750                 return;
00751         }
00752 
00753         new_pass_buf = (char *)malloc(len+number_of_commas+1);
00754         if(new_pass_buf == NULL)
00755                 return;
00756 
00757         for(i=0,j=0;i<len;i++,j++) {
00758                 new_pass_buf[j] = pass[i];
00759                 if(pass[i] == ',') {
00760                         j++;
00761                         new_pass_buf[j] = pass[i];
00762                 }
00763         }
00764         new_pass_buf[len+number_of_commas] = 0;
00765 
00766         free(*ppasswrd);
00767         *ppasswrd = new_pass_buf;
00768         
00769         return;
00770 }
00771 
00772 /* Usernames can not have backslash in them and we use
00773    [BB check if usernames can have forward slash in them BB] 
00774    backslash as domain\user separator character
00775 */
00776 static char * check_for_domain(char **ppuser)
00777 {
00778         char * original_string;
00779         char * usernm;
00780         char * domainnm;
00781         int    original_len;
00782         int    len;
00783         int    i;
00784 
00785         if(ppuser == NULL)
00786                 return NULL;
00787 
00788         original_string = *ppuser;
00789 
00790         if (original_string == NULL)
00791                 return NULL;
00792         
00793         original_len = strlen(original_string);
00794 
00795         usernm = strchr(*ppuser,'/');
00796         if (usernm == NULL) {
00797                 usernm = strchr(*ppuser,'\\');
00798                 if (usernm == NULL)
00799                         return NULL;
00800         }
00801 
00802         if(got_domain) {
00803                 printf("Domain name specified twice. Username probably malformed\n");
00804                 return NULL;
00805         }
00806 
00807         usernm[0] = 0;
00808         domainnm = *ppuser;
00809         if (domainnm[0] != 0) {
00810                 got_domain = 1;
00811         } else {
00812                 printf("null domain\n");
00813         }
00814         len = strlen(domainnm);
00815         /* reset domainm to new buffer, and copy
00816         domain name into it */
00817         domainnm = (char *)malloc(len+1);
00818         if(domainnm == NULL)
00819                 return NULL;
00820 
00821         strlcpy(domainnm,*ppuser,len+1);
00822 
00823 /*      move_string(*ppuser, usernm+1) */
00824         len = strlen(usernm+1);
00825 
00826         if(len >= original_len) {
00827                 /* should not happen */
00828                 return domainnm;
00829         }
00830 
00831         for(i=0;i<original_len;i++) {
00832                 if(i<len)
00833                         original_string[i] = usernm[i+1];
00834                 else /* stuff with commas to remove last parm */
00835                         original_string[i] = ',';
00836         }
00837 
00838         /* BB add check for more than one slash? 
00839           strchr(*ppuser,'/');
00840           strchr(*ppuser,'\\') 
00841         */
00842         
00843         return domainnm;
00844 }
00845 
00846 /* replace all occurances of "from" in a string with "to" */
00847 static void replace_char(char *string, char from, char to, int maxlen)
00848 {
00849         char *lastchar = string + maxlen;
00850         while (string) {
00851                 string = strchr(string, from);
00852                 if (string) {
00853                         *string = to;
00854                         if (string >= lastchar)
00855                                 return;
00856                 }
00857         }
00858 }
00859 
00860 /* Note that caller frees the returned buffer if necessary */
00861 static char * parse_server(char ** punc_name)
00862 {
00863         char * unc_name = *punc_name;
00864         int length = strnlen(unc_name, MAX_UNC_LEN);
00865         char * share;
00866         char * ipaddress_string = NULL;
00867         struct hostent * host_entry = NULL;
00868         struct in_addr server_ipaddr;
00869 
00870         if(length > (MAX_UNC_LEN - 1)) {
00871                 printf("mount error: UNC name too long");
00872                 return NULL;
00873         }
00874         if (strncasecmp("cifs://",unc_name,7) == 0)
00875                 return parse_cifs_url(unc_name+7);
00876         if (strncasecmp("smb://",unc_name,6) == 0) {
00877                 return parse_cifs_url(unc_name+6);
00878         }
00879 
00880         if(length < 3) {
00881                 /* BB add code to find DFS root here */
00882                 printf("\nMounting the DFS root for domain not implemented yet\n");
00883                 return NULL;
00884         } else {
00885                 if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
00886                         /* check for nfs syntax ie server:share */
00887                         share = strchr(unc_name,':');
00888                         if(share) {
00889                                 *punc_name = (char *)malloc(length+3);
00890                                 if(*punc_name == NULL) {
00891                                         /* put the original string back  if 
00892                                            no memory left */
00893                                         *punc_name = unc_name;
00894                                         return NULL;
00895                                 }
00896                                 *share = '/';
00897                                 strncpy((*punc_name)+2,unc_name,length);
00898                                 free(unc_name);
00899                                 unc_name = *punc_name;
00900                                 unc_name[length+2] = 0;
00901                                 goto continue_unc_parsing;
00902                         } else {
00903                                 printf("mount error: improperly formatted UNC name.");
00904                                 printf(" %s does not begin with \\\\ or //\n",unc_name);
00905                                 return NULL;
00906                         }
00907                 } else {
00908 continue_unc_parsing:
00909                         unc_name[0] = '/';
00910                         unc_name[1] = '/';
00911                         unc_name += 2;
00912 
00913                         /* allow for either delimiter between host and sharename */
00914                         if ((share = strpbrk(unc_name, "/\\"))) {
00915                                 *share = 0;  /* temporarily terminate the string */
00916                                 share += 1;
00917                                 if(got_ip == 0) {
00918                                         host_entry = gethostbyname(unc_name);
00919                                 }
00920                                 *(share - 1) = '/'; /* put delimiter back */
00921 
00922                                 /* we don't convert the prefixpath delimiters since '\\' is a valid char in posix paths */
00923                                 if ((prefixpath = strpbrk(share, "/\\"))) {
00924                                         *prefixpath = 0;  /* permanently terminate the string */
00925                                         if (!strlen(++prefixpath))
00926                                                 prefixpath = NULL; /* this needs to be done explicitly */
00927                                 }
00928                                 if(got_ip) {
00929                                         if(verboseflag)
00930                                                 printf("ip address specified explicitly\n");
00931                                         return NULL;
00932                                 }
00933                                 if(host_entry == NULL) {
00934                                         printf("mount error: could not find target server. TCP name %s not found\n", unc_name);
00935                                         return NULL;
00936                                 } else {
00937                                         /* BB should we pass an alternate version of the share name as Unicode */
00938                                         /* BB what about ipv6? BB */
00939                                         /* BB add retries with alternate servers in list */
00940 
00941                                         memcpy(&server_ipaddr.s_addr, host_entry->h_addr, 4);
00942 
00943                                         ipaddress_string = inet_ntoa(server_ipaddr);                                                                                     
00944                                         if(ipaddress_string == NULL) {
00945                                                 printf("mount error: could not get valid ip address for target server\n");
00946                                                 return NULL;
00947                                         }
00948                                         return ipaddress_string; 
00949                                 }
00950                         } else {
00951                                 /* BB add code to find DFS root (send null path on get DFS Referral to specified server here */
00952                                 printf("Mounting the DFS root for a particular server not implemented yet\n");
00953                                 return NULL;
00954                         }
00955                 }
00956         }
00957 }
00958 
00959 static struct option longopts[] = {
00960         { "all", 0, NULL, 'a' },
00961         { "help",0, NULL, 'h' },
00962         { "move",0, NULL, 'm' },
00963         { "bind",0, NULL, 'b' },
00964         { "read-only", 0, NULL, 'r' },
00965         { "ro", 0, NULL, 'r' },
00966         { "verbose", 0, NULL, 'v' },
00967         { "version", 0, NULL, 'V' },
00968         { "read-write", 0, NULL, 'w' },
00969         { "rw", 0, NULL, 'w' },
00970         { "options", 1, NULL, 'o' },
00971         { "type", 1, NULL, 't' },
00972         { "rsize",1, NULL, 'R' },
00973         { "wsize",1, NULL, 'W' },
00974         { "uid", 1, NULL, '1'},
00975         { "gid", 1, NULL, '2'},
00976         { "user",1,NULL,'u'},
00977         { "username",1,NULL,'u'},
00978         { "dom",1,NULL,'d'},
00979         { "domain",1,NULL,'d'},
00980         { "password",1,NULL,'p'},
00981         { "pass",1,NULL,'p'},
00982         { "credentials",1,NULL,'c'},
00983         { "port",1,NULL,'P'},
00984         /* { "uuid",1,NULL,'U'}, */ /* BB unimplemented */
00985         { NULL, 0, NULL, 0 }
00986 };
00987 
00988 /* convert a string to uppercase. return false if the string
00989  * wasn't ASCII or was a NULL ptr */
00990 static int
00991 uppercase_string(char *string)
00992 {
00993         if (!string)
00994                 return 0;
00995 
00996         while (*string) {
00997                 /* check for unicode */
00998                 if ((unsigned char) string[0] & 0x80)
00999                         return 0;
01000                 *string = toupper((unsigned char) *string);
01001                 string++;
01002         }
01003 
01004         return 1;
01005 }
01006 
01007 int main(int argc, char ** argv)
01008 {
01009         int c;
01010         int flags = MS_MANDLOCK; /* no need to set legacy MS_MGC_VAL */
01011         char * orgoptions = NULL;
01012         char * share_name = NULL;
01013         char * ipaddr = NULL;
01014         char * uuid = NULL;
01015         char * mountpoint = NULL;
01016         char * options = NULL;
01017         char * resolved_path = NULL;
01018         char * temp;
01019         char * dev_name;
01020         int rc;
01021         int rsize = 0;
01022         int wsize = 0;
01023         int nomtab = 0;
01024         int uid = 0;
01025         int gid = 0;
01026         int optlen = 0;
01027         int orgoptlen = 0;
01028         size_t options_size = 0;
01029         int retry = 0; /* set when we have to retry mount with uppercase */
01030         struct stat statbuf;
01031         struct utsname sysinfo;
01032         struct mntent mountent;
01033         FILE * pmntfile;
01034 
01035         /* setlocale(LC_ALL, "");
01036         bindtextdomain(PACKAGE, LOCALEDIR);
01037         textdomain(PACKAGE); */
01038 
01039         if(argc && argv) {
01040                 thisprogram = argv[0];
01041         } else {
01042                 mount_cifs_usage();
01043                 exit(1);
01044         }
01045 
01046         if(thisprogram == NULL)
01047                 thisprogram = "mount.cifs";
01048 
01049         uname(&sysinfo);
01050         /* BB add workstation name and domain and pass down */
01051 
01052 /* #ifdef _GNU_SOURCE
01053         printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
01054 #endif */
01055         if(argc > 2) {
01056                 dev_name = argv[1];
01057                 share_name = strndup(argv[1], MAX_UNC_LEN);
01058                 if (share_name == NULL) {
01059                         fprintf(stderr, "%s: %s", argv[0], strerror(ENOMEM));
01060                         exit(1);
01061                 }
01062                 mountpoint = argv[2];
01063         } else {
01064                 mount_cifs_usage();
01065                 exit(1);
01066         }
01067 
01068         /* add sharename in opts string as unc= parm */
01069 
01070         while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsSU:vVwt:",
01071                          longopts, NULL)) != -1) {
01072                 switch (c) {
01073 /* No code to do the following  options yet */
01074 /*      case 'l':
01075                 list_with_volumelabel = 1;
01076                 break;
01077         case 'L':
01078                 volumelabel = optarg;
01079                 break; */
01080 /*      case 'a':              
01081                 ++mount_all;
01082                 break; */
01083 
01084                 case '?':
01085                 case 'h':        /* help */
01086                         mount_cifs_usage ();
01087                         exit(1);
01088                 case 'n':
01089                     ++nomtab;
01090                     break;
01091                 case 'b':
01092 #ifdef MS_BIND
01093                         flags |= MS_BIND;
01094 #else
01095                         fprintf(stderr,
01096                                 "option 'b' (MS_BIND) not supported\n");
01097 #endif
01098                         break;
01099                 case 'm':
01100 #ifdef MS_MOVE                
01101                         flags |= MS_MOVE;
01102 #else
01103                         fprintf(stderr,
01104                                 "option 'm' (MS_MOVE) not supported\n");
01105 #endif
01106                         break;
01107                 case 'o':
01108                         orgoptions = strdup(optarg);
01109                     break;
01110                 case 'r':  /* mount readonly */
01111                         flags |= MS_RDONLY;
01112                         break;
01113                 case 'U':
01114                         uuid = optarg;
01115                         break;
01116                 case 'v':
01117                         ++verboseflag;
01118                         break;
01119                 case 'V':          
01120                         printf ("mount.cifs version: %s.%s%s\n",
01121                         MOUNT_CIFS_VERSION_MAJOR,
01122                         MOUNT_CIFS_VERSION_MINOR,
01123                         MOUNT_CIFS_VENDOR_SUFFIX);
01124                         if(mountpassword) {
01125                                 memset(mountpassword,0,64);
01126                         }
01127                         exit (0);
01128                 case 'w':
01129                         flags &= ~MS_RDONLY;
01130                         break;
01131                 case 'R':
01132                         rsize = atoi(optarg) ;
01133                         break;
01134                 case 'W':
01135                         wsize = atoi(optarg);
01136                         break;
01137                 case '1':
01138                         if (isdigit(*optarg)) {
01139                                 char *ep;
01140 
01141                                 uid = strtoul(optarg, &ep, 10);
01142                                 if (*ep) {
01143                                         printf("bad uid value \"%s\"\n", optarg);
01144                                         exit(1);
01145                                 }
01146                         } else {
01147                                 struct passwd *pw;
01148 
01149                                 if (!(pw = getpwnam(optarg))) {
01150                                         printf("bad user name \"%s\"\n", optarg);
01151                                         exit(1);
01152                                 }
01153                                 uid = pw->pw_uid;
01154                                 endpwent();
01155                         }
01156                         break;
01157                 case '2':
01158                         if (isdigit(*optarg)) {
01159                                 char *ep;
01160 
01161                                 gid = strtoul(optarg, &ep, 10);
01162                                 if (*ep) {
01163                                         printf("bad gid value \"%s\"\n", optarg);
01164                                         exit(1);
01165                                 }
01166                         } else {
01167                                 struct group *gr;
01168 
01169                                 if (!(gr = getgrnam(optarg))) {
01170                                         printf("bad user name \"%s\"\n", optarg);
01171                                         exit(1);
01172                                 }
01173                                 gid = gr->gr_gid;
01174                                 endpwent();
01175                         }
01176                         break;
01177                 case 'u':
01178                         got_user = 1;
01179                         user_name = optarg;
01180                         break;
01181                 case 'd':
01182                         domain_name = optarg; /* BB fix this - currently ignored */
01183                         got_domain = 1;
01184                         break;
01185                 case 'p':
01186                         if(mountpassword == NULL)
01187                                 mountpassword = (char *)calloc(65,1);
01188                         if(mountpassword) {
01189                                 got_password = 1;
01190                                 strncpy(mountpassword,optarg,64);
01191                         }
01192                         break;
01193                 case 'S':
01194                         get_password_from_file(0 /* stdin */,NULL);
01195                         break;
01196                 case 't':
01197                         break;
01198                 default:
01199                         printf("unknown mount option %c\n",c);
01200                         mount_cifs_usage();
01201                         exit(1);
01202                 }
01203         }
01204 
01205         if((argc < 3) || (dev_name == NULL) || (mountpoint == NULL)) {
01206                 mount_cifs_usage();
01207                 exit(1);
01208         }
01209 
01210         if (getenv("PASSWD")) {
01211                 if(mountpassword == NULL)
01212                         mountpassword = (char *)calloc(65,1);
01213                 if(mountpassword) {
01214                         strncpy(mountpassword,getenv("PASSWD"),64);
01215                         got_password = 1;
01216                 }
01217         } else if (getenv("PASSWD_FD")) {
01218                 get_password_from_file(atoi(getenv("PASSWD_FD")),NULL);
01219         } else if (getenv("PASSWD_FILE")) {
01220                 get_password_from_file(0, getenv("PASSWD_FILE"));
01221         }
01222 
01223         if (orgoptions && parse_options(&orgoptions, &flags)) {
01224                 rc = -1;
01225                 goto mount_exit;
01226         }
01227         ipaddr = parse_server(&share_name);
01228         if((ipaddr == NULL) && (got_ip == 0)) {
01229                 printf("No ip address specified and hostname not found\n");
01230                 rc = -1;
01231                 goto mount_exit;
01232         }
01233         
01234         /* BB save off path and pop after mount returns? */
01235         resolved_path = (char *)malloc(PATH_MAX+1);
01236         if(resolved_path) {
01237                 /* Note that if we can not canonicalize the name, we get
01238                 another chance to see if it is valid when we chdir to it */
01239                 if (realpath(mountpoint, resolved_path)) {
01240                         mountpoint = resolved_path; 
01241                 }
01242         }
01243         if(chdir(mountpoint)) {
01244                 printf("mount error: can not change directory into mount target %s\n",mountpoint);
01245                 rc = -1;
01246                 goto mount_exit;
01247         }
01248 
01249         if(stat (".", &statbuf)) {
01250                 printf("mount error: mount point %s does not exist\n",mountpoint);
01251                 rc = -1;
01252                 goto mount_exit;
01253         }
01254 
01255         if (S_ISDIR(statbuf.st_mode) == 0) {
01256                 printf("mount error: mount point %s is not a directory\n",mountpoint);
01257                 rc = -1;
01258                 goto mount_exit;
01259         }
01260 
01261         if((getuid() != 0) && (geteuid() == 0)) {
01262                 if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) {
01263 #ifndef CIFS_ALLOW_USR_SUID
01264                         /* Do not allow user mounts to control suid flag
01265                         for mount unless explicitly built that way */
01266                         flags |= MS_NOSUID | MS_NODEV;
01267 #endif                                          
01268                 } else {
01269                         printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n"); 
01270                         return -1;
01271                 }
01272         }
01273 
01274         if(got_user == 0) {
01275                 user_name = getusername();
01276                 got_user = 1;
01277         }
01278        
01279         if(got_password == 0) {
01280                 char *tmp_pass;
01281                 tmp_pass = getpass("Password: "); /* BB obsolete sys call but
01282                                                      no good replacement yet */
01283                 mountpassword = (char *)calloc(65,1);
01284                 if (!tmp_pass || !mountpassword) {
01285                         printf("Password not entered, exiting.\n");
01286                         return -1;
01287                 }
01288                 strncpy(mountpassword, tmp_pass, 64);
01289                                                  
01290                 got_password = 1;
01291         }
01292         /* FIXME launch daemon (handles dfs name resolution and credential change) 
01293            remember to clear parms and overwrite password field before launching */
01294 mount_retry:
01295         if(orgoptions) {
01296                 optlen = strlen(orgoptions);
01297                 orgoptlen = optlen;
01298         } else
01299                 optlen = 0;
01300         if(share_name)
01301                 optlen += strlen(share_name) + 4;
01302         else {
01303                 printf("No server share name specified\n");
01304                 printf("\nMounting the DFS root for server not implemented yet\n");
01305                 exit(1);
01306         }
01307         if(user_name)
01308                 optlen += strlen(user_name) + 6;
01309         if(ipaddr)
01310                 optlen += strlen(ipaddr) + 4;
01311         if(mountpassword)
01312                 optlen += strlen(mountpassword) + 6;
01313         if(options) {
01314                 free(options);
01315                 options = NULL;
01316         }
01317         options_size = optlen + 10 + 64;
01318         options = (char *)malloc(options_size /* space for commas in password */ + 8 /* space for domain=  , domain name itself was counted as part of the length username string above */);
01319 
01320         if(options == NULL) {
01321                 printf("Could not allocate memory for mount options\n");
01322                 return -1;
01323         }
01324 
01325         options[0] = 0;
01326         strlcpy(options,"unc=",options_size);
01327         strlcat(options,share_name,options_size);
01328         /* scan backwards and reverse direction of slash */
01329         temp = strrchr(options, '/');
01330         if(temp > options + 6)
01331                 *temp = '\\';
01332         if(ipaddr) {
01333                 strlcat(options,",ip=",options_size);
01334                 strlcat(options,ipaddr,options_size);
01335         }
01336 
01337         if(user_name) {
01338                 /* check for syntax like user=domain\user */
01339                 if(got_domain == 0)
01340                         domain_name = check_for_domain(&user_name);
01341                 strlcat(options,",user=",options_size);
01342                 strlcat(options,user_name,options_size);
01343         }
01344         if(retry == 0) {
01345                 if(domain_name) {
01346                         /* extra length accounted for in option string above */
01347                         strlcat(options,",domain=",options_size);
01348                         strlcat(options,domain_name,options_size);
01349                 }
01350         }
01351         if(mountpassword) {
01352                 /* Commas have to be doubled, or else they will
01353                 look like the parameter separator */
01354 /*              if(sep is not set)*/
01355                 if(retry == 0)
01356                         check_for_comma(&mountpassword);
01357                 strlcat(options,",pass=",options_size);
01358                 strlcat(options,mountpassword,options_size);
01359         }
01360 
01361         strlcat(options,",ver=",options_size);
01362         strlcat(options,MOUNT_CIFS_VERSION_MAJOR,options_size);
01363 
01364         if(orgoptions) {
01365                 strlcat(options,",",options_size);
01366                 strlcat(options,orgoptions,options_size);
01367         }
01368         if(prefixpath) {
01369                 strlcat(options,",prefixpath=",options_size);
01370                 strlcat(options,prefixpath,options_size); /* no need to cat the / */
01371         }
01372         if(verboseflag)
01373                 printf("\nmount.cifs kernel mount options %s \n",options);
01374 
01375         /* convert all '\\' to '/' in share portion so that /proc/mounts looks pretty */
01376         replace_char(dev_name, '\\', '/', strlen(share_name));
01377 
01378         if(mount(dev_name, mountpoint, "cifs", flags, options)) {
01379         /* remember to kill daemon on error */
01380                 switch (errno) {
01381                 case 0:
01382                         printf("mount failed but no error number set\n");
01383                         break;
01384                 case ENODEV:
01385                         printf("mount error: cifs filesystem not supported by the system\n");
01386                         break;
01387                 case ENXIO:
01388                         if(retry == 0) {
01389                                 retry = 1;
01390                                 if (uppercase_string(dev_name) &&
01391                                     uppercase_string(share_name) &&
01392                                     uppercase_string(prefixpath)) {
01393                                         printf("retrying with upper case share name\n");
01394                                         goto mount_retry;
01395                                 }
01396                         }
01397                 default:
01398                         printf("mount error %d = %s\n",errno,strerror(errno));
01399                 }
01400                 printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
01401                 rc = -1;
01402                 goto mount_exit;
01403         } else {
01404                 pmntfile = setmntent(MOUNTED, "a+");
01405                 if(pmntfile) {
01406                         mountent.mnt_fsname = dev_name;
01407                         mountent.mnt_dir = mountpoint;
01408                         mountent.mnt_type = CONST_DISCARD(char *,"cifs");
01409                         mountent.mnt_opts = (char *)malloc(220);
01410                         if(mountent.mnt_opts) {
01411                                 char * mount_user = getusername();
01412                                 memset(mountent.mnt_opts,0,200);
01413                                 if(flags & MS_RDONLY)
01414                                         strlcat(mountent.mnt_opts,"ro",220);
01415                                 else
01416                                         strlcat(mountent.mnt_opts,"rw",220);
01417                                 if(flags & MS_MANDLOCK)
01418                                         strlcat(mountent.mnt_opts,",mand",220);
01419                                 if(flags & MS_NOEXEC)
01420                                         strlcat(mountent.mnt_opts,",noexec",220);
01421                                 if(flags & MS_NOSUID)
01422                                         strlcat(mountent.mnt_opts,",nosuid",220);
01423                                 if(flags & MS_NODEV)
01424                                         strlcat(mountent.mnt_opts,",nodev",220);
01425                                 if(flags & MS_SYNCHRONOUS)
01426                                         strlcat(mountent.mnt_opts,",synch",220);
01427                                 if(mount_user) {
01428                                         if(getuid() != 0) {
01429                                                 strlcat(mountent.mnt_opts,",user=",220);
01430                                                 strlcat(mountent.mnt_opts,mount_user,220);
01431                                         }
01432                                         /* free(mount_user); do not free static mem */
01433                                 }
01434                         }
01435                         mountent.mnt_freq = 0;
01436                         mountent.mnt_passno = 0;
01437                         rc = addmntent(pmntfile,&mountent);
01438                         endmntent(pmntfile);
01439                         if(mountent.mnt_opts) {
01440                                 free(mountent.mnt_opts);
01441                                 mountent.mnt_opts = NULL;
01442                         }
01443                 } else {
01444                     printf("could not update mount table\n");
01445                 }
01446         }
01447         rc = 0;
01448 mount_exit:
01449         if(mountpassword) {
01450                 int len = strlen(mountpassword);
01451                 memset(mountpassword,0,len);
01452                 free(mountpassword);
01453                 mountpassword = NULL;
01454         }
01455 
01456         if(options) {
01457                 memset(options,0,optlen);
01458                 free(options);
01459                 options = NULL;
01460         }
01461 
01462         if(orgoptions) {
01463                 memset(orgoptions,0,orgoptlen);
01464                 free(orgoptions);
01465                 orgoptions = NULL;
01466         }
01467         if(resolved_path) {
01468                 free(resolved_path);
01469                 resolved_path = NULL;
01470         }
01471 
01472         free(share_name);
01473         return rc;
01474 }

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