aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteve French <stevef@steveft21.ltcsamba>2004-07-23 23:42:08 -0500
committerSteve French <cifs.adm@hostme.bitkeeper.com>2004-07-23 23:42:08 -0500
commit4e9d02f560b188d384592ed02796f3843cef506b (patch)
treef9628861a5b7a7f1ab62347f9be4bdfbba0df0dc /fs
parent7ff907063de3baf130c06386b2cc7bb99104b96c (diff)
downloadhistory-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.h21
-rw-r--r--fs/cifs/cifsproto.h7
-rw-r--r--fs/cifs/cifssmb.c133
-rw-r--r--fs/cifs/xattr.c6
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;