diff options
author | Steve French <stevef@steveft21.ltcsamba> | 2004-07-23 23:42:08 -0500 |
---|---|---|
committer | Steve French <cifs.adm@hostme.bitkeeper.com> | 2004-07-23 23:42:08 -0500 |
commit | 4e9d02f560b188d384592ed02796f3843cef506b (patch) | |
tree | f9628861a5b7a7f1ab62347f9be4bdfbba0df0dc /fs | |
parent | 7ff907063de3baf130c06386b2cc7bb99104b96c (diff) | |
download | history-4e9d02f560b188d384592ed02796f3843cef506b.tar.gz |
[CIFS] xattr suport part 2: add listxattr support
Signed-off-by: Steve French (sfrench@us.ibm.com)
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifspdu.h | 21 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 7 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 133 | ||||
-rw-r--r-- | fs/cifs/xattr.c | 6 |
4 files changed, 154 insertions, 13 deletions
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 067eb4e3eebb1a..20351015823d12 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -1620,6 +1620,19 @@ typedef struct { char LinkDest[1]; } FILE_UNIX_LINK_INFO; /* level 513 QPathInfo */ +typedef struct { + __u16 CreationDate; + __u16 CreationTime; + __u16 LastAccessDate; + __u16 LastAccessTime; + __u16 LastWriteDate; + __u16 LastWriteTime; + __u32 DataSize; /* File Size (EOF) */ + __u32 AllocationSize; + __u16 Attributes; /* verify not u32 */ + __u32 EASize; +} FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */ + /* defines for enumerating possible values of the Unix type field below */ #define UNIX_FILE 0 #define UNIX_DIR 1 @@ -1680,12 +1693,12 @@ typedef struct { } FILE_DIRECTORY_INFO; /* level 257 FF response data area */ struct gea { - unsigned char cbName; - char szName[1]; + unsigned char name_len; + char name[1]; }; struct gealist { - unsigned long cbList; + unsigned long list_len; struct gea list[1]; }; @@ -1693,7 +1706,7 @@ struct fea { unsigned char EA_flags; __u8 name_len; __u16 value_len; - char szName[1]; + char name[1]; /* optionally followed by value */ }; /* flags for _FEA.fEA */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 2d74913e7cc28e..7dca9b9695a46b 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -222,8 +222,7 @@ extern int CIFSSMBCopy(int xid, extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, const int notify_subdirs,const __u16 netfid,__u32 filter, const struct nls_table *nls_codepage); -extern int CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, - const unsigned char *searchName, - char * EAData, size_t size, - const struct nls_table *nls_codepage); +extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, + const unsigned char *searchName, char * EAData, + size_t bufsize, const struct nls_table *nls_codepage); #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index c748d158f06062..b027b972090c93 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2770,6 +2770,89 @@ SetTimesRetry: return rc; } + +int +CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName, + FILE_INFO_STANDARD * data, const struct nls_table *nls_codepage) +{ + TRANSACTION2_SPI_REQ *pSMB = NULL; + TRANSACTION2_SPI_RSP *pSMBr = NULL; + int name_len; + int rc = 0; + int bytes_returned = 0; + char *data_offset; + + cFYI(1, ("In SetTimesLegacy")); + +SetTimesRetryLegacy: + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, + (void **) &pSMBr); + if (rc) + return rc; + + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { + name_len = + cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530 + /* find define for this maxpathcomponent */ + , nls_codepage); + name_len++; /* trailing null */ + name_len *= 2; + } else { /* BB improve the check for buffer overruns BB */ + name_len = strnlen(fileName, 530); + name_len++; /* trailing null */ + strncpy(pSMB->FileName, fileName, name_len); + } +/* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info + in parent function, from the better and ususal FILE_BASIC_INFO */ + pSMB->ParameterCount = 6 + name_len; + pSMB->DataCount = sizeof (FILE_INFO_STANDARD); + pSMB->MaxParameterCount = cpu_to_le16(2); + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ + pSMB->MaxSetupCount = 0; + pSMB->Reserved = 0; + pSMB->Flags = 0; + pSMB->Timeout = 0; + pSMB->Reserved2 = 0; + pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req, + InformationLevel) - 4; + pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount; + data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset; + pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset); + pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); + pSMB->SetupCount = 1; + pSMB->Reserved3 = 0; + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); + pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount; + + pSMB->DataCount = cpu_to_le16(pSMB->DataCount); + pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount); + pSMB->TotalDataCount = pSMB->DataCount; + pSMB->TotalParameterCount = pSMB->ParameterCount; + /* I doubt that passthrough levels apply to this old + preNT info level */ +/* if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2); + else*/ + pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD); + pSMB->Reserved4 = 0; + pSMB->hdr.smb_buf_length += pSMB->ByteCount; + memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD)); + pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount); + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned, 0); + if (rc) { + cFYI(1, ("SetPathInfo (times legacy) returned %d", rc)); + } + + if (pSMB) + cifs_buf_release(pSMB); + + if (rc == -EAGAIN) + goto SetTimesRetryLegacy; + + return rc; +} + int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon, char *fileName, __u64 mode, __u64 uid, __u64 gid, @@ -2915,10 +2998,10 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, return rc; } #ifdef CONFIG_CIFS_XATTR -int +ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, - char * EAData, size_t size, + char * EAData, size_t buf_size, const struct nls_table *nls_codepage) { /* BB assumes one setup word */ @@ -2927,6 +3010,8 @@ CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, int rc = 0; int bytes_returned; int name_len; + struct fea * temp_fea; + char * temp_ptr; cFYI(1, ("In Query All EAs path %s", searchName)); QAllEAsRetry: @@ -2942,7 +3027,7 @@ QAllEAsRetry: , nls_codepage); name_len++; /* trailing null */ name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ + } else { /* BB improve the check for buffer overruns BB */ name_len = strnlen(searchName, 530); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); @@ -3002,6 +3087,48 @@ QAllEAsRetry: (((char *) &pSMBr->hdr.Protocol) + pSMBr->DataOffset); cFYI(1,("ea length %d",ea_response_data->list_len)); + name_len = ea_response_data->list_len; + if(name_len <= 8) { + /* returned EA size zeroed at top of function */ + cFYI(1,("empty EA list returned from server")); + } else { + /* account for ea list len */ + name_len -= 4; + temp_fea = ea_response_data->list; + temp_ptr = (char *)temp_fea; + while(name_len > 0) { + name_len -= 4; + temp_ptr += 4; + rc += temp_fea->name_len; + /* account for prefix user. and trailing null */ + rc = rc + 5 + 1; + if(rc<buf_size) { + memcpy(EAData,"user.",5); + EAData+=5; + memcpy(EAData,temp_ptr,temp_fea->name_len); + EAData+=temp_fea->name_len; + /* null terminate name */ + *EAData = 0; + EAData = EAData + 1; + } else if(buf_size == 0) { + /* skip copy - calc size only */ + } else { + /* stop before overrun buffer */ + rc = -ERANGE; + break; + } + name_len -= temp_fea->name_len; + temp_ptr += temp_fea->name_len; + /* account for trailing null */ + name_len--; + temp_ptr++; + name_len -= temp_fea->value_len; + temp_ptr += temp_fea->value_len; + /* no trailing null to account for in value len */ + /* go on to next EA */ + temp_fea = (struct fea *)temp_ptr; + } + } } } if (pSMB) diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index dd6a2c08cd73f0..7c0bfea9bd0e3c 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -55,6 +55,7 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * ea_data, size_t ea_size) struct cifsTconInfo *pTcon; struct super_block * sb; char * full_path; + if(direntry == NULL) return -EIO; if(direntry->d_inode == NULL) @@ -74,13 +75,14 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * ea_data, size_t ea_size) FreeXid(xid); return -ENOMEM; } - /* return dosattributes as pseudo xattr */ + /* return dos attributes as pseudo xattr */ /* return alt name if available as pseudo attr */ /* if proc/fs/cifs/streamstoxattr is set then search server for EAs or streams to returns as xattrs */ - rc = CIFSSMBQAllEAs(xid,pTcon,full_path,ea_data,ea_size,cifs_sb->local_nls); + rc = CIFSSMBQAllEAs(xid,pTcon,full_path,ea_data,ea_size, + cifs_sb->local_nls); FreeXid(xid); #endif return rc; |