r39: * importing .cvsignore files
[Samba/gebeck_regimport.git] / source / client / mount.cifs.c
blobc31a9d66b34a152a60b508557169ed7d50839223
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 "2"
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");
78 if(mountpassword) {
79 memset(mountpassword,0,64);
80 free(mountpassword);
82 exit(1);
85 /* caller frees username if necessary */
86 static char * getusername(void) {
87 char *username = NULL;
88 struct passwd *password = getpwuid(getuid());
90 if (password) {
91 username = password->pw_name;
93 return username;
96 char * parse_cifs_url(char * unc_name)
98 printf("\ncifs url %s\n",unc_name);
99 return NULL;
102 static int open_cred_file(char * file_name)
104 char * line_buf;
105 char * temp_val;
106 FILE * fs;
107 int i, length;
108 fs = fopen(file_name,"r");
109 if(fs == NULL)
110 return errno;
111 line_buf = malloc(4096);
112 if(line_buf == NULL)
113 return -ENOMEM;
115 while(fgets(line_buf,4096,fs)) {
116 /* parse line from credential file */
118 /* eat leading white space */
119 for(i=0;i<4086;i++) {
120 if((line_buf[i] != ' ') && (line_buf[i] != '\t'))
121 break;
122 /* if whitespace - skip past it */
124 if (strncasecmp("username",line_buf+i,8) == 0) {
125 temp_val = strchr(line_buf + i,'=');
126 if(temp_val) {
127 /* go past equals sign */
128 temp_val++;
129 for(length = 0;length<4087;length++) {
130 if(temp_val[length] == '\n')
131 break;
133 if(length > 4086) {
134 printf("cifs.mount failed due to malformed username in credentials file");
135 memset(line_buf,0,4096);
136 if(mountpassword) {
137 memset(mountpassword,0,64);
139 exit(1);
140 } else {
141 got_user = 1;
142 user_name = calloc(1 + length,1);
143 /* BB adding free of user_name string before exit,
144 not really necessary but would be cleaner */
145 strncpy(user_name,temp_val, length);
148 } else if (strncasecmp("password",line_buf+i,8) == 0) {
149 temp_val = strchr(line_buf+i,'=');
150 if(temp_val) {
151 /* go past equals sign */
152 temp_val++;
153 for(length = 0;length<65;length++) {
154 if(temp_val[length] == '\n')
155 break;
157 if(length > 64) {
158 printf("cifs.mount failed: password in credentials file too long\n");
159 memset(line_buf,0, 4096);
160 if(mountpassword) {
161 memset(mountpassword,0,64);
163 exit(1);
164 } else {
165 if(mountpassword == NULL) {
166 mountpassword = calloc(65,1);
167 } else
168 memset(mountpassword,0,64);
169 if(mountpassword) {
170 /* BB add handling for commas in password here */
171 strncpy(mountpassword,temp_val,length);
172 got_password = 1;
178 fclose(fs);
179 if(line_buf) {
180 memset(line_buf,0,4096);
181 free(line_buf);
183 return 0;
186 static int get_password_from_file(int file_descript, char * filename)
188 int rc = 0;
189 int i;
190 char c;
192 if(mountpassword == NULL)
193 mountpassword = calloc(65,1);
194 else
195 memset(mountpassword, 0, 64);
197 if(filename != NULL) {
198 file_descript = open(filename, O_RDONLY);
199 if(file_descript < 0) {
200 printf("cifs.mount failed. %s attempting to open password file %s\n",
201 strerror(errno),filename);
202 exit(1);
205 /* else file already open and fd provided */
207 for(i=0;i<64;i++) {
208 rc = read(file_descript,&c,1);
209 if(rc < 0) {
210 printf("cifs.mount failed. Error %s reading password file\n",strerror(errno));
211 memset(mountpassword,0,64);
212 if(filename != NULL)
213 close(file_descript);
214 exit(1);
215 } else if(rc == 0) {
216 if(mountpassword[0] == 0) {
217 if(verboseflag)
218 printf("\nWarning: null password used since cifs password file empty");
220 break;
221 } else /* read valid character */ {
222 if((c == 0) || (c == '\n')) {
223 break;
224 } else
225 mountpassword[i] = c;
228 if((i == 64) && (verboseflag)) {
229 printf("\nWarning: password longer than 64 characters specified in cifs password file");
231 got_password = 1;
232 if(filename != NULL) {
233 close(file_descript);
236 return rc;
239 static int parse_options(char * options, int * filesys_flags)
241 char * data;
242 char * percent_char = 0;
243 char * value = 0;
244 char * next_keyword = 0;
245 int rc = 0;
247 if (!options)
248 return 1;
249 else
250 data = options;
252 if(verboseflag)
253 printf("\n parsing options: %s", options);
255 /* while ((data = strsep(&options, ",")) != NULL) { */
256 while(data != NULL) {
257 /* check if ends with trailing comma */
258 if(*data == 0)
259 break;
261 /* format is keyword=value,keyword2=value2,keyword3=value3 etc.) */
262 /* data = next keyword */
263 /* value = next value ie stuff after equal sign */
265 next_keyword = strchr(data,',');
267 /* temporarily null terminate end of keyword=value pair */
268 if(next_keyword)
269 *next_keyword = 0;
271 /* if (!*data)
272 continue; */
274 /* temporarily null terminate keyword to make keyword and value distinct */
275 if ((value = strchr(data, '=')) != NULL) {
276 *value = '\0';
277 value++;
280 if (strncmp(data, "user", 4) == 0) {
281 if (!value || !*value) {
282 printf("invalid or missing username\n");
283 return 1; /* needs_arg; */
285 if (strnlen(value, 260) < 260) {
286 got_user=1;
287 percent_char = strchr(value,'%');
288 if(percent_char) {
289 *percent_char = ',';
290 if(mountpassword == NULL)
291 mountpassword = calloc(65,1);
292 if(mountpassword) {
293 if(got_password)
294 printf("\ncifs.mount warning - password specified twice\n");
295 got_password = 1;
296 percent_char++;
297 strncpy(mountpassword, percent_char,64);
298 /* remove password from username */
299 while(*percent_char != 0) {
300 *percent_char = ',';
301 percent_char++;
305 } else {
306 printf("username too long\n");
307 return 1;
309 } else if (strncmp(data, "pass", 4) == 0) {
310 if (!value || !*value) {
311 if(got_password) {
312 printf("\npassword specified twice, ignoring second\n");
313 } else
314 got_password = 1;
315 } else if (strnlen(value, 17) < 17) {
316 if(got_password)
317 printf("\ncifs.mount warning - password specified twice\n");
318 got_password = 1;
319 } else {
320 printf("password too long\n");
321 return 1;
323 } else if (strncmp(data, "ip", 2) == 0) {
324 if (!value || !*value) {
325 printf("target ip address argument missing");
326 } else if (strnlen(value, 35) < 35) {
327 got_ip = 1;
328 } else {
329 printf("ip address too long\n");
330 return 1;
332 } else if ((strncmp(data, "unc", 3) == 0)
333 || (strncmp(data, "target", 6) == 0)
334 || (strncmp(data, "path", 4) == 0)) {
335 if (!value || !*value) {
336 printf("invalid path to network resource\n");
337 return 1; /* needs_arg; */
338 } else if(strnlen(value,5) < 5) {
339 printf("UNC name too short");
342 if (strnlen(value, 300) < 300) {
343 got_unc = 1;
344 if (strncmp(value, "//", 2) == 0) {
345 if(got_unc)
346 printf("unc name specified twice, ignoring second\n");
347 else
348 got_unc = 1;
349 } else if (strncmp(value, "\\\\", 2) != 0) {
350 printf("UNC Path does not begin with // or \\\\ \n");
351 return 1;
352 } else {
353 if(got_unc)
354 printf("unc name specified twice, ignoring second\n");
355 else
356 got_unc = 1;
358 } else {
359 printf("CIFS: UNC name too long\n");
360 return 1;
362 } else if ((strncmp(data, "domain", 3) == 0)
363 || (strncmp(data, "workgroup", 5) == 0)) {
364 if (!value || !*value) {
365 printf("CIFS: invalid domain name\n");
366 return 1; /* needs_arg; */
368 if (strnlen(value, 65) < 65) {
369 got_domain = 1;
370 } else {
371 printf("domain name too long\n");
372 return 1;
374 } else if (strncmp(data, "cred", 4) == 0) {
375 if (value && *value) {
376 rc = open_cred_file(value);
377 if(rc) {
378 printf("error %d opening credential file %s\n",rc, value);
379 return 1;
381 } else {
382 printf("invalid credential file name specified\n");
383 return 1;
385 } else if (strncmp(data, "uid", 3) == 0) {
386 if (value && *value) {
387 got_uid = 1;
389 } else if (strncmp(data, "gid", 3) == 0) {
390 if (value && *value) {
391 got_gid = 1;
393 /* fmask and dmask synonyms for people used to smbfs syntax */
394 } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) {
395 if (!value || !*value) {
396 printf ("Option '%s' requires a numerical argument\n", data);
397 return 1;
400 if (value[0] != '0') {
401 printf ("WARNING: '%s' not expressed in octal.\n", data);
404 if (strcmp (data, "fmask") == 0) {
405 printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
406 data = "file_mode"; /* BB fix this */
408 } else if (strcmp(data, "dir_mode") == 0 || strcmp(data, "dmask")==0) {
409 if (!value || !*value) {
410 printf ("Option '%s' requires a numerical argument\n", data);
411 return 1;
414 if (value[0] != '0') {
415 printf ("WARNING: '%s' not expressed in octal.\n", data);
418 if (strcmp (data, "dmask") == 0) {
419 printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
420 data = "dir_mode";
422 /* the following eight mount options should be
423 stripped out from what is passed into the kernel
424 since these eight options are best passed as the
425 mount flags rather than redundantly to the kernel
426 and could generate spurious warnings depending on the
427 level of the corresponding cifs vfs kernel code */
428 } else if (strncmp(data, "nosuid", 6) == 0) {
429 *filesys_flags |= MS_NOSUID;
430 } else if (strncmp(data, "suid", 4) == 0) {
431 *filesys_flags &= ~MS_NOSUID;
432 } else if (strncmp(data, "nodev", 5) == 0) {
433 *filesys_flags |= MS_NODEV;
434 } else if (strncmp(data, "dev", 3) == 0) {
435 *filesys_flags &= ~MS_NODEV;
436 } else if (strncmp(data, "noexec", 6) == 0) {
437 *filesys_flags |= MS_NOEXEC;
438 } else if (strncmp(data, "exec", 4) == 0) {
439 *filesys_flags &= ~MS_NOEXEC;
440 } else if (strncmp(data, "ro", 2) == 0) {
441 *filesys_flags |= MS_RDONLY;
442 } else if (strncmp(data, "rw", 2) == 0) {
443 *filesys_flags &= ~MS_RDONLY;
444 } /* else if (strnicmp(data, "port", 4) == 0) {
445 if (value && *value) {
446 vol->port =
447 simple_strtoul(value, &value, 0);
449 } else if (strnicmp(data, "rsize", 5) == 0) {
450 if (value && *value) {
451 vol->rsize =
452 simple_strtoul(value, &value, 0);
454 } else if (strnicmp(data, "wsize", 5) == 0) {
455 if (value && *value) {
456 vol->wsize =
457 simple_strtoul(value, &value, 0);
459 } else if (strnicmp(data, "version", 3) == 0) {
460 } else {
461 printf("CIFS: Unknown mount option %s\n",data);
462 } */ /* nothing to do on those four mount options above.
463 Just pass to kernel and ignore them here */
465 /* move to next option */
466 data = next_keyword+1;
468 /* put overwritten equals sign back */
469 if(value) {
470 value--;
471 *value = '=';
474 /* put previous overwritten comma back */
475 if(next_keyword)
476 *next_keyword = ',';
477 else
478 data = 0;
481 return 0;
484 /* Note that caller frees the returned buffer if necessary */
485 char * parse_server(char * unc_name)
487 int length = strnlen(unc_name,1024);
488 char * share;
489 char * ipaddress_string = NULL;
490 struct hostent * host_entry;
491 struct in_addr server_ipaddr;
492 int rc;
494 if(length > 1023) {
495 printf("mount error: UNC name too long");
496 return 0;
498 if (strncasecmp("cifs://",unc_name,7) == 0)
499 return parse_cifs_url(unc_name+7);
500 if (strncasecmp("smb://",unc_name,6) == 0) {
501 return parse_cifs_url(unc_name+6);
504 if(length < 3) {
505 /* BB add code to find DFS root here */
506 printf("\nMounting the DFS root for domain not implemented yet");
507 return 0;
508 } else {
509 if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
510 printf("mount error: improperly formatted UNC name.");
511 printf(" %s does not begin with \\\\ or //\n",unc_name);
512 return 0;
513 } else {
514 unc_name[0] = '\\';
515 unc_name[0] = '/';
516 unc_name[1] = '/';
517 unc_name += 2;
518 if ((share = strchr(unc_name, '/')) ||
519 (share = strchr(unc_name,'\\'))) {
520 *share = 0; /* temporarily terminate the string */
521 share += 1;
522 host_entry = gethostbyname(unc_name);
523 *(share - 1) = '/'; /* put the slash back */
524 /* rc = getipnodebyname(unc_name, AF_INET, AT_ADDRCONFIG ,&rc);*/
525 if(host_entry == NULL) {
526 printf("mount error: could not find target server. TCP name %s not found ", unc_name);
527 printf(" rc = %d\n",rc);
528 return 0;
530 else {
531 /* BB should we pass an alternate version of the share name as Unicode */
532 /* BB what about ipv6? BB */
533 /* BB add retries with alternate servers in list */
535 memcpy(&server_ipaddr.s_addr, host_entry->h_addr, 4);
537 ipaddress_string = inet_ntoa(server_ipaddr);
538 if(ipaddress_string == NULL) {
539 printf("mount error: could not get valid ip address for target server\n");
540 return 0;
542 return ipaddress_string;
544 } else {
545 /* BB add code to find DFS root (send null path on get DFS Referral to specified server here */
546 printf("Mounting the DFS root for a particular server not implemented yet\n");
547 return 0;
553 static struct option longopts[] = {
554 { "all", 0, 0, 'a' },
555 { "help",0, 0, 'h' },
556 { "move",0, 0, 'm' },
557 { "bind",0, 0, 'b' },
558 { "read-only", 0, 0, 'r' },
559 { "ro", 0, 0, 'r' },
560 { "verbose", 0, 0, 'v' },
561 { "version", 0, 0, 'V' },
562 { "read-write", 0, 0, 'w' },
563 { "rw", 0, 0, 'w' },
564 { "options", 1, 0, 'o' },
565 { "type", 1, 0, 't' },
566 { "rsize",1, 0, 'R' },
567 { "wsize",1, 0, 'W' },
568 { "uid", 1, 0, '1'},
569 { "gid", 1, 0, '2'},
570 { "user",1,0,'u'},
571 { "username",1,0,'u'},
572 { "dom",1,0,'d'},
573 { "domain",1,0,'d'},
574 { "password",1,0,'p'},
575 { "pass",1,0,'p'},
576 { "credentials",1,0,'c'},
577 { "port",1,0,'P'},
578 /* { "uuid",1,0,'U'}, */ /* BB unimplemented */
579 { NULL, 0, 0, 0 }
582 int main(int argc, char ** argv)
584 int c;
585 int flags = MS_MANDLOCK; /* no need to set legacy MS_MGC_VAL */
586 char * orgoptions = NULL;
587 char * share_name = NULL;
588 char * domain_name = NULL;
589 char * ipaddr = NULL;
590 char * uuid = NULL;
591 char * mountpoint;
592 char * options;
593 char * temp;
594 int rc;
595 int rsize = 0;
596 int wsize = 0;
597 int nomtab = 0;
598 int uid = 0;
599 int gid = 0;
600 int optlen = 0;
601 int orgoptlen = 0;
602 struct stat statbuf;
603 struct utsname sysinfo;
604 struct mntent mountent;
605 FILE * pmntfile;
607 /* setlocale(LC_ALL, "");
608 bindtextdomain(PACKAGE, LOCALEDIR);
609 textdomain(PACKAGE); */
611 if(argc && argv) {
612 thisprogram = argv[0];
614 if(thisprogram == NULL)
615 thisprogram = "mount.cifs";
617 uname(&sysinfo);
618 /* BB add workstation name and domain and pass down */
620 /* #ifdef _GNU_SOURCE
621 printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
622 #endif */
624 share_name = argv[1];
625 mountpoint = argv[2];
627 /* add sharename in opts string as unc= parm */
629 while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsU:vVwt:",
630 longopts, NULL)) != -1) {
631 switch (c) {
632 /* No code to do the following options yet */
633 /* case 'l':
634 list_with_volumelabel = 1;
635 break;
636 case 'L':
637 volumelabel = optarg;
638 break; */
639 /* case 'a':
640 ++mount_all;
641 break; */
643 case '?':
644 case 'h': /* help */
645 mount_cifs_usage ();
646 exit(1);
647 case 'n':
648 ++nomtab;
649 break;
650 case 'b':
651 flags |= MS_BIND;
652 break;
653 case 'm':
654 flags |= MS_MOVE;
655 break;
656 case 'o':
657 orgoptions = strdup(optarg);
658 break;
659 case 'r': /* mount readonly */
660 flags |= MS_RDONLY;
661 break;
662 case 'U':
663 uuid = optarg;
664 break;
665 case 'v':
666 ++verboseflag;
667 break;
668 case 'V':
669 printf ("mount.cifs version: %s.%s%s\n",
670 MOUNT_CIFS_VERSION_MAJOR,
671 MOUNT_CIFS_VERSION_MINOR,
672 MOUNT_CIFS_VENDOR_SUFFIX);
673 if(mountpassword) {
674 memset(mountpassword,0,64);
676 exit (0);
677 case 'w':
678 flags &= ~MS_RDONLY;
679 break;
680 case 'R':
681 rsize = atoi(optarg) ;
682 break;
683 case 'W':
684 wsize = atoi(optarg);
685 break;
686 case '1':
687 uid = atoi(optarg);
688 break;
689 case '2':
690 gid = atoi(optarg);
691 break;
692 case 'u':
693 got_user = 1;
694 user_name = optarg;
695 break;
696 case 'd':
697 domain_name = optarg;
698 break;
699 case 'p':
700 if(mountpassword == NULL)
701 mountpassword = calloc(65,1);
702 if(mountpassword) {
703 got_password = 1;
704 strncpy(mountpassword,optarg,64);
706 break;
707 case 't':
708 break;
709 default:
710 printf("unknown mount option %c\n",c);
711 mount_cifs_usage();
712 exit(1);
716 if(argc < 3)
717 mount_cifs_usage();
719 if (getenv("PASSWD")) {
720 if(mountpassword == NULL)
721 mountpassword = calloc(65,1);
722 if(mountpassword) {
723 strncpy(mountpassword,getenv("PASSWD"),64);
724 got_password = 1;
726 } else if (getenv("PASSWD_FD")) {
727 get_password_from_file(atoi(getenv("PASSWD_FD")),NULL);
728 } else if (getenv("PASSWD_FILE")) {
729 get_password_from_file(0, getenv("PASSWD_FILE"));
732 ipaddr = parse_server(share_name);
734 if (orgoptions && parse_options(orgoptions, &flags))
735 return 1;
737 /* BB save off path and pop after mount returns? */
738 /* BB canonicalize the path in argv[1]? */
740 if(chdir(mountpoint)) {
741 printf("mount error: can not change directory into mount target %s\n",mountpoint);
742 return -1;
745 if(stat (".", &statbuf)) {
746 printf("mount error: mount point %s does not exist\n",mountpoint);
747 return -1;
750 if (S_ISDIR(statbuf.st_mode) == 0) {
751 printf("mount error: mount point %s is not a directory\n",mountpoint);
752 return -1;
755 if((getuid() != 0) && (geteuid() == 0)) {
756 if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) {
757 #ifndef CIFS_ALLOW_USR_SUID
758 /* Do not allow user mounts to control suid flag
759 for mount unless explicitly built that way */
760 flags |= MS_NOSUID | MS_NODEV;
761 #endif
762 } else {
763 printf("mount error: permission denied or not superuser and cifs.mount not installed SUID\n");
764 return -1;
768 if(got_user == 0)
769 user_name = getusername();
771 if(got_password == 0) {
772 mountpassword = getpass("Password: "); /* BB obsolete */
773 got_password = 1;
775 /* FIXME launch daemon (handles dfs name resolution and credential change)
776 remember to clear parms and overwrite password field before launching */
777 if(orgoptions) {
778 optlen = strlen(orgoptions);
779 orgoptlen = optlen;
780 } else
781 optlen = 0;
782 if(share_name)
783 optlen += strlen(share_name) + 4;
784 if(user_name)
785 optlen += strlen(user_name) + 6;
786 if(ipaddr)
787 optlen += strlen(ipaddr) + 4;
788 if(mountpassword)
789 optlen += strlen(mountpassword) + 6;
790 options = malloc(optlen + 10);
792 if(options == NULL) {
793 printf("Could not allocate memory for mount options\n");
794 return -1;
798 options[0] = 0;
799 strncat(options,"unc=",4);
800 strcat(options,share_name);
801 /* scan backwards and reverse direction of slash */
802 temp = strrchr(options, '/');
803 if(temp > options + 6)
804 *temp = '\\';
805 if(ipaddr) {
806 strncat(options,",ip=",4);
807 strcat(options,ipaddr);
809 if(user_name) {
810 strncat(options,",user=",6);
811 strcat(options,user_name);
813 if(mountpassword) {
814 strncat(options,",pass=",6);
815 strcat(options,mountpassword);
817 strncat(options,",ver=",5);
818 strcat(options,MOUNT_CIFS_VERSION_MAJOR);
820 if(orgoptions) {
821 strcat(options,",");
822 strcat(options,orgoptions);
824 if(verboseflag)
825 printf("\ncifs.mount kernel mount options %s \n",options);
826 if(mount(share_name, mountpoint, "cifs", flags, options)) {
827 /* remember to kill daemon on error */
828 switch (errno) {
829 case 0:
830 printf("mount failed but no error number set\n");
831 break;
832 case ENODEV:
833 printf("mount error: cifs filesystem not supported by the system\n");
834 break;
835 default:
836 printf("mount error %d = %s\n",errno,strerror(errno));
838 printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
839 if(mountpassword) {
840 memset(mountpassword,0,64);
842 return -1;
843 } else {
844 pmntfile = setmntent(MOUNTED, "a+");
845 if(pmntfile) {
846 mountent.mnt_fsname = share_name;
847 mountent.mnt_dir = mountpoint;
848 mountent.mnt_type = "cifs";
849 mountent.mnt_opts = malloc(200);
850 if(mountent.mnt_opts) {
851 memset(mountent.mnt_opts,0,200);
852 if(flags & MS_RDONLY)
853 strcat(mountent.mnt_opts,"ro");
854 else
855 strcat(mountent.mnt_opts,"rw");
856 if(flags & MS_MANDLOCK)
857 strcat(mountent.mnt_opts,",mand");
858 else
859 strcat(mountent.mnt_opts,",nomand");
860 if(flags & MS_NOEXEC)
861 strcat(mountent.mnt_opts,",noexec");
862 if(flags & MS_NOSUID)
863 strcat(mountent.mnt_opts,",nosuid");
864 if(flags & MS_NODEV)
865 strcat(mountent.mnt_opts,",nodev");
866 if(flags & MS_SYNCHRONOUS)
867 strcat(mountent.mnt_opts,",synch");
869 mountent.mnt_freq = 0;
870 mountent.mnt_passno = 0;
871 rc = addmntent(pmntfile,&mountent);
872 endmntent(pmntfile);
873 if(mountent.mnt_opts)
874 free(mountent.mnt_opts);
875 } else {
876 printf("could not update mount table\n");
879 if(mountpassword) {
880 memset(mountpassword,0,64);
881 free(mountpassword);
884 if(options) {
885 memset(options,0,optlen);
886 free(options);
889 if(orgoptions) {
890 memset(orgoptions,0,orgoptlen);
891 free(orgoptions);
893 return 0;