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 */
64 static int got_password
= 0;
65 static int got_user
= 0;
66 static int got_domain
= 0;
67 static int got_ip
= 0;
68 static int got_unc
= 0;
69 static int got_uid
= 0;
70 static int got_gid
= 0;
71 static int free_share_name
= 0;
72 static char * user_name
= NULL
;
73 static char * mountpassword
= NULL
;
74 char * domain_name
= NULL
;
80 open nofollow - avoid symlink exposure?
81 get owner of dir see if matches self or if root
82 call system(umount argv) etc.
86 static char * check_for_domain(char **);
89 static void mount_cifs_usage(void)
91 printf("\nUsage: %s <remotetarget> <dir> -o <options>\n", thisprogram
);
92 printf("\nMount the remote target, specified as a UNC name,");
93 printf(" to a local directory.\n\nOptions:\n");
94 printf("\tuser=<arg>\n\tpass=<arg>\n\tdom=<arg>\n");
95 printf("\nLess commonly used options:");
96 printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,rw,ro,");
97 printf("\n\tsep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,serverino,");
98 printf("\n\tdirectio,mapchars,nomapchars,nolock,servernetbiosname=<SRV_RFC1001NAME>");
99 printf("\n\nOptions not needed for servers supporting CIFS Unix extensions");
100 printf("\n\t(e.g. unneeded for mounts to most Samba versions):");
101 printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>,sfu");
102 printf("\n\nRarely used options:");
103 printf("\n\tport=<tcpport>,rsize=<size>,wsize=<size>,unc=<unc_name>,ip=<ip_address>,");
104 printf("\n\tdev,nodev,nouser_xattr,netbiosname=<OUR_RFC1001NAME>,hard,soft,intr,");
105 printf("\n\tnointr,ignorecase,noposixpaths,noacl");
106 printf("\n\nOptions are described in more detail in the manual page");
107 printf("\n\tman 8 mount.cifs\n");
108 printf("\nTo display the version number of the mount helper:");
109 printf("\n\t%s -V\n",thisprogram
);
112 memset(mountpassword
,0,64);
118 /* caller frees username if necessary */
119 static char * getusername(void) {
120 char *username
= NULL
;
121 struct passwd
*password
= getpwuid(getuid());
124 username
= password
->pw_name
;
129 static char * parse_cifs_url(char * unc_name
)
131 printf("\nMounting cifs URL not implemented yet. Attempt to mount %s\n",unc_name
);
135 static int open_cred_file(char * file_name
)
141 fs
= fopen(file_name
,"r");
144 line_buf
= malloc(4096);
145 if(line_buf
== NULL
) {
150 while(fgets(line_buf
,4096,fs
)) {
151 /* parse line from credential file */
153 /* eat leading white space */
154 for(i
=0;i
<4086;i
++) {
155 if((line_buf
[i
] != ' ') && (line_buf
[i
] != '\t'))
157 /* if whitespace - skip past it */
159 if (strncasecmp("username",line_buf
+i
,8) == 0) {
160 temp_val
= strchr(line_buf
+ i
,'=');
162 /* go past equals sign */
164 for(length
= 0;length
<4087;length
++) {
165 if(temp_val
[length
] == '\n')
169 printf("mount.cifs failed due to malformed username in credentials file");
170 memset(line_buf
,0,4096);
172 memset(mountpassword
,0,64);
177 user_name
= calloc(1 + length
,1);
178 /* BB adding free of user_name string before exit,
179 not really necessary but would be cleaner */
180 strncpy(user_name
,temp_val
, length
);
183 } else if (strncasecmp("password",line_buf
+i
,8) == 0) {
184 temp_val
= strchr(line_buf
+i
,'=');
186 /* go past equals sign */
188 for(length
= 0;length
<65;length
++) {
189 if(temp_val
[length
] == '\n')
193 printf("mount.cifs failed: password in credentials file too long\n");
194 memset(line_buf
,0, 4096);
196 memset(mountpassword
,0,64);
200 if(mountpassword
== NULL
) {
201 mountpassword
= calloc(65,1);
203 memset(mountpassword
,0,64);
205 strncpy(mountpassword
,temp_val
,length
);
210 } else if (strncasecmp("domain",line_buf
+i
,6) == 0) {
211 temp_val
= strchr(line_buf
+i
,'=');
213 /* go past equals sign */
216 printf("\nDomain %s\n",temp_val
);
217 for(length
= 0;length
<65;length
++) {
218 if(temp_val
[length
] == '\n')
222 printf("mount.cifs failed: domain in credentials file too long\n");
224 memset(mountpassword
,0,64);
228 if(domain_name
== NULL
) {
229 domain_name
= calloc(65,1);
231 memset(domain_name
,0,64);
233 strncpy(domain_name
,temp_val
,length
);
243 memset(line_buf
,0,4096);
249 static int get_password_from_file(int file_descript
, char * filename
)
255 if(mountpassword
== NULL
)
256 mountpassword
= calloc(65,1);
258 memset(mountpassword
, 0, 64);
260 if(filename
!= NULL
) {
261 file_descript
= open(filename
, O_RDONLY
);
262 if(file_descript
< 0) {
263 printf("mount.cifs failed. %s attempting to open password file %s\n",
264 strerror(errno
),filename
);
268 /* else file already open and fd provided */
271 rc
= read(file_descript
,&c
,1);
273 printf("mount.cifs failed. Error %s reading password file\n",strerror(errno
));
274 memset(mountpassword
,0,64);
276 close(file_descript
);
279 if(mountpassword
[0] == 0) {
281 printf("\nWarning: null password used since cifs password file empty");
284 } else /* read valid character */ {
285 if((c
== 0) || (c
== '\n')) {
288 mountpassword
[i
] = c
;
291 if((i
== 64) && (verboseflag
)) {
292 printf("\nWarning: password longer than 64 characters specified in cifs password file");
295 if(filename
!= NULL
) {
296 close(file_descript
);
302 static int parse_options(char ** optionsp
, int * filesys_flags
)
305 char * percent_char
= NULL
;
307 char * next_keyword
= NULL
;
313 if (!optionsp
|| !*optionsp
)
318 printf("parsing options: %s\n", data
);
320 /* BB fixme check for separator override BB */
322 /* while ((data = strsep(&options, ",")) != NULL) { */
323 while(data
!= NULL
) {
324 /* check if ends with trailing comma */
328 /* format is keyword=value,keyword2=value2,keyword3=value3 etc.) */
329 /* data = next keyword */
330 /* value = next value ie stuff after equal sign */
332 next_keyword
= strchr(data
,','); /* BB handle sep= */
334 /* temporarily null terminate end of keyword=value pair */
338 /* temporarily null terminate keyword to make keyword and value distinct */
339 if ((value
= strchr(data
, '=')) != NULL
) {
344 if (strncmp(data
, "users",5) == 0) {
345 if(!value
|| !*value
) {
348 } else if (strncmp(data
, "user_xattr",10) == 0) {
349 /* do nothing - need to skip so not parsed as user name */
350 } else if (strncmp(data
, "user", 4) == 0) {
352 if (!value
|| !*value
) {
353 if(data
[4] == '\0') {
355 printf("\nskipping empty user mount parameter\n");
356 /* remove the parm since it would otherwise be confusing
357 to the kernel code which would think it was a real username */
360 printf("username specified with no parameter\n");
361 return 1; /* needs_arg; */
364 if (strnlen(value
, 260) < 260) {
366 percent_char
= strchr(value
,'%');
369 if(mountpassword
== NULL
)
370 mountpassword
= calloc(65,1);
373 printf("\nmount.cifs warning - password specified twice\n");
376 strncpy(mountpassword
, percent_char
,64);
377 /* remove password from username */
378 while(*percent_char
!= 0) {
384 /* this is only case in which the user
385 name buf is not malloc - so we have to
386 check for domain name embedded within
387 the user name here since the later
388 call to check_for_domain will not be
390 domain_name
= check_for_domain(&value
);
392 printf("username too long\n");
396 } else if (strncmp(data
, "pass", 4) == 0) {
397 if (!value
|| !*value
) {
399 printf("\npassword specified twice, ignoring second\n");
402 } else if (strnlen(value
, 17) < 17) {
404 printf("\nmount.cifs warning - password specified twice\n");
407 printf("password too long\n");
410 } else if (strncmp(data
, "ip", 2) == 0) {
411 if (!value
|| !*value
) {
412 printf("target ip address argument missing");
413 } else if (strnlen(value
, 35) < 35) {
415 printf("ip address %s override specified\n",value
);
418 printf("ip address too long\n");
421 } else if ((strncmp(data
, "unc", 3) == 0)
422 || (strncmp(data
, "target", 6) == 0)
423 || (strncmp(data
, "path", 4) == 0)) {
424 if (!value
|| !*value
) {
425 printf("invalid path to network resource\n");
426 return 1; /* needs_arg; */
427 } else if(strnlen(value
,5) < 5) {
428 printf("UNC name too short");
431 if (strnlen(value
, 300) < 300) {
433 if (strncmp(value
, "//", 2) == 0) {
435 printf("unc name specified twice, ignoring second\n");
438 } else if (strncmp(value
, "\\\\", 2) != 0) {
439 printf("UNC Path does not begin with // or \\\\ \n");
443 printf("unc name specified twice, ignoring second\n");
448 printf("CIFS: UNC name too long\n");
451 } else if ((strncmp(data
, "domain", 3) == 0)
452 || (strncmp(data
, "workgroup", 5) == 0)) {
453 if (!value
|| !*value
) {
454 printf("CIFS: invalid domain name\n");
455 return 1; /* needs_arg; */
457 if (strnlen(value
, 65) < 65) {
460 printf("domain name too long\n");
463 } else if (strncmp(data
, "cred", 4) == 0) {
464 if (value
&& *value
) {
465 rc
= open_cred_file(value
);
467 printf("error %d opening credential file %s\n",rc
, value
);
471 printf("invalid credential file name specified\n");
474 } else if (strncmp(data
, "uid", 3) == 0) {
475 if (value
&& *value
) {
477 if (!isdigit(*value
)) {
479 static char temp
[32];
481 if (!(pw
= getpwnam(value
))) {
482 printf("bad user name \"%s\"\n", value
);
485 sprintf(temp
, "%u", pw
->pw_uid
);
490 } else if (strncmp(data
, "gid", 3) == 0) {
491 if (value
&& *value
) {
493 if (!isdigit(*value
)) {
495 static char temp
[32];
497 if (!(gr
= getgrnam(value
))) {
498 printf("bad group name \"%s\"\n", value
);
501 sprintf(temp
, "%u", gr
->gr_gid
);
506 /* fmask and dmask synonyms for people used to smbfs syntax */
507 } else if (strcmp(data
, "file_mode") == 0 || strcmp(data
, "fmask")==0) {
508 if (!value
|| !*value
) {
509 printf ("Option '%s' requires a numerical argument\n", data
);
513 if (value
[0] != '0') {
514 printf ("WARNING: '%s' not expressed in octal.\n", data
);
517 if (strcmp (data
, "fmask") == 0) {
518 printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
519 data
= "file_mode"; /* BB fix this */
521 } else if (strcmp(data
, "dir_mode") == 0 || strcmp(data
, "dmask")==0) {
522 if (!value
|| !*value
) {
523 printf ("Option '%s' requires a numerical argument\n", data
);
527 if (value
[0] != '0') {
528 printf ("WARNING: '%s' not expressed in octal.\n", data
);
531 if (strcmp (data
, "dmask") == 0) {
532 printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
535 /* the following eight mount options should be
536 stripped out from what is passed into the kernel
537 since these eight options are best passed as the
538 mount flags rather than redundantly to the kernel
539 and could generate spurious warnings depending on the
540 level of the corresponding cifs vfs kernel code */
541 } else if (strncmp(data
, "nosuid", 6) == 0) {
542 *filesys_flags
|= MS_NOSUID
;
543 } else if (strncmp(data
, "suid", 4) == 0) {
544 *filesys_flags
&= ~MS_NOSUID
;
545 } else if (strncmp(data
, "nodev", 5) == 0) {
546 *filesys_flags
|= MS_NODEV
;
547 } else if ((strncmp(data
, "nobrl", 5) == 0) ||
548 (strncmp(data
, "nolock", 6) == 0)) {
549 *filesys_flags
&= ~MS_MANDLOCK
;
550 } else if (strncmp(data
, "dev", 3) == 0) {
551 *filesys_flags
&= ~MS_NODEV
;
552 } else if (strncmp(data
, "noexec", 6) == 0) {
553 *filesys_flags
|= MS_NOEXEC
;
554 } else if (strncmp(data
, "exec", 4) == 0) {
555 *filesys_flags
&= ~MS_NOEXEC
;
556 } else if (strncmp(data
, "guest", 5) == 0) {
558 /* remove the parm since it would otherwise be logged by kern */
560 } else if (strncmp(data
, "ro", 2) == 0) {
561 *filesys_flags
|= MS_RDONLY
;
562 } else if (strncmp(data
, "rw", 2) == 0) {
563 *filesys_flags
&= ~MS_RDONLY
;
564 } else if (strncmp(data
, "remount", 7) == 0) {
565 *filesys_flags
|= MS_REMOUNT
;
566 } /* else if (strnicmp(data, "port", 4) == 0) {
567 if (value && *value) {
569 simple_strtoul(value, &value, 0);
571 } else if (strnicmp(data, "rsize", 5) == 0) {
572 if (value && *value) {
574 simple_strtoul(value, &value, 0);
576 } else if (strnicmp(data, "wsize", 5) == 0) {
577 if (value && *value) {
579 simple_strtoul(value, &value, 0);
581 } else if (strnicmp(data, "version", 3) == 0) {
583 printf("CIFS: Unknown mount option %s\n",data);
584 } */ /* nothing to do on those four mount options above.
585 Just pass to kernel and ignore them here */
587 /* Copy (possibly modified) option to out */
588 word_len
= strlen(data
);
590 word_len
+= 1 + strlen(value
);
592 out
= realloc(out
, out_len
+ word_len
+ 2);
599 out
[out_len
++] = ',';
601 sprintf(out
+ out_len
, "%s=%s", data
, value
);
603 sprintf(out
+ out_len
, "%s", data
);
604 out_len
= strlen(out
);
613 /* replace all (one or more) commas with double commas */
614 static void check_for_comma(char ** ppasswrd
)
619 int number_of_commas
= 0;
634 if(number_of_commas
== 0)
636 if(number_of_commas
> 64) {
637 /* would otherwise overflow the mount options buffer */
638 printf("\nInvalid password. Password contains too many commas.\n");
642 new_pass_buf
= malloc(len
+number_of_commas
+1);
643 if(new_pass_buf
== NULL
)
646 for(i
=0,j
=0;i
<len
;i
++,j
++) {
647 new_pass_buf
[j
] = pass
[i
];
650 new_pass_buf
[j
] = pass
[i
];
653 new_pass_buf
[len
+number_of_commas
] = 0;
656 *ppasswrd
= new_pass_buf
;
661 /* Usernames can not have backslash in them and we use
662 [BB check if usernames can have forward slash in them BB]
663 backslash as domain\user separator character
665 static char * check_for_domain(char **ppuser
)
667 char * original_string
;
677 original_string
= *ppuser
;
679 if (original_string
== NULL
)
682 original_len
= strlen(original_string
);
684 usernm
= strchr(*ppuser
,'/');
685 if (usernm
== NULL
) {
686 usernm
= strchr(*ppuser
,'\\');
692 printf("Domain name specified twice. Username probably malformed\n");
698 if (domainnm
[0] != 0) {
701 printf("null domain\n");
703 len
= strlen(domainnm
);
704 /* reset domainm to new buffer, and copy
705 domain name into it */
706 domainnm
= malloc(len
+1);
710 strcpy(domainnm
,*ppuser
);
712 /* move_string(*ppuser, usernm+1) */
713 len
= strlen(usernm
+1);
715 if(len
>= original_len
) {
716 /* should not happen */
720 for(i
=0;i
<original_len
;i
++) {
722 original_string
[i
] = usernm
[i
+1];
723 else /* stuff with commas to remove last parm */
724 original_string
[i
] = ',';
727 /* BB add check for more than one slash?
735 /* Note that caller frees the returned buffer if necessary */
736 static char * parse_server(char ** punc_name
)
738 char * unc_name
= *punc_name
;
739 int length
= strnlen(unc_name
,1024);
741 char * ipaddress_string
= NULL
;
742 struct hostent
* host_entry
= NULL
;
743 struct in_addr server_ipaddr
;
746 printf("mount error: UNC name too long");
749 if (strncasecmp("cifs://",unc_name
,7) == 0)
750 return parse_cifs_url(unc_name
+7);
751 if (strncasecmp("smb://",unc_name
,6) == 0) {
752 return parse_cifs_url(unc_name
+6);
756 /* BB add code to find DFS root here */
757 printf("\nMounting the DFS root for domain not implemented yet");
760 if(strncmp(unc_name
,"//",2) && strncmp(unc_name
,"\\\\",2)) {
761 /* check for nfs syntax ie server:share */
762 share
= strchr(unc_name
,':');
765 *punc_name
= malloc(length
+3);
766 if(*punc_name
== NULL
) {
767 /* put the original string back if
769 *punc_name
= unc_name
;
774 strncpy((*punc_name
)+2,unc_name
,length
);
775 unc_name
= *punc_name
;
776 unc_name
[length
+2] = 0;
777 goto continue_unc_parsing
;
779 printf("mount error: improperly formatted UNC name.");
780 printf(" %s does not begin with \\\\ or //\n",unc_name
);
784 continue_unc_parsing
:
788 if ((share
= strchr(unc_name
, '/')) ||
789 (share
= strchr(unc_name
,'\\'))) {
790 *share
= 0; /* temporarily terminate the string */
793 host_entry
= gethostbyname(unc_name
);
795 *(share
- 1) = '/'; /* put the slash back */
798 printf("ip address specified explicitly\n");
801 if(host_entry
== NULL
) {
802 printf("mount error: could not find target server. TCP name %s not found\n", unc_name
);
805 /* BB should we pass an alternate version of the share name as Unicode */
806 /* BB what about ipv6? BB */
807 /* BB add retries with alternate servers in list */
809 memcpy(&server_ipaddr
.s_addr
, host_entry
->h_addr
, 4);
811 ipaddress_string
= inet_ntoa(server_ipaddr
);
812 if(ipaddress_string
== NULL
) {
813 printf("mount error: could not get valid ip address for target server\n");
816 return ipaddress_string
;
819 /* BB add code to find DFS root (send null path on get DFS Referral to specified server here */
820 printf("Mounting the DFS root for a particular server not implemented yet\n");
827 static struct option longopts
[] = {
828 { "all", 0, NULL
, 'a' },
829 { "help",0, NULL
, 'h' },
830 { "move",0, NULL
, 'm' },
831 { "bind",0, NULL
, 'b' },
832 { "read-only", 0, NULL
, 'r' },
833 { "ro", 0, NULL
, 'r' },
834 { "verbose", 0, NULL
, 'v' },
835 { "version", 0, NULL
, 'V' },
836 { "read-write", 0, NULL
, 'w' },
837 { "rw", 0, NULL
, 'w' },
838 { "options", 1, NULL
, 'o' },
839 { "type", 1, NULL
, 't' },
840 { "rsize",1, NULL
, 'R' },
841 { "wsize",1, NULL
, 'W' },
842 { "uid", 1, NULL
, '1'},
843 { "gid", 1, NULL
, '2'},
844 { "user",1,NULL
,'u'},
845 { "username",1,NULL
,'u'},
847 { "domain",1,NULL
,'d'},
848 { "password",1,NULL
,'p'},
849 { "pass",1,NULL
,'p'},
850 { "credentials",1,NULL
,'c'},
851 { "port",1,NULL
,'P'},
852 /* { "uuid",1,NULL,'U'}, */ /* BB unimplemented */
856 int main(int argc
, char ** argv
)
859 int flags
= MS_MANDLOCK
; /* no need to set legacy MS_MGC_VAL */
860 char * orgoptions
= NULL
;
861 char * share_name
= NULL
;
862 char * ipaddr
= NULL
;
866 char * resolved_path
;
876 int retry
= 0; /* set when we have to retry mount with uppercase */
878 struct utsname sysinfo
;
879 struct mntent mountent
;
882 /* setlocale(LC_ALL, "");
883 bindtextdomain(PACKAGE, LOCALEDIR);
884 textdomain(PACKAGE); */
887 thisprogram
= argv
[0];
889 if(thisprogram
== NULL
)
890 thisprogram
= "mount.cifs";
893 /* BB add workstation name and domain and pass down */
895 /* #ifdef _GNU_SOURCE
896 printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
899 share_name
= argv
[1];
900 mountpoint
= argv
[2];
902 /* add sharename in opts string as unc= parm */
904 while ((c
= getopt_long (argc
, argv
, "afFhilL:no:O:rsSU:vVwt:",
905 longopts
, NULL
)) != -1) {
907 /* No code to do the following options yet */
909 list_with_volumelabel = 1;
912 volumelabel = optarg;
932 orgoptions
= strdup(optarg
);
934 case 'r': /* mount readonly */
944 printf ("mount.cifs version: %s.%s%s\n",
945 MOUNT_CIFS_VERSION_MAJOR
,
946 MOUNT_CIFS_VERSION_MINOR
,
947 MOUNT_CIFS_VENDOR_SUFFIX
);
949 memset(mountpassword
,0,64);
956 rsize
= atoi(optarg
) ;
959 wsize
= atoi(optarg
);
962 if (isdigit(*optarg
)) {
965 uid
= strtoul(optarg
, &ep
, 10);
967 printf("bad uid value \"%s\"\n", optarg
);
973 if (!(pw
= getpwnam(optarg
))) {
974 printf("bad user name \"%s\"\n", optarg
);
982 if (isdigit(*optarg
)) {
985 gid
= strtoul(optarg
, &ep
, 10);
987 printf("bad gid value \"%s\"\n", optarg
);
993 if (!(gr
= getgrnam(optarg
))) {
994 printf("bad user name \"%s\"\n", optarg
);
1006 domain_name
= optarg
; /* BB fix this - currently ignored */
1010 if(mountpassword
== NULL
)
1011 mountpassword
= calloc(65,1);
1014 strncpy(mountpassword
,optarg
,64);
1018 get_password_from_file(0 /* stdin */,NULL
);
1023 printf("unknown mount option %c\n",c
);
1032 if (getenv("PASSWD")) {
1033 if(mountpassword
== NULL
)
1034 mountpassword
= calloc(65,1);
1036 strncpy(mountpassword
,getenv("PASSWD"),64);
1039 } else if (getenv("PASSWD_FD")) {
1040 get_password_from_file(atoi(getenv("PASSWD_FD")),NULL
);
1041 } else if (getenv("PASSWD_FILE")) {
1042 get_password_from_file(0, getenv("PASSWD_FILE"));
1045 if (orgoptions
&& parse_options(&orgoptions
, &flags
))
1047 ipaddr
= parse_server(&share_name
);
1048 if((ipaddr
== NULL
) && (got_ip
== 0)) {
1049 printf("No ip address specified and hostname not found\n");
1053 /* BB save off path and pop after mount returns? */
1054 resolved_path
= malloc(PATH_MAX
+1);
1056 /* Note that if we can not canonicalize the name, we get
1057 another chance to see if it is valid when we chdir to it */
1058 if (realpath(mountpoint
, resolved_path
)) {
1059 mountpoint
= resolved_path
;
1062 if(chdir(mountpoint
)) {
1063 printf("mount error: can not change directory into mount target %s\n",mountpoint
);
1067 if(stat (".", &statbuf
)) {
1068 printf("mount error: mount point %s does not exist\n",mountpoint
);
1072 if (S_ISDIR(statbuf
.st_mode
) == 0) {
1073 printf("mount error: mount point %s is not a directory\n",mountpoint
);
1077 if((getuid() != 0) && (geteuid() == 0)) {
1078 if((statbuf
.st_uid
== getuid()) && (S_IRWXU
== (statbuf
.st_mode
& S_IRWXU
))) {
1079 #ifndef CIFS_ALLOW_USR_SUID
1080 /* Do not allow user mounts to control suid flag
1081 for mount unless explicitly built that way */
1082 flags
|= MS_NOSUID
| MS_NODEV
;
1085 printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n");
1091 user_name
= getusername();
1095 if(got_password
== 0) {
1096 mountpassword
= getpass("Password: "); /* BB obsolete */
1099 /* FIXME launch daemon (handles dfs name resolution and credential change)
1100 remember to clear parms and overwrite password field before launching */
1103 optlen
= strlen(orgoptions
);
1108 optlen
+= strlen(share_name
) + 4;
1110 printf("No server share name specified\n");
1113 optlen
+= strlen(user_name
) + 6;
1115 optlen
+= strlen(ipaddr
) + 4;
1117 optlen
+= strlen(mountpassword
) + 6;
1118 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 */);
1120 if(options
== NULL
) {
1121 printf("Could not allocate memory for mount options\n");
1127 strncat(options
,"unc=",4);
1128 strcat(options
,share_name
);
1129 /* scan backwards and reverse direction of slash */
1130 temp
= strrchr(options
, '/');
1131 if(temp
> options
+ 6)
1134 strncat(options
,",ip=",4);
1135 strcat(options
,ipaddr
);
1139 /* check for syntax like user=domain\user */
1141 domain_name
= check_for_domain(&user_name
);
1142 strncat(options
,",user=",6);
1143 strcat(options
,user_name
);
1147 /* extra length accounted for in option string above */
1148 strncat(options
,",domain=",8);
1149 strcat(options
,domain_name
);
1153 /* Commas have to be doubled, or else they will
1154 look like the parameter separator */
1155 /* if(sep is not set)*/
1157 check_for_comma(&mountpassword
);
1158 strncat(options
,",pass=",6);
1159 strcat(options
,mountpassword
);
1162 strncat(options
,",ver=",5);
1163 strcat(options
,MOUNT_CIFS_VERSION_MAJOR
);
1166 strcat(options
,",");
1167 strcat(options
,orgoptions
);
1170 printf("\nmount.cifs kernel mount options %s \n",options
);
1171 if(mount(share_name
, mountpoint
, "cifs", flags
, options
)) {
1172 /* remember to kill daemon on error */
1177 printf("mount failed but no error number set\n");
1180 printf("mount error: cifs filesystem not supported by the system\n");
1186 while (*tmp
&& !(((unsigned char)tmp
[0]) & 0x80)) {
1187 *tmp
= toupper((unsigned char)*tmp
);
1191 printf("retrying with upper case share name\n");
1197 printf("mount error %d = %s\n",errno
,strerror(errno
));
1199 printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
1201 memset(mountpassword
,0,64);
1205 pmntfile
= setmntent(MOUNTED
, "a+");
1207 mountent
.mnt_fsname
= share_name
;
1208 mountent
.mnt_dir
= mountpoint
;
1209 mountent
.mnt_type
= "cifs";
1210 mountent
.mnt_opts
= malloc(220);
1211 if(mountent
.mnt_opts
) {
1212 char * mount_user
= getusername();
1213 memset(mountent
.mnt_opts
,0,200);
1214 if(flags
& MS_RDONLY
)
1215 strcat(mountent
.mnt_opts
,"ro");
1217 strcat(mountent
.mnt_opts
,"rw");
1218 if(flags
& MS_MANDLOCK
)
1219 strcat(mountent
.mnt_opts
,",mand");
1220 if(flags
& MS_NOEXEC
)
1221 strcat(mountent
.mnt_opts
,",noexec");
1222 if(flags
& MS_NOSUID
)
1223 strcat(mountent
.mnt_opts
,",nosuid");
1224 if(flags
& MS_NODEV
)
1225 strcat(mountent
.mnt_opts
,",nodev");
1226 if(flags
& MS_SYNCHRONOUS
)
1227 strcat(mountent
.mnt_opts
,",synch");
1230 strcat(mountent
.mnt_opts
,",user=");
1231 strcat(mountent
.mnt_opts
,mount_user
);
1236 mountent
.mnt_freq
= 0;
1237 mountent
.mnt_passno
= 0;
1238 rc
= addmntent(pmntfile
,&mountent
);
1239 endmntent(pmntfile
);
1240 if(mountent
.mnt_opts
)
1241 free(mountent
.mnt_opts
);
1243 printf("could not update mount table\n");
1247 int len
= strlen(mountpassword
);
1248 memset(mountpassword
,0,len
);
1249 free(mountpassword
);
1253 memset(options
,0,optlen
);
1258 memset(orgoptions
,0,orgoptlen
);
1262 free(resolved_path
);
1265 if(free_share_name
) {