2 Mount helper utility for Linux CIFS VFS (virtual filesystem) client
3 Copyright (C) 2003,2005 Steve French (sfrench@us.ibm.com)
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
28 #include <sys/types.h>
29 #include <sys/mount.h>
31 #include <sys/utsname.h>
32 #include <sys/socket.h>
33 #include <arpa/inet.h>
41 #define MOUNT_CIFS_VERSION_MAJOR "1"
42 #define MOUNT_CIFS_VERSION_MINOR "8"
44 #ifndef MOUNT_CIFS_VENDOR_SUFFIX
45 #define MOUNT_CIFS_VENDOR_SUFFIX ""
54 static int got_password = 0;
55 static int got_user = 0;
56 static int got_domain = 0;
57 static int got_ip = 0;
58 static int got_unc = 0;
59 static int got_uid = 0;
60 static int got_gid = 0;
61 static int free_share_name = 0;
62 static char * user_name = NULL;
63 static char * mountpassword = NULL;
64 char * domain_name = NULL;
70 open nofollow - avoid symlink exposure?
71 get owner of dir see if matches self or if root
72 call system(umount argv) etc.
76 static char * check_for_domain(char **);
79 static void mount_cifs_usage(void)
81 printf("\nUsage: %s <remotetarget> <dir> -o <options>\n", thisprogram);
82 printf("\nMount the remote target, specified as a UNC name,");
83 printf(" to a local directory.\n\nOptions:\n");
84 printf("\tuser=<arg>\n\tpass=<arg>\n\tdom=<arg>\n");
85 printf("\nLess commonly used options:");
86 printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,rw,ro,\n\tsep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,serverino,\n\tdirectio,mapchars,nomapchars");
87 printf("\n\nOptions not needed for servers supporting CIFS Unix extensions\n\t(e.g. most Samba versions):");
88 printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>");
89 printf("\n\nRarely used options:");
90 printf("\n\tport=<tcpport>,rsize=<size>,wsize=<size>,unc=<unc_name>,ip=<ip_address>,\n\tdev,nodev,nouser_xattr,netbiosname,hard,soft,intr,nointr,noacl");
91 printf("\n\nOptions are described in more detail in the manual page");
92 printf("\n\tman 8 mount.cifs\n");
93 printf("\nTo display the version number of the mount helper:");
94 printf("\n\t%s -V\n",thisprogram);
97 memset(mountpassword,0,64);
103 /* caller frees username if necessary */
104 static char * getusername(void) {
105 char *username = NULL;
106 struct passwd *password = getpwuid(getuid());
109 username = password->pw_name;
114 static char * parse_cifs_url(char * unc_name)
116 printf("\nMounting cifs URL not implemented yet. Attempt to mount %s\n",unc_name);
120 static int open_cred_file(char * file_name)
126 fs = fopen(file_name,"r");
129 line_buf = malloc(4096);
133 while(fgets(line_buf,4096,fs)) {
134 /* parse line from credential file */
136 /* eat leading white space */
137 for(i=0;i<4086;i++) {
138 if((line_buf[i] != ' ') && (line_buf[i] != '\t'))
140 /* if whitespace - skip past it */
142 if (strncasecmp("username",line_buf+i,8) == 0) {
143 temp_val = strchr(line_buf + i,'=');
145 /* go past equals sign */
147 for(length = 0;length<4087;length++) {
148 if(temp_val[length] == '\n')
152 printf("mount.cifs failed due to malformed username in credentials file");
153 memset(line_buf,0,4096);
155 memset(mountpassword,0,64);
160 user_name = calloc(1 + length,1);
161 /* BB adding free of user_name string before exit,
162 not really necessary but would be cleaner */
163 strncpy(user_name,temp_val, length);
166 } else if (strncasecmp("password",line_buf+i,8) == 0) {
167 temp_val = strchr(line_buf+i,'=');
169 /* go past equals sign */
171 for(length = 0;length<65;length++) {
172 if(temp_val[length] == '\n')
176 printf("mount.cifs failed: password in credentials file too long\n");
177 memset(line_buf,0, 4096);
179 memset(mountpassword,0,64);
183 if(mountpassword == NULL) {
184 mountpassword = calloc(65,1);
186 memset(mountpassword,0,64);
188 strncpy(mountpassword,temp_val,length);
193 } else if (strncasecmp("domain",line_buf+i,6) == 0) {
194 temp_val = strchr(line_buf+i,'=');
196 /* go past equals sign */
199 printf("\nDomain %s\n",temp_val);
200 for(length = 0;length<65;length++) {
201 if(temp_val[length] == '\n')
205 printf("mount.cifs failed: domain in credentials file too long\n");
207 memset(mountpassword,0,64);
211 if(domain_name == NULL) {
212 domain_name = calloc(65,1);
214 memset(domain_name,0,64);
216 strncpy(domain_name,temp_val,length);
226 memset(line_buf,0,4096);
232 static int get_password_from_file(int file_descript, char * filename)
238 if(mountpassword == NULL)
239 mountpassword = calloc(65,1);
241 memset(mountpassword, 0, 64);
243 if(filename != NULL) {
244 file_descript = open(filename, O_RDONLY);
245 if(file_descript < 0) {
246 printf("mount.cifs failed. %s attempting to open password file %s\n",
247 strerror(errno),filename);
251 /* else file already open and fd provided */
254 rc = read(file_descript,&c,1);
256 printf("mount.cifs failed. Error %s reading password file\n",strerror(errno));
257 memset(mountpassword,0,64);
259 close(file_descript);
262 if(mountpassword[0] == 0) {
264 printf("\nWarning: null password used since cifs password file empty");
267 } else /* read valid character */ {
268 if((c == 0) || (c == '\n')) {
271 mountpassword[i] = c;
274 if((i == 64) && (verboseflag)) {
275 printf("\nWarning: password longer than 64 characters specified in cifs password file");
278 if(filename != NULL) {
279 close(file_descript);
285 static int parse_options(char * options, int * filesys_flags)
288 char * percent_char = NULL;
290 char * next_keyword = NULL;
299 printf("parsing options: %s\n", options);
301 /* BB fixme check for separator override BB */
303 /* while ((data = strsep(&options, ",")) != NULL) { */
304 while(data != NULL) {
305 /* check if ends with trailing comma */
309 /* format is keyword=value,keyword2=value2,keyword3=value3 etc.) */
310 /* data = next keyword */
311 /* value = next value ie stuff after equal sign */
313 next_keyword = strchr(data,','); /* BB handle sep= */
315 /* temporarily null terminate end of keyword=value pair */
319 /* temporarily null terminate keyword to make keyword and value distinct */
320 if ((value = strchr(data, '=')) != NULL) {
325 if (strncmp(data, "users",5) == 0) {
326 if(!value || !*value) {
327 strncpy(data,",,,,,",5);
329 } else if (strncmp(data, "user_xattr",10) == 0) {
330 /* do nothing - need to skip so not parsed as user name */
331 } else if (strncmp(data, "user", 4) == 0) {
333 if (!value || !*value) {
334 if(data[4] == '\0') {
336 printf("\nskipping empty user mount parameter\n");
337 /* remove the parm since it would otherwise be confusing
338 to the kernel code which would think it was a real username */
344 printf("username specified with no parameter\n");
345 return 1; /* needs_arg; */
348 if (strnlen(value, 260) < 260) {
350 percent_char = strchr(value,'%');
353 if(mountpassword == NULL)
354 mountpassword = calloc(65,1);
357 printf("\nmount.cifs warning - password specified twice\n");
360 strncpy(mountpassword, percent_char,64);
361 /* remove password from username */
362 while(*percent_char != 0) {
368 /* this is only case in which the user
369 name buf is not malloc - so we have to
370 check for domain name embedded within
371 the user name here since the later
372 call to check_for_domain will not be
374 domain_name = check_for_domain(&value);
376 printf("username too long\n");
380 } else if (strncmp(data, "pass", 4) == 0) {
381 if (!value || !*value) {
383 printf("\npassword specified twice, ignoring second\n");
386 } else if (strnlen(value, 17) < 17) {
388 printf("\nmount.cifs warning - password specified twice\n");
391 printf("password too long\n");
394 } else if (strncmp(data, "ip", 2) == 0) {
395 if (!value || !*value) {
396 printf("target ip address argument missing");
397 } else if (strnlen(value, 35) < 35) {
399 printf("ip address %s override specified\n",value);
402 printf("ip address too long\n");
405 } else if ((strncmp(data, "unc", 3) == 0)
406 || (strncmp(data, "target", 6) == 0)
407 || (strncmp(data, "path", 4) == 0)) {
408 if (!value || !*value) {
409 printf("invalid path to network resource\n");
410 return 1; /* needs_arg; */
411 } else if(strnlen(value,5) < 5) {
412 printf("UNC name too short");
415 if (strnlen(value, 300) < 300) {
417 if (strncmp(value, "//", 2) == 0) {
419 printf("unc name specified twice, ignoring second\n");
422 } else if (strncmp(value, "\\\\", 2) != 0) {
423 printf("UNC Path does not begin with // or \\\\ \n");
427 printf("unc name specified twice, ignoring second\n");
432 printf("CIFS: UNC name too long\n");
435 } else if ((strncmp(data, "domain", 3) == 0)
436 || (strncmp(data, "workgroup", 5) == 0)) {
437 if (!value || !*value) {
438 printf("CIFS: invalid domain name\n");
439 return 1; /* needs_arg; */
441 if (strnlen(value, 65) < 65) {
444 printf("domain name too long\n");
447 } else if (strncmp(data, "cred", 4) == 0) {
448 if (value && *value) {
449 rc = open_cred_file(value);
451 printf("error %d opening credential file %s\n",rc, value);
455 printf("invalid credential file name specified\n");
458 } else if (strncmp(data, "uid", 3) == 0) {
459 if (value && *value) {
462 } else if (strncmp(data, "gid", 3) == 0) {
463 if (value && *value) {
466 /* fmask and dmask synonyms for people used to smbfs syntax */
467 } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) {
468 if (!value || !*value) {
469 printf ("Option '%s' requires a numerical argument\n", data);
473 if (value[0] != '0') {
474 printf ("WARNING: '%s' not expressed in octal.\n", data);
477 if (strcmp (data, "fmask") == 0) {
478 printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
479 data = "file_mode"; /* BB fix this */
481 } else if (strcmp(data, "dir_mode") == 0 || strcmp(data, "dmask")==0) {
482 if (!value || !*value) {
483 printf ("Option '%s' requires a numerical argument\n", data);
487 if (value[0] != '0') {
488 printf ("WARNING: '%s' not expressed in octal.\n", data);
491 if (strcmp (data, "dmask") == 0) {
492 printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
495 /* the following eight mount options should be
496 stripped out from what is passed into the kernel
497 since these eight options are best passed as the
498 mount flags rather than redundantly to the kernel
499 and could generate spurious warnings depending on the
500 level of the corresponding cifs vfs kernel code */
501 } else if (strncmp(data, "nosuid", 6) == 0) {
502 *filesys_flags |= MS_NOSUID;
503 } else if (strncmp(data, "suid", 4) == 0) {
504 *filesys_flags &= ~MS_NOSUID;
505 } else if (strncmp(data, "nodev", 5) == 0) {
506 *filesys_flags |= MS_NODEV;
507 } else if (strncmp(data, "dev", 3) == 0) {
508 *filesys_flags &= ~MS_NODEV;
509 } else if (strncmp(data, "noexec", 6) == 0) {
510 *filesys_flags |= MS_NOEXEC;
511 } else if (strncmp(data, "exec", 4) == 0) {
512 *filesys_flags &= ~MS_NOEXEC;
513 } else if (strncmp(data, "guest", 5) == 0) {
515 /* remove the parm since it would otherwise be logged by kern */
521 } else if (strncmp(data, "ro", 2) == 0) {
522 *filesys_flags |= MS_RDONLY;
523 } else if (strncmp(data, "rw", 2) == 0) {
524 *filesys_flags &= ~MS_RDONLY;
525 } else if (strncmp(data, "remount", 7) == 0) {
526 *filesys_flags |= MS_REMOUNT;
527 } /* else if (strnicmp(data, "port", 4) == 0) {
528 if (value && *value) {
530 simple_strtoul(value, &value, 0);
532 } else if (strnicmp(data, "rsize", 5) == 0) {
533 if (value && *value) {
535 simple_strtoul(value, &value, 0);
537 } else if (strnicmp(data, "wsize", 5) == 0) {
538 if (value && *value) {
540 simple_strtoul(value, &value, 0);
542 } else if (strnicmp(data, "version", 3) == 0) {
544 printf("CIFS: Unknown mount option %s\n",data);
545 } */ /* nothing to do on those four mount options above.
546 Just pass to kernel and ignore them here */
548 /* move to next option */
549 data = next_keyword+1;
551 /* put overwritten equals sign back */
557 /* put previous overwritten comma back */
559 *next_keyword = ','; /* BB handle sep= */
566 /* replace all (one or more) commas with double commas */
567 static void check_for_comma(char ** ppasswrd)
572 int number_of_commas = 0;
573 int len = strlen(*ppasswrd);
585 if(number_of_commas == 0)
587 if(number_of_commas > 64) {
588 /* would otherwise overflow the mount options buffer */
589 printf("\nInvalid password. Password contains too many commas.\n");
593 new_pass_buf = malloc(len+number_of_commas+1);
594 if(new_pass_buf == NULL)
597 for(i=0,j=0;i<len;i++,j++) {
598 new_pass_buf[j] = pass[i];
601 new_pass_buf[j] = pass[i];
604 new_pass_buf[len+number_of_commas] = 0;
607 *ppasswrd = new_pass_buf;
612 /* Usernames can not have backslash in them and we use
613 [BB check if usernames can have forward slash in them BB]
614 backslash as domain\user separator character
616 static char * check_for_domain(char **ppuser)
618 char * original_string;
628 original_string = *ppuser;
630 if (original_string == NULL)
633 original_len = strlen(original_string);
635 usernm = strchr(*ppuser,'/');
636 if (usernm == NULL) {
637 usernm = strchr(*ppuser,'\\');
643 printf("Domain name specified twice. Username probably malformed\n");
649 if (domainnm[0] != 0) {
652 printf("null domain\n");
654 len = strlen(domainnm);
655 /* reset domainm to new buffer, and copy
656 domain name into it */
657 domainnm = malloc(len+1);
661 strcpy(domainnm,*ppuser);
663 /* move_string(*ppuser, usernm+1) */
664 len = strlen(usernm+1);
666 if(len >= original_len) {
667 /* should not happen */
671 for(i=0;i<original_len;i++) {
673 original_string[i] = usernm[i+1];
674 else /* stuff with commas to remove last parm */
675 original_string[i] = ',';
678 /* BB add check for more than one slash?
686 /* Note that caller frees the returned buffer if necessary */
687 static char * parse_server(char ** punc_name)
689 char * unc_name = *punc_name;
690 int length = strnlen(unc_name,1024);
692 char * ipaddress_string = NULL;
693 struct hostent * host_entry = NULL;
694 struct in_addr server_ipaddr;
698 printf("mount error: UNC name too long");
701 if (strncasecmp("cifs://",unc_name,7) == 0)
702 return parse_cifs_url(unc_name+7);
703 if (strncasecmp("smb://",unc_name,6) == 0) {
704 return parse_cifs_url(unc_name+6);
708 /* BB add code to find DFS root here */
709 printf("\nMounting the DFS root for domain not implemented yet");
712 if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
713 /* check for nfs syntax ie server:share */
714 share = strchr(unc_name,':');
717 *punc_name = malloc(length+3);
719 strncpy((*punc_name)+2,unc_name,length);
720 unc_name = *punc_name;
721 unc_name[length+2] = 0;
722 goto continue_unc_parsing;
724 printf("mount error: improperly formatted UNC name.");
725 printf(" %s does not begin with \\\\ or //\n",unc_name);
729 continue_unc_parsing:
733 if ((share = strchr(unc_name, '/')) ||
734 (share = strchr(unc_name,'\\'))) {
735 *share = 0; /* temporarily terminate the string */
738 host_entry = gethostbyname(unc_name);
740 *(share - 1) = '/'; /* put the slash back */
743 printf("ip address specified explicitly\n");
746 if(host_entry == NULL) {
747 printf("mount error: could not find target server. TCP name %s not found ", unc_name);
748 printf(" rc = %d\n",rc);
751 /* BB should we pass an alternate version of the share name as Unicode */
752 /* BB what about ipv6? BB */
753 /* BB add retries with alternate servers in list */
755 memcpy(&server_ipaddr.s_addr, host_entry->h_addr, 4);
757 ipaddress_string = inet_ntoa(server_ipaddr);
758 if(ipaddress_string == NULL) {
759 printf("mount error: could not get valid ip address for target server\n");
762 return ipaddress_string;
765 /* BB add code to find DFS root (send null path on get DFS Referral to specified server here */
766 printf("Mounting the DFS root for a particular server not implemented yet\n");
773 static struct option longopts[] = {
774 { "all", 0, NULL, 'a' },
775 { "help",0, NULL, 'h' },
776 { "move",0, NULL, 'm' },
777 { "bind",0, NULL, 'b' },
778 { "read-only", 0, NULL, 'r' },
779 { "ro", 0, NULL, 'r' },
780 { "verbose", 0, NULL, 'v' },
781 { "version", 0, NULL, 'V' },
782 { "read-write", 0, NULL, 'w' },
783 { "rw", 0, NULL, 'w' },
784 { "options", 1, NULL, 'o' },
785 { "type", 1, NULL, 't' },
786 { "rsize",1, NULL, 'R' },
787 { "wsize",1, NULL, 'W' },
788 { "uid", 1, NULL, '1'},
789 { "gid", 1, NULL, '2'},
790 { "user",1,NULL,'u'},
791 { "username",1,NULL,'u'},
793 { "domain",1,NULL,'d'},
794 { "password",1,NULL,'p'},
795 { "pass",1,NULL,'p'},
796 { "credentials",1,NULL,'c'},
797 { "port",1,NULL,'P'},
798 /* { "uuid",1,NULL,'U'}, */ /* BB unimplemented */
802 int main(int argc, char ** argv)
805 int flags = MS_MANDLOCK; /* no need to set legacy MS_MGC_VAL */
806 char * orgoptions = NULL;
807 char * share_name = NULL;
808 char * ipaddr = NULL;
812 char * resolved_path;
822 int retry = 0; /* set when we have to retry mount with uppercase */
824 struct utsname sysinfo;
825 struct mntent mountent;
828 /* setlocale(LC_ALL, "");
829 bindtextdomain(PACKAGE, LOCALEDIR);
830 textdomain(PACKAGE); */
833 thisprogram = argv[0];
835 if(thisprogram == NULL)
836 thisprogram = "mount.cifs";
839 /* BB add workstation name and domain and pass down */
841 /* #ifdef _GNU_SOURCE
842 printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
845 share_name = argv[1];
846 mountpoint = argv[2];
848 /* add sharename in opts string as unc= parm */
850 while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsSU:vVwt:",
851 longopts, NULL)) != -1) {
853 /* No code to do the following options yet */
855 list_with_volumelabel = 1;
858 volumelabel = optarg;
878 orgoptions = strdup(optarg);
880 case 'r': /* mount readonly */
890 printf ("mount.cifs version: %s.%s%s\n",
891 MOUNT_CIFS_VERSION_MAJOR,
892 MOUNT_CIFS_VERSION_MINOR,
893 MOUNT_CIFS_VENDOR_SUFFIX);
895 memset(mountpassword,0,64);
902 rsize = atoi(optarg) ;
905 wsize = atoi(optarg);
918 domain_name = optarg; /* BB fix this - currently ignored */
922 if(mountpassword == NULL)
923 mountpassword = calloc(65,1);
926 strncpy(mountpassword,optarg,64);
930 get_password_from_file(0 /* stdin */,NULL);
935 printf("unknown mount option %c\n",c);
944 if (getenv("PASSWD")) {
945 if(mountpassword == NULL)
946 mountpassword = calloc(65,1);
948 strncpy(mountpassword,getenv("PASSWD"),64);
951 } else if (getenv("PASSWD_FD")) {
952 get_password_from_file(atoi(getenv("PASSWD_FD")),NULL);
953 } else if (getenv("PASSWD_FILE")) {
954 get_password_from_file(0, getenv("PASSWD_FILE"));
957 if (orgoptions && parse_options(orgoptions, &flags))
959 ipaddr = parse_server(&share_name);
960 if((ipaddr == NULL) && (got_ip == 0)) {
961 printf("No ip address specified and hostname not found\n");
965 /* BB save off path and pop after mount returns? */
966 resolved_path = malloc(PATH_MAX+1);
968 /* Note that if we can not canonicalize the name, we get
969 another chance to see if it is valid when we chdir to it */
970 if (realpath(mountpoint, resolved_path)) {
971 mountpoint = resolved_path;
974 if(chdir(mountpoint)) {
975 printf("mount error: can not change directory into mount target %s\n",mountpoint);
979 if(stat (".", &statbuf)) {
980 printf("mount error: mount point %s does not exist\n",mountpoint);
984 if (S_ISDIR(statbuf.st_mode) == 0) {
985 printf("mount error: mount point %s is not a directory\n",mountpoint);
989 if((getuid() != 0) && (geteuid() == 0)) {
990 if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) {
991 #ifndef CIFS_ALLOW_USR_SUID
992 /* Do not allow user mounts to control suid flag
993 for mount unless explicitly built that way */
994 flags |= MS_NOSUID | MS_NODEV;
997 printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n");
1003 user_name = getusername();
1007 if(got_password == 0) {
1008 mountpassword = getpass("Password: "); /* BB obsolete */
1011 /* FIXME launch daemon (handles dfs name resolution and credential change)
1012 remember to clear parms and overwrite password field before launching */
1015 optlen = strlen(orgoptions);
1020 optlen += strlen(share_name) + 4;
1022 optlen += strlen(user_name) + 6;
1024 optlen += strlen(ipaddr) + 4;
1026 optlen += strlen(mountpassword) + 6;
1027 options = malloc(optlen + 10 + 64 /* space for commas in password */ + 8 /* space for domain= , domain name itself was counted as part of the length username string above */);
1029 if(options == NULL) {
1030 printf("Could not allocate memory for mount options\n");
1036 strncat(options,"unc=",4);
1037 strcat(options,share_name);
1038 /* scan backwards and reverse direction of slash */
1039 temp = strrchr(options, '/');
1040 if(temp > options + 6)
1043 strncat(options,",ip=",4);
1044 strcat(options,ipaddr);
1048 /* check for syntax like user=domain\user */
1050 domain_name = check_for_domain(&user_name);
1051 strncat(options,",user=",6);
1052 strcat(options,user_name);
1056 /* extra length accounted for in option string above */
1057 strncat(options,",domain=",8);
1058 strcat(options,domain_name);
1062 /* Commas have to be doubled, or else they will
1063 look like the parameter separator */
1064 /* if(sep is not set)*/
1066 check_for_comma(&mountpassword);
1067 strncat(options,",pass=",6);
1068 strcat(options,mountpassword);
1071 strncat(options,",ver=",5);
1072 strcat(options,MOUNT_CIFS_VERSION_MAJOR);
1075 strcat(options,",");
1076 strcat(options,orgoptions);
1079 printf("\nmount.cifs kernel mount options %s \n",options);
1080 if(mount(share_name, mountpoint, "cifs", flags, options)) {
1081 /* remember to kill daemon on error */
1086 printf("mount failed but no error number set\n");
1089 printf("mount error: cifs filesystem not supported by the system\n");
1095 while (*tmp && !(((unsigned char)tmp[0]) & 0x80)) {
1096 *tmp = toupper((unsigned char)*tmp);
1100 printf("retrying with upper case share name\n");
1106 printf("mount error %d = %s\n",errno,strerror(errno));
1108 printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
1110 memset(mountpassword,0,64);
1114 pmntfile = setmntent(MOUNTED, "a+");
1116 mountent.mnt_fsname = share_name;
1117 mountent.mnt_dir = mountpoint;
1118 mountent.mnt_type = "cifs";
1119 mountent.mnt_opts = malloc(220);
1120 if(mountent.mnt_opts) {
1121 char * mount_user = getusername();
1122 memset(mountent.mnt_opts,0,200);
1123 if(flags & MS_RDONLY)
1124 strcat(mountent.mnt_opts,"ro");
1126 strcat(mountent.mnt_opts,"rw");
1127 if(flags & MS_MANDLOCK)
1128 strcat(mountent.mnt_opts,",mand");
1130 strcat(mountent.mnt_opts,",nomand");
1131 if(flags & MS_NOEXEC)
1132 strcat(mountent.mnt_opts,",noexec");
1133 if(flags & MS_NOSUID)
1134 strcat(mountent.mnt_opts,",nosuid");
1135 if(flags & MS_NODEV)
1136 strcat(mountent.mnt_opts,",nodev");
1137 if(flags & MS_SYNCHRONOUS)
1138 strcat(mountent.mnt_opts,",synch");
1141 strcat(mountent.mnt_opts,",user=");
1142 strcat(mountent.mnt_opts,mount_user);
1147 mountent.mnt_freq = 0;
1148 mountent.mnt_passno = 0;
1149 rc = addmntent(pmntfile,&mountent);
1150 endmntent(pmntfile);
1151 if(mountent.mnt_opts)
1152 free(mountent.mnt_opts);
1154 printf("could not update mount table\n");
1158 int len = strlen(mountpassword);
1159 memset(mountpassword,0,len);
1160 free(mountpassword);
1164 memset(options,0,optlen);
1169 memset(orgoptions,0,orgoptlen);
1173 free(resolved_path);
1176 if(free_share_name) {