r775: merge trunk 774 to samba 3_0 - fix bad compare in for loop
[Samba.git] / source3 / client / mount.cifs.c
blob5670a147468c172efb7f68e95037f7f9d60fcdc6
1 /*
2 Mount helper utility for Linux CIFS VFS (virtual filesystem) client
3 Copyright (C) 2003 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. */
19 #ifndef _GNU_SOURCE
20 #define _GNU_SOURCE
21 #endif
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <pwd.h>
27 #include <sys/types.h>
28 #include <sys/mount.h>
29 #include <sys/stat.h>
30 #include <sys/utsname.h>
31 #include <sys/socket.h>
32 #include <arpa/inet.h>
33 #include <getopt.h>
34 #include <errno.h>
35 #include <netdb.h>
36 #include <string.h>
37 #include <mntent.h>
38 #include <fcntl.h>
40 #define MOUNT_CIFS_VERSION_MAJOR "1"
41 #define MOUNT_CIFS_VERSION_MINOR "3"
43 #ifndef MOUNT_CIFS_VENDOR_SUFFIX
44 #define MOUNT_CIFS_VENDOR_SUFFIX ""
45 #endif
47 #ifndef MS_MOVE
48 #define MS_MOVE 8192
49 #endif
51 char * thisprogram;
52 int verboseflag = 0;
53 static int got_password = 0;
54 static int got_user = 0;
55 static int got_domain = 0;
56 static int got_ip = 0;
57 static int got_unc = 0;
58 static int got_uid = 0;
59 static int got_gid = 0;
60 static char * user_name = NULL;
61 char * mountpassword = NULL;
64 /* BB finish BB
66 cifs_umount
67 open nofollow - avoid symlink exposure?
68 get owner of dir see if matches self or if root
69 call system(umount argv) etc.
71 BB end finish BB */
73 static void mount_cifs_usage(void)
75 printf("\nUsage: %s <remotetarget> <dir> -o <options>\n", thisprogram);
76 printf("\nMount the remote target, specified as a UNC name,");
77 printf(" to a local directory.\n\nOptions:\n");
78 printf("\tuser=<arg>\n\tpass=<arg>\n\tdom=<arg>\n");
79 printf("\nOther less commonly used options are described in the manual page");
80 printf("\n\tman 8 mount.cifs\n");
81 printf("\nTo display the version number of the mount helper:");
82 printf("\n\t%s -V\n",thisprogram);
84 if(mountpassword) {
85 memset(mountpassword,0,64);
86 free(mountpassword);
88 exit(1);
91 /* caller frees username if necessary */
92 static char * getusername(void) {
93 char *username = NULL;
94 struct passwd *password = getpwuid(getuid());
96 if (password) {
97 username = password->pw_name;
99 return username;
102 char * parse_cifs_url(char * unc_name)
104 printf("\nMounting cifs URL not implemented yet. Attempt to mount %s\n",unc_name);
105 return NULL;
108 static int open_cred_file(char * file_name)
110 char * line_buf;
111 char * temp_val;
112 FILE * fs;
113 int i, length;
114 fs = fopen(file_name,"r");
115 if(fs == NULL)
116 return errno;
117 line_buf = malloc(4096);
118 if(line_buf == NULL)
119 return -ENOMEM;
121 while(fgets(line_buf,4096,fs)) {
122 /* parse line from credential file */
124 /* eat leading white space */
125 for(i=0;i<4086;i++) {
126 if((line_buf[i] != ' ') && (line_buf[i] != '\t'))
127 break;
128 /* if whitespace - skip past it */
130 if (strncasecmp("username",line_buf+i,8) == 0) {
131 temp_val = strchr(line_buf + i,'=');
132 if(temp_val) {
133 /* go past equals sign */
134 temp_val++;
135 for(length = 0;length<4087;length++) {
136 if(temp_val[length] == '\n')
137 break;
139 if(length > 4086) {
140 printf("mount.cifs failed due to malformed username in credentials file");
141 memset(line_buf,0,4096);
142 if(mountpassword) {
143 memset(mountpassword,0,64);
145 exit(1);
146 } else {
147 got_user = 1;
148 user_name = calloc(1 + length,1);
149 /* BB adding free of user_name string before exit,
150 not really necessary but would be cleaner */
151 strncpy(user_name,temp_val, length);
154 } else if (strncasecmp("password",line_buf+i,8) == 0) {
155 temp_val = strchr(line_buf+i,'=');
156 if(temp_val) {
157 /* go past equals sign */
158 temp_val++;
159 for(length = 0;length<65;length++) {
160 if(temp_val[length] == '\n')
161 break;
163 if(length > 64) {
164 printf("mount.cifs failed: password in credentials file too long\n");
165 memset(line_buf,0, 4096);
166 if(mountpassword) {
167 memset(mountpassword,0,64);
169 exit(1);
170 } else {
171 if(mountpassword == NULL) {
172 mountpassword = calloc(65,1);
173 } else
174 memset(mountpassword,0,64);
175 if(mountpassword) {
176 /* BB add handling for commas in password here */
177 strncpy(mountpassword,temp_val,length);
178 got_password = 1;
184 fclose(fs);
185 if(line_buf) {
186 memset(line_buf,0,4096);
187 free(line_buf);
189 return 0;
192 static int get_password_from_file(int file_descript, char * filename)
194 int rc = 0;
195 int i;
196 char c;
198 if(mountpassword == NULL)
199 mountpassword = calloc(65,1);
200 else
201 memset(mountpassword, 0, 64);
203 if(filename != NULL) {
204 file_descript = open(filename, O_RDONLY);
205 if(file_descript < 0) {
206 printf("mount.cifs failed. %s attempting to open password file %s\n",
207 strerror(errno),filename);
208 exit(1);
211 /* else file already open and fd provided */
213 for(i=0;i<64;i++) {
214 rc = read(file_descript,&c,1);
215 if(rc < 0) {
216 printf("mount.cifs failed. Error %s reading password file\n",strerror(errno));
217 memset(mountpassword,0,64);
218 if(filename != NULL)
219 close(file_descript);
220 exit(1);
221 } else if(rc == 0) {
222 if(mountpassword[0] == 0) {
223 if(verboseflag)
224 printf("\nWarning: null password used since cifs password file empty");
226 break;
227 } else /* read valid character */ {
228 if((c == 0) || (c == '\n')) {
229 break;
230 } else
231 mountpassword[i] = c;
234 if((i == 64) && (verboseflag)) {
235 printf("\nWarning: password longer than 64 characters specified in cifs password file");
237 got_password = 1;
238 if(filename != NULL) {
239 close(file_descript);
242 return rc;
245 static int parse_options(char * options, int * filesys_flags)
247 char * data;
248 char * percent_char = 0;
249 char * value = 0;
250 char * next_keyword = 0;
251 int rc = 0;
253 if (!options)
254 return 1;
255 else
256 data = options;
258 if(verboseflag)
259 printf("\n parsing options: %s", options);
261 /* while ((data = strsep(&options, ",")) != NULL) { */
262 while(data != NULL) {
263 /* check if ends with trailing comma */
264 if(*data == 0)
265 break;
267 /* format is keyword=value,keyword2=value2,keyword3=value3 etc.) */
268 /* data = next keyword */
269 /* value = next value ie stuff after equal sign */
271 next_keyword = strchr(data,',');
273 /* temporarily null terminate end of keyword=value pair */
274 if(next_keyword)
275 *next_keyword = 0;
277 /* if (!*data)
278 continue; */
280 /* temporarily null terminate keyword to make keyword and value distinct */
281 if ((value = strchr(data, '=')) != NULL) {
282 *value = '\0';
283 value++;
286 if (strncmp(data, "user", 4) == 0) {
287 if (!value || !*value) {
288 if(data[4] == '\0') {
289 if(verboseflag)
290 printf("\nskipping empty user mount parameter\n");
291 /* remove the parm since it would otherwise be confusing
292 to the kernel code which would think it was a real username */
293 data[0] = ',';
294 data[1] = ',';
295 data[2] = ',';
296 data[3] = ',';
297 /* BB remove it from mount line so as not to confuse kernel code */
298 } else {
299 printf("username specified with no parameter\n");
300 return 1; /* needs_arg; */
302 } else {
303 if (strnlen(value, 260) < 260) {
304 got_user=1;
305 percent_char = strchr(value,'%');
306 if(percent_char) {
307 *percent_char = ',';
308 if(mountpassword == NULL)
309 mountpassword = calloc(65,1);
310 if(mountpassword) {
311 if(got_password)
312 printf("\nmount.cifs warning - password specified twice\n");
313 got_password = 1;
314 percent_char++;
315 strncpy(mountpassword, percent_char,64);
316 /* remove password from username */
317 while(*percent_char != 0) {
318 *percent_char = ',';
319 percent_char++;
323 } else {
324 printf("username too long\n");
325 return 1;
328 } else if (strncmp(data, "pass", 4) == 0) {
329 if (!value || !*value) {
330 if(got_password) {
331 printf("\npassword specified twice, ignoring second\n");
332 } else
333 got_password = 1;
334 } else if (strnlen(value, 17) < 17) {
335 if(got_password)
336 printf("\nmount.cifs warning - password specified twice\n");
337 got_password = 1;
338 } else {
339 printf("password too long\n");
340 return 1;
342 } else if (strncmp(data, "ip", 2) == 0) {
343 if (!value || !*value) {
344 printf("target ip address argument missing");
345 } else if (strnlen(value, 35) < 35) {
346 got_ip = 1;
347 } else {
348 printf("ip address too long\n");
349 return 1;
351 } else if ((strncmp(data, "unc", 3) == 0)
352 || (strncmp(data, "target", 6) == 0)
353 || (strncmp(data, "path", 4) == 0)) {
354 if (!value || !*value) {
355 printf("invalid path to network resource\n");
356 return 1; /* needs_arg; */
357 } else if(strnlen(value,5) < 5) {
358 printf("UNC name too short");
361 if (strnlen(value, 300) < 300) {
362 got_unc = 1;
363 if (strncmp(value, "//", 2) == 0) {
364 if(got_unc)
365 printf("unc name specified twice, ignoring second\n");
366 else
367 got_unc = 1;
368 } else if (strncmp(value, "\\\\", 2) != 0) {
369 printf("UNC Path does not begin with // or \\\\ \n");
370 return 1;
371 } else {
372 if(got_unc)
373 printf("unc name specified twice, ignoring second\n");
374 else
375 got_unc = 1;
377 } else {
378 printf("CIFS: UNC name too long\n");
379 return 1;
381 } else if ((strncmp(data, "domain", 3) == 0)
382 || (strncmp(data, "workgroup", 5) == 0)) {
383 if (!value || !*value) {
384 printf("CIFS: invalid domain name\n");
385 return 1; /* needs_arg; */
387 if (strnlen(value, 65) < 65) {
388 got_domain = 1;
389 } else {
390 printf("domain name too long\n");
391 return 1;
393 } else if (strncmp(data, "cred", 4) == 0) {
394 if (value && *value) {
395 rc = open_cred_file(value);
396 if(rc) {
397 printf("error %d opening credential file %s\n",rc, value);
398 return 1;
400 } else {
401 printf("invalid credential file name specified\n");
402 return 1;
404 } else if (strncmp(data, "uid", 3) == 0) {
405 if (value && *value) {
406 got_uid = 1;
408 } else if (strncmp(data, "gid", 3) == 0) {
409 if (value && *value) {
410 got_gid = 1;
412 /* fmask and dmask synonyms for people used to smbfs syntax */
413 } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) {
414 if (!value || !*value) {
415 printf ("Option '%s' requires a numerical argument\n", data);
416 return 1;
419 if (value[0] != '0') {
420 printf ("WARNING: '%s' not expressed in octal.\n", data);
423 if (strcmp (data, "fmask") == 0) {
424 printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
425 data = "file_mode"; /* BB fix this */
427 } else if (strcmp(data, "dir_mode") == 0 || strcmp(data, "dmask")==0) {
428 if (!value || !*value) {
429 printf ("Option '%s' requires a numerical argument\n", data);
430 return 1;
433 if (value[0] != '0') {
434 printf ("WARNING: '%s' not expressed in octal.\n", data);
437 if (strcmp (data, "dmask") == 0) {
438 printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
439 data = "dir_mode";
441 /* the following eight mount options should be
442 stripped out from what is passed into the kernel
443 since these eight options are best passed as the
444 mount flags rather than redundantly to the kernel
445 and could generate spurious warnings depending on the
446 level of the corresponding cifs vfs kernel code */
447 } else if (strncmp(data, "nosuid", 6) == 0) {
448 *filesys_flags |= MS_NOSUID;
449 } else if (strncmp(data, "suid", 4) == 0) {
450 *filesys_flags &= ~MS_NOSUID;
451 } else if (strncmp(data, "nodev", 5) == 0) {
452 *filesys_flags |= MS_NODEV;
453 } else if (strncmp(data, "dev", 3) == 0) {
454 *filesys_flags &= ~MS_NODEV;
455 } else if (strncmp(data, "noexec", 6) == 0) {
456 *filesys_flags |= MS_NOEXEC;
457 } else if (strncmp(data, "exec", 4) == 0) {
458 *filesys_flags &= ~MS_NOEXEC;
459 } else if (strncmp(data, "guest", 5) == 0) {
460 got_password=1;
461 } else if (strncmp(data, "ro", 2) == 0) {
462 *filesys_flags |= MS_RDONLY;
463 } else if (strncmp(data, "rw", 2) == 0) {
464 *filesys_flags &= ~MS_RDONLY;
465 } /* else if (strnicmp(data, "port", 4) == 0) {
466 if (value && *value) {
467 vol->port =
468 simple_strtoul(value, &value, 0);
470 } else if (strnicmp(data, "rsize", 5) == 0) {
471 if (value && *value) {
472 vol->rsize =
473 simple_strtoul(value, &value, 0);
475 } else if (strnicmp(data, "wsize", 5) == 0) {
476 if (value && *value) {
477 vol->wsize =
478 simple_strtoul(value, &value, 0);
480 } else if (strnicmp(data, "version", 3) == 0) {
481 } else {
482 printf("CIFS: Unknown mount option %s\n",data);
483 } */ /* nothing to do on those four mount options above.
484 Just pass to kernel and ignore them here */
486 /* move to next option */
487 data = next_keyword+1;
489 /* put overwritten equals sign back */
490 if(value) {
491 value--;
492 *value = '=';
495 /* put previous overwritten comma back */
496 if(next_keyword)
497 *next_keyword = ',';
498 else
499 data = 0;
501 return 0;
504 /* Note that caller frees the returned buffer if necessary */
505 char * parse_server(char * unc_name)
507 int length = strnlen(unc_name,1024);
508 char * share;
509 char * ipaddress_string = NULL;
510 struct hostent * host_entry;
511 struct in_addr server_ipaddr;
512 int rc;
514 if(length > 1023) {
515 printf("mount error: UNC name too long");
516 return 0;
518 if (strncasecmp("cifs://",unc_name,7) == 0)
519 return parse_cifs_url(unc_name+7);
520 if (strncasecmp("smb://",unc_name,6) == 0) {
521 return parse_cifs_url(unc_name+6);
524 if(length < 3) {
525 /* BB add code to find DFS root here */
526 printf("\nMounting the DFS root for domain not implemented yet");
527 return 0;
528 } else {
529 if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
530 printf("mount error: improperly formatted UNC name.");
531 printf(" %s does not begin with \\\\ or //\n",unc_name);
532 return 0;
533 } else {
534 unc_name[0] = '\\';
535 unc_name[0] = '/';
536 unc_name[1] = '/';
537 unc_name += 2;
538 if ((share = strchr(unc_name, '/')) ||
539 (share = strchr(unc_name,'\\'))) {
540 *share = 0; /* temporarily terminate the string */
541 share += 1;
542 host_entry = gethostbyname(unc_name);
543 *(share - 1) = '/'; /* put the slash back */
544 /* rc = getipnodebyname(unc_name, AF_INET, AT_ADDRCONFIG ,&rc);*/
545 if(host_entry == NULL) {
546 printf("mount error: could not find target server. TCP name %s not found ", unc_name);
547 printf(" rc = %d\n",rc);
548 return 0;
550 else {
551 /* BB should we pass an alternate version of the share name as Unicode */
552 /* BB what about ipv6? BB */
553 /* BB add retries with alternate servers in list */
555 memcpy(&server_ipaddr.s_addr, host_entry->h_addr, 4);
557 ipaddress_string = inet_ntoa(server_ipaddr);
558 if(ipaddress_string == NULL) {
559 printf("mount error: could not get valid ip address for target server\n");
560 return 0;
562 return ipaddress_string;
564 } else {
565 /* BB add code to find DFS root (send null path on get DFS Referral to specified server here */
566 printf("Mounting the DFS root for a particular server not implemented yet\n");
567 return 0;
573 static struct option longopts[] = {
574 { "all", 0, 0, 'a' },
575 { "help",0, 0, 'h' },
576 { "move",0, 0, 'm' },
577 { "bind",0, 0, 'b' },
578 { "read-only", 0, 0, 'r' },
579 { "ro", 0, 0, 'r' },
580 { "verbose", 0, 0, 'v' },
581 { "version", 0, 0, 'V' },
582 { "read-write", 0, 0, 'w' },
583 { "rw", 0, 0, 'w' },
584 { "options", 1, 0, 'o' },
585 { "type", 1, 0, 't' },
586 { "rsize",1, 0, 'R' },
587 { "wsize",1, 0, 'W' },
588 { "uid", 1, 0, '1'},
589 { "gid", 1, 0, '2'},
590 { "user",1,0,'u'},
591 { "username",1,0,'u'},
592 { "dom",1,0,'d'},
593 { "domain",1,0,'d'},
594 { "password",1,0,'p'},
595 { "pass",1,0,'p'},
596 { "credentials",1,0,'c'},
597 { "port",1,0,'P'},
598 /* { "uuid",1,0,'U'}, */ /* BB unimplemented */
599 { NULL, 0, 0, 0 }
602 int main(int argc, char ** argv)
604 int c;
605 int flags = MS_MANDLOCK; /* no need to set legacy MS_MGC_VAL */
606 char * orgoptions = NULL;
607 char * share_name = NULL;
608 char * domain_name = NULL;
609 char * ipaddr = NULL;
610 char * uuid = NULL;
611 char * mountpoint;
612 char * options;
613 char * resolved_path;
614 char * temp;
615 int rc;
616 int rsize = 0;
617 int wsize = 0;
618 int nomtab = 0;
619 int uid = 0;
620 int gid = 0;
621 int optlen = 0;
622 int orgoptlen = 0;
623 struct stat statbuf;
624 struct utsname sysinfo;
625 struct mntent mountent;
626 FILE * pmntfile;
628 /* setlocale(LC_ALL, "");
629 bindtextdomain(PACKAGE, LOCALEDIR);
630 textdomain(PACKAGE); */
632 if(argc && argv) {
633 thisprogram = argv[0];
635 if(thisprogram == NULL)
636 thisprogram = "mount.cifs";
638 uname(&sysinfo);
639 /* BB add workstation name and domain and pass down */
641 /* #ifdef _GNU_SOURCE
642 printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
643 #endif */
645 share_name = argv[1];
646 mountpoint = argv[2];
648 /* add sharename in opts string as unc= parm */
650 while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsSU:vVwt:",
651 longopts, NULL)) != -1) {
652 switch (c) {
653 /* No code to do the following options yet */
654 /* case 'l':
655 list_with_volumelabel = 1;
656 break;
657 case 'L':
658 volumelabel = optarg;
659 break; */
660 /* case 'a':
661 ++mount_all;
662 break; */
664 case '?':
665 case 'h': /* help */
666 mount_cifs_usage ();
667 exit(1);
668 case 'n':
669 ++nomtab;
670 break;
671 case 'b':
672 flags |= MS_BIND;
673 break;
674 case 'm':
675 flags |= MS_MOVE;
676 break;
677 case 'o':
678 orgoptions = strdup(optarg);
679 break;
680 case 'r': /* mount readonly */
681 flags |= MS_RDONLY;
682 break;
683 case 'U':
684 uuid = optarg;
685 break;
686 case 'v':
687 ++verboseflag;
688 break;
689 case 'V':
690 printf ("mount.cifs version: %s.%s%s\n",
691 MOUNT_CIFS_VERSION_MAJOR,
692 MOUNT_CIFS_VERSION_MINOR,
693 MOUNT_CIFS_VENDOR_SUFFIX);
694 if(mountpassword) {
695 memset(mountpassword,0,64);
697 exit (0);
698 case 'w':
699 flags &= ~MS_RDONLY;
700 break;
701 case 'R':
702 rsize = atoi(optarg) ;
703 break;
704 case 'W':
705 wsize = atoi(optarg);
706 break;
707 case '1':
708 uid = atoi(optarg);
709 break;
710 case '2':
711 gid = atoi(optarg);
712 break;
713 case 'u':
714 got_user = 1;
715 user_name = optarg;
716 break;
717 case 'd':
718 domain_name = optarg;
719 break;
720 case 'p':
721 if(mountpassword == NULL)
722 mountpassword = calloc(65,1);
723 if(mountpassword) {
724 got_password = 1;
725 strncpy(mountpassword,optarg,64);
727 break;
728 case 'S':
729 get_password_from_file(0 /* stdin */,NULL);
730 break;
731 case 't':
732 break;
733 default:
734 printf("unknown mount option %c\n",c);
735 mount_cifs_usage();
736 exit(1);
740 if(argc < 3)
741 mount_cifs_usage();
743 if (getenv("PASSWD")) {
744 if(mountpassword == NULL)
745 mountpassword = calloc(65,1);
746 if(mountpassword) {
747 strncpy(mountpassword,getenv("PASSWD"),64);
748 got_password = 1;
750 } else if (getenv("PASSWD_FD")) {
751 get_password_from_file(atoi(getenv("PASSWD_FD")),NULL);
752 } else if (getenv("PASSWD_FILE")) {
753 get_password_from_file(0, getenv("PASSWD_FILE"));
756 ipaddr = parse_server(share_name);
758 if(ipaddr == NULL)
759 return -1;
761 if (orgoptions && parse_options(orgoptions, &flags))
762 return -1;
764 /* BB save off path and pop after mount returns? */
765 resolved_path = malloc(PATH_MAX+1);
766 if(resolved_path) {
767 /* Note that if we can not canonicalize the name, we get
768 another chance to see if it is valid when we chdir to it */
769 if (realpath(mountpoint, resolved_path)) {
770 mountpoint = resolved_path;
773 if(chdir(mountpoint)) {
774 printf("mount error: can not change directory into mount target %s\n",mountpoint);
775 return -1;
778 if(stat (".", &statbuf)) {
779 printf("mount error: mount point %s does not exist\n",mountpoint);
780 return -1;
783 if (S_ISDIR(statbuf.st_mode) == 0) {
784 printf("mount error: mount point %s is not a directory\n",mountpoint);
785 return -1;
788 if((getuid() != 0) && (geteuid() == 0)) {
789 if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) {
790 #ifndef CIFS_ALLOW_USR_SUID
791 /* Do not allow user mounts to control suid flag
792 for mount unless explicitly built that way */
793 flags |= MS_NOSUID | MS_NODEV;
794 #endif
795 } else {
796 printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n");
797 return -1;
801 if(got_user == 0)
802 user_name = getusername();
804 if(got_password == 0) {
805 mountpassword = getpass("Password: "); /* BB obsolete */
806 got_password = 1;
808 /* FIXME launch daemon (handles dfs name resolution and credential change)
809 remember to clear parms and overwrite password field before launching */
810 if(orgoptions) {
811 optlen = strlen(orgoptions);
812 orgoptlen = optlen;
813 } else
814 optlen = 0;
815 if(share_name)
816 optlen += strlen(share_name) + 4;
817 if(user_name)
818 optlen += strlen(user_name) + 6;
819 if(ipaddr)
820 optlen += strlen(ipaddr) + 4;
821 if(mountpassword)
822 optlen += strlen(mountpassword) + 6;
823 options = malloc(optlen + 10);
825 if(options == NULL) {
826 printf("Could not allocate memory for mount options\n");
827 return -1;
831 options[0] = 0;
832 strncat(options,"unc=",4);
833 strcat(options,share_name);
834 /* scan backwards and reverse direction of slash */
835 temp = strrchr(options, '/');
836 if(temp > options + 6)
837 *temp = '\\';
838 if(ipaddr) {
839 strncat(options,",ip=",4);
840 strcat(options,ipaddr);
842 if(user_name) {
843 strncat(options,",user=",6);
844 strcat(options,user_name);
846 if(mountpassword) {
847 strncat(options,",pass=",6);
848 strcat(options,mountpassword);
850 strncat(options,",ver=",5);
851 strcat(options,MOUNT_CIFS_VERSION_MAJOR);
853 if(orgoptions) {
854 strcat(options,",");
855 strcat(options,orgoptions);
857 if(verboseflag)
858 printf("\nmount.cifs kernel mount options %s \n",options);
859 if(mount(share_name, mountpoint, "cifs", flags, options)) {
860 /* remember to kill daemon on error */
861 switch (errno) {
862 case 0:
863 printf("mount failed but no error number set\n");
864 break;
865 case ENODEV:
866 printf("mount error: cifs filesystem not supported by the system\n");
867 break;
868 default:
869 printf("mount error %d = %s\n",errno,strerror(errno));
871 printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
872 if(mountpassword) {
873 memset(mountpassword,0,64);
875 return -1;
876 } else {
877 pmntfile = setmntent(MOUNTED, "a+");
878 if(pmntfile) {
879 mountent.mnt_fsname = share_name;
880 mountent.mnt_dir = mountpoint;
881 mountent.mnt_type = "cifs";
882 mountent.mnt_opts = malloc(200);
883 if(mountent.mnt_opts) {
884 memset(mountent.mnt_opts,0,200);
885 if(flags & MS_RDONLY)
886 strcat(mountent.mnt_opts,"ro");
887 else
888 strcat(mountent.mnt_opts,"rw");
889 if(flags & MS_MANDLOCK)
890 strcat(mountent.mnt_opts,",mand");
891 else
892 strcat(mountent.mnt_opts,",nomand");
893 if(flags & MS_NOEXEC)
894 strcat(mountent.mnt_opts,",noexec");
895 if(flags & MS_NOSUID)
896 strcat(mountent.mnt_opts,",nosuid");
897 if(flags & MS_NODEV)
898 strcat(mountent.mnt_opts,",nodev");
899 if(flags & MS_SYNCHRONOUS)
900 strcat(mountent.mnt_opts,",synch");
902 mountent.mnt_freq = 0;
903 mountent.mnt_passno = 0;
904 rc = addmntent(pmntfile,&mountent);
905 endmntent(pmntfile);
906 if(mountent.mnt_opts)
907 free(mountent.mnt_opts);
908 } else {
909 printf("could not update mount table\n");
912 if(mountpassword) {
913 memset(mountpassword,0,64);
914 free(mountpassword);
917 if(options) {
918 memset(options,0,optlen);
919 free(options);
922 if(orgoptions) {
923 memset(orgoptions,0,orgoptlen);
924 free(orgoptions);
926 if(resolved_path) {
927 free(resolved_path);
930 return 0;