summaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2010-02-12 13:44:17 +0100
committerSteve French <sfrench@us.ibm.com>2010-03-06 05:38:25 +0100
commitc8634fd3115497ac311f57be9c12f993437745cf (patch)
tree67f309df555e2d9af25ce3d141d6bc92a5895107 /fs/cifs/cifssmb.c
parentcifs: add a CIFSSMBQFileInfo function (diff)
downloadlinux-c8634fd3115497ac311f57be9c12f993437745cf.tar.xz
linux-c8634fd3115497ac311f57be9c12f993437745cf.zip
cifs: add a CIFSSMBUnixQFileInfo function
...to allow us to get unix attrs via filehandle. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 4ed97825db3d..903d53871da7 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -3399,6 +3399,75 @@ QPathInfoRetry:
}
int
+CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
+ u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
+{
+ struct smb_t2_qfi_req *pSMB = NULL;
+ struct smb_t2_qfi_rsp *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ __u16 params, byte_count;
+
+UnixQFileInfoRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 2 /* level */ + 2 /* fid */;
+ pSMB->t2.TotalDataCount = 0;
+ pSMB->t2.MaxParameterCount = cpu_to_le16(4);
+ /* BB find exact max data count below from sess structure BB */
+ pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
+ pSMB->t2.MaxSetupCount = 0;
+ pSMB->t2.Reserved = 0;
+ pSMB->t2.Flags = 0;
+ pSMB->t2.Timeout = 0;
+ pSMB->t2.Reserved2 = 0;
+ pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
+ Fid) - 4);
+ pSMB->t2.DataCount = 0;
+ pSMB->t2.DataOffset = 0;
+ pSMB->t2.SetupCount = 1;
+ pSMB->t2.Reserved3 = 0;
+ pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->t2.TotalParameterCount = cpu_to_le16(params);
+ pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
+ pSMB->Pad = 0;
+ pSMB->Fid = netfid;
+ pSMB->hdr.smb_buf_length += byte_count;
+
+ 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));
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
+ cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
+ "Unix Extensions can be disabled on mount "
+ "by specifying the nosfu mount option."));
+ rc = -EIO; /* bad smb */
+ } else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ memcpy((char *) pFindData,
+ (char *) &pSMBr->hdr.Protocol +
+ data_offset,
+ sizeof(FILE_UNIX_BASIC_INFO));
+ }
+ }
+
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto UnixQFileInfoRetry;
+
+ return rc;
+}
+
+int
CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
FILE_UNIX_BASIC_INFO *pFindData,