diff options
-rw-r--r-- | fs/cifs/CHANGES | 2 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 17 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 59 | ||||
-rw-r--r-- | fs/cifs/connect.c | 5 | ||||
-rw-r--r-- | fs/cifs/inode.c | 12 |
6 files changed, 96 insertions, 3 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 2137002aecc4..299ed312cea5 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -1,6 +1,8 @@ | |||
1 | Version 1.36 | 1 | Version 1.36 |
2 | ------------ | 2 | ------------ |
3 | Add support for moounting to older pre-CIFS servers such as Windows9x and ME. | 3 | Add support for moounting to older pre-CIFS servers such as Windows9x and ME. |
4 | For these older servers, add option for passing netbios name of server in | ||
5 | on mount (servernetbiosname). | ||
4 | Add mount option for disabling the default behavior of sending byte range lock | 6 | Add mount option for disabling the default behavior of sending byte range lock |
5 | requests to the server (necessary for certain applications which break with | 7 | requests to the server (necessary for certain applications which break with |
6 | mandatory lock behavior such as Evolution), and also mount option for | 8 | mandatory lock behavior such as Evolution), and also mount option for |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 49cc66825309..42c16cf32284 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -36,6 +36,7 @@ | |||
36 | #define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */ | 36 | #define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */ |
37 | #define SMB_COM_DELETE 0x06 /* trivial response */ | 37 | #define SMB_COM_DELETE 0x06 /* trivial response */ |
38 | #define SMB_COM_RENAME 0x07 /* trivial response */ | 38 | #define SMB_COM_RENAME 0x07 /* trivial response */ |
39 | #define SMB_COM_QUERY_INFORMATION 0x08 /* aka getattr */ | ||
39 | #define SMB_COM_SETATTR 0x09 /* trivial response */ | 40 | #define SMB_COM_SETATTR 0x09 /* trivial response */ |
40 | #define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */ | 41 | #define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */ |
41 | #define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/ | 42 | #define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/ |
@@ -885,6 +886,22 @@ typedef struct smb_com_create_directory_rsp { | |||
885 | __u16 ByteCount; /* bct = 0 */ | 886 | __u16 ByteCount; /* bct = 0 */ |
886 | } CREATE_DIRECTORY_RSP; | 887 | } CREATE_DIRECTORY_RSP; |
887 | 888 | ||
889 | typedef struct smb_com_query_information_req { | ||
890 | struct smb_hdr hdr; /* wct = 0 */ | ||
891 | __le16 ByteCount; /* 1 + namelen + 1 */ | ||
892 | __u8 BufferFormat; /* 4 = ASCII */ | ||
893 | unsigned char FileName[1]; | ||
894 | } QUERY_INFORMATION_REQ; | ||
895 | |||
896 | typedef struct smb_com_query_information_rsp { | ||
897 | struct smb_hdr hdr; /* wct = 10 */ | ||
898 | __le16 attr; | ||
899 | __le32 last_write_time; | ||
900 | __le32 size; | ||
901 | __u16 reserved[5]; | ||
902 | __le16 ByteCount; /* bcc = 0 */ | ||
903 | } QUERY_INFORMATION_RSP; | ||
904 | |||
888 | typedef struct smb_com_setattr_req { | 905 | typedef struct smb_com_setattr_req { |
889 | struct smb_hdr hdr; /* wct = 8 */ | 906 | struct smb_hdr hdr; /* wct = 8 */ |
890 | __le16 attr; | 907 | __le16 attr; |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index b9b13e3fe79d..0cc0612eacb4 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -105,6 +105,10 @@ extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, | |||
105 | const unsigned char *searchName, | 105 | const unsigned char *searchName, |
106 | FILE_ALL_INFO * findData, | 106 | FILE_ALL_INFO * findData, |
107 | const struct nls_table *nls_codepage, int remap); | 107 | const struct nls_table *nls_codepage, int remap); |
108 | extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, | ||
109 | const unsigned char *searchName, | ||
110 | FILE_ALL_INFO * findData, | ||
111 | const struct nls_table *nls_codepage, int remap); | ||
108 | 112 | ||
109 | extern int CIFSSMBUnixQPathInfo(const int xid, | 113 | extern int CIFSSMBUnixQPathInfo(const int xid, |
110 | struct cifsTconInfo *tcon, | 114 | struct cifsTconInfo *tcon, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 1292db50fe65..811ab3dffafa 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -2200,6 +2200,65 @@ GetExtAttrOut: | |||
2200 | 2200 | ||
2201 | #endif /* CONFIG_POSIX */ | 2201 | #endif /* CONFIG_POSIX */ |
2202 | 2202 | ||
2203 | /* Legacy Query Path Information call for lookup to old servers such | ||
2204 | as Win9x/WinME */ | ||
2205 | int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, | ||
2206 | const unsigned char *searchName, | ||
2207 | FILE_ALL_INFO * pFinfo, | ||
2208 | const struct nls_table *nls_codepage, int remap) | ||
2209 | { | ||
2210 | QUERY_INFORMATION_REQ * pSMB; | ||
2211 | QUERY_INFORMATION_RSP * pSMBr; | ||
2212 | int rc = 0; | ||
2213 | int bytes_returned; | ||
2214 | int name_len; | ||
2215 | |||
2216 | cFYI(1, ("In SMBQPath path %s", searchName)); | ||
2217 | QInfRetry: | ||
2218 | rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB, | ||
2219 | (void **) &pSMBr); | ||
2220 | if (rc) | ||
2221 | return rc; | ||
2222 | |||
2223 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | ||
2224 | name_len = | ||
2225 | cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, | ||
2226 | PATH_MAX, nls_codepage, remap); | ||
2227 | name_len++; /* trailing null */ | ||
2228 | name_len *= 2; | ||
2229 | } else { | ||
2230 | name_len = strnlen(searchName, PATH_MAX); | ||
2231 | name_len++; /* trailing null */ | ||
2232 | strncpy(pSMB->FileName, searchName, name_len); | ||
2233 | } | ||
2234 | pSMB->BufferFormat = 0x04; | ||
2235 | name_len++; /* account for buffer type byte */ | ||
2236 | pSMB->hdr.smb_buf_length += (__u16) name_len; | ||
2237 | pSMB->ByteCount = cpu_to_le16(name_len); | ||
2238 | |||
2239 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
2240 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
2241 | if (rc) { | ||
2242 | cFYI(1, ("Send error in QueryInfo = %d", rc)); | ||
2243 | } else if (pFinfo) { /* decode response */ | ||
2244 | memset(pFinfo, 0, sizeof(FILE_ALL_INFO)); | ||
2245 | pFinfo->AllocationSize = (__le64) pSMBr->size; | ||
2246 | pFinfo->EndOfFile = (__le64) pSMBr->size; | ||
2247 | pFinfo->Attributes = (__le32) pSMBr->attr; | ||
2248 | } else | ||
2249 | rc = -EIO; /* bad buffer passed in */ | ||
2250 | |||
2251 | cifs_buf_release(pSMB); | ||
2252 | |||
2253 | if (rc == -EAGAIN) | ||
2254 | goto QInfRetry; | ||
2255 | |||
2256 | return rc; | ||
2257 | } | ||
2258 | |||
2259 | |||
2260 | |||
2261 | |||
2203 | int | 2262 | int |
2204 | CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, | 2263 | CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, |
2205 | const unsigned char *searchName, | 2264 | const unsigned char *searchName, |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 9d61844e89b6..c75bae1242dc 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -1730,8 +1730,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1730 | else | 1730 | else |
1731 | cifs_sb->wsize = CIFSMaxBufSize; /* default */ | 1731 | cifs_sb->wsize = CIFSMaxBufSize; /* default */ |
1732 | if(cifs_sb->rsize < PAGE_CACHE_SIZE) { | 1732 | if(cifs_sb->rsize < PAGE_CACHE_SIZE) { |
1733 | cifs_sb->rsize = PAGE_CACHE_SIZE; | 1733 | cifs_sb->rsize = PAGE_CACHE_SIZE; |
1734 | cERROR(1,("Attempt to set readsize for mount to less than one page (4096)")); | 1734 | /* Windows ME does this */ |
1735 | cFYI(1,("Attempt to set readsize for mount to less than one page (4096)")); | ||
1735 | } | 1736 | } |
1736 | cifs_sb->mnt_uid = volume_info.linux_uid; | 1737 | cifs_sb->mnt_uid = volume_info.linux_uid; |
1737 | cifs_sb->mnt_gid = volume_info.linux_gid; | 1738 | cifs_sb->mnt_gid = volume_info.linux_gid; |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 2d50b3507d13..34f0168c4041 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -215,8 +215,18 @@ int cifs_get_inode_info(struct inode **pinode, | |||
215 | pfindData = (FILE_ALL_INFO *)buf; | 215 | pfindData = (FILE_ALL_INFO *)buf; |
216 | /* could do find first instead but this returns more info */ | 216 | /* could do find first instead but this returns more info */ |
217 | rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, | 217 | rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, |
218 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 218 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
219 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 219 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
220 | /* BB optimize code so we do not make the above call | ||
221 | when server claims no NT SMB support and the above call | ||
222 | failed at least once - set flag in tcon or mount */ | ||
223 | if((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { | ||
224 | rc = SMBQueryInformation(xid, pTcon, search_path, | ||
225 | pfindData, cifs_sb->local_nls, | ||
226 | cifs_sb->mnt_cifs_flags & | ||
227 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
228 | } | ||
229 | |||
220 | } | 230 | } |
221 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ | 231 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ |
222 | if (rc) { | 232 | if (rc) { |