]> err.no Git - linux-2.6/blobdiff - fs/cifs/connect.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6
[linux-2.6] / fs / cifs / connect.c
index 5d394c726860740316e6fb96172aeccc888d6214..c78762051da4e5b15da45fa06b46b66d85e55d82 100644 (file)
@@ -89,6 +89,7 @@ struct smb_vol {
        unsigned int wsize;
        unsigned int sockopt;
        unsigned short int port;
+       char * prepath;
 };
 
 static int ipv4_connect(struct sockaddr_in *psin_server, 
@@ -771,12 +772,12 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
        separator[1] = 0; 
 
        memset(vol->source_rfc1001_name,0x20,15);
-       for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
+       for(i=0;i < strnlen(utsname()->nodename,15);i++) {
                /* does not have to be a perfect mapping since the field is
                informational, only used for servers that do not support
                port 445 and it can be overridden at mount time */
                vol->source_rfc1001_name[i] = 
-                       toupper(system_utsname.nodename[i]);
+                       toupper(utsname()->nodename[i]);
        }
        vol->source_rfc1001_name[15] = 0;
        /* null target name indicates to use *SMBSERVR default called name
@@ -993,6 +994,28 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
                                printk(KERN_WARNING "CIFS: domain name too long\n");
                                return 1;
                        }
+                } else if (strnicmp(data, "prefixpath", 10) == 0) {
+                        if (!value || !*value) {
+                                printk(KERN_WARNING
+                                       "CIFS: invalid path prefix\n");
+                                return 1;       /* needs_arg; */
+                        }
+                        if ((temp_len = strnlen(value, 1024)) < 1024) {
+                               if(value[0] != '/')
+                                       temp_len++;  /* missing leading slash */
+                                vol->prepath = kmalloc(temp_len+1,GFP_KERNEL);
+                                if(vol->prepath == NULL)
+                                        return 1;
+                               if(value[0] != '/') {
+                                       vol->prepath[0] = '/';
+                                       strcpy(vol->prepath+1,value);
+                               } else
+                                       strcpy(vol->prepath,value);
+                               cFYI(1,("prefix path %s",vol->prepath));
+                        } else {
+                                printk(KERN_WARNING "CIFS: prefix too long\n");
+                                return 1;
+                        }
                } else if (strnicmp(data, "iocharset", 9) == 0) {
                        if (!value || !*value) {
                                printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
@@ -1605,6 +1628,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
        if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
                kfree(volume_info.UNC);
                kfree(volume_info.password);
+               kfree(volume_info.prepath);
                FreeXid(xid);
                return -EINVAL;
        }
@@ -1619,6 +1643,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
            locations such as env variables and files on disk */
                kfree(volume_info.UNC);
                kfree(volume_info.password);
+               kfree(volume_info.prepath);
                FreeXid(xid);
                return -EINVAL;
        }
@@ -1639,6 +1664,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        /* we failed translating address */
                        kfree(volume_info.UNC);
                        kfree(volume_info.password);
+                       kfree(volume_info.prepath);
                        FreeXid(xid);
                        return -EINVAL;
                }
@@ -1651,6 +1677,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                cERROR(1,("Connecting to DFS root not implemented yet"));
                kfree(volume_info.UNC);
                kfree(volume_info.password);
+               kfree(volume_info.prepath);
                FreeXid(xid);
                return -EINVAL;
        } else /* which servers DFS root would we conect to */ {
@@ -1658,6 +1685,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                       ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
                kfree(volume_info.UNC);
                kfree(volume_info.password);
+               kfree(volume_info.prepath);
                FreeXid(xid);
                return -EINVAL;
        }
@@ -1672,6 +1700,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
                        kfree(volume_info.UNC);
                        kfree(volume_info.password);
+                       kfree(volume_info.prepath);
                        FreeXid(xid);
                        return -ELIBACC;
                }
@@ -1688,6 +1717,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
        else {
                kfree(volume_info.UNC);
                kfree(volume_info.password);
+               kfree(volume_info.prepath);
                FreeXid(xid);
                return -EINVAL;
        }
@@ -1710,6 +1740,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                                sock_release(csocket);
                        kfree(volume_info.UNC);
                        kfree(volume_info.password);
+                       kfree(volume_info.prepath);
                        FreeXid(xid);
                        return rc;
                }
@@ -1720,6 +1751,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        sock_release(csocket);
                        kfree(volume_info.UNC);
                        kfree(volume_info.password);
+                       kfree(volume_info.prepath);
                        FreeXid(xid);
                        return rc;
                } else {
@@ -1744,6 +1776,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                                sock_release(csocket);
                                kfree(volume_info.UNC);
                                kfree(volume_info.password);
+                               kfree(volume_info.prepath);
                                FreeXid(xid);
                                return rc;
                        }
@@ -1831,6 +1864,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        /* Windows ME may prefer this */
                        cFYI(1,("readsize set to minimum 2048"));
                }
+               /* calculate prepath */
+               cifs_sb->prepath = volume_info.prepath;
+               if(cifs_sb->prepath) {
+                       cifs_sb->prepathlen = strlen(cifs_sb->prepath);
+                       cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb);
+                       volume_info.prepath = NULL;
+               } else 
+                       cifs_sb->prepathlen = 0;
                cifs_sb->mnt_uid = volume_info.linux_uid;
                cifs_sb->mnt_gid = volume_info.linux_gid;
                cifs_sb->mnt_file_mode = volume_info.file_mode;
@@ -2008,6 +2049,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
        the password ptr is put in the new session structure (in which case the
        password will be freed at unmount time) */
        kfree(volume_info.UNC);
+       kfree(volume_info.prepath);
        FreeXid(xid);
        return rc;
 }
@@ -2111,7 +2153,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                  32, nls_codepage);
                bcc_ptr += 2 * bytes_returned;
                bytes_returned =
-                   cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
+                   cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release,
                                  32, nls_codepage);
                bcc_ptr += 2 * bytes_returned;
                bcc_ptr += 2;
@@ -2138,8 +2180,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                }
                strcpy(bcc_ptr, "Linux version ");
                bcc_ptr += strlen("Linux version ");
-               strcpy(bcc_ptr, system_utsname.release);
-               bcc_ptr += strlen(system_utsname.release) + 1;
+               strcpy(bcc_ptr, utsname()->release);
+               bcc_ptr += strlen(utsname()->release) + 1;
                strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
                bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
        }
@@ -2403,7 +2445,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                  32, nls_codepage);
                bcc_ptr += 2 * bytes_returned;
                bytes_returned =
-                   cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
+                   cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
                                  nls_codepage);
                bcc_ptr += 2 * bytes_returned;
                bcc_ptr += 2;   /* null terminate Linux version */
@@ -2420,8 +2462,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
        } else {                /* ASCII */
                strcpy(bcc_ptr, "Linux version ");
                bcc_ptr += strlen("Linux version ");
-               strcpy(bcc_ptr, system_utsname.release);
-               bcc_ptr += strlen(system_utsname.release) + 1;
+               strcpy(bcc_ptr, utsname()->release);
+               bcc_ptr += strlen(utsname()->release) + 1;
                strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
                bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
                bcc_ptr++;      /* empty domain field */
@@ -2794,7 +2836,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                  32, nls_codepage);
                bcc_ptr += 2 * bytes_returned;
                bytes_returned =
-                   cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
+                   cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
                                  nls_codepage);
                bcc_ptr += 2 * bytes_returned;
                bcc_ptr += 2;   /* null term version string */
@@ -2846,8 +2888,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 
                strcpy(bcc_ptr, "Linux version ");
                bcc_ptr += strlen("Linux version ");
-               strcpy(bcc_ptr, system_utsname.release);
-               bcc_ptr += strlen(system_utsname.release) + 1;
+               strcpy(bcc_ptr, utsname()->release);
+               bcc_ptr += strlen(utsname()->release) + 1;
                strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
                bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
                bcc_ptr++;      /* null domain */
@@ -3195,6 +3237,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
        int xid;
        struct cifsSesInfo *ses = NULL;
        struct task_struct *cifsd_task;
+       char * tmp;
 
        xid = GetXid();
 
@@ -3228,6 +3271,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
        }
        
        cifs_sb->tcon = NULL;
+       tmp = cifs_sb->prepath;
+       cifs_sb->prepathlen = 0;
+       cifs_sb->prepath = NULL;
+       kfree(tmp);
        if (ses)
                schedule_timeout_interruptible(msecs_to_jiffies(500));
        if (ses)