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 */
66 #define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr)))
68 const char *thisprogram;
70 static int got_password = 0;
71 static int got_user = 0;
72 static int got_domain = 0;
73 static int got_ip = 0;
74 static int got_unc = 0;
75 static int got_uid = 0;
76 static int got_gid = 0;
77 static int free_share_name = 0;
78 static char * user_name = NULL;
79 static char * mountpassword = NULL;
80 char * domain_name = NULL;
86 open nofollow - avoid symlink exposure?
87 get owner of dir see if matches self or if root
88 call system(umount argv) etc.
92 static char * check_for_domain(char **);
95 static void mount_cifs_usage(void)
97 printf("\nUsage: %s <remotetarget> <dir> -o <options>\n", thisprogram);
98 printf("\nMount the remote target, specified as a UNC name,");
99 printf(" to a local directory.\n\nOptions:\n");
100 printf("\tuser=<arg>\n\tpass=<arg>\n\tdom=<arg>\n");
101 printf("\nLess commonly used options:");
102 printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,rw,ro,");
103 printf("\n\tsep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,serverino,");
104 printf("\n\tdirectio,mapchars,nomapchars,nolock,servernetbiosname=<SRV_RFC1001NAME>");
105 printf("\n\nOptions not needed for servers supporting CIFS Unix extensions");
106 printf("\n\t(e.g. unneeded for mounts to most Samba versions):");
107 printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>,sfu");
108 printf("\n\nRarely used options:");
109 printf("\n\tport=<tcpport>,rsize=<size>,wsize=<size>,unc=<unc_name>,ip=<ip_address>,");
110 printf("\n\tdev,nodev,nouser_xattr,netbiosname=<OUR_RFC1001NAME>,hard,soft,intr,");
111 printf("\n\tnointr,ignorecase,noposixpaths,noacl");
112 printf("\n\nOptions are described in more detail in the manual page");
113 printf("\n\tman 8 mount.cifs\n");
114 printf("\nTo display the version number of the mount helper:");
115 printf("\n\t%s -V\n",thisprogram);
118 memset(mountpassword,0,64);
124 /* caller frees username if necessary */
125 static char * getusername(void) {
126 char *username = NULL;
127 struct passwd *password = getpwuid(getuid());
130 username = password->pw_name;
135 static char * parse_cifs_url(char * unc_name)
137 printf("\nMounting cifs URL not implemented yet. Attempt to mount %s\n",unc_name);
141 static int open_cred_file(char * file_name)
147 fs = fopen(file_name,"r");
150 line_buf = (char *)malloc(4096);
151 if(line_buf == NULL) {
156 while(fgets(line_buf,4096,fs)) {
157 /* parse line from credential file */
159 /* eat leading white space */
160 for(i=0;i<4086;i++) {
161 if((line_buf[i] != ' ') && (line_buf[i] != '\t'))
163 /* if whitespace - skip past it */
165 if (strncasecmp("username",line_buf+i,8) == 0) {
166 temp_val = strchr(line_buf + i,'=');
168 /* go past equals sign */
170 for(length = 0;length<4087;length++) {
171 if(temp_val[length] == '\n')
175 printf("mount.cifs failed due to malformed username in credentials file");
176 memset(line_buf,0,4096);
178 memset(mountpassword,0,64);
183 user_name = (char *)calloc(1 + length,1);
184 /* BB adding free of user_name string before exit,
185 not really necessary but would be cleaner */
186 strncpy(user_name,temp_val, length);
189 } else if (strncasecmp("password",line_buf+i,8) == 0) {
190 temp_val = strchr(line_buf+i,'=');
192 /* go past equals sign */
194 for(length = 0;length<65;length++) {
195 if(temp_val[length] == '\n')
199 printf("mount.cifs failed: password in credentials file too long\n");
200 memset(line_buf,0, 4096);
202 memset(mountpassword,0,64);
206 if(mountpassword == NULL) {
207 mountpassword = (char *)calloc(65,1);
209 memset(mountpassword,0,64);
211 strncpy(mountpassword,temp_val,length);
216 } else if (strncasecmp("domain",line_buf+i,6) == 0) {
217 temp_val = strchr(line_buf+i,'=');
219 /* go past equals sign */
222 printf("\nDomain %s\n",temp_val);
223 for(length = 0;length<65;length++) {
224 if(temp_val[length] == '\n')
228 printf("mount.cifs failed: domain in credentials file too long\n");
230 memset(mountpassword,0,64);
234 if(domain_name == NULL) {
235 domain_name = (char *)calloc(65,1);
237 memset(domain_name,0,64);
239 strncpy(domain_name,temp_val,length);
249 memset(line_buf,0,4096);
255 static int get_password_from_file(int file_descript, char * filename)
261 if(mountpassword == NULL)
262 mountpassword = (char *)calloc(65,1);
264 memset(mountpassword, 0, 64);
266 if (mountpassword == NULL) {
267 printf("malloc failed\n");
271 if(filename != NULL) {
272 file_descript = open(filename, O_RDONLY);
273 if(file_descript < 0) {
274 printf("mount.cifs failed. %s attempting to open password file %s\n",
275 strerror(errno),filename);
279 /* else file already open and fd provided */
282 rc = read(file_descript,&c,1);
284 printf("mount.cifs failed. Error %s reading password file\n",strerror(errno));
285 memset(mountpassword,0,64);
287 close(file_descript);
290 if(mountpassword[0] == 0) {
292 printf("\nWarning: null password used since cifs password file empty");
295 } else /* read valid character */ {
296 if((c == 0) || (c == '\n')) {
299 mountpassword[i] = c;
302 if((i == 64) && (verboseflag)) {
303 printf("\nWarning: password longer than 64 characters specified in cifs password file");
306 if(filename != NULL) {
307 close(file_descript);
313 static int parse_options(char ** optionsp, int * filesys_flags)
316 char * percent_char = NULL;
318 char * next_keyword = NULL;
324 if (!optionsp || !*optionsp)
329 printf("parsing options: %s\n", data);
331 /* BB fixme check for separator override BB */
333 /* while ((data = strsep(&options, ",")) != NULL) { */
334 while(data != NULL) {
335 /* check if ends with trailing comma */
339 /* format is keyword=value,keyword2=value2,keyword3=value3 etc.) */
340 /* data = next keyword */
341 /* value = next value ie stuff after equal sign */
343 next_keyword = strchr(data,','); /* BB handle sep= */
345 /* temporarily null terminate end of keyword=value pair */
349 /* temporarily null terminate keyword to make keyword and value distinct */
350 if ((value = strchr(data, '=')) != NULL) {
355 if (strncmp(data, "users",5) == 0) {
356 if(!value || !*value) {
359 } else if (strncmp(data, "user_xattr",10) == 0) {
360 /* do nothing - need to skip so not parsed as user name */
361 } else if (strncmp(data, "user", 4) == 0) {
363 if (!value || !*value) {
364 if(data[4] == '\0') {
366 printf("\nskipping empty user mount parameter\n");
367 /* remove the parm since it would otherwise be confusing
368 to the kernel code which would think it was a real username */
371 printf("username specified with no parameter\n");
372 return 1; /* needs_arg; */
375 if (strnlen(value, 260) < 260) {
377 percent_char = strchr(value,'%');
380 if(mountpassword == NULL)
381 mountpassword = (char *)calloc(65,1);
384 printf("\nmount.cifs warning - password specified twice\n");
387 strncpy(mountpassword, percent_char,64);
388 /* remove password from username */
389 while(*percent_char != 0) {
395 /* this is only case in which the user
396 name buf is not malloc - so we have to
397 check for domain name embedded within
398 the user name here since the later
399 call to check_for_domain will not be
401 domain_name = check_for_domain(&value);
403 printf("username too long\n");
407 } else if (strncmp(data, "pass", 4) == 0) {
408 if (!value || !*value) {
410 printf("\npassword specified twice, ignoring second\n");
413 } else if (strnlen(value, 17) < 17) {
415 printf("\nmount.cifs warning - password specified twice\n");
418 printf("password too long\n");
421 } else if (strncmp(data, "ip", 2) == 0) {
422 if (!value || !*value) {
423 printf("target ip address argument missing");
424 } else if (strnlen(value, 35) < 35) {
426 printf("ip address %s override specified\n",value);
429 printf("ip address too long\n");
432 } else if ((strncmp(data, "unc", 3) == 0)
433 || (strncmp(data, "target", 6) == 0)
434 || (strncmp(data, "path", 4) == 0)) {
435 if (!value || !*value) {
436 printf("invalid path to network resource\n");
437 return 1; /* needs_arg; */
438 } else if(strnlen(value,5) < 5) {
439 printf("UNC name too short");
442 if (strnlen(value, 300) < 300) {
444 if (strncmp(value, "//", 2) == 0) {
446 printf("unc name specified twice, ignoring second\n");
449 } else if (strncmp(value, "\\\\", 2) != 0) {
450 printf("UNC Path does not begin with // or \\\\ \n");
454 printf("unc name specified twice, ignoring second\n");
459 printf("CIFS: UNC name too long\n");
462 } else if ((strncmp(data, "domain", 3) == 0)
463 || (strncmp(data, "workgroup", 5) == 0)) {
464 if (!value || !*value) {
465 printf("CIFS: invalid domain name\n");
466 return 1; /* needs_arg; */
468 if (strnlen(value, 65) < 65) {
471 printf("domain name too long\n");
474 } else if (strncmp(data, "cred", 4) == 0) {
475 if (value && *value) {
476 rc = open_cred_file(value);
478 printf("error %d opening credential file %s\n",rc, value);
482 printf("invalid credential file name specified\n");
485 } else if (strncmp(data, "uid", 3) == 0) {
486 if (value && *value) {
488 if (!isdigit(*value)) {
490 static char temp[32];
492 if (!(pw = getpwnam(value))) {
493 printf("bad user name \"%s\"\n", value);
496 sprintf(temp, "%u", pw->pw_uid);
501 } else if (strncmp(data, "gid", 3) == 0) {
502 if (value && *value) {
504 if (!isdigit(*value)) {
506 static char temp[32];
508 if (!(gr = getgrnam(value))) {
509 printf("bad group name \"%s\"\n", value);
512 sprintf(temp, "%u", gr->gr_gid);
517 /* fmask and dmask synonyms for people used to smbfs syntax */
518 } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) {
519 if (!value || !*value) {
520 printf ("Option '%s' requires a numerical argument\n", data);
524 if (value[0] != '0') {
525 printf ("WARNING: '%s' not expressed in octal.\n", data);
528 if (strcmp (data, "fmask") == 0) {
529 printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
530 data = "file_mode"; /* BB fix this */
532 } else if (strcmp(data, "dir_mode") == 0 || strcmp(data, "dmask")==0) {
533 if (!value || !*value) {
534 printf ("Option '%s' requires a numerical argument\n", data);
538 if (value[0] != '0') {
539 printf ("WARNING: '%s' not expressed in octal.\n", data);
542 if (strcmp (data, "dmask") == 0) {
543 printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
546 /* the following eight mount options should be
547 stripped out from what is passed into the kernel
548 since these eight options are best passed as the
549 mount flags rather than redundantly to the kernel
550 and could generate spurious warnings depending on the
551 level of the corresponding cifs vfs kernel code */
552 } else if (strncmp(data, "nosuid", 6) == 0) {
553 *filesys_flags |= MS_NOSUID;
554 } else if (strncmp(data, "suid", 4) == 0) {
555 *filesys_flags &= ~MS_NOSUID;
556 } else if (strncmp(data, "nodev", 5) == 0) {
557 *filesys_flags |= MS_NODEV;
558 } else if ((strncmp(data, "nobrl", 5) == 0) ||
559 (strncmp(data, "nolock", 6) == 0)) {
560 *filesys_flags &= ~MS_MANDLOCK;
561 } else if (strncmp(data, "dev", 3) == 0) {
562 *filesys_flags &= ~MS_NODEV;
563 } else if (strncmp(data, "noexec", 6) == 0) {
564 *filesys_flags |= MS_NOEXEC;
565 } else if (strncmp(data, "exec", 4) == 0) {
566 *filesys_flags &= ~MS_NOEXEC;
567 } else if (strncmp(data, "guest", 5) == 0) {
569 /* remove the parm since it would otherwise be logged by kern */
571 } else if (strncmp(data, "ro", 2) == 0) {
572 *filesys_flags |= MS_RDONLY;
573 } else if (strncmp(data, "rw", 2) == 0) {
574 *filesys_flags &= ~MS_RDONLY;
575 } else if (strncmp(data, "remount", 7) == 0) {
576 *filesys_flags |= MS_REMOUNT;
577 } /* else if (strnicmp(data, "port", 4) == 0) {
578 if (value && *value) {
580 simple_strtoul(value, &value, 0);
582 } else if (strnicmp(data, "rsize", 5) == 0) {
583 if (value && *value) {
585 simple_strtoul(value, &value, 0);
587 } else if (strnicmp(data, "wsize", 5) == 0) {
588 if (value && *value) {
590 simple_strtoul(value, &value, 0);
592 } else if (strnicmp(data, "version", 3) == 0) {
594 printf("CIFS: Unknown mount option %s\n",data);
595 } */ /* nothing to do on those four mount options above.
596 Just pass to kernel and ignore them here */
598 /* Copy (possibly modified) option to out */
599 word_len = strlen(data);
601 word_len += 1 + strlen(value);
603 out = (char *)realloc(out, out_len + word_len + 2);
610 out[out_len++] = ',';
612 sprintf(out + out_len, "%s=%s", data, value);
614 sprintf(out + out_len, "%s", data);
615 out_len = strlen(out);
624 /* replace all (one or more) commas with double commas */
625 static void check_for_comma(char ** ppasswrd)
630 int number_of_commas = 0;
645 if(number_of_commas == 0)
647 if(number_of_commas > 64) {
648 /* would otherwise overflow the mount options buffer */
649 printf("\nInvalid password. Password contains too many commas.\n");
653 new_pass_buf = (char *)malloc(len+number_of_commas+1);
654 if(new_pass_buf == NULL)
657 for(i=0,j=0;i<len;i++,j++) {
658 new_pass_buf[j] = pass[i];
661 new_pass_buf[j] = pass[i];
664 new_pass_buf[len+number_of_commas] = 0;
667 *ppasswrd = new_pass_buf;
672 /* Usernames can not have backslash in them and we use
673 [BB check if usernames can have forward slash in them BB]
674 backslash as domain\user separator character
676 static char * check_for_domain(char **ppuser)
678 char * original_string;
688 original_string = *ppuser;
690 if (original_string == NULL)
693 original_len = strlen(original_string);
695 usernm = strchr(*ppuser,'/');
696 if (usernm == NULL) {
697 usernm = strchr(*ppuser,'\\');
703 printf("Domain name specified twice. Username probably malformed\n");
709 if (domainnm[0] != 0) {
712 printf("null domain\n");
714 len = strlen(domainnm);
715 /* reset domainm to new buffer, and copy
716 domain name into it */
717 domainnm = (char *)malloc(len+1);
721 strcpy(domainnm,*ppuser);
723 /* move_string(*ppuser, usernm+1) */
724 len = strlen(usernm+1);
726 if(len >= original_len) {
727 /* should not happen */
731 for(i=0;i<original_len;i++) {
733 original_string[i] = usernm[i+1];
734 else /* stuff with commas to remove last parm */
735 original_string[i] = ',';
738 /* BB add check for more than one slash?
746 /* Note that caller frees the returned buffer if necessary */
747 static char * parse_server(char ** punc_name)
749 char * unc_name = *punc_name;
750 int length = strnlen(unc_name,1024);
752 char * ipaddress_string = NULL;
753 struct hostent * host_entry = NULL;
754 struct in_addr server_ipaddr;
757 printf("mount error: UNC name too long");
760 if (strncasecmp("cifs://",unc_name,7) == 0)
761 return parse_cifs_url(unc_name+7);
762 if (strncasecmp("smb://",unc_name,6) == 0) {
763 return parse_cifs_url(unc_name+6);
767 /* BB add code to find DFS root here */
768 printf("\nMounting the DFS root for domain not implemented yet\n");
771 if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
772 /* check for nfs syntax ie server:share */
773 share = strchr(unc_name,':');
776 *punc_name = (char *)malloc(length+3);
777 if(*punc_name == NULL) {
778 /* put the original string back if
780 *punc_name = unc_name;
785 strncpy((*punc_name)+2,unc_name,length);
786 unc_name = *punc_name;
787 unc_name[length+2] = 0;
788 goto continue_unc_parsing;
790 printf("mount error: improperly formatted UNC name.");
791 printf(" %s does not begin with \\\\ or //\n",unc_name);
795 continue_unc_parsing:
799 if ((share = strchr(unc_name, '/')) ||
800 (share = strchr(unc_name,'\\'))) {
801 *share = 0; /* temporarily terminate the string */
804 host_entry = gethostbyname(unc_name);
806 *(share - 1) = '/'; /* put the slash back */
809 printf("ip address specified explicitly\n");
812 if(host_entry == NULL) {
813 printf("mount error: could not find target server. TCP name %s not found\n", unc_name);
816 /* BB should we pass an alternate version of the share name as Unicode */
817 /* BB what about ipv6? BB */
818 /* BB add retries with alternate servers in list */
820 memcpy(&server_ipaddr.s_addr, host_entry->h_addr, 4);
822 ipaddress_string = inet_ntoa(server_ipaddr);
823 if(ipaddress_string == NULL) {
824 printf("mount error: could not get valid ip address for target server\n");
827 return ipaddress_string;
830 /* BB add code to find DFS root (send null path on get DFS Referral to specified server here */
831 printf("Mounting the DFS root for a particular server not implemented yet\n");
838 static struct option longopts[] = {
839 { "all", 0, NULL, 'a' },
840 { "help",0, NULL, 'h' },
841 { "move",0, NULL, 'm' },
842 { "bind",0, NULL, 'b' },
843 { "read-only", 0, NULL, 'r' },
844 { "ro", 0, NULL, 'r' },
845 { "verbose", 0, NULL, 'v' },
846 { "version", 0, NULL, 'V' },
847 { "read-write", 0, NULL, 'w' },
848 { "rw", 0, NULL, 'w' },
849 { "options", 1, NULL, 'o' },
850 { "type", 1, NULL, 't' },
851 { "rsize",1, NULL, 'R' },
852 { "wsize",1, NULL, 'W' },
853 { "uid", 1, NULL, '1'},
854 { "gid", 1, NULL, '2'},
855 { "user",1,NULL,'u'},
856 { "username",1,NULL,'u'},
858 { "domain",1,NULL,'d'},
859 { "password",1,NULL,'p'},
860 { "pass",1,NULL,'p'},
861 { "credentials",1,NULL,'c'},
862 { "port",1,NULL,'P'},
863 /* { "uuid",1,NULL,'U'}, */ /* BB unimplemented */
867 int main(int argc, char ** argv)
870 int flags = MS_MANDLOCK; /* no need to set legacy MS_MGC_VAL */
871 char * orgoptions = NULL;
872 char * share_name = NULL;
873 char * ipaddr = NULL;
875 char * mountpoint = NULL;
877 char * resolved_path;
887 int retry = 0; /* set when we have to retry mount with uppercase */
889 struct utsname sysinfo;
890 struct mntent mountent;
893 /* setlocale(LC_ALL, "");
894 bindtextdomain(PACKAGE, LOCALEDIR);
895 textdomain(PACKAGE); */
898 thisprogram = argv[0];
904 if(thisprogram == NULL)
905 thisprogram = "mount.cifs";
908 /* BB add workstation name and domain and pass down */
910 /* #ifdef _GNU_SOURCE
911 printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
914 share_name = argv[1];
915 mountpoint = argv[2];
918 /* add sharename in opts string as unc= parm */
920 while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsSU:vVwt:",
921 longopts, NULL)) != -1) {
923 /* No code to do the following options yet */
925 list_with_volumelabel = 1;
928 volumelabel = optarg;
946 "option 'b' (MS_BIND) not supported\n");
954 "option 'm' (MS_MOVE) not supported\n");
958 orgoptions = strdup(optarg);
960 case 'r': /* mount readonly */
970 printf ("mount.cifs version: %s.%s%s\n",
971 MOUNT_CIFS_VERSION_MAJOR,
972 MOUNT_CIFS_VERSION_MINOR,
973 MOUNT_CIFS_VENDOR_SUFFIX);
975 memset(mountpassword,0,64);
982 rsize = atoi(optarg) ;
985 wsize = atoi(optarg);
988 if (isdigit(*optarg)) {
991 uid = strtoul(optarg, &ep, 10);
993 printf("bad uid value \"%s\"\n", optarg);
999 if (!(pw = getpwnam(optarg))) {
1000 printf("bad user name \"%s\"\n", optarg);
1008 if (isdigit(*optarg)) {
1011 gid = strtoul(optarg, &ep, 10);
1013 printf("bad gid value \"%s\"\n", optarg);
1019 if (!(gr = getgrnam(optarg))) {
1020 printf("bad user name \"%s\"\n", optarg);
1032 domain_name = optarg; /* BB fix this - currently ignored */
1036 if(mountpassword == NULL)
1037 mountpassword = (char *)calloc(65,1);
1040 strncpy(mountpassword,optarg,64);
1044 get_password_from_file(0 /* stdin */,NULL);
1049 printf("unknown mount option %c\n",c);
1055 if((argc < 3) || (share_name == NULL) || (mountpoint == NULL)) {
1060 if (getenv("PASSWD")) {
1061 if(mountpassword == NULL)
1062 mountpassword = (char *)calloc(65,1);
1064 strncpy(mountpassword,getenv("PASSWD"),64);
1067 } else if (getenv("PASSWD_FD")) {
1068 get_password_from_file(atoi(getenv("PASSWD_FD")),NULL);
1069 } else if (getenv("PASSWD_FILE")) {
1070 get_password_from_file(0, getenv("PASSWD_FILE"));
1073 if (orgoptions && parse_options(&orgoptions, &flags))
1075 ipaddr = parse_server(&share_name);
1076 if((ipaddr == NULL) && (got_ip == 0)) {
1077 printf("No ip address specified and hostname not found\n");
1081 /* BB save off path and pop after mount returns? */
1082 resolved_path = (char *)malloc(PATH_MAX+1);
1084 /* Note that if we can not canonicalize the name, we get
1085 another chance to see if it is valid when we chdir to it */
1086 if (realpath(mountpoint, resolved_path)) {
1087 mountpoint = resolved_path;
1090 if(chdir(mountpoint)) {
1091 printf("mount error: can not change directory into mount target %s\n",mountpoint);
1095 if(stat (".", &statbuf)) {
1096 printf("mount error: mount point %s does not exist\n",mountpoint);
1100 if (S_ISDIR(statbuf.st_mode) == 0) {
1101 printf("mount error: mount point %s is not a directory\n",mountpoint);
1105 if((getuid() != 0) && (geteuid() == 0)) {
1106 if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) {
1107 #ifndef CIFS_ALLOW_USR_SUID
1108 /* Do not allow user mounts to control suid flag
1109 for mount unless explicitly built that way */
1110 flags |= MS_NOSUID | MS_NODEV;
1113 printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n");
1119 user_name = getusername();
1123 if(got_password == 0) {
1124 mountpassword = getpass("Password: "); /* BB obsolete */
1127 /* FIXME launch daemon (handles dfs name resolution and credential change)
1128 remember to clear parms and overwrite password field before launching */
1131 optlen = strlen(orgoptions);
1136 optlen += strlen(share_name) + 4;
1138 printf("No server share name specified\n");
1139 printf("\nMounting the DFS root for server not implemented yet\n");
1143 optlen += strlen(user_name) + 6;
1145 optlen += strlen(ipaddr) + 4;
1147 optlen += strlen(mountpassword) + 6;
1148 options = (char *)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 */);
1150 if(options == NULL) {
1151 printf("Could not allocate memory for mount options\n");
1157 strncat(options,"unc=",4);
1158 strcat(options,share_name);
1159 /* scan backwards and reverse direction of slash */
1160 temp = strrchr(options, '/');
1161 if(temp > options + 6)
1164 strncat(options,",ip=",4);
1165 strcat(options,ipaddr);
1169 /* check for syntax like user=domain\user */
1171 domain_name = check_for_domain(&user_name);
1172 strncat(options,",user=",6);
1173 strcat(options,user_name);
1177 /* extra length accounted for in option string above */
1178 strncat(options,",domain=",8);
1179 strcat(options,domain_name);
1183 /* Commas have to be doubled, or else they will
1184 look like the parameter separator */
1185 /* if(sep is not set)*/
1187 check_for_comma(&mountpassword);
1188 strncat(options,",pass=",6);
1189 strcat(options,mountpassword);
1192 strncat(options,",ver=",5);
1193 strcat(options,MOUNT_CIFS_VERSION_MAJOR);
1196 strcat(options,",");
1197 strcat(options,orgoptions);
1200 printf("\nmount.cifs kernel mount options %s \n",options);
1201 if(mount(share_name, mountpoint, "cifs", flags, options)) {
1202 /* remember to kill daemon on error */
1207 printf("mount failed but no error number set\n");
1210 printf("mount error: cifs filesystem not supported by the system\n");
1216 while (*tmp && !(((unsigned char)tmp[0]) & 0x80)) {
1217 *tmp = toupper((unsigned char)*tmp);
1221 printf("retrying with upper case share name\n");
1227 printf("mount error %d = %s\n",errno,strerror(errno));
1229 printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
1231 memset(mountpassword,0,64);
1235 pmntfile = setmntent(MOUNTED, "a+");
1237 mountent.mnt_fsname = share_name;
1238 mountent.mnt_dir = mountpoint;
1239 mountent.mnt_type = CONST_DISCARD(char *,"cifs");
1240 mountent.mnt_opts = (char *)malloc(220);
1241 if(mountent.mnt_opts) {
1242 char * mount_user = getusername();
1243 memset(mountent.mnt_opts,0,200);
1244 if(flags & MS_RDONLY)
1245 strcat(mountent.mnt_opts,"ro");
1247 strcat(mountent.mnt_opts,"rw");
1248 if(flags & MS_MANDLOCK)
1249 strcat(mountent.mnt_opts,",mand");
1250 if(flags & MS_NOEXEC)
1251 strcat(mountent.mnt_opts,",noexec");
1252 if(flags & MS_NOSUID)
1253 strcat(mountent.mnt_opts,",nosuid");
1254 if(flags & MS_NODEV)
1255 strcat(mountent.mnt_opts,",nodev");
1256 if(flags & MS_SYNCHRONOUS)
1257 strcat(mountent.mnt_opts,",synch");
1260 strcat(mountent.mnt_opts,",user=");
1261 strcat(mountent.mnt_opts,mount_user);
1266 mountent.mnt_freq = 0;
1267 mountent.mnt_passno = 0;
1268 rc = addmntent(pmntfile,&mountent);
1269 endmntent(pmntfile);
1270 if(mountent.mnt_opts)
1271 free(mountent.mnt_opts);
1273 printf("could not update mount table\n");
1277 int len = strlen(mountpassword);
1278 memset(mountpassword,0,len);
1279 free(mountpassword);
1283 memset(options,0,optlen);
1288 memset(orgoptions,0,orgoptlen);
1292 free(resolved_path);
1295 if(free_share_name) {