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. */
29 #include <sys/types.h>
30 #include <sys/mount.h>
32 #include <sys/utsname.h>
33 #include <sys/socket.h>
34 #include <arpa/inet.h>
42 #define MOUNT_CIFS_VERSION_MAJOR "1"
43 #define MOUNT_CIFS_VERSION_MINOR "10"
45 #ifndef MOUNT_CIFS_VENDOR_SUFFIX
47 #include "include/version.h"
48 #ifdef SAMBA_VERSION_VENDOR_SUFFIX
49 #define MOUNT_CIFS_VENDOR_SUFFIX "-"SAMBA_VERSION_OFFICIAL_STRING"-"SAMBA_VERSION_VENDOR_SUFFIX
51 #define MOUNT_CIFS_VENDOR_SUFFIX "-"SAMBA_VERSION_OFFICIAL_STRING
52 #endif /* SAMBA_VERSION_OFFICIAL_STRING and SAMBA_VERSION_VENDOR_SUFFIX */
54 #define MOUNT_CIFS_VENDOR_SUFFIX ""
55 #endif /* _SAMBA_BUILD_ */
56 #endif /* MOUNT_CIFS_VENDOR_SUFFIX */
62 #define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr)))
64 const char *thisprogram;
66 static int got_password = 0;
67 static int got_user = 0;
68 static int got_domain = 0;
69 static int got_ip = 0;
70 static int got_unc = 0;
71 static int got_uid = 0;
72 static int got_gid = 0;
73 static int free_share_name = 0;
74 static char * user_name = NULL;
75 static char * mountpassword = NULL;
76 char * domain_name = NULL;
82 open nofollow - avoid symlink exposure?
83 get owner of dir see if matches self or if root
84 call system(umount argv) etc.
88 static char * check_for_domain(char **);
91 static void mount_cifs_usage(void)
93 printf("\nUsage: %s <remotetarget> <dir> -o <options>\n", thisprogram);
94 printf("\nMount the remote target, specified as a UNC name,");
95 printf(" to a local directory.\n\nOptions:\n");
96 printf("\tuser=<arg>\n\tpass=<arg>\n\tdom=<arg>\n");
97 printf("\nLess commonly used options:");
98 printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,rw,ro,");
99 printf("\n\tsep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,serverino,");
100 printf("\n\tdirectio,mapchars,nomapchars,nolock,servernetbiosname=<SRV_RFC1001NAME>");
101 printf("\n\nOptions not needed for servers supporting CIFS Unix extensions");
102 printf("\n\t(e.g. unneeded for mounts to most Samba versions):");
103 printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>,sfu");
104 printf("\n\nRarely used options:");
105 printf("\n\tport=<tcpport>,rsize=<size>,wsize=<size>,unc=<unc_name>,ip=<ip_address>,");
106 printf("\n\tdev,nodev,nouser_xattr,netbiosname=<OUR_RFC1001NAME>,hard,soft,intr,");
107 printf("\n\tnointr,ignorecase,noposixpaths,noacl");
108 printf("\n\nOptions are described in more detail in the manual page");
109 printf("\n\tman 8 mount.cifs\n");
110 printf("\nTo display the version number of the mount helper:");
111 printf("\n\t%s -V\n",thisprogram);
114 memset(mountpassword,0,64);
120 /* caller frees username if necessary */
121 static char * getusername(void) {
122 char *username = NULL;
123 struct passwd *password = getpwuid(getuid());
126 username = password->pw_name;
131 static char * parse_cifs_url(char * unc_name)
133 printf("\nMounting cifs URL not implemented yet. Attempt to mount %s\n",unc_name);
137 static int open_cred_file(char * file_name)
143 fs = fopen(file_name,"r");
146 line_buf = malloc(4096);
147 if(line_buf == NULL) {
152 while(fgets(line_buf,4096,fs)) {
153 /* parse line from credential file */
155 /* eat leading white space */
156 for(i=0;i<4086;i++) {
157 if((line_buf[i] != ' ') && (line_buf[i] != '\t'))
159 /* if whitespace - skip past it */
161 if (strncasecmp("username",line_buf+i,8) == 0) {
162 temp_val = strchr(line_buf + i,'=');
164 /* go past equals sign */
166 for(length = 0;length<4087;length++) {
167 if(temp_val[length] == '\n')
171 printf("mount.cifs failed due to malformed username in credentials file");
172 memset(line_buf,0,4096);
174 memset(mountpassword,0,64);
179 user_name = calloc(1 + length,1);
180 /* BB adding free of user_name string before exit,
181 not really necessary but would be cleaner */
182 strncpy(user_name,temp_val, length);
185 } else if (strncasecmp("password",line_buf+i,8) == 0) {
186 temp_val = strchr(line_buf+i,'=');
188 /* go past equals sign */
190 for(length = 0;length<65;length++) {
191 if(temp_val[length] == '\n')
195 printf("mount.cifs failed: password in credentials file too long\n");
196 memset(line_buf,0, 4096);
198 memset(mountpassword,0,64);
202 if(mountpassword == NULL) {
203 mountpassword = calloc(65,1);
205 memset(mountpassword,0,64);
207 strncpy(mountpassword,temp_val,length);
212 } else if (strncasecmp("domain",line_buf+i,6) == 0) {
213 temp_val = strchr(line_buf+i,'=');
215 /* go past equals sign */
218 printf("\nDomain %s\n",temp_val);
219 for(length = 0;length<65;length++) {
220 if(temp_val[length] == '\n')
224 printf("mount.cifs failed: domain in credentials file too long\n");
226 memset(mountpassword,0,64);
230 if(domain_name == NULL) {
231 domain_name = calloc(65,1);
233 memset(domain_name,0,64);
235 strncpy(domain_name,temp_val,length);
245 memset(line_buf,0,4096);
251 static int get_password_from_file(int file_descript, char * filename)
257 if(mountpassword == NULL)
258 mountpassword = calloc(65,1);
260 memset(mountpassword, 0, 64);
262 if(filename != NULL) {
263 file_descript = open(filename, O_RDONLY);
264 if(file_descript < 0) {
265 printf("mount.cifs failed. %s attempting to open password file %s\n",
266 strerror(errno),filename);
270 /* else file already open and fd provided */
273 rc = read(file_descript,&c,1);
275 printf("mount.cifs failed. Error %s reading password file\n",strerror(errno));
276 memset(mountpassword,0,64);
278 close(file_descript);
281 if(mountpassword[0] == 0) {
283 printf("\nWarning: null password used since cifs password file empty");
286 } else /* read valid character */ {
287 if((c == 0) || (c == '\n')) {
290 mountpassword[i] = c;
293 if((i == 64) && (verboseflag)) {
294 printf("\nWarning: password longer than 64 characters specified in cifs password file");
297 if(filename != NULL) {
298 close(file_descript);
304 static int parse_options(char ** optionsp, int * filesys_flags)
307 char * percent_char = NULL;
309 char * next_keyword = NULL;
315 if (!optionsp || !*optionsp)
320 printf("parsing options: %s\n", data);
322 /* BB fixme check for separator override BB */
324 /* while ((data = strsep(&options, ",")) != NULL) { */
325 while(data != NULL) {
326 /* check if ends with trailing comma */
330 /* format is keyword=value,keyword2=value2,keyword3=value3 etc.) */
331 /* data = next keyword */
332 /* value = next value ie stuff after equal sign */
334 next_keyword = strchr(data,','); /* BB handle sep= */
336 /* temporarily null terminate end of keyword=value pair */
340 /* temporarily null terminate keyword to make keyword and value distinct */
341 if ((value = strchr(data, '=')) != NULL) {
346 if (strncmp(data, "users",5) == 0) {
347 if(!value || !*value) {
350 } else if (strncmp(data, "user_xattr",10) == 0) {
351 /* do nothing - need to skip so not parsed as user name */
352 } else if (strncmp(data, "user", 4) == 0) {
354 if (!value || !*value) {
355 if(data[4] == '\0') {
357 printf("\nskipping empty user mount parameter\n");
358 /* remove the parm since it would otherwise be confusing
359 to the kernel code which would think it was a real username */
362 printf("username specified with no parameter\n");
363 return 1; /* needs_arg; */
366 if (strnlen(value, 260) < 260) {
368 percent_char = strchr(value,'%');
371 if(mountpassword == NULL)
372 mountpassword = calloc(65,1);
375 printf("\nmount.cifs warning - password specified twice\n");
378 strncpy(mountpassword, percent_char,64);
379 /* remove password from username */
380 while(*percent_char != 0) {
386 /* this is only case in which the user
387 name buf is not malloc - so we have to
388 check for domain name embedded within
389 the user name here since the later
390 call to check_for_domain will not be
392 domain_name = check_for_domain(&value);
394 printf("username too long\n");
398 } else if (strncmp(data, "pass", 4) == 0) {
399 if (!value || !*value) {
401 printf("\npassword specified twice, ignoring second\n");
404 } else if (strnlen(value, 17) < 17) {
406 printf("\nmount.cifs warning - password specified twice\n");
409 printf("password too long\n");
412 } else if (strncmp(data, "ip", 2) == 0) {
413 if (!value || !*value) {
414 printf("target ip address argument missing");
415 } else if (strnlen(value, 35) < 35) {
417 printf("ip address %s override specified\n",value);
420 printf("ip address too long\n");
423 } else if ((strncmp(data, "unc", 3) == 0)
424 || (strncmp(data, "target", 6) == 0)
425 || (strncmp(data, "path", 4) == 0)) {
426 if (!value || !*value) {
427 printf("invalid path to network resource\n");
428 return 1; /* needs_arg; */
429 } else if(strnlen(value,5) < 5) {
430 printf("UNC name too short");
433 if (strnlen(value, 300) < 300) {
435 if (strncmp(value, "//", 2) == 0) {
437 printf("unc name specified twice, ignoring second\n");
440 } else if (strncmp(value, "\\\\", 2) != 0) {
441 printf("UNC Path does not begin with // or \\\\ \n");
445 printf("unc name specified twice, ignoring second\n");
450 printf("CIFS: UNC name too long\n");
453 } else if ((strncmp(data, "domain", 3) == 0)
454 || (strncmp(data, "workgroup", 5) == 0)) {
455 if (!value || !*value) {
456 printf("CIFS: invalid domain name\n");
457 return 1; /* needs_arg; */
459 if (strnlen(value, 65) < 65) {
462 printf("domain name too long\n");
465 } else if (strncmp(data, "cred", 4) == 0) {
466 if (value && *value) {
467 rc = open_cred_file(value);
469 printf("error %d opening credential file %s\n",rc, value);
473 printf("invalid credential file name specified\n");
476 } else if (strncmp(data, "uid", 3) == 0) {
477 if (value && *value) {
479 if (!isdigit(*value)) {
481 static char temp[32];
483 if (!(pw = getpwnam(value))) {
484 printf("bad user name \"%s\"\n", value);
487 sprintf(temp, "%u", pw->pw_uid);
492 } else if (strncmp(data, "gid", 3) == 0) {
493 if (value && *value) {
495 if (!isdigit(*value)) {
497 static char temp[32];
499 if (!(gr = getgrnam(value))) {
500 printf("bad group name \"%s\"\n", value);
503 sprintf(temp, "%u", gr->gr_gid);
508 /* fmask and dmask synonyms for people used to smbfs syntax */
509 } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) {
510 if (!value || !*value) {
511 printf ("Option '%s' requires a numerical argument\n", data);
515 if (value[0] != '0') {
516 printf ("WARNING: '%s' not expressed in octal.\n", data);
519 if (strcmp (data, "fmask") == 0) {
520 printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
521 data = "file_mode"; /* BB fix this */
523 } else if (strcmp(data, "dir_mode") == 0 || strcmp(data, "dmask")==0) {
524 if (!value || !*value) {
525 printf ("Option '%s' requires a numerical argument\n", data);
529 if (value[0] != '0') {
530 printf ("WARNING: '%s' not expressed in octal.\n", data);
533 if (strcmp (data, "dmask") == 0) {
534 printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
537 /* the following eight mount options should be
538 stripped out from what is passed into the kernel
539 since these eight options are best passed as the
540 mount flags rather than redundantly to the kernel
541 and could generate spurious warnings depending on the
542 level of the corresponding cifs vfs kernel code */
543 } else if (strncmp(data, "nosuid", 6) == 0) {
544 *filesys_flags |= MS_NOSUID;
545 } else if (strncmp(data, "suid", 4) == 0) {
546 *filesys_flags &= ~MS_NOSUID;
547 } else if (strncmp(data, "nodev", 5) == 0) {
548 *filesys_flags |= MS_NODEV;
549 } else if ((strncmp(data, "nobrl", 5) == 0) ||
550 (strncmp(data, "nolock", 6) == 0)) {
551 *filesys_flags &= ~MS_MANDLOCK;
552 } else if (strncmp(data, "dev", 3) == 0) {
553 *filesys_flags &= ~MS_NODEV;
554 } else if (strncmp(data, "noexec", 6) == 0) {
555 *filesys_flags |= MS_NOEXEC;
556 } else if (strncmp(data, "exec", 4) == 0) {
557 *filesys_flags &= ~MS_NOEXEC;
558 } else if (strncmp(data, "guest", 5) == 0) {
560 /* remove the parm since it would otherwise be logged by kern */
562 } else if (strncmp(data, "ro", 2) == 0) {
563 *filesys_flags |= MS_RDONLY;
564 } else if (strncmp(data, "rw", 2) == 0) {
565 *filesys_flags &= ~MS_RDONLY;
566 } else if (strncmp(data, "remount", 7) == 0) {
567 *filesys_flags |= MS_REMOUNT;
568 } /* else if (strnicmp(data, "port", 4) == 0) {
569 if (value && *value) {
571 simple_strtoul(value, &value, 0);
573 } else if (strnicmp(data, "rsize", 5) == 0) {
574 if (value && *value) {
576 simple_strtoul(value, &value, 0);
578 } else if (strnicmp(data, "wsize", 5) == 0) {
579 if (value && *value) {
581 simple_strtoul(value, &value, 0);
583 } else if (strnicmp(data, "version", 3) == 0) {
585 printf("CIFS: Unknown mount option %s\n",data);
586 } */ /* nothing to do on those four mount options above.
587 Just pass to kernel and ignore them here */
589 /* Copy (possibly modified) option to out */
590 word_len = strlen(data);
592 word_len += 1 + strlen(value);
594 out = realloc(out, out_len + word_len + 2);
601 out[out_len++] = ',';
603 sprintf(out + out_len, "%s=%s", data, value);
605 sprintf(out + out_len, "%s", data);
606 out_len = strlen(out);
615 /* replace all (one or more) commas with double commas */
616 static void check_for_comma(char ** ppasswrd)
621 int number_of_commas = 0;
636 if(number_of_commas == 0)
638 if(number_of_commas > 64) {
639 /* would otherwise overflow the mount options buffer */
640 printf("\nInvalid password. Password contains too many commas.\n");
644 new_pass_buf = malloc(len+number_of_commas+1);
645 if(new_pass_buf == NULL)
648 for(i=0,j=0;i<len;i++,j++) {
649 new_pass_buf[j] = pass[i];
652 new_pass_buf[j] = pass[i];
655 new_pass_buf[len+number_of_commas] = 0;
658 *ppasswrd = new_pass_buf;
663 /* Usernames can not have backslash in them and we use
664 [BB check if usernames can have forward slash in them BB]
665 backslash as domain\user separator character
667 static char * check_for_domain(char **ppuser)
669 char * original_string;
679 original_string = *ppuser;
681 if (original_string == NULL)
684 original_len = strlen(original_string);
686 usernm = strchr(*ppuser,'/');
687 if (usernm == NULL) {
688 usernm = strchr(*ppuser,'\\');
694 printf("Domain name specified twice. Username probably malformed\n");
700 if (domainnm[0] != 0) {
703 printf("null domain\n");
705 len = strlen(domainnm);
706 /* reset domainm to new buffer, and copy
707 domain name into it */
708 domainnm = malloc(len+1);
712 strcpy(domainnm,*ppuser);
714 /* move_string(*ppuser, usernm+1) */
715 len = strlen(usernm+1);
717 if(len >= original_len) {
718 /* should not happen */
722 for(i=0;i<original_len;i++) {
724 original_string[i] = usernm[i+1];
725 else /* stuff with commas to remove last parm */
726 original_string[i] = ',';
729 /* BB add check for more than one slash?
737 /* Note that caller frees the returned buffer if necessary */
738 static char * parse_server(char ** punc_name)
740 char * unc_name = *punc_name;
741 int length = strnlen(unc_name,1024);
743 char * ipaddress_string = NULL;
744 struct hostent * host_entry = NULL;
745 struct in_addr server_ipaddr;
748 printf("mount error: UNC name too long");
751 if (strncasecmp("cifs://",unc_name,7) == 0)
752 return parse_cifs_url(unc_name+7);
753 if (strncasecmp("smb://",unc_name,6) == 0) {
754 return parse_cifs_url(unc_name+6);
758 /* BB add code to find DFS root here */
759 printf("\nMounting the DFS root for domain not implemented yet");
762 if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
763 /* check for nfs syntax ie server:share */
764 share = strchr(unc_name,':');
767 *punc_name = malloc(length+3);
768 if(*punc_name == NULL) {
769 /* put the original string back if
771 *punc_name = unc_name;
776 strncpy((*punc_name)+2,unc_name,length);
777 unc_name = *punc_name;
778 unc_name[length+2] = 0;
779 goto continue_unc_parsing;
781 printf("mount error: improperly formatted UNC name.");
782 printf(" %s does not begin with \\\\ or //\n",unc_name);
786 continue_unc_parsing:
790 if ((share = strchr(unc_name, '/')) ||
791 (share = strchr(unc_name,'\\'))) {
792 *share = 0; /* temporarily terminate the string */
795 host_entry = gethostbyname(unc_name);
797 *(share - 1) = '/'; /* put the slash back */
800 printf("ip address specified explicitly\n");
803 if(host_entry == NULL) {
804 printf("mount error: could not find target server. TCP name %s not found\n", unc_name);
807 /* BB should we pass an alternate version of the share name as Unicode */
808 /* BB what about ipv6? BB */
809 /* BB add retries with alternate servers in list */
811 memcpy(&server_ipaddr.s_addr, host_entry->h_addr, 4);
813 ipaddress_string = inet_ntoa(server_ipaddr);
814 if(ipaddress_string == NULL) {
815 printf("mount error: could not get valid ip address for target server\n");
818 return ipaddress_string;
821 /* BB add code to find DFS root (send null path on get DFS Referral to specified server here */
822 printf("Mounting the DFS root for a particular server not implemented yet\n");
829 static struct option longopts[] = {
830 { "all", 0, NULL, 'a' },
831 { "help",0, NULL, 'h' },
832 { "move",0, NULL, 'm' },
833 { "bind",0, NULL, 'b' },
834 { "read-only", 0, NULL, 'r' },
835 { "ro", 0, NULL, 'r' },
836 { "verbose", 0, NULL, 'v' },
837 { "version", 0, NULL, 'V' },
838 { "read-write", 0, NULL, 'w' },
839 { "rw", 0, NULL, 'w' },
840 { "options", 1, NULL, 'o' },
841 { "type", 1, NULL, 't' },
842 { "rsize",1, NULL, 'R' },
843 { "wsize",1, NULL, 'W' },
844 { "uid", 1, NULL, '1'},
845 { "gid", 1, NULL, '2'},
846 { "user",1,NULL,'u'},
847 { "username",1,NULL,'u'},
849 { "domain",1,NULL,'d'},
850 { "password",1,NULL,'p'},
851 { "pass",1,NULL,'p'},
852 { "credentials",1,NULL,'c'},
853 { "port",1,NULL,'P'},
854 /* { "uuid",1,NULL,'U'}, */ /* BB unimplemented */
858 int main(int argc, char ** argv)
861 int flags = MS_MANDLOCK; /* no need to set legacy MS_MGC_VAL */
862 char * orgoptions = NULL;
863 char * share_name = NULL;
864 char * ipaddr = NULL;
866 char * mountpoint = NULL;
868 char * resolved_path;
878 int retry = 0; /* set when we have to retry mount with uppercase */
880 struct utsname sysinfo;
881 struct mntent mountent;
884 /* setlocale(LC_ALL, "");
885 bindtextdomain(PACKAGE, LOCALEDIR);
886 textdomain(PACKAGE); */
889 thisprogram = argv[0];
891 if(thisprogram == NULL)
892 thisprogram = "mount.cifs";
895 /* BB add workstation name and domain and pass down */
897 /* #ifdef _GNU_SOURCE
898 printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
901 share_name = argv[1];
902 mountpoint = argv[2];
905 /* add sharename in opts string as unc= parm */
907 while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsSU:vVwt:",
908 longopts, NULL)) != -1) {
910 /* No code to do the following options yet */
912 list_with_volumelabel = 1;
915 volumelabel = optarg;
935 orgoptions = strdup(optarg);
937 case 'r': /* mount readonly */
947 printf ("mount.cifs version: %s.%s%s\n",
948 MOUNT_CIFS_VERSION_MAJOR,
949 MOUNT_CIFS_VERSION_MINOR,
950 MOUNT_CIFS_VENDOR_SUFFIX);
952 memset(mountpassword,0,64);
959 rsize = atoi(optarg) ;
962 wsize = atoi(optarg);
965 if (isdigit(*optarg)) {
968 uid = strtoul(optarg, &ep, 10);
970 printf("bad uid value \"%s\"\n", optarg);
976 if (!(pw = getpwnam(optarg))) {
977 printf("bad user name \"%s\"\n", optarg);
985 if (isdigit(*optarg)) {
988 gid = strtoul(optarg, &ep, 10);
990 printf("bad gid value \"%s\"\n", optarg);
996 if (!(gr = getgrnam(optarg))) {
997 printf("bad user name \"%s\"\n", optarg);
1009 domain_name = optarg; /* BB fix this - currently ignored */
1013 if(mountpassword == NULL)
1014 mountpassword = calloc(65,1);
1017 strncpy(mountpassword,optarg,64);
1021 get_password_from_file(0 /* stdin */,NULL);
1026 printf("unknown mount option %c\n",c);
1032 if((argc < 3) || (share_name == NULL) || (mountpoint == NULL)) {
1037 if (getenv("PASSWD")) {
1038 if(mountpassword == NULL)
1039 mountpassword = calloc(65,1);
1041 strncpy(mountpassword,getenv("PASSWD"),64);
1044 } else if (getenv("PASSWD_FD")) {
1045 get_password_from_file(atoi(getenv("PASSWD_FD")),NULL);
1046 } else if (getenv("PASSWD_FILE")) {
1047 get_password_from_file(0, getenv("PASSWD_FILE"));
1050 if (orgoptions && parse_options(&orgoptions, &flags))
1052 ipaddr = parse_server(&share_name);
1053 if((ipaddr == NULL) && (got_ip == 0)) {
1054 printf("No ip address specified and hostname not found\n");
1058 /* BB save off path and pop after mount returns? */
1059 resolved_path = malloc(PATH_MAX+1);
1061 /* Note that if we can not canonicalize the name, we get
1062 another chance to see if it is valid when we chdir to it */
1063 if (realpath(mountpoint, resolved_path)) {
1064 mountpoint = resolved_path;
1067 if(chdir(mountpoint)) {
1068 printf("mount error: can not change directory into mount target %s\n",mountpoint);
1072 if(stat (".", &statbuf)) {
1073 printf("mount error: mount point %s does not exist\n",mountpoint);
1077 if (S_ISDIR(statbuf.st_mode) == 0) {
1078 printf("mount error: mount point %s is not a directory\n",mountpoint);
1082 if((getuid() != 0) && (geteuid() == 0)) {
1083 if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) {
1084 #ifndef CIFS_ALLOW_USR_SUID
1085 /* Do not allow user mounts to control suid flag
1086 for mount unless explicitly built that way */
1087 flags |= MS_NOSUID | MS_NODEV;
1090 printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n");
1096 user_name = getusername();
1100 if(got_password == 0) {
1101 mountpassword = getpass("Password: "); /* BB obsolete */
1104 /* FIXME launch daemon (handles dfs name resolution and credential change)
1105 remember to clear parms and overwrite password field before launching */
1108 optlen = strlen(orgoptions);
1113 optlen += strlen(share_name) + 4;
1115 printf("No server share name specified\n");
1118 optlen += strlen(user_name) + 6;
1120 optlen += strlen(ipaddr) + 4;
1122 optlen += strlen(mountpassword) + 6;
1123 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 */);
1125 if(options == NULL) {
1126 printf("Could not allocate memory for mount options\n");
1132 strncat(options,"unc=",4);
1133 strcat(options,share_name);
1134 /* scan backwards and reverse direction of slash */
1135 temp = strrchr(options, '/');
1136 if(temp > options + 6)
1139 strncat(options,",ip=",4);
1140 strcat(options,ipaddr);
1144 /* check for syntax like user=domain\user */
1146 domain_name = check_for_domain(&user_name);
1147 strncat(options,",user=",6);
1148 strcat(options,user_name);
1152 /* extra length accounted for in option string above */
1153 strncat(options,",domain=",8);
1154 strcat(options,domain_name);
1158 /* Commas have to be doubled, or else they will
1159 look like the parameter separator */
1160 /* if(sep is not set)*/
1162 check_for_comma(&mountpassword);
1163 strncat(options,",pass=",6);
1164 strcat(options,mountpassword);
1167 strncat(options,",ver=",5);
1168 strcat(options,MOUNT_CIFS_VERSION_MAJOR);
1171 strcat(options,",");
1172 strcat(options,orgoptions);
1175 printf("\nmount.cifs kernel mount options %s \n",options);
1176 if(mount(share_name, mountpoint, "cifs", flags, options)) {
1177 /* remember to kill daemon on error */
1182 printf("mount failed but no error number set\n");
1185 printf("mount error: cifs filesystem not supported by the system\n");
1191 while (*tmp && !(((unsigned char)tmp[0]) & 0x80)) {
1192 *tmp = toupper((unsigned char)*tmp);
1196 printf("retrying with upper case share name\n");
1202 printf("mount error %d = %s\n",errno,strerror(errno));
1204 printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
1206 memset(mountpassword,0,64);
1210 pmntfile = setmntent(MOUNTED, "a+");
1212 mountent.mnt_fsname = share_name;
1213 mountent.mnt_dir = mountpoint;
1214 mountent.mnt_type = CONST_DISCARD(char *,"cifs");
1215 mountent.mnt_opts = malloc(220);
1216 if(mountent.mnt_opts) {
1217 char * mount_user = getusername();
1218 memset(mountent.mnt_opts,0,200);
1219 if(flags & MS_RDONLY)
1220 strcat(mountent.mnt_opts,"ro");
1222 strcat(mountent.mnt_opts,"rw");
1223 if(flags & MS_MANDLOCK)
1224 strcat(mountent.mnt_opts,",mand");
1225 if(flags & MS_NOEXEC)
1226 strcat(mountent.mnt_opts,",noexec");
1227 if(flags & MS_NOSUID)
1228 strcat(mountent.mnt_opts,",nosuid");
1229 if(flags & MS_NODEV)
1230 strcat(mountent.mnt_opts,",nodev");
1231 if(flags & MS_SYNCHRONOUS)
1232 strcat(mountent.mnt_opts,",synch");
1235 strcat(mountent.mnt_opts,",user=");
1236 strcat(mountent.mnt_opts,mount_user);
1241 mountent.mnt_freq = 0;
1242 mountent.mnt_passno = 0;
1243 rc = addmntent(pmntfile,&mountent);
1244 endmntent(pmntfile);
1245 if(mountent.mnt_opts)
1246 free(mountent.mnt_opts);
1248 printf("could not update mount table\n");
1252 int len = strlen(mountpassword);
1253 memset(mountpassword,0,len);
1254 free(mountpassword);
1258 memset(options,0,optlen);
1263 memset(orgoptions,0,orgoptlen);
1267 free(resolved_path);
1270 if(free_share_name) {