summaryrefslogtreecommitdiff
path: root/source3/client/mount.cifs.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/client/mount.cifs.c')
-rw-r--r--source3/client/mount.cifs.c98
1 files changed, 69 insertions, 29 deletions
diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c
index ec245ed200..79f402a7d4 100644
--- a/source3/client/mount.cifs.c
+++ b/source3/client/mount.cifs.c
@@ -39,7 +39,7 @@
#include <fcntl.h>
#define MOUNT_CIFS_VERSION_MAJOR "1"
-#define MOUNT_CIFS_VERSION_MINOR "10"
+#define MOUNT_CIFS_VERSION_MINOR "11"
#ifndef MOUNT_CIFS_VENDOR_SUFFIX
#ifdef _SAMBA_BUILD_
@@ -62,6 +62,8 @@
#define MS_BIND 4096
#endif
+#define MAX_UNC_LEN 1024
+
#define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr)))
const char *thisprogram;
@@ -73,7 +75,6 @@ static int got_ip = 0;
static int got_unc = 0;
static int got_uid = 0;
static int got_gid = 0;
-static int free_share_name = 0;
static char * user_name = NULL;
static char * mountpassword = NULL;
char * domain_name = NULL;
@@ -135,14 +136,16 @@ static void mount_cifs_usage(void)
printf("\nLess commonly used options:");
printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,rw,ro,");
printf("\n\tsep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,serverino,");
- printf("\n\tdirectio,mapchars,nomapchars,nolock,servernetbiosname=<SRV_RFC1001NAME>");
+ printf("\n\tmapchars,nomapchars,nolock,servernetbiosname=<SRV_RFC1001NAME>");
+ printf("\n\tdirectio,nounix,cifsacl,sec=<authentication mechanism>,sign");
printf("\n\nOptions not needed for servers supporting CIFS Unix extensions");
printf("\n\t(e.g. unneeded for mounts to most Samba versions):");
printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>,sfu");
printf("\n\nRarely used options:");
printf("\n\tport=<tcpport>,rsize=<size>,wsize=<size>,unc=<unc_name>,ip=<ip_address>,");
printf("\n\tdev,nodev,nouser_xattr,netbiosname=<OUR_RFC1001NAME>,hard,soft,intr,");
- printf("\n\tnointr,ignorecase,noposixpaths,noacl");
+ printf("\n\tnointr,ignorecase,noposixpaths,noacl,prefixpath=<path>,nobrl");
+ printf("\n\tin6_addr");
printf("\n\nOptions are described in more detail in the manual page");
printf("\n\tman 8 mount.cifs\n");
printf("\nTo display the version number of the mount helper:");
@@ -828,17 +831,27 @@ static char * check_for_domain(char **ppuser)
return domainnm;
}
+/* replace all occurances of "from" in a string with "to" */
+static void replace_char(char *string, char from, char to)
+{
+ while (string) {
+ string = strchr(string, from);
+ if (string)
+ *string = to;
+ }
+}
+
/* Note that caller frees the returned buffer if necessary */
static char * parse_server(char ** punc_name)
{
char * unc_name = *punc_name;
- int length = strnlen(unc_name,1024);
+ int length = strnlen(unc_name, MAX_UNC_LEN);
char * share;
char * ipaddress_string = NULL;
struct hostent * host_entry = NULL;
struct in_addr server_ipaddr;
- if(length > 1023) {
+ if(length > (MAX_UNC_LEN - 1)) {
printf("mount error: UNC name too long");
return NULL;
}
@@ -857,7 +870,6 @@ static char * parse_server(char ** punc_name)
/* check for nfs syntax ie server:share */
share = strchr(unc_name,':');
if(share) {
- free_share_name = 1;
*punc_name = (char *)malloc(length+3);
if(*punc_name == NULL) {
/* put the original string back if
@@ -865,9 +877,9 @@ static char * parse_server(char ** punc_name)
*punc_name = unc_name;
return NULL;
}
-
*share = '/';
strncpy((*punc_name)+2,unc_name,length);
+ free(unc_name);
unc_name = *punc_name;
unc_name[length+2] = 0;
goto continue_unc_parsing;
@@ -878,18 +890,21 @@ static char * parse_server(char ** punc_name)
}
} else {
continue_unc_parsing:
- unc_name[0] = '/';
- unc_name[1] = '/';
+ unc_name[0] = '\\';
+ unc_name[1] = '\\';
unc_name += 2;
- if ((share = strchr(unc_name, '/')) ||
- (share = strchr(unc_name,'\\'))) {
+
+ /* convert any '/' in unc to '\\' */
+ replace_char(unc_name, '/', '\\');
+
+ if ((share = strchr(unc_name,'\\'))) {
*share = 0; /* temporarily terminate the string */
share += 1;
if(got_ip == 0) {
host_entry = gethostbyname(unc_name);
}
- *(share - 1) = '/'; /* put the slash back */
- if ((prefixpath = strchr(share, '/'))) {
+ *(share - 1) = '\\'; /* put delimiter back */
+ if ((prefixpath = strchr(share, '\\'))) {
*prefixpath = 0; /* permanently terminate the string */
if (!strlen(++prefixpath))
prefixpath = NULL; /* this needs to be done explicitly */
@@ -954,6 +969,25 @@ static struct option longopts[] = {
{ NULL, 0, NULL, 0 }
};
+/* convert a string to uppercase. return false if the string
+ * wasn't ASCII or was a NULL ptr */
+static int
+uppercase_string(char *string)
+{
+ if (!string)
+ return 0;
+
+ while (*string) {
+ /* check for unicode */
+ if ((unsigned char) string[0] & 0x80)
+ return 0;
+ *string = toupper((unsigned char) *string);
+ string++;
+ }
+
+ return 1;
+}
+
int main(int argc, char ** argv)
{
int c;
@@ -966,6 +1000,7 @@ int main(int argc, char ** argv)
char * options = NULL;
char * resolved_path = NULL;
char * temp;
+ char * dev_name;
int rc;
int rsize = 0;
int wsize = 0;
@@ -1002,8 +1037,16 @@ int main(int argc, char ** argv)
printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
#endif */
if(argc > 2) {
- share_name = argv[1];
+ dev_name = argv[1];
+ share_name = strndup(argv[1], MAX_UNC_LEN);
+ if (share_name == NULL) {
+ fprintf(stderr, "%s: %s", argv[0], strerror(ENOMEM));
+ exit(1);
+ }
mountpoint = argv[2];
+ } else {
+ mount_cifs_usage();
+ exit(1);
}
/* add sharename in opts string as unc= parm */
@@ -1143,7 +1186,7 @@ int main(int argc, char ** argv)
}
}
- if((argc < 3) || (share_name == NULL) || (mountpoint == NULL)) {
+ if((argc < 3) || (dev_name == NULL) || (mountpoint == NULL)) {
mount_cifs_usage();
exit(1);
}
@@ -1301,10 +1344,12 @@ mount_retry:
}
if(verboseflag)
printf("\nmount.cifs kernel mount options %s \n",options);
- if(mount(share_name, mountpoint, "cifs", flags, options)) {
- /* remember to kill daemon on error */
- char * tmp;
+ /* convert all '\\' to '/' so that /proc/mounts looks pretty */
+ replace_char(dev_name, '\\', '/');
+
+ if(mount(dev_name, mountpoint, "cifs", flags, options)) {
+ /* remember to kill daemon on error */
switch (errno) {
case 0:
printf("mount failed but no error number set\n");
@@ -1315,12 +1360,9 @@ mount_retry:
case ENXIO:
if(retry == 0) {
retry = 1;
- tmp = share_name;
- while (*tmp && !(((unsigned char)tmp[0]) & 0x80)) {
- *tmp = toupper((unsigned char)*tmp);
- tmp++;
- }
- if(!*tmp) {
+ if (uppercase_string(dev_name) &&
+ uppercase_string(share_name) &&
+ uppercase_string(prefixpath)) {
printf("retrying with upper case share name\n");
goto mount_retry;
}
@@ -1334,7 +1376,7 @@ mount_retry:
} else {
pmntfile = setmntent(MOUNTED, "a+");
if(pmntfile) {
- mountent.mnt_fsname = share_name;
+ mountent.mnt_fsname = dev_name;
mountent.mnt_dir = mountpoint;
mountent.mnt_type = CONST_DISCARD(char *,"cifs");
mountent.mnt_opts = (char *)malloc(220);
@@ -1394,8 +1436,6 @@ mount_exit:
free(resolved_path);
}
- if(free_share_name) {
- free(share_name);
- }
+ free(share_name);
return rc;
}