diff options
author | Steve French <sfrench@us.ibm.com> | 2006-09-21 03:02:52 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2006-09-21 03:02:52 -0400 |
commit | 2fe87f02a04ad6e7075023a87fe38eb458a4bb9d (patch) | |
tree | ec095fecdccad724faa6560cf7a81a9494a5a093 /fs/cifs/connect.c | |
parent | b835bebe95608c81270636a78b70333afb011925 (diff) |
[CIFS] Support deep tree mounts (e.g. mounts to //server/share/path)
Samba bugzilla #4040
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 5d394c726860..0e9ba0b9d71e 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -89,6 +89,7 @@ struct smb_vol { | |||
89 | unsigned int wsize; | 89 | unsigned int wsize; |
90 | unsigned int sockopt; | 90 | unsigned int sockopt; |
91 | unsigned short int port; | 91 | unsigned short int port; |
92 | char * prepath; | ||
92 | }; | 93 | }; |
93 | 94 | ||
94 | static int ipv4_connect(struct sockaddr_in *psin_server, | 95 | static int ipv4_connect(struct sockaddr_in *psin_server, |
@@ -993,6 +994,28 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
993 | printk(KERN_WARNING "CIFS: domain name too long\n"); | 994 | printk(KERN_WARNING "CIFS: domain name too long\n"); |
994 | return 1; | 995 | return 1; |
995 | } | 996 | } |
997 | } else if (strnicmp(data, "prefixpath", 10) == 0) { | ||
998 | if (!value || !*value) { | ||
999 | printk(KERN_WARNING | ||
1000 | "CIFS: invalid path prefix\n"); | ||
1001 | return 1; /* needs_arg; */ | ||
1002 | } | ||
1003 | if ((temp_len = strnlen(value, 1024)) < 1024) { | ||
1004 | if(value[0] != '/') | ||
1005 | temp_len++; /* missing leading slash */ | ||
1006 | vol->prepath = kmalloc(temp_len+1,GFP_KERNEL); | ||
1007 | if(vol->prepath == NULL) | ||
1008 | return 1; | ||
1009 | if(value[0] != '/') { | ||
1010 | vol->prepath[0] = '/'; | ||
1011 | strcpy(vol->prepath+1,value); | ||
1012 | } else | ||
1013 | strcpy(vol->prepath,value); | ||
1014 | cFYI(1,("prefix path %s",vol->prepath)); | ||
1015 | } else { | ||
1016 | printk(KERN_WARNING "CIFS: prefix too long\n"); | ||
1017 | return 1; | ||
1018 | } | ||
996 | } else if (strnicmp(data, "iocharset", 9) == 0) { | 1019 | } else if (strnicmp(data, "iocharset", 9) == 0) { |
997 | if (!value || !*value) { | 1020 | if (!value || !*value) { |
998 | printk(KERN_WARNING "CIFS: invalid iocharset specified\n"); | 1021 | printk(KERN_WARNING "CIFS: invalid iocharset specified\n"); |
@@ -1605,6 +1628,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1605 | if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { | 1628 | if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { |
1606 | kfree(volume_info.UNC); | 1629 | kfree(volume_info.UNC); |
1607 | kfree(volume_info.password); | 1630 | kfree(volume_info.password); |
1631 | kfree(volume_info.prepath); | ||
1608 | FreeXid(xid); | 1632 | FreeXid(xid); |
1609 | return -EINVAL; | 1633 | return -EINVAL; |
1610 | } | 1634 | } |
@@ -1619,6 +1643,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1619 | locations such as env variables and files on disk */ | 1643 | locations such as env variables and files on disk */ |
1620 | kfree(volume_info.UNC); | 1644 | kfree(volume_info.UNC); |
1621 | kfree(volume_info.password); | 1645 | kfree(volume_info.password); |
1646 | kfree(volume_info.prepath); | ||
1622 | FreeXid(xid); | 1647 | FreeXid(xid); |
1623 | return -EINVAL; | 1648 | return -EINVAL; |
1624 | } | 1649 | } |
@@ -1639,6 +1664,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1639 | /* we failed translating address */ | 1664 | /* we failed translating address */ |
1640 | kfree(volume_info.UNC); | 1665 | kfree(volume_info.UNC); |
1641 | kfree(volume_info.password); | 1666 | kfree(volume_info.password); |
1667 | kfree(volume_info.prepath); | ||
1642 | FreeXid(xid); | 1668 | FreeXid(xid); |
1643 | return -EINVAL; | 1669 | return -EINVAL; |
1644 | } | 1670 | } |
@@ -1651,6 +1677,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1651 | cERROR(1,("Connecting to DFS root not implemented yet")); | 1677 | cERROR(1,("Connecting to DFS root not implemented yet")); |
1652 | kfree(volume_info.UNC); | 1678 | kfree(volume_info.UNC); |
1653 | kfree(volume_info.password); | 1679 | kfree(volume_info.password); |
1680 | kfree(volume_info.prepath); | ||
1654 | FreeXid(xid); | 1681 | FreeXid(xid); |
1655 | return -EINVAL; | 1682 | return -EINVAL; |
1656 | } else /* which servers DFS root would we conect to */ { | 1683 | } 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, | |||
1658 | ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified")); | 1685 | ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified")); |
1659 | kfree(volume_info.UNC); | 1686 | kfree(volume_info.UNC); |
1660 | kfree(volume_info.password); | 1687 | kfree(volume_info.password); |
1688 | kfree(volume_info.prepath); | ||
1661 | FreeXid(xid); | 1689 | FreeXid(xid); |
1662 | return -EINVAL; | 1690 | return -EINVAL; |
1663 | } | 1691 | } |
@@ -1672,6 +1700,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1672 | cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset)); | 1700 | cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset)); |
1673 | kfree(volume_info.UNC); | 1701 | kfree(volume_info.UNC); |
1674 | kfree(volume_info.password); | 1702 | kfree(volume_info.password); |
1703 | kfree(volume_info.prepath); | ||
1675 | FreeXid(xid); | 1704 | FreeXid(xid); |
1676 | return -ELIBACC; | 1705 | return -ELIBACC; |
1677 | } | 1706 | } |
@@ -1688,6 +1717,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1688 | else { | 1717 | else { |
1689 | kfree(volume_info.UNC); | 1718 | kfree(volume_info.UNC); |
1690 | kfree(volume_info.password); | 1719 | kfree(volume_info.password); |
1720 | kfree(volume_info.prepath); | ||
1691 | FreeXid(xid); | 1721 | FreeXid(xid); |
1692 | return -EINVAL; | 1722 | return -EINVAL; |
1693 | } | 1723 | } |
@@ -1710,6 +1740,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1710 | sock_release(csocket); | 1740 | sock_release(csocket); |
1711 | kfree(volume_info.UNC); | 1741 | kfree(volume_info.UNC); |
1712 | kfree(volume_info.password); | 1742 | kfree(volume_info.password); |
1743 | kfree(volume_info.prepath); | ||
1713 | FreeXid(xid); | 1744 | FreeXid(xid); |
1714 | return rc; | 1745 | return rc; |
1715 | } | 1746 | } |
@@ -1720,6 +1751,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1720 | sock_release(csocket); | 1751 | sock_release(csocket); |
1721 | kfree(volume_info.UNC); | 1752 | kfree(volume_info.UNC); |
1722 | kfree(volume_info.password); | 1753 | kfree(volume_info.password); |
1754 | kfree(volume_info.prepath); | ||
1723 | FreeXid(xid); | 1755 | FreeXid(xid); |
1724 | return rc; | 1756 | return rc; |
1725 | } else { | 1757 | } else { |
@@ -1744,6 +1776,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1744 | sock_release(csocket); | 1776 | sock_release(csocket); |
1745 | kfree(volume_info.UNC); | 1777 | kfree(volume_info.UNC); |
1746 | kfree(volume_info.password); | 1778 | kfree(volume_info.password); |
1779 | kfree(volume_info.prepath); | ||
1747 | FreeXid(xid); | 1780 | FreeXid(xid); |
1748 | return rc; | 1781 | return rc; |
1749 | } | 1782 | } |
@@ -1831,6 +1864,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1831 | /* Windows ME may prefer this */ | 1864 | /* Windows ME may prefer this */ |
1832 | cFYI(1,("readsize set to minimum 2048")); | 1865 | cFYI(1,("readsize set to minimum 2048")); |
1833 | } | 1866 | } |
1867 | /* calculate prepath */ | ||
1868 | cifs_sb->prepath = volume_info.prepath; | ||
1869 | if(cifs_sb->prepath) { | ||
1870 | cifs_sb->prepathlen = strlen(cifs_sb->prepath); | ||
1871 | cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb); | ||
1872 | volume_info.prepath = NULL; | ||
1873 | } else | ||
1874 | cifs_sb->prepathlen = 0; | ||
1834 | cifs_sb->mnt_uid = volume_info.linux_uid; | 1875 | cifs_sb->mnt_uid = volume_info.linux_uid; |
1835 | cifs_sb->mnt_gid = volume_info.linux_gid; | 1876 | cifs_sb->mnt_gid = volume_info.linux_gid; |
1836 | cifs_sb->mnt_file_mode = volume_info.file_mode; | 1877 | 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, | |||
2008 | the password ptr is put in the new session structure (in which case the | 2049 | the password ptr is put in the new session structure (in which case the |
2009 | password will be freed at unmount time) */ | 2050 | password will be freed at unmount time) */ |
2010 | kfree(volume_info.UNC); | 2051 | kfree(volume_info.UNC); |
2052 | kfree(volume_info.prepath); | ||
2011 | FreeXid(xid); | 2053 | FreeXid(xid); |
2012 | return rc; | 2054 | return rc; |
2013 | } | 2055 | } |
@@ -3195,6 +3237,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
3195 | int xid; | 3237 | int xid; |
3196 | struct cifsSesInfo *ses = NULL; | 3238 | struct cifsSesInfo *ses = NULL; |
3197 | struct task_struct *cifsd_task; | 3239 | struct task_struct *cifsd_task; |
3240 | char * tmp; | ||
3198 | 3241 | ||
3199 | xid = GetXid(); | 3242 | xid = GetXid(); |
3200 | 3243 | ||
@@ -3228,6 +3271,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
3228 | } | 3271 | } |
3229 | 3272 | ||
3230 | cifs_sb->tcon = NULL; | 3273 | cifs_sb->tcon = NULL; |
3274 | tmp = cifs_sb->prepath; | ||
3275 | cifs_sb->prepathlen = 0; | ||
3276 | cifs_sb->prepath = NULL; | ||
3277 | kfree(tmp); | ||
3231 | if (ses) | 3278 | if (ses) |
3232 | schedule_timeout_interruptible(msecs_to_jiffies(500)); | 3279 | schedule_timeout_interruptible(msecs_to_jiffies(500)); |
3233 | if (ses) | 3280 | if (ses) |