From 7b74756ead27656f46e31b855eee0f532ca65bbb Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Thu, 17 Oct 2013 13:47:15 +0200 Subject: [PATCH 1/8] add struct FILE_STANDARD_INFO --- cifspdu.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cifspdu.h b/cifspdu.h index b9d59a9..fb34463 100644 --- a/cifspdu.h +++ b/cifspdu.h @@ -2221,6 +2221,16 @@ typedef struct { /* data block encoding of response to level 263 QPathInfo */ char FileName[1]; } __attribute__((packed)) FILE_ALL_INFO; /* level 0x107 QPathInfo */ +typedef struct { + __le64 AllocationSize; + __le64 EndOfFile; /* size ie offset to first free byte in file */ + __le32 NumberOfLinks; /* hard links */ + __u8 DeletePending; + __u8 Directory; + __u16 Pad; +} __attribute__((packed)) FILE_STANDARD_INFO; /* level 0x102 QPathInfo */ + + /* defines for enumerating possible values of the Unix type field below */ #define UNIX_FILE 0 #define UNIX_DIR 1 -- 1.7.9.5 From 22747ff2373415f1e4b0f095fe371d295db3ead1 Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Mon, 21 Oct 2013 16:24:01 +0200 Subject: [PATCH 2/8] refactor CIFSSMBQPathInfo() --- cifssmb.c | 59 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/cifssmb.c b/cifssmb.c index 76d0d29..d2e5a90 100644 --- a/cifssmb.c +++ b/cifssmb.c @@ -3956,13 +3956,13 @@ QFileInfoRetry: return rc; } -int -CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, - const char *search_name, FILE_ALL_INFO *data, - int legacy /* old style infolevel */, - const struct nls_table *nls_codepage, int remap) +static int +CIFSSMBQPathInfoImpl(const unsigned int xid, struct cifs_tcon *tcon, + const char *search_name, + void *data, int size, + __u16 level, __u16 bcc, + const struct nls_table *nls_codepage, int remap) { - /* level 263 SMB_QUERY_FILE_ALL_INFO */ TRANSACTION2_QPI_REQ *pSMB = NULL; TRANSACTION2_QPI_RSP *pSMBr = NULL; int rc = 0; @@ -3970,7 +3970,7 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, int name_len; __u16 params, byte_count; - /* cFYI(1, "In QPathInfo path %s", search_name); */ + cFYI(1, "In QPathInfo level %u path %s", level, search_name); QPathInfoRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -4009,10 +4009,7 @@ QPathInfoRetry: byte_count = params + 1 /* pad */ ; pSMB->TotalParameterCount = cpu_to_le16(params); pSMB->ParameterCount = pSMB->TotalParameterCount; - if (legacy) - pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD); - else - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); + pSMB->InformationLevel = level; pSMB->Reserved4 = 0; inc_rfc1001_len(pSMB, byte_count); pSMB->ByteCount = cpu_to_le16(byte_count); @@ -4026,25 +4023,10 @@ QPathInfoRetry: if (rc) /* BB add auto retry on EOPNOTSUPP? */ rc = -EIO; - else if (!legacy && get_bcc(&pSMBr->hdr) < 40) + else if (get_bcc(&pSMBr->hdr) < bcc) rc = -EIO; /* bad smb */ - else if (legacy && get_bcc(&pSMBr->hdr) < 24) - rc = -EIO; /* 24 or 26 expected but we do not read - last field */ else if (data) { - int size; __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - - /* - * On legacy responses we do not read the last field, - * EAsize, fortunately since it varies by subdialect and - * also note it differs on Set vs Get, ie two bytes or 4 - * bytes depending but we don't care here. - */ - if (legacy) - size = sizeof(FILE_INFO_STANDARD); - else - size = sizeof(FILE_ALL_INFO); memcpy((char *) data, (char *) &pSMBr->hdr.Protocol + data_offset, size); } else @@ -4058,6 +4040,29 @@ QPathInfoRetry: } int +CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, + const char *search_name, FILE_ALL_INFO *data, + int legacy /* old style infolevel */, + const struct nls_table *nls_codepage, int remap) +{ + if (legacy) { + /* 24 or 26 expected but on legacy responses we do not read the + last field, EAsize, fortunately since it varies by subdialect + and also note it differs on Set vs. Get, ie two bytes or 4 + bytes depending but we don't care here */ + return CIFSSMBQPathInfoImpl(xid, tcon, search_name, + data, sizeof(FILE_INFO_STANDARD), + SMB_INFO_STANDARD, 24, + nls_codepage, remap); + } else { + return CIFSSMBQPathInfoImpl(xid, tcon, search_name, + data, sizeof(FILE_ALL_INFO), + SMB_QUERY_FILE_ALL_INFO, 40, + nls_codepage, remap); + } +} + +int CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon, u16 netfid, FILE_UNIX_BASIC_INFO *pFindData) { -- 1.7.9.5 From 1be6b96f1d771d367bed9b0f1382b632387be1f4 Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Mon, 21 Oct 2013 16:28:49 +0200 Subject: [PATCH 3/8] add function CIFSSMBQPathInfoBasic() --- cifsproto.h | 3 +++ cifssmb.c | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/cifsproto.h b/cifsproto.h index 1988c1b..7e66557 100644 --- a/cifsproto.h +++ b/cifsproto.h @@ -236,6 +236,9 @@ extern int CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, const char *search_Name, FILE_ALL_INFO *data, int legacy /* whether to use old info level */, const struct nls_table *nls_codepage, int remap); +extern int CIFSSMBQPathInfoBasic(const unsigned int xid, struct cifs_tcon *tcon, + const char *search_name, FILE_BASIC_INFO *data, + const struct nls_table *nls_codepage, int remap); extern int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon, const char *search_name, FILE_ALL_INFO *data, const struct nls_table *nls_codepage, int remap); diff --git a/cifssmb.c b/cifssmb.c index d2e5a90..177debf 100644 --- a/cifssmb.c +++ b/cifssmb.c @@ -4063,6 +4063,17 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, } int +CIFSSMBQPathInfoBasic(const unsigned int xid, struct cifs_tcon *tcon, + const char *search_name, FILE_BASIC_INFO *data, + const struct nls_table *nls_codepage, int remap) +{ + return CIFSSMBQPathInfoImpl(xid, tcon, search_name, + data, sizeof(FILE_BASIC_INFO), + SMB_QUERY_FILE_BASIC_INFO, 40 /*???*/, + nls_codepage, remap); +} + +int CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon, u16 netfid, FILE_UNIX_BASIC_INFO *pFindData) { -- 1.7.9.5 From f858368d4f0dcc55b3e33b30256373636a36a96c Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Mon, 21 Oct 2013 16:33:31 +0200 Subject: [PATCH 4/8] add function CIFSSMBQPathInfoStandard() --- cifsproto.h | 3 +++ cifssmb.c | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/cifsproto.h b/cifsproto.h index 7e66557..883f291 100644 --- a/cifsproto.h +++ b/cifsproto.h @@ -239,6 +239,9 @@ extern int CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, extern int CIFSSMBQPathInfoBasic(const unsigned int xid, struct cifs_tcon *tcon, const char *search_name, FILE_BASIC_INFO *data, const struct nls_table *nls_codepage, int remap); +extern int CIFSSMBQPathInfoStandard(const unsigned int xid, struct cifs_tcon *tcon, + const char *search_name, FILE_STANDARD_INFO *data, + const struct nls_table *nls_codepage, int remap); extern int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon, const char *search_name, FILE_ALL_INFO *data, const struct nls_table *nls_codepage, int remap); diff --git a/cifssmb.c b/cifssmb.c index 177debf..b4a04da 100644 --- a/cifssmb.c +++ b/cifssmb.c @@ -4074,6 +4074,17 @@ CIFSSMBQPathInfoBasic(const unsigned int xid, struct cifs_tcon *tcon, } int +CIFSSMBQPathInfoStandard(const unsigned int xid, struct cifs_tcon *tcon, + const char *search_name, FILE_STANDARD_INFO *data, + const struct nls_table *nls_codepage, int remap) +{ + return CIFSSMBQPathInfoImpl(xid, tcon, search_name, + data, sizeof(FILE_STANDARD_INFO), + SMB_QUERY_FILE_STANDARD_INFO, 24 /*???*/, + nls_codepage, remap); +} + +int CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon, u16 netfid, FILE_UNIX_BASIC_INFO *pFindData) { -- 1.7.9.5 From f54196b7456f9da51494fa1d3cf14f8b49c6f974 Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Mon, 21 Oct 2013 17:02:52 +0200 Subject: [PATCH 5/8] fallback to CIFSSMBQPathInfoBasic() in cifs_is_path_accessible() --- smb1ops.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/smb1ops.c b/smb1ops.c index 47bc5a8..4755da9 100644 --- a/smb1ops.c +++ b/smb1ops.c @@ -509,20 +509,23 @@ cifs_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, { int rc; FILE_ALL_INFO *file_info; + const int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; file_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); if (file_info == NULL) return -ENOMEM; rc = CIFSSMBQPathInfo(xid, tcon, full_path, file_info, - 0 /* not legacy */, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + 0 /* not legacy */, cifs_sb->local_nls, remap); + if (rc == -EIO) { + rc = CIFSSMBQPathInfoBasic(xid, tcon, full_path, + (FILE_BASIC_INFO*)file_info, + cifs_sb->local_nls, remap); + } if (rc == -EOPNOTSUPP || rc == -EINVAL) rc = SMBQueryInformation(xid, tcon, full_path, file_info, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + cifs_sb->local_nls, remap); kfree(file_info); return rc; } -- 1.7.9.5 From 7d4b157ce9731c114df5d32f1dbddce9805ef56b Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Tue, 22 Oct 2013 09:52:59 +0200 Subject: [PATCH 6/8] fallback to CIFSSMBQPathInfoBasic()/Standard() in cifs_is_path_accessible() --- smb1ops.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/smb1ops.c b/smb1ops.c index 4755da9..5eb3202 100644 --- a/smb1ops.c +++ b/smb1ops.c @@ -536,11 +536,23 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, FILE_ALL_INFO *data, bool *adjustTZ) { int rc; + const int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; /* could do find first instead but this returns more info */ rc = CIFSSMBQPathInfo(xid, tcon, full_path, data, 0 /* not legacy */, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + cifs_sb->local_nls, remap); + + if (rc == -EIO) { + rc = CIFSSMBQPathInfoBasic(xid, tcon, full_path, + (FILE_BASIC_INFO*)data, + cifs_sb->local_nls, remap); + if (!rc) { + rc = CIFSSMBQPathInfoStandard(xid, tcon, full_path, + (void*)data + sizeof(FILE_BASIC_INFO), + cifs_sb->local_nls, remap); + } + } + /* * BB optimize code so we do not make the above call when server claims * no NT SMB support and the above call failed at least once - set flag @@ -548,9 +560,7 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, */ if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { rc = SMBQueryInformation(xid, tcon, full_path, data, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + cifs_sb->local_nls, remap); *adjustTZ = true; } return rc; -- 1.7.9.5 From 36a6cd27d6843f43b00c71d83b8b7399e530b6e0 Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Tue, 22 Oct 2013 10:01:40 +0200 Subject: [PATCH 7/8] fix some cFYI in cifssmb.c --- cifssmb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cifssmb.c b/cifssmb.c index b4a04da..61092ce 100644 --- a/cifssmb.c +++ b/cifssmb.c @@ -3933,7 +3933,7 @@ QFileInfoRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, "Send error in QPathInfo = %d", rc); + cFYI(1, "Send error in QFileInfo = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4128,7 +4128,7 @@ UnixQFileInfoRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, "Send error in QPathInfo = %d", rc); + cFYI(1, "Send error in UnixQFileInfo = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4214,7 +4214,7 @@ UnixQPathInfoRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, "Send error in QPathInfo = %d", rc); + cFYI(1, "Send error in UnixQPathInfo = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); -- 1.7.9.5 From ea533f3f334c07d6e058ec0411652455af4b5388 Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Tue, 22 Oct 2013 11:02:57 +0200 Subject: [PATCH 8/8] cFYI --- smb1ops.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/smb1ops.c b/smb1ops.c index 5eb3202..e7c527a 100644 --- a/smb1ops.c +++ b/smb1ops.c @@ -518,6 +518,7 @@ cifs_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, rc = CIFSSMBQPathInfo(xid, tcon, full_path, file_info, 0 /* not legacy */, cifs_sb->local_nls, remap); if (rc == -EIO) { + cFYI(1, "is_path_accessible: FALLBACK"); rc = CIFSSMBQPathInfoBasic(xid, tcon, full_path, (FILE_BASIC_INFO*)file_info, cifs_sb->local_nls, remap); @@ -543,6 +544,7 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, cifs_sb->local_nls, remap); if (rc == -EIO) { + cFYI(1, "cifs_query_path_info: FALLBACK"); rc = CIFSSMBQPathInfoBasic(xid, tcon, full_path, (FILE_BASIC_INFO*)data, cifs_sb->local_nls, remap); -- 1.7.9.5