Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
81d10c10
Commit
81d10c10
authored
Jul 26, 2004
by
Steve French
Committed by
Steve French
Jul 26, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[CIFS] xattr support part 3 add query EA support to retrieve individual xattr values
Signed-off-by: Steve French (sfrench@us.ibm.com)
parent
ccceff7d
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
255 additions
and
6 deletions
+255
-6
fs/cifs/cifsproto.h
fs/cifs/cifsproto.h
+4
-0
fs/cifs/cifssmb.c
fs/cifs/cifssmb.c
+152
-0
fs/cifs/xattr.c
fs/cifs/xattr.c
+99
-6
No files found.
fs/cifs/cifsproto.h
View file @
81d10c10
...
...
@@ -225,4 +225,8 @@ extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
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
);
extern
ssize_t
CIFSSMBQueryEA
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
unsigned
char
*
searchName
,
const
unsigned
char
*
ea_name
,
unsigned
char
*
ea_value
,
size_t
buf_size
,
const
struct
nls_table
*
nls_codepage
);
#endif
/* _CIFSPROTO_H */
fs/cifs/cifssmb.c
View file @
81d10c10
...
...
@@ -3086,6 +3086,8 @@ CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
ea_response_data
=
(
struct
fealist
*
)
(((
char
*
)
&
pSMBr
->
hdr
.
Protocol
)
+
pSMBr
->
DataOffset
);
ea_response_data
->
list_len
=
cpu_to_le32
(
ea_response_data
->
list_len
);
cFYI
(
1
,(
"ea length %d"
,
ea_response_data
->
list_len
));
name_len
=
ea_response_data
->
list_len
;
if
(
name_len
<=
8
)
{
...
...
@@ -3122,8 +3124,10 @@ CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
/* account for trailing null */
name_len
--
;
temp_ptr
++
;
temp_fea
->
value_len
=
cpu_to_le16
(
temp_fea
->
value_len
);
name_len
-=
temp_fea
->
value_len
;
temp_ptr
+=
temp_fea
->
value_len
;
/* BB check that temp_ptr is still within smb BB*/
/* no trailing null to account for in value len */
/* go on to next EA */
temp_fea
=
(
struct
fea
*
)
temp_ptr
;
...
...
@@ -3138,4 +3142,152 @@ CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
return
rc
;
}
ssize_t
CIFSSMBQueryEA
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
unsigned
char
*
searchName
,
const
unsigned
char
*
ea_name
,
unsigned
char
*
ea_value
,
size_t
buf_size
,
const
struct
nls_table
*
nls_codepage
)
{
TRANSACTION2_QPI_REQ
*
pSMB
=
NULL
;
TRANSACTION2_QPI_RSP
*
pSMBr
=
NULL
;
int
rc
=
0
;
int
bytes_returned
;
int
name_len
;
struct
fea
*
temp_fea
;
char
*
temp_ptr
;
cFYI
(
1
,
(
"In Query EA path %s"
,
searchName
));
QEARetry:
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
,
searchName
,
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
(
searchName
,
530
);
name_len
++
;
/* trailing null */
strncpy
(
pSMB
->
FileName
,
searchName
,
name_len
);
}
pSMB
->
TotalParameterCount
=
2
/* level */
+
4
/* reserved */
+
name_len
/* includes null */
;
pSMB
->
TotalDataCount
=
0
;
pSMB
->
MaxParameterCount
=
cpu_to_le16
(
2
);
pSMB
->
MaxDataCount
=
cpu_to_le16
(
4000
);
/* 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
=
cpu_to_le16
(
offsetof
(
struct
smb_com_transaction2_qpi_req
,
InformationLevel
)
-
4
);
pSMB
->
DataCount
=
0
;
pSMB
->
DataOffset
=
0
;
pSMB
->
SetupCount
=
1
;
pSMB
->
Reserved3
=
0
;
pSMB
->
SubCommand
=
cpu_to_le16
(
TRANS2_QUERY_PATH_INFORMATION
);
pSMB
->
ByteCount
=
pSMB
->
TotalParameterCount
+
1
/* pad */
;
pSMB
->
TotalParameterCount
=
cpu_to_le16
(
pSMB
->
TotalParameterCount
);
pSMB
->
ParameterCount
=
pSMB
->
TotalParameterCount
;
pSMB
->
InformationLevel
=
cpu_to_le16
(
SMB_INFO_QUERY_ALL_EAS
);
pSMB
->
Reserved4
=
0
;
pSMB
->
hdr
.
smb_buf_length
+=
pSMB
->
ByteCount
;
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
,
(
"Send error in Query EA = %d"
,
rc
));
}
else
{
/* decode response */
pSMBr
->
DataOffset
=
le16_to_cpu
(
pSMBr
->
DataOffset
);
/* BB also check enough total bytes returned */
/* BB we need to improve the validity checking
of these trans2 responses */
if
((
pSMBr
->
ByteCount
<
4
)
||
(
pSMBr
->
DataOffset
>
512
))
rc
=
-
EIO
;
/* bad smb */
/* else if (pFindData){
memcpy((char *) pFindData,
(char *) &pSMBr->hdr.Protocol +
pSMBr->DataOffset, kl);
}*/
else
{
/* check that length of list is not more than bcc */
/* check that each entry does not go beyond length
of list */
/* check that each element of each entry does not
go beyond end of list */
struct
fealist
*
ea_response_data
;
rc
=
-
ENOENT
;
/* validate_trans2_offsets() */
/* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
ea_response_data
=
(
struct
fealist
*
)
(((
char
*
)
&
pSMBr
->
hdr
.
Protocol
)
+
pSMBr
->
DataOffset
);
ea_response_data
->
list_len
=
cpu_to_le32
(
ea_response_data
->
list_len
);
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
;
/* loop through checking if we have a matching
name and then return the associated value */
while
(
name_len
>
0
)
{
name_len
-=
4
;
temp_ptr
+=
4
;
temp_fea
->
value_len
=
cpu_to_le16
(
temp_fea
->
value_len
);
/* BB validate that value_len falls within SMB,
even though maximum for name_len is 255 */
if
(
memcmp
(
temp_fea
->
name
,
ea_name
,
temp_fea
->
name_len
)
==
0
)
{
/* found a match */
rc
=
temp_fea
->
value_len
;
/* account for prefix user. and trailing null */
if
(
rc
<=
buf_size
)
{
memcpy
(
ea_value
,
temp_fea
->
name
+
temp_fea
->
name_len
+
1
,
rc
);
/* ea values, unlike ea names,
are not null terminated */
}
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
)
cifs_buf_release
(
pSMB
);
if
(
rc
==
-
EAGAIN
)
goto
QEARetry
;
return
rc
;
}
#endif
fs/cifs/xattr.c
View file @
81d10c10
...
...
@@ -26,27 +26,117 @@
#include "cifsproto.h"
#include "cifs_debug.h"
#define CIFS_XATTR_DOS_ATTRIB "user.DOSATTRIB"
#define CIFS_XATTR_USER_PREFIX "user."
#define CIFS_XATTR_SYSTEM_PREFIX "system."
#define CIFS_XATTR_OS2_PREFIX "OS2."
/* BB should check for this someday */
/* also note could add check for security prefix XATTR_SECURITY_PREFIX */
int
cifs_removexattr
(
struct
dentry
*
direntry
,
const
char
*
name
)
{
int
rc
=
-
EOPNOTSUPP
;
return
rc
;
}
int
cifs_setxattr
(
struct
dentry
*
direntry
,
const
char
*
name
,
const
void
*
value
,
size_t
size
,
int
flags
)
int
cifs_setxattr
(
struct
dentry
*
direntry
,
const
char
*
ea_
name
,
const
void
*
ea_value
,
size_t
buf_
size
,
int
flags
)
{
int
rc
=
-
EOPNOTSUPP
;
#ifdef CONFIG_CIFS_XATTR
int
xid
;
struct
cifs_sb_info
*
cifs_sb
;
struct
cifsTconInfo
*
pTcon
;
struct
super_block
*
sb
;
char
*
full_path
;
if
(
direntry
==
NULL
)
return
-
EIO
;
if
(
direntry
->
d_inode
==
NULL
)
return
-
EIO
;
sb
=
direntry
->
d_inode
->
i_sb
;
if
(
sb
==
NULL
)
return
-
EIO
;
xid
=
GetXid
();
cifs_sb
=
CIFS_SB
(
sb
);
pTcon
=
cifs_sb
->
tcon
;
down
(
&
sb
->
s_vfs_rename_sem
);
full_path
=
build_path_from_dentry
(
direntry
);
up
(
&
sb
->
s_vfs_rename_sem
);
if
(
full_path
==
NULL
)
{
FreeXid
(
xid
);
return
-
ENOMEM
;
}
/* 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 = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,buf_size,
cifs_sb->local_nls);*/
if
(
full_path
)
kfree
(
full_path
);
FreeXid
(
xid
);
#endif
return
rc
;
}
ssize_t
cifs_getxattr
(
struct
dentry
*
direntry
,
const
char
*
name
,
void
*
value
,
size_t
size
)
ssize_t
cifs_getxattr
(
struct
dentry
*
direntry
,
const
char
*
ea_
name
,
void
*
ea_value
,
size_t
buf_
size
)
{
ssize_t
rc
=
-
EOPNOTSUPP
;
#ifdef CONFIG_CIFS_XATTR
int
xid
;
struct
cifs_sb_info
*
cifs_sb
;
struct
cifsTconInfo
*
pTcon
;
struct
super_block
*
sb
;
char
*
full_path
;
if
(
direntry
==
NULL
)
return
-
EIO
;
if
(
direntry
->
d_inode
==
NULL
)
return
-
EIO
;
sb
=
direntry
->
d_inode
->
i_sb
;
if
(
sb
==
NULL
)
return
-
EIO
;
xid
=
GetXid
();
cifs_sb
=
CIFS_SB
(
sb
);
pTcon
=
cifs_sb
->
tcon
;
down
(
&
sb
->
s_vfs_rename_sem
);
full_path
=
build_path_from_dentry
(
direntry
);
up
(
&
sb
->
s_vfs_rename_sem
);
if
(
full_path
==
NULL
)
{
FreeXid
(
xid
);
return
-
ENOMEM
;
}
/* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */
if
(
memcmp
(
ea_name
,
CIFS_XATTR_USER_PREFIX
,
5
))
{
cFYI
(
1
,(
"illegal xattr namespace %s (only user namespace supported)"
,
ea_name
));
/* BB what if no namespace prefix? */
/* Should we just pass them to server, except for system? */
}
else
{
/* We could add a check here
if proc/fs/cifs/streamstoxattr is set then
search server for EAs or streams to
returns as xattrs */
ea_name
+=
5
;
/* skip past user. */
rc
=
CIFSSMBQueryEA
(
xid
,
pTcon
,
full_path
,
ea_name
,
ea_value
,
buf_size
,
cifs_sb
->
local_nls
);
}
if
(
full_path
)
kfree
(
full_path
);
FreeXid
(
xid
);
#endif
return
rc
;
}
ssize_t
cifs_listxattr
(
struct
dentry
*
direntry
,
char
*
ea_data
,
size_t
ea
_size
)
ssize_t
cifs_listxattr
(
struct
dentry
*
direntry
,
char
*
data
,
size_t
buf
_size
)
{
ssize_t
rc
=
-
EOPNOTSUPP
;
#ifdef CONFIG_CIFS_XATTR
...
...
@@ -81,8 +171,11 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * ea_data, size_t ea_size)
/* 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
,
rc
=
CIFSSMBQAllEAs
(
xid
,
pTcon
,
full_path
,
data
,
buf
_size
,
cifs_sb
->
local_nls
);
if
(
full_path
)
kfree
(
full_path
);
FreeXid
(
xid
);
#endif
return
rc
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment