Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: (24 commits) [CIFS] merge conflict in fs/cifs/export.c [CIFS] Allow disabling CIFS Unix Extensions as mount option [CIFS] More whitespace/formatting fixes (noticed by checkpatch) [CIFS] Typo in previous patch [CIFS] zero_user_page() conversions [CIFS] use simple_prepare_write to zero page data [CIFS] Fix build break - inet.h not included when experimental ifdef off [CIFS] Add support for new POSIX unlink [CIFS] whitespace/formatting fixes [CIFS] Fix oops in cifs_create when nfsd server exports cifs mount [CIFS] whitespace cleanup [CIFS] Fix packet signatures for NTLMv2 case [CIFS] more whitespace fixes [CIFS] more whitespace cleanup [CIFS] whitespace cleanup [CIFS] whitespace cleanup [CIFS] ipv6 support no longer experimental [CIFS] Mount should fail if server signing off but client mount option requires it [CIFS] whitespace fixes [CIFS] Fix sign mount option and sign proc config setting ...
This commit is contained in:
commit
789c56b7f7
38 changed files with 3435 additions and 3151 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
Version 1.50
|
||||||
|
------------
|
||||||
|
Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is
|
||||||
|
done with "serverino" mount option). Add support for POSIX Unlink
|
||||||
|
(helps with certain sharing violation cases when server such as
|
||||||
|
Samba supports newer POSIX CIFS Protocol Extensions).
|
||||||
|
|
||||||
Version 1.49
|
Version 1.49
|
||||||
------------
|
------------
|
||||||
IPv6 support. Enable ipv6 addresses to be passed on mount (put the ipv6
|
IPv6 support. Enable ipv6 addresses to be passed on mount (put the ipv6
|
||||||
|
@ -8,7 +15,11 @@ when Unix Extensions were ignored). This allows users to override the
|
||||||
default uid and gid for files when they are certain that the uids or
|
default uid and gid for files when they are certain that the uids or
|
||||||
gids on the server do not match those of the client. Make "sec=none"
|
gids on the server do not match those of the client. Make "sec=none"
|
||||||
mount override username (so that null user connection is attempted)
|
mount override username (so that null user connection is attempted)
|
||||||
to match what documentation said.
|
to match what documentation said. Support for very large reads, over 127K,
|
||||||
|
available to some newer servers (such as Samba 3.0.26 and later but
|
||||||
|
note that it also requires setting CIFSMaxBufSize at module install
|
||||||
|
time to a larger value which may hurt performance in some cases).
|
||||||
|
Make sign option force signing (or fail if server does not support it).
|
||||||
|
|
||||||
Version 1.48
|
Version 1.48
|
||||||
------------
|
------------
|
||||||
|
|
|
@ -301,10 +301,21 @@ A partial list of the supported mount options follows:
|
||||||
during the local client kernel build will be used.
|
during the local client kernel build will be used.
|
||||||
If server does not support Unicode, this parameter is
|
If server does not support Unicode, this parameter is
|
||||||
unused.
|
unused.
|
||||||
rsize default read size (usually 16K)
|
rsize default read size (usually 16K). The client currently
|
||||||
wsize default write size (usually 16K, 32K is often better over GigE)
|
can not use rsize larger than CIFSMaxBufSize. CIFSMaxBufSize
|
||||||
maximum wsize currently allowed by CIFS is 57344 (14 4096 byte
|
defaults to 16K and may be changed (from 8K to the maximum
|
||||||
pages)
|
kmalloc size allowed by your kernel) at module install time
|
||||||
|
for cifs.ko. Setting CIFSMaxBufSize to a very large value
|
||||||
|
will cause cifs to use more memory and may reduce performance
|
||||||
|
in some cases. To use rsize greater than 127K (the original
|
||||||
|
cifs protocol maximum) also requires that the server support
|
||||||
|
a new Unix Capability flag (for very large read) which some
|
||||||
|
newer servers (e.g. Samba 3.0.26 or later) do. rsize can be
|
||||||
|
set from a minimum of 2048 to a maximum of 130048 (127K or
|
||||||
|
CIFSMaxBufSize, whichever is smaller)
|
||||||
|
wsize default write size (default 57344)
|
||||||
|
maximum wsize currently allowed by CIFS is 57344 (fourteen
|
||||||
|
4096 byte pages)
|
||||||
rw mount the network share read-write (note that the
|
rw mount the network share read-write (note that the
|
||||||
server may still consider the share read-only)
|
server may still consider the share read-only)
|
||||||
ro mount network share read-only
|
ro mount network share read-only
|
||||||
|
@ -359,7 +370,7 @@ A partial list of the supported mount options follows:
|
||||||
Note that this does not affect the normal ACL check on the
|
Note that this does not affect the normal ACL check on the
|
||||||
target machine done by the server software (of the server
|
target machine done by the server software (of the server
|
||||||
ACL against the user name provided at mount time).
|
ACL against the user name provided at mount time).
|
||||||
serverino Use servers inode numbers instead of generating automatically
|
serverino Use server's inode numbers instead of generating automatically
|
||||||
incrementing inode numbers on the client. Although this will
|
incrementing inode numbers on the client. Although this will
|
||||||
make it easier to spot hardlinked files (as they will have
|
make it easier to spot hardlinked files (as they will have
|
||||||
the same inode numbers) and inode numbers may be persistent,
|
the same inode numbers) and inode numbers may be persistent,
|
||||||
|
@ -367,12 +378,11 @@ A partial list of the supported mount options follows:
|
||||||
are unique if multiple server side mounts are exported under a
|
are unique if multiple server side mounts are exported under a
|
||||||
single share (since inode numbers on the servers might not
|
single share (since inode numbers on the servers might not
|
||||||
be unique if multiple filesystems are mounted under the same
|
be unique if multiple filesystems are mounted under the same
|
||||||
shared higher level directory). Note that this requires that
|
shared higher level directory). Note that some older
|
||||||
the server support the CIFS Unix Extensions as other servers
|
(e.g. pre-Windows 2000) do not support returning UniqueIDs
|
||||||
do not return a unique IndexNumber on SMB FindFirst (most
|
or the CIFS Unix Extensions equivalent and for those
|
||||||
servers return zero as the IndexNumber). Parameter has no
|
this mount option will have no effect. Exporting cifs mounts
|
||||||
effect to Windows servers and others which do not support the
|
under nfsd requires this mount option on the cifs mount.
|
||||||
CIFS Unix Extensions.
|
|
||||||
noserverino Client generates inode numbers (rather than using the actual one
|
noserverino Client generates inode numbers (rather than using the actual one
|
||||||
from the server) by default.
|
from the server) by default.
|
||||||
setuids If the CIFS Unix extensions are negotiated with the server
|
setuids If the CIFS Unix extensions are negotiated with the server
|
||||||
|
@ -582,10 +592,10 @@ the start of smb requests and responses can be enabled via:
|
||||||
|
|
||||||
echo 1 > /proc/fs/cifs/traceSMB
|
echo 1 > /proc/fs/cifs/traceSMB
|
||||||
|
|
||||||
Two other experimental features are under development and to test
|
Two other experimental features are under development. To test these
|
||||||
require enabling CONFIG_CIFS_EXPERIMENTAL
|
requires enabling CONFIG_CIFS_EXPERIMENTAL
|
||||||
|
|
||||||
More efficient write operations
|
ipv6 enablement
|
||||||
|
|
||||||
DNOTIFY fcntl: needed for support of directory change
|
DNOTIFY fcntl: needed for support of directory change
|
||||||
notification and perhaps later for file leases)
|
notification and perhaps later for file leases)
|
||||||
|
|
12
fs/cifs/TODO
12
fs/cifs/TODO
|
@ -18,9 +18,9 @@ better)
|
||||||
|
|
||||||
d) Kerberos/SPNEGO session setup support - (started)
|
d) Kerberos/SPNEGO session setup support - (started)
|
||||||
|
|
||||||
e) More testing of NTLMv2 authentication (mostly implemented - double check
|
e) Cleanup now unneeded SessSetup code in
|
||||||
that NTLMv2 signing works, also need to cleanup now unneeded SessSetup code in
|
fs/cifs/connect.c and add back in NTLMSSP code if any servers
|
||||||
fs/cifs/connect.c)
|
need it
|
||||||
|
|
||||||
f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
|
f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
|
||||||
used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
|
used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
|
||||||
|
@ -106,6 +106,12 @@ but recognizes them
|
||||||
succeed but still return access denied (appears to be Windows
|
succeed but still return access denied (appears to be Windows
|
||||||
server not cifs client problem) and has not been reproduced recently.
|
server not cifs client problem) and has not been reproduced recently.
|
||||||
NTFS partitions do not have this problem.
|
NTFS partitions do not have this problem.
|
||||||
|
4) Unix/POSIX capabilities are reset after reconnection, and affect
|
||||||
|
a few fields in the tree connection but we do do not know which
|
||||||
|
superblocks to apply these changes to. We should probably walk
|
||||||
|
the list of superblocks to set these. Also need to check the
|
||||||
|
flags on the second mount to the same share, and see if we
|
||||||
|
can do the same trick that NFS does to remount duplicate shares.
|
||||||
|
|
||||||
Misc testing to do
|
Misc testing to do
|
||||||
==================
|
==================
|
||||||
|
|
|
@ -459,7 +459,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
unsigned int cls, con, tag, oidlen, rc;
|
unsigned int cls, con, tag, oidlen, rc;
|
||||||
int use_ntlmssp = FALSE;
|
int use_ntlmssp = FALSE;
|
||||||
|
|
||||||
*secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
|
*secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/
|
||||||
|
|
||||||
/* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
|
/* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
|
||||||
|
|
||||||
|
@ -498,7 +498,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|
||||||
|| (tag != ASN1_EOC)) {
|
|| (tag != ASN1_EOC)) {
|
||||||
cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0",
|
cFYI(1,
|
||||||
|
("cls = %d con = %d tag = %d end = %p (%d) exit 0",
|
||||||
cls, con, tag, end, *end));
|
cls, con, tag, end, *end));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -508,7 +509,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|
||||||
|| (tag != ASN1_SEQ)) {
|
|| (tag != ASN1_SEQ)) {
|
||||||
cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1",
|
cFYI(1,
|
||||||
|
("cls = %d con = %d tag = %d end = %p (%d) exit 1",
|
||||||
cls, con, tag, end, *end));
|
cls, con, tag, end, *end));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -540,32 +542,34 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
|
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Error 1 decoding negTokenInit header exit 2"));
|
("Error decoding negTokenInit hdr exit2"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
|
if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
|
||||||
rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
|
rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
|
||||||
if(rc) {
|
if (rc) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
|
("OID len = %d oid = 0x%lx 0x%lx "
|
||||||
oidlen, *oid, *(oid + 1), *(oid + 2),
|
"0x%lx 0x%lx",
|
||||||
*(oid + 3)));
|
oidlen, *oid, *(oid + 1),
|
||||||
rc = compare_oid(oid, oidlen, NTLMSSP_OID,
|
*(oid + 2), *(oid + 3)));
|
||||||
NTLMSSP_OID_LEN);
|
rc = compare_oid(oid, oidlen,
|
||||||
|
NTLMSSP_OID, NTLMSSP_OID_LEN);
|
||||||
kfree(oid);
|
kfree(oid);
|
||||||
if (rc)
|
if (rc)
|
||||||
use_ntlmssp = TRUE;
|
use_ntlmssp = TRUE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cFYI(1,("This should be an oid what is going on? "));
|
cFYI(1, ("Should be an oid what is going on?"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Error decoding last part of negTokenInit exit 3"));
|
("Error decoding last part negTokenInit exit3"));
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */
|
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
|
||||||
|
/* tag = 3 indicating mechListMIC */
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
|
("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
|
||||||
cls, con, tag, end, *end));
|
cls, con, tag, end, *end));
|
||||||
|
@ -573,7 +577,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
}
|
}
|
||||||
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Error decoding last part of negTokenInit exit 5"));
|
("Error decoding last part negTokenInit exit5"));
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|
||||||
|| (tag != ASN1_SEQ)) {
|
|| (tag != ASN1_SEQ)) {
|
||||||
|
@ -584,7 +588,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
|
|
||||||
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Error decoding last part of negTokenInit exit 7"));
|
("Error decoding last part negTokenInit exit 7"));
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
|
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
|
@ -594,16 +598,17 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
}
|
}
|
||||||
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Error decoding last part of negTokenInit exit 9"));
|
("Error decoding last part negTokenInit exit9"));
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
|
} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
|
||||||
|| (tag != ASN1_GENSTR)) {
|
|| (tag != ASN1_GENSTR)) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Exit 10 cls = %d con = %d tag = %d end = %p (%d)",
|
("Exit10 cls = %d con = %d tag = %d end = %p (%d)",
|
||||||
cls, con, tag, end, *end));
|
cls, con, tag, end, *end));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */
|
cFYI(1, ("Need to call asn1_octets_decode() function for %s",
|
||||||
|
ctx.pointer)); /* is this UTF-8 or ASCII? */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if (use_kerberos)
|
/* if (use_kerberos)
|
||||||
|
|
|
@ -58,7 +58,7 @@ cifs_dump_mem(char *label, void *data, int length)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_DEBUG2
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
void cifs_dump_detail(struct smb_hdr * smb)
|
void cifs_dump_detail(struct smb_hdr *smb)
|
||||||
{
|
{
|
||||||
cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
|
cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
|
||||||
smb->Command, smb->Status.CifsError,
|
smb->Command, smb->Status.CifsError,
|
||||||
|
@ -67,10 +67,10 @@ void cifs_dump_detail(struct smb_hdr * smb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void cifs_dump_mids(struct TCP_Server_Info * server)
|
void cifs_dump_mids(struct TCP_Server_Info *server)
|
||||||
{
|
{
|
||||||
struct list_head *tmp;
|
struct list_head *tmp;
|
||||||
struct mid_q_entry * mid_entry;
|
struct mid_q_entry *mid_entry;
|
||||||
|
|
||||||
if (server == NULL)
|
if (server == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -114,12 +114,12 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
{
|
{
|
||||||
struct list_head *tmp;
|
struct list_head *tmp;
|
||||||
struct list_head *tmp1;
|
struct list_head *tmp1;
|
||||||
struct mid_q_entry * mid_entry;
|
struct mid_q_entry *mid_entry;
|
||||||
struct cifsSesInfo *ses;
|
struct cifsSesInfo *ses;
|
||||||
struct cifsTconInfo *tcon;
|
struct cifsTconInfo *tcon;
|
||||||
int i;
|
int i;
|
||||||
int length = 0;
|
int length = 0;
|
||||||
char * original_buf = buf;
|
char *original_buf = buf;
|
||||||
|
|
||||||
*beginBuffer = buf + offset;
|
*beginBuffer = buf + offset;
|
||||||
|
|
||||||
|
@ -145,7 +145,6 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
(ses->serverNOS == NULL)) {
|
(ses->serverNOS == NULL)) {
|
||||||
buf += sprintf(buf, "\nentry for %s not fully "
|
buf += sprintf(buf, "\nentry for %s not fully "
|
||||||
"displayed\n\t", ses->serverName);
|
"displayed\n\t", ses->serverName);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
length =
|
length =
|
||||||
sprintf(buf,
|
sprintf(buf,
|
||||||
|
@ -901,90 +900,14 @@ security_flags_write(struct file *file, const char __user *buffer,
|
||||||
}
|
}
|
||||||
/* flags look ok - update the global security flags for cifs module */
|
/* flags look ok - update the global security flags for cifs module */
|
||||||
extended_security = flags;
|
extended_security = flags;
|
||||||
|
if (extended_security & CIFSSEC_MUST_SIGN) {
|
||||||
|
/* requiring signing implies signing is allowed */
|
||||||
|
extended_security |= CIFSSEC_MAY_SIGN;
|
||||||
|
cFYI(1, ("packet signing now required"));
|
||||||
|
} else if ((extended_security & CIFSSEC_MAY_SIGN) == 0) {
|
||||||
|
cFYI(1, ("packet signing disabled"));
|
||||||
|
}
|
||||||
|
/* BB should we turn on MAY flags for other MUST options? */
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static int
|
|
||||||
ntlmv2_enabled_read(char *page, char **start, off_t off,
|
|
||||||
int count, int *eof, void *data)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
|
|
||||||
len = sprintf(page, "%d\n", ntlmv2_support);
|
|
||||||
|
|
||||||
len -= off;
|
|
||||||
*start = page + off;
|
|
||||||
|
|
||||||
if (len > count)
|
|
||||||
len = count;
|
|
||||||
else
|
|
||||||
*eof = 1;
|
|
||||||
|
|
||||||
if (len < 0)
|
|
||||||
len = 0;
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
static int
|
|
||||||
ntlmv2_enabled_write(struct file *file, const char __user *buffer,
|
|
||||||
unsigned long count, void *data)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = get_user(c, buffer);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
if (c == '0' || c == 'n' || c == 'N')
|
|
||||||
ntlmv2_support = 0;
|
|
||||||
else if (c == '1' || c == 'y' || c == 'Y')
|
|
||||||
ntlmv2_support = 1;
|
|
||||||
else if (c == '2')
|
|
||||||
ntlmv2_support = 2;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
packet_signing_enabled_read(char *page, char **start, off_t off,
|
|
||||||
int count, int *eof, void *data)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
|
|
||||||
len = sprintf(page, "%d\n", sign_CIFS_PDUs);
|
|
||||||
|
|
||||||
len -= off;
|
|
||||||
*start = page + off;
|
|
||||||
|
|
||||||
if (len > count)
|
|
||||||
len = count;
|
|
||||||
else
|
|
||||||
*eof = 1;
|
|
||||||
|
|
||||||
if (len < 0)
|
|
||||||
len = 0;
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
static int
|
|
||||||
packet_signing_enabled_write(struct file *file, const char __user *buffer,
|
|
||||||
unsigned long count, void *data)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = get_user(c, buffer);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
if (c == '0' || c == 'n' || c == 'N')
|
|
||||||
sign_CIFS_PDUs = 0;
|
|
||||||
else if (c == '1' || c == 'y' || c == 'Y')
|
|
||||||
sign_CIFS_PDUs = 1;
|
|
||||||
else if (c == '2')
|
|
||||||
sign_CIFS_PDUs = 2;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,6 +43,6 @@ struct cifs_sb_info {
|
||||||
mode_t mnt_dir_mode;
|
mode_t mnt_dir_mode;
|
||||||
int mnt_cifs_flags;
|
int mnt_cifs_flags;
|
||||||
int prepathlen;
|
int prepathlen;
|
||||||
char * prepath;
|
char *prepath;
|
||||||
};
|
};
|
||||||
#endif /* _CIFS_FS_SB_H */
|
#endif /* _CIFS_FS_SB_H */
|
||||||
|
|
|
@ -66,7 +66,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len,
|
||||||
{
|
{
|
||||||
int charlen;
|
int charlen;
|
||||||
int i;
|
int i;
|
||||||
wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */
|
wchar_t *wchar_to = (wchar_t *)to; /* needed to quiet sparse */
|
||||||
|
|
||||||
for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
|
for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Convert a unicode character to upper or lower case using
|
* Convert a unicode character to upper or lower case using
|
||||||
* compressed tables.
|
* compressed tables.
|
||||||
*
|
*
|
||||||
* Copyright (c) International Business Machines Corp., 2000,2005555555555555555555555555555555555555555555555555555555
|
* Copyright (c) International Business Machines Corp., 2000,2007
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -70,7 +70,7 @@ int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
|
||||||
* Address of the first string
|
* Address of the first string
|
||||||
*/
|
*/
|
||||||
static inline wchar_t *
|
static inline wchar_t *
|
||||||
UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
|
UniStrcat(wchar_t *ucs1, const wchar_t *ucs2)
|
||||||
{
|
{
|
||||||
wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
|
wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
|
||||||
* or NULL if the character is not in the string
|
* or NULL if the character is not in the string
|
||||||
*/
|
*/
|
||||||
static inline wchar_t *
|
static inline wchar_t *
|
||||||
UniStrchr(const wchar_t * ucs, wchar_t uc)
|
UniStrchr(const wchar_t *ucs, wchar_t uc)
|
||||||
{
|
{
|
||||||
while ((*ucs != uc) && *ucs)
|
while ((*ucs != uc) && *ucs)
|
||||||
ucs++;
|
ucs++;
|
||||||
|
@ -107,7 +107,7 @@ UniStrchr(const wchar_t * ucs, wchar_t uc)
|
||||||
* > 0: First string is greater than second
|
* > 0: First string is greater than second
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int
|
||||||
UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
|
UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2)
|
||||||
{
|
{
|
||||||
while ((*ucs1 == *ucs2) && *ucs1) {
|
while ((*ucs1 == *ucs2) && *ucs1) {
|
||||||
ucs1++;
|
ucs1++;
|
||||||
|
@ -120,7 +120,7 @@ UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
|
||||||
* UniStrcpy: Copy a string
|
* UniStrcpy: Copy a string
|
||||||
*/
|
*/
|
||||||
static inline wchar_t *
|
static inline wchar_t *
|
||||||
UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2)
|
UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)
|
||||||
{
|
{
|
||||||
wchar_t *anchor = ucs1; /* save the start of result string */
|
wchar_t *anchor = ucs1; /* save the start of result string */
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2)
|
||||||
* UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
|
* UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
|
||||||
*/
|
*/
|
||||||
static inline size_t
|
static inline size_t
|
||||||
UniStrlen(const wchar_t * ucs1)
|
UniStrlen(const wchar_t *ucs1)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
@ -142,10 +142,11 @@ UniStrlen(const wchar_t * ucs1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a string (length limited)
|
* UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a
|
||||||
|
* string (length limited)
|
||||||
*/
|
*/
|
||||||
static inline size_t
|
static inline size_t
|
||||||
UniStrnlen(const wchar_t * ucs1, int maxlen)
|
UniStrnlen(const wchar_t *ucs1, int maxlen)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
@ -161,7 +162,7 @@ UniStrnlen(const wchar_t * ucs1, int maxlen)
|
||||||
* UniStrncat: Concatenate length limited string
|
* UniStrncat: Concatenate length limited string
|
||||||
*/
|
*/
|
||||||
static inline wchar_t *
|
static inline wchar_t *
|
||||||
UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
|
UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
|
||||||
{
|
{
|
||||||
wchar_t *anchor = ucs1; /* save pointer to string 1 */
|
wchar_t *anchor = ucs1; /* save pointer to string 1 */
|
||||||
|
|
||||||
|
@ -179,7 +180,7 @@ UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
|
||||||
* UniStrncmp: Compare length limited string
|
* UniStrncmp: Compare length limited string
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int
|
||||||
UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
|
UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
|
||||||
{
|
{
|
||||||
if (!n)
|
if (!n)
|
||||||
return 0; /* Null strings are equal */
|
return 0; /* Null strings are equal */
|
||||||
|
@ -194,7 +195,7 @@ UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
|
||||||
* UniStrncmp_le: Compare length limited string - native to little-endian
|
* UniStrncmp_le: Compare length limited string - native to little-endian
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int
|
||||||
UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
|
UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
|
||||||
{
|
{
|
||||||
if (!n)
|
if (!n)
|
||||||
return 0; /* Null strings are equal */
|
return 0; /* Null strings are equal */
|
||||||
|
@ -209,7 +210,7 @@ UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
|
||||||
* UniStrncpy: Copy length limited string with pad
|
* UniStrncpy: Copy length limited string with pad
|
||||||
*/
|
*/
|
||||||
static inline wchar_t *
|
static inline wchar_t *
|
||||||
UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
|
UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
|
||||||
{
|
{
|
||||||
wchar_t *anchor = ucs1;
|
wchar_t *anchor = ucs1;
|
||||||
|
|
||||||
|
@ -226,7 +227,7 @@ UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
|
||||||
* UniStrncpy_le: Copy length limited string with pad to little-endian
|
* UniStrncpy_le: Copy length limited string with pad to little-endian
|
||||||
*/
|
*/
|
||||||
static inline wchar_t *
|
static inline wchar_t *
|
||||||
UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
|
UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
|
||||||
{
|
{
|
||||||
wchar_t *anchor = ucs1;
|
wchar_t *anchor = ucs1;
|
||||||
|
|
||||||
|
@ -247,7 +248,7 @@ UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
|
||||||
* NULL if no matching string is found
|
* NULL if no matching string is found
|
||||||
*/
|
*/
|
||||||
static inline wchar_t *
|
static inline wchar_t *
|
||||||
UniStrstr(const wchar_t * ucs1, const wchar_t * ucs2)
|
UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)
|
||||||
{
|
{
|
||||||
const wchar_t *anchor1 = ucs1;
|
const wchar_t *anchor1 = ucs1;
|
||||||
const wchar_t *anchor2 = ucs2;
|
const wchar_t *anchor2 = ucs2;
|
||||||
|
@ -297,7 +298,7 @@ UniToupper(register wchar_t uc)
|
||||||
* UniStrupr: Upper case a unicode string
|
* UniStrupr: Upper case a unicode string
|
||||||
*/
|
*/
|
||||||
static inline wchar_t *
|
static inline wchar_t *
|
||||||
UniStrupr(register wchar_t * upin)
|
UniStrupr(register wchar_t *upin)
|
||||||
{
|
{
|
||||||
register wchar_t *up;
|
register wchar_t *up;
|
||||||
|
|
||||||
|
@ -338,7 +339,7 @@ UniTolower(wchar_t uc)
|
||||||
* UniStrlwr: Lower case a unicode string
|
* UniStrlwr: Lower case a unicode string
|
||||||
*/
|
*/
|
||||||
static inline wchar_t *
|
static inline wchar_t *
|
||||||
UniStrlwr(register wchar_t * upin)
|
UniStrlwr(register wchar_t *upin)
|
||||||
{
|
{
|
||||||
register wchar_t *up;
|
register wchar_t *up;
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
|
|
||||||
/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
|
/* Calculate and return the CIFS signature based on the mac key and SMB PDU */
|
||||||
/* the 16 byte signature must be allocated by the caller */
|
/* the 16 byte signature must be allocated by the caller */
|
||||||
/* Note we only use the 1st eight bytes */
|
/* Note we only use the 1st eight bytes */
|
||||||
/* Note that the smb header signature field on input contains the
|
/* Note that the smb header signature field on input contains the
|
||||||
|
@ -40,94 +40,32 @@ extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
|
||||||
extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
|
extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
|
||||||
unsigned char *p24);
|
unsigned char *p24);
|
||||||
|
|
||||||
static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu,
|
static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
|
||||||
const char * key, char * signature)
|
const struct mac_key *key, char *signature)
|
||||||
{
|
{
|
||||||
struct MD5Context context;
|
struct MD5Context context;
|
||||||
|
|
||||||
if((cifs_pdu == NULL) || (signature == NULL))
|
if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
MD5Init(&context);
|
MD5Init(&context);
|
||||||
MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
|
MD5Update(&context, (char *)&key->data, key->len);
|
||||||
MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
|
MD5Update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
|
||||||
MD5Final(signature,&context);
|
|
||||||
|
MD5Final(signature, &context);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
|
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
|
||||||
__u32 * pexpected_response_sequence_number)
|
__u32 *pexpected_response_sequence_number)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
char smb_signature[20];
|
char smb_signature[20];
|
||||||
|
|
||||||
if((cifs_pdu == NULL) || (server == NULL))
|
if ((cifs_pdu == NULL) || (server == NULL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
|
if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
|
||||||
return rc;
|
|
||||||
|
|
||||||
spin_lock(&GlobalMid_Lock);
|
|
||||||
cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(server->sequence_number);
|
|
||||||
cifs_pdu->Signature.Sequence.Reserved = 0;
|
|
||||||
|
|
||||||
*pexpected_response_sequence_number = server->sequence_number++;
|
|
||||||
server->sequence_number++;
|
|
||||||
spin_unlock(&GlobalMid_Lock);
|
|
||||||
|
|
||||||
rc = cifs_calculate_signature(cifs_pdu, server->mac_signing_key,smb_signature);
|
|
||||||
if(rc)
|
|
||||||
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
|
|
||||||
else
|
|
||||||
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
|
|
||||||
const char * key, char * signature)
|
|
||||||
{
|
|
||||||
struct MD5Context context;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if((iov == NULL) || (signature == NULL))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
MD5Init(&context);
|
|
||||||
MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
|
|
||||||
for(i=0;i<n_vec;i++) {
|
|
||||||
if(iov[i].iov_base == NULL) {
|
|
||||||
cERROR(1,("null iovec entry"));
|
|
||||||
return -EIO;
|
|
||||||
} else if(iov[i].iov_len == 0)
|
|
||||||
break; /* bail out if we are sent nothing to sign */
|
|
||||||
/* The first entry includes a length field (which does not get
|
|
||||||
signed that occupies the first 4 bytes before the header */
|
|
||||||
if(i==0) {
|
|
||||||
if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
|
|
||||||
break; /* nothing to sign or corrupt header */
|
|
||||||
MD5Update(&context,iov[0].iov_base+4, iov[0].iov_len-4);
|
|
||||||
} else
|
|
||||||
MD5Update(&context,iov[i].iov_base, iov[i].iov_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
MD5Final(signature,&context);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int cifs_sign_smb2(struct kvec * iov, int n_vec, struct TCP_Server_Info *server,
|
|
||||||
__u32 * pexpected_response_sequence_number)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
char smb_signature[20];
|
|
||||||
struct smb_hdr * cifs_pdu = iov[0].iov_base;
|
|
||||||
|
|
||||||
if((cifs_pdu == NULL) || (server == NULL))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
spin_lock(&GlobalMid_Lock);
|
spin_lock(&GlobalMid_Lock);
|
||||||
|
@ -139,60 +77,129 @@ int cifs_sign_smb2(struct kvec * iov, int n_vec, struct TCP_Server_Info *server,
|
||||||
server->sequence_number++;
|
server->sequence_number++;
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
|
|
||||||
rc = cifs_calc_signature2(iov, n_vec, server->mac_signing_key,
|
rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key,
|
||||||
smb_signature);
|
smb_signature);
|
||||||
if(rc)
|
if (rc)
|
||||||
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
|
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
|
||||||
else
|
else
|
||||||
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
|
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
|
static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
|
||||||
|
const struct mac_key *key, char *signature)
|
||||||
|
{
|
||||||
|
struct MD5Context context;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((iov == NULL) || (signature == NULL) || (key == NULL))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
MD5Init(&context);
|
||||||
|
MD5Update(&context, (char *)&key->data, key->len);
|
||||||
|
for (i = 0; i < n_vec; i++) {
|
||||||
|
if (iov[i].iov_base == NULL) {
|
||||||
|
cERROR(1, ("null iovec entry"));
|
||||||
|
return -EIO;
|
||||||
|
} else if (iov[i].iov_len == 0)
|
||||||
|
break; /* bail out if we are sent nothing to sign */
|
||||||
|
/* The first entry includes a length field (which does not get
|
||||||
|
signed that occupies the first 4 bytes before the header */
|
||||||
|
if (i == 0) {
|
||||||
|
if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
|
||||||
|
break; /* nothing to sign or corrupt header */
|
||||||
|
MD5Update(&context, iov[0].iov_base+4,
|
||||||
|
iov[0].iov_len-4);
|
||||||
|
} else
|
||||||
|
MD5Update(&context, iov[i].iov_base, iov[i].iov_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
MD5Final(signature, &context);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
|
||||||
|
__u32 * pexpected_response_sequence_number)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
char smb_signature[20];
|
||||||
|
struct smb_hdr *cifs_pdu = iov[0].iov_base;
|
||||||
|
|
||||||
|
if ((cifs_pdu == NULL) || (server == NULL))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
spin_lock(&GlobalMid_Lock);
|
||||||
|
cifs_pdu->Signature.Sequence.SequenceNumber =
|
||||||
|
cpu_to_le32(server->sequence_number);
|
||||||
|
cifs_pdu->Signature.Sequence.Reserved = 0;
|
||||||
|
|
||||||
|
*pexpected_response_sequence_number = server->sequence_number++;
|
||||||
|
server->sequence_number++;
|
||||||
|
spin_unlock(&GlobalMid_Lock);
|
||||||
|
|
||||||
|
rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key,
|
||||||
|
smb_signature);
|
||||||
|
if (rc)
|
||||||
|
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
|
||||||
|
else
|
||||||
|
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cifs_verify_signature(struct smb_hdr *cifs_pdu,
|
||||||
|
const struct mac_key *mac_key,
|
||||||
__u32 expected_sequence_number)
|
__u32 expected_sequence_number)
|
||||||
{
|
{
|
||||||
unsigned int rc;
|
unsigned int rc;
|
||||||
char server_response_sig[8];
|
char server_response_sig[8];
|
||||||
char what_we_think_sig_should_be[20];
|
char what_we_think_sig_should_be[20];
|
||||||
|
|
||||||
if((cifs_pdu == NULL) || (mac_key == NULL))
|
if ((cifs_pdu == NULL) || (mac_key == NULL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
|
if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
|
if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
|
||||||
struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu;
|
struct smb_com_lock_req *pSMB =
|
||||||
if(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
|
(struct smb_com_lock_req *)cifs_pdu;
|
||||||
|
if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BB what if signatures are supposed to be on for session but server does not
|
/* BB what if signatures are supposed to be on for session but
|
||||||
send one? BB */
|
server does not send one? BB */
|
||||||
|
|
||||||
/* Do not need to verify session setups with signature "BSRSPYL " */
|
/* Do not need to verify session setups with signature "BSRSPYL " */
|
||||||
if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
|
if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
|
||||||
cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
|
cFYI(1, ("dummy signature received for smb command 0x%x",
|
||||||
|
cifs_pdu->Command));
|
||||||
|
|
||||||
/* save off the origiginal signature so we can modify the smb and check
|
/* save off the origiginal signature so we can modify the smb and check
|
||||||
its signature against what the server sent */
|
its signature against what the server sent */
|
||||||
memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
|
memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8);
|
||||||
|
|
||||||
cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(expected_sequence_number);
|
cifs_pdu->Signature.Sequence.SequenceNumber =
|
||||||
|
cpu_to_le32(expected_sequence_number);
|
||||||
cifs_pdu->Signature.Sequence.Reserved = 0;
|
cifs_pdu->Signature.Sequence.Reserved = 0;
|
||||||
|
|
||||||
rc = cifs_calculate_signature(cifs_pdu, mac_key,
|
rc = cifs_calculate_signature(cifs_pdu, mac_key,
|
||||||
what_we_think_sig_should_be);
|
what_we_think_sig_should_be);
|
||||||
|
|
||||||
if(rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
/* cifs_dump_mem("what we think it should be: ",
|
||||||
|
what_we_think_sig_should_be, 16); */
|
||||||
|
|
||||||
/* cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */
|
if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
|
||||||
|
|
||||||
if(memcmp(server_response_sig, what_we_think_sig_should_be, 8))
|
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -200,89 +207,94 @@ int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We fill in key by putting in 40 byte array which was allocated by caller */
|
/* We fill in key by putting in 40 byte array which was allocated by caller */
|
||||||
int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
|
int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
|
||||||
|
const char *password)
|
||||||
{
|
{
|
||||||
char temp_key[16];
|
char temp_key[16];
|
||||||
if ((key == NULL) || (rn == NULL))
|
if ((key == NULL) || (rn == NULL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
E_md4hash(password, temp_key);
|
E_md4hash(password, temp_key);
|
||||||
mdfour(key,temp_key,16);
|
mdfour(key->data.ntlm, temp_key, 16);
|
||||||
memcpy(key+16,rn, CIFS_SESS_KEY_SIZE);
|
memcpy(key->data.ntlm+16, rn, CIFS_SESS_KEY_SIZE);
|
||||||
|
key->len = 40;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses,
|
int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *ses,
|
||||||
const struct nls_table * nls_info)
|
const struct nls_table *nls_info)
|
||||||
{
|
{
|
||||||
char temp_hash[16];
|
char temp_hash[16];
|
||||||
struct HMACMD5Context ctx;
|
struct HMACMD5Context ctx;
|
||||||
char * ucase_buf;
|
char *ucase_buf;
|
||||||
__le16 * unicode_buf;
|
__le16 *unicode_buf;
|
||||||
unsigned int i,user_name_len,dom_name_len;
|
unsigned int i, user_name_len, dom_name_len;
|
||||||
|
|
||||||
if(ses == NULL)
|
if (ses == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
E_md4hash(ses->password, temp_hash);
|
E_md4hash(ses->password, temp_hash);
|
||||||
|
|
||||||
hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
|
hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
|
||||||
user_name_len = strlen(ses->userName);
|
user_name_len = strlen(ses->userName);
|
||||||
if(user_name_len > MAX_USERNAME_SIZE)
|
if (user_name_len > MAX_USERNAME_SIZE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if(ses->domainName == NULL)
|
if (ses->domainName == NULL)
|
||||||
return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
|
return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
|
||||||
dom_name_len = strlen(ses->domainName);
|
dom_name_len = strlen(ses->domainName);
|
||||||
if(dom_name_len > MAX_USERNAME_SIZE)
|
if (dom_name_len > MAX_USERNAME_SIZE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
|
ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
|
||||||
if(ucase_buf == NULL)
|
if (ucase_buf == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
|
unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
|
||||||
if(unicode_buf == NULL) {
|
if (unicode_buf == NULL) {
|
||||||
kfree(ucase_buf);
|
kfree(ucase_buf);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0;i<user_name_len;i++)
|
for (i = 0; i < user_name_len; i++)
|
||||||
ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
|
ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
|
||||||
ucase_buf[i] = 0;
|
ucase_buf[i] = 0;
|
||||||
user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
|
user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf,
|
||||||
|
MAX_USERNAME_SIZE*2, nls_info);
|
||||||
unicode_buf[user_name_len] = 0;
|
unicode_buf[user_name_len] = 0;
|
||||||
user_name_len++;
|
user_name_len++;
|
||||||
|
|
||||||
for(i=0;i<dom_name_len;i++)
|
for (i = 0; i < dom_name_len; i++)
|
||||||
ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
|
ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
|
||||||
ucase_buf[i] = 0;
|
ucase_buf[i] = 0;
|
||||||
dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
|
dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf,
|
||||||
|
MAX_USERNAME_SIZE*2, nls_info);
|
||||||
|
|
||||||
unicode_buf[user_name_len + dom_name_len] = 0;
|
unicode_buf[user_name_len + dom_name_len] = 0;
|
||||||
hmac_md5_update((const unsigned char *) unicode_buf,
|
hmac_md5_update((const unsigned char *) unicode_buf,
|
||||||
(user_name_len+dom_name_len)*2,&ctx);
|
(user_name_len+dom_name_len)*2, &ctx);
|
||||||
|
|
||||||
hmac_md5_final(ses->server->mac_signing_key,&ctx);
|
hmac_md5_final(ses->server->ntlmv2_hash, &ctx);
|
||||||
kfree(ucase_buf);
|
kfree(ucase_buf);
|
||||||
kfree(unicode_buf);
|
kfree(unicode_buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
|
void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char password_with_pad[CIFS_ENCPWD_SIZE];
|
char password_with_pad[CIFS_ENCPWD_SIZE];
|
||||||
|
|
||||||
if(ses->server == NULL)
|
if (ses->server == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
|
memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
|
||||||
if(ses->password)
|
if (ses->password)
|
||||||
strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
|
strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
|
||||||
|
|
||||||
if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
|
if ((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
|
||||||
if(extended_security & CIFSSEC_MAY_PLNTXT) {
|
if (extended_security & CIFSSEC_MAY_PLNTXT) {
|
||||||
memcpy(lnm_session_key, password_with_pad, CIFS_ENCPWD_SIZE);
|
memcpy(lnm_session_key, password_with_pad,
|
||||||
|
CIFS_ENCPWD_SIZE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +309,7 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
|
||||||
utf8 and other multibyte codepages each need their own strupper
|
utf8 and other multibyte codepages each need their own strupper
|
||||||
function since a byte at a time will ont work. */
|
function since a byte at a time will ont work. */
|
||||||
|
|
||||||
for(i = 0; i < CIFS_ENCPWD_SIZE; i++) {
|
for (i = 0; i < CIFS_ENCPWD_SIZE; i++) {
|
||||||
password_with_pad[i] = toupper(password_with_pad[i]);
|
password_with_pad[i] = toupper(password_with_pad[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,18 +320,18 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
|
||||||
#endif /* CIFS_WEAK_PW_HASH */
|
#endif /* CIFS_WEAK_PW_HASH */
|
||||||
|
|
||||||
static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
|
static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
|
||||||
const struct nls_table * nls_cp)
|
const struct nls_table *nls_cp)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int len;
|
int len;
|
||||||
char nt_hash[16];
|
char nt_hash[16];
|
||||||
struct HMACMD5Context * pctxt;
|
struct HMACMD5Context *pctxt;
|
||||||
wchar_t * user;
|
wchar_t *user;
|
||||||
wchar_t * domain;
|
wchar_t *domain;
|
||||||
|
|
||||||
pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
|
pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
|
||||||
|
|
||||||
if(pctxt == NULL)
|
if (pctxt == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* calculate md4 hash of password */
|
/* calculate md4 hash of password */
|
||||||
|
@ -331,21 +343,24 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
|
||||||
/* convert ses->userName to unicode and uppercase */
|
/* convert ses->userName to unicode and uppercase */
|
||||||
len = strlen(ses->userName);
|
len = strlen(ses->userName);
|
||||||
user = kmalloc(2 + (len * 2), GFP_KERNEL);
|
user = kmalloc(2 + (len * 2), GFP_KERNEL);
|
||||||
if(user == NULL)
|
if (user == NULL)
|
||||||
goto calc_exit_2;
|
goto calc_exit_2;
|
||||||
len = cifs_strtoUCS(user, ses->userName, len, nls_cp);
|
len = cifs_strtoUCS(user, ses->userName, len, nls_cp);
|
||||||
UniStrupr(user);
|
UniStrupr(user);
|
||||||
hmac_md5_update((char *)user, 2*len, pctxt);
|
hmac_md5_update((char *)user, 2*len, pctxt);
|
||||||
|
|
||||||
/* convert ses->domainName to unicode and uppercase */
|
/* convert ses->domainName to unicode and uppercase */
|
||||||
if(ses->domainName) {
|
if (ses->domainName) {
|
||||||
len = strlen(ses->domainName);
|
len = strlen(ses->domainName);
|
||||||
|
|
||||||
domain = kmalloc(2 + (len * 2), GFP_KERNEL);
|
domain = kmalloc(2 + (len * 2), GFP_KERNEL);
|
||||||
if(domain == NULL)
|
if (domain == NULL)
|
||||||
goto calc_exit_1;
|
goto calc_exit_1;
|
||||||
len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
|
len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
|
||||||
UniStrupr(domain);
|
/* the following line was removed since it didn't work well
|
||||||
|
with lower cased domain name that passed as an option.
|
||||||
|
Maybe converting the domain name earlier makes sense */
|
||||||
|
/* UniStrupr(domain); */
|
||||||
|
|
||||||
hmac_md5_update((char *)domain, 2*len, pctxt);
|
hmac_md5_update((char *)domain, 2*len, pctxt);
|
||||||
|
|
||||||
|
@ -356,16 +371,17 @@ calc_exit_1:
|
||||||
calc_exit_2:
|
calc_exit_2:
|
||||||
/* BB FIXME what about bytes 24 through 40 of the signing key?
|
/* BB FIXME what about bytes 24 through 40 of the signing key?
|
||||||
compare with the NTLM example */
|
compare with the NTLM example */
|
||||||
hmac_md5_final(ses->server->mac_signing_key, pctxt);
|
hmac_md5_final(ses->server->ntlmv2_hash, pctxt);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
|
void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
|
||||||
const struct nls_table * nls_cp)
|
const struct nls_table *nls_cp)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct ntlmv2_resp * buf = (struct ntlmv2_resp *)resp_buf;
|
struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf;
|
||||||
|
struct HMACMD5Context context;
|
||||||
|
|
||||||
buf->blob_signature = cpu_to_le32(0x00000101);
|
buf->blob_signature = cpu_to_le32(0x00000101);
|
||||||
buf->reserved = 0;
|
buf->reserved = 0;
|
||||||
|
@ -379,21 +395,31 @@ void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
|
||||||
|
|
||||||
/* calculate buf->ntlmv2_hash */
|
/* calculate buf->ntlmv2_hash */
|
||||||
rc = calc_ntlmv2_hash(ses, nls_cp);
|
rc = calc_ntlmv2_hash(ses, nls_cp);
|
||||||
if(rc)
|
if (rc)
|
||||||
cERROR(1,("could not get v2 hash rc %d",rc));
|
cERROR(1, ("could not get v2 hash rc %d", rc));
|
||||||
CalcNTLMv2_response(ses, resp_buf);
|
CalcNTLMv2_response(ses, resp_buf);
|
||||||
|
|
||||||
|
/* now calculate the MAC key for NTLMv2 */
|
||||||
|
hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
|
||||||
|
hmac_md5_update(resp_buf, 16, &context);
|
||||||
|
hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context);
|
||||||
|
|
||||||
|
memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf,
|
||||||
|
sizeof(struct ntlmv2_resp));
|
||||||
|
ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CalcNTLMv2_response(const struct cifsSesInfo * ses, char * v2_session_response)
|
void CalcNTLMv2_response(const struct cifsSesInfo *ses,
|
||||||
|
char *v2_session_response)
|
||||||
{
|
{
|
||||||
struct HMACMD5Context context;
|
struct HMACMD5Context context;
|
||||||
/* rest of v2 struct already generated */
|
/* rest of v2 struct already generated */
|
||||||
memcpy(v2_session_response + 8, ses->server->cryptKey,8);
|
memcpy(v2_session_response + 8, ses->server->cryptKey, 8);
|
||||||
hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context);
|
hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
|
||||||
|
|
||||||
hmac_md5_update(v2_session_response+8,
|
hmac_md5_update(v2_session_response+8,
|
||||||
sizeof(struct ntlmv2_resp) - 8, &context);
|
sizeof(struct ntlmv2_resp) - 8, &context);
|
||||||
|
|
||||||
hmac_md5_final(v2_session_response,&context);
|
hmac_md5_final(v2_session_response, &context);
|
||||||
/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
|
/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
|
||||||
}
|
}
|
||||||
|
|
127
fs/cifs/cifsfs.c
127
fs/cifs/cifsfs.c
|
@ -64,23 +64,27 @@ unsigned int multiuser_mount = 0;
|
||||||
unsigned int extended_security = CIFSSEC_DEF;
|
unsigned int extended_security = CIFSSEC_DEF;
|
||||||
/* unsigned int ntlmv2_support = 0; */
|
/* unsigned int ntlmv2_support = 0; */
|
||||||
unsigned int sign_CIFS_PDUs = 1;
|
unsigned int sign_CIFS_PDUs = 1;
|
||||||
extern struct task_struct * oplockThread; /* remove sparse warning */
|
extern struct task_struct *oplockThread; /* remove sparse warning */
|
||||||
struct task_struct * oplockThread = NULL;
|
struct task_struct *oplockThread = NULL;
|
||||||
/* extern struct task_struct * dnotifyThread; remove sparse warning */
|
/* extern struct task_struct * dnotifyThread; remove sparse warning */
|
||||||
static struct task_struct * dnotifyThread = NULL;
|
static struct task_struct *dnotifyThread = NULL;
|
||||||
static const struct super_operations cifs_super_ops;
|
static const struct super_operations cifs_super_ops;
|
||||||
unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
|
unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
|
||||||
module_param(CIFSMaxBufSize, int, 0);
|
module_param(CIFSMaxBufSize, int, 0);
|
||||||
MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
|
MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header). "
|
||||||
|
"Default: 16384 Range: 8192 to 130048");
|
||||||
unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
|
unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
|
||||||
module_param(cifs_min_rcv, int, 0);
|
module_param(cifs_min_rcv, int, 0);
|
||||||
MODULE_PARM_DESC(cifs_min_rcv,"Network buffers in pool. Default: 4 Range: 1 to 64");
|
MODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: "
|
||||||
|
"1 to 64");
|
||||||
unsigned int cifs_min_small = 30;
|
unsigned int cifs_min_small = 30;
|
||||||
module_param(cifs_min_small, int, 0);
|
module_param(cifs_min_small, int, 0);
|
||||||
MODULE_PARM_DESC(cifs_min_small,"Small network buffers in pool. Default: 30 Range: 2 to 256");
|
MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
|
||||||
|
"Range: 2 to 256");
|
||||||
unsigned int cifs_max_pending = CIFS_MAX_REQ;
|
unsigned int cifs_max_pending = CIFS_MAX_REQ;
|
||||||
module_param(cifs_max_pending, int, 0);
|
module_param(cifs_max_pending, int, 0);
|
||||||
MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
|
MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. "
|
||||||
|
"Default: 50 Range: 2 to 256");
|
||||||
|
|
||||||
extern mempool_t *cifs_sm_req_poolp;
|
extern mempool_t *cifs_sm_req_poolp;
|
||||||
extern mempool_t *cifs_req_poolp;
|
extern mempool_t *cifs_req_poolp;
|
||||||
|
@ -98,7 +102,7 @@ cifs_read_super(struct super_block *sb, void *data,
|
||||||
|
|
||||||
/* BB should we make this contingent on mount parm? */
|
/* BB should we make this contingent on mount parm? */
|
||||||
sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
|
sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
|
||||||
sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
|
sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);
|
||||||
cifs_sb = CIFS_SB(sb);
|
cifs_sb = CIFS_SB(sb);
|
||||||
if (cifs_sb == NULL)
|
if (cifs_sb == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -114,12 +118,9 @@ cifs_read_super(struct super_block *sb, void *data,
|
||||||
|
|
||||||
sb->s_magic = CIFS_MAGIC_NUMBER;
|
sb->s_magic = CIFS_MAGIC_NUMBER;
|
||||||
sb->s_op = &cifs_super_ops;
|
sb->s_op = &cifs_super_ops;
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
|
||||||
if (experimEnabled != 0)
|
|
||||||
sb->s_export_op = &cifs_export_ops;
|
|
||||||
#endif /* EXPERIMENTAL */
|
|
||||||
/* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
|
/* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
|
||||||
sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
|
sb->s_blocksize =
|
||||||
|
cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
|
||||||
#ifdef CONFIG_CIFS_QUOTA
|
#ifdef CONFIG_CIFS_QUOTA
|
||||||
sb->s_qcop = &cifs_quotactl_ops;
|
sb->s_qcop = &cifs_quotactl_ops;
|
||||||
#endif
|
#endif
|
||||||
|
@ -139,6 +140,13 @@ cifs_read_super(struct super_block *sb, void *data,
|
||||||
goto out_no_root;
|
goto out_no_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||||
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||||
|
cFYI(1, ("export ops supported"));
|
||||||
|
sb->s_export_op = &cifs_export_ops;
|
||||||
|
}
|
||||||
|
#endif /* EXPERIMENTAL */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_no_root:
|
out_no_root:
|
||||||
|
@ -164,7 +172,7 @@ cifs_put_super(struct super_block *sb)
|
||||||
cFYI(1, ("In cifs_put_super"));
|
cFYI(1, ("In cifs_put_super"));
|
||||||
cifs_sb = CIFS_SB(sb);
|
cifs_sb = CIFS_SB(sb);
|
||||||
if (cifs_sb == NULL) {
|
if (cifs_sb == NULL) {
|
||||||
cFYI(1,("Empty cifs superblock info passed to unmount"));
|
cFYI(1, ("Empty cifs superblock info passed to unmount"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rc = cifs_umount(sb, cifs_sb);
|
rc = cifs_umount(sb, cifs_sb);
|
||||||
|
@ -217,8 +225,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||||
bypassed it because we detected that this was an older LANMAN sess */
|
bypassed it because we detected that this was an older LANMAN sess */
|
||||||
if (rc)
|
if (rc)
|
||||||
rc = SMBOldQFSInfo(xid, pTcon, buf);
|
rc = SMBOldQFSInfo(xid, pTcon, buf);
|
||||||
/*
|
/* int f_type;
|
||||||
int f_type;
|
|
||||||
__fsid_t f_fsid;
|
__fsid_t f_fsid;
|
||||||
int f_namelen; */
|
int f_namelen; */
|
||||||
/* BB get from info in tcon struct at mount time call to QFSAttrInfo */
|
/* BB get from info in tcon struct at mount time call to QFSAttrInfo */
|
||||||
|
@ -227,7 +234,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||||
longer available? */
|
longer available? */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
|
static int cifs_permission(struct inode *inode, int mask, struct nameidata *nd)
|
||||||
{
|
{
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
|
|
||||||
|
@ -309,20 +316,20 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
|
||||||
seq_printf(s, ",posixpaths");
|
seq_printf(s, ",posixpaths");
|
||||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
|
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
|
||||||
!(cifs_sb->tcon->ses->capabilities & CAP_UNIX))
|
!(cifs_sb->tcon->unix_ext))
|
||||||
seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
|
seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
|
||||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
|
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
|
||||||
!(cifs_sb->tcon->ses->capabilities & CAP_UNIX))
|
!(cifs_sb->tcon->unix_ext))
|
||||||
seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
|
seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
|
||||||
seq_printf(s, ",rsize=%d",cifs_sb->rsize);
|
seq_printf(s, ",rsize=%d", cifs_sb->rsize);
|
||||||
seq_printf(s, ",wsize=%d",cifs_sb->wsize);
|
seq_printf(s, ",wsize=%d", cifs_sb->wsize);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_QUOTA
|
#ifdef CONFIG_CIFS_QUOTA
|
||||||
int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
|
int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid,
|
||||||
struct fs_disk_quota * pdquota)
|
struct fs_disk_quota *pdquota)
|
||||||
{
|
{
|
||||||
int xid;
|
int xid;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
@ -337,7 +344,7 @@ int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
|
||||||
|
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
if (pTcon) {
|
if (pTcon) {
|
||||||
cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
|
cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
|
||||||
} else {
|
} else {
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -346,8 +353,8 @@ int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
|
int cifs_xquota_get(struct super_block *sb, int quota_type, qid_t qid,
|
||||||
struct fs_disk_quota * pdquota)
|
struct fs_disk_quota *pdquota)
|
||||||
{
|
{
|
||||||
int xid;
|
int xid;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
@ -361,7 +368,7 @@ int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
|
||||||
|
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
if (pTcon) {
|
if (pTcon) {
|
||||||
cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
|
cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
|
||||||
} else {
|
} else {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
}
|
}
|
||||||
|
@ -370,7 +377,7 @@ int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
|
int cifs_xstate_set(struct super_block *sb, unsigned int flags, int operation)
|
||||||
{
|
{
|
||||||
int xid;
|
int xid;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
@ -384,7 +391,7 @@ int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
|
||||||
|
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
if (pTcon) {
|
if (pTcon) {
|
||||||
cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
|
cFYI(1, ("flags: 0x%x operation: 0x%x", flags, operation));
|
||||||
} else {
|
} else {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
}
|
}
|
||||||
|
@ -393,7 +400,7 @@ int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
|
int cifs_xstate_get(struct super_block *sb, struct fs_quota_stat *qstats)
|
||||||
{
|
{
|
||||||
int xid;
|
int xid;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
@ -407,7 +414,7 @@ int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
|
||||||
}
|
}
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
if (pTcon) {
|
if (pTcon) {
|
||||||
cFYI(1,("pqstats %p",qstats));
|
cFYI(1, ("pqstats %p", qstats));
|
||||||
} else {
|
} else {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
}
|
}
|
||||||
|
@ -424,10 +431,10 @@ static struct quotactl_ops cifs_quotactl_ops = {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
|
static void cifs_umount_begin(struct vfsmount *vfsmnt, int flags)
|
||||||
{
|
{
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo * tcon;
|
struct cifsTconInfo *tcon;
|
||||||
|
|
||||||
if (!(flags & MNT_FORCE))
|
if (!(flags & MNT_FORCE))
|
||||||
return;
|
return;
|
||||||
|
@ -445,9 +452,8 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
|
||||||
|
|
||||||
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
|
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
|
||||||
/* cancel_notify_requests(tcon); */
|
/* cancel_notify_requests(tcon); */
|
||||||
if (tcon->ses && tcon->ses->server)
|
if (tcon->ses && tcon->ses->server) {
|
||||||
{
|
cFYI(1, ("wake up tasks now - umount begin not complete"));
|
||||||
cFYI(1,("wake up tasks now - umount begin not complete"));
|
|
||||||
wake_up_all(&tcon->ses->server->request_q);
|
wake_up_all(&tcon->ses->server->request_q);
|
||||||
wake_up_all(&tcon->ses->server->response_q);
|
wake_up_all(&tcon->ses->server->response_q);
|
||||||
msleep(1); /* yield */
|
msleep(1); /* yield */
|
||||||
|
@ -481,9 +487,10 @@ static const struct super_operations cifs_super_ops = {
|
||||||
.alloc_inode = cifs_alloc_inode,
|
.alloc_inode = cifs_alloc_inode,
|
||||||
.destroy_inode = cifs_destroy_inode,
|
.destroy_inode = cifs_destroy_inode,
|
||||||
/* .drop_inode = generic_delete_inode,
|
/* .drop_inode = generic_delete_inode,
|
||||||
.delete_inode = cifs_delete_inode, *//* Do not need the above two functions
|
.delete_inode = cifs_delete_inode, */ /* Do not need above two
|
||||||
unless later we add lazy close of inodes or unless the kernel forgets to call
|
functions unless later we add lazy close of inodes or unless the
|
||||||
us with the same number of releases (closes) as opens */
|
kernel forgets to call us with the same number of releases (closes)
|
||||||
|
as opens */
|
||||||
.show_options = cifs_show_options,
|
.show_options = cifs_show_options,
|
||||||
.umount_begin = cifs_umount_begin,
|
.umount_begin = cifs_umount_begin,
|
||||||
.remount_fs = cifs_remount,
|
.remount_fs = cifs_remount,
|
||||||
|
@ -697,7 +704,7 @@ const struct file_operations cifs_dir_ops = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cifs_init_once(void *inode, struct kmem_cache * cachep, unsigned long flags)
|
cifs_init_once(void *inode, struct kmem_cache *cachep, unsigned long flags)
|
||||||
{
|
{
|
||||||
struct cifsInodeInfo *cifsi = inode;
|
struct cifsInodeInfo *cifsi = inode;
|
||||||
|
|
||||||
|
@ -749,7 +756,7 @@ cifs_init_request_bufs(void)
|
||||||
cifs_min_rcv = 1;
|
cifs_min_rcv = 1;
|
||||||
else if (cifs_min_rcv > 64) {
|
else if (cifs_min_rcv > 64) {
|
||||||
cifs_min_rcv = 64;
|
cifs_min_rcv = 64;
|
||||||
cERROR(1,("cifs_min_rcv set to maximum (64)"));
|
cERROR(1, ("cifs_min_rcv set to maximum (64)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
|
cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
|
||||||
|
@ -780,7 +787,7 @@ cifs_init_request_bufs(void)
|
||||||
cifs_min_small = 2;
|
cifs_min_small = 2;
|
||||||
else if (cifs_min_small > 256) {
|
else if (cifs_min_small > 256) {
|
||||||
cifs_min_small = 256;
|
cifs_min_small = 256;
|
||||||
cFYI(1,("cifs_min_small set to maximum (256)"));
|
cFYI(1, ("cifs_min_small set to maximum (256)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
|
cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
|
||||||
|
@ -841,11 +848,11 @@ cifs_destroy_mids(void)
|
||||||
kmem_cache_destroy(cifs_oplock_cachep);
|
kmem_cache_destroy(cifs_oplock_cachep);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cifs_oplock_thread(void * dummyarg)
|
static int cifs_oplock_thread(void *dummyarg)
|
||||||
{
|
{
|
||||||
struct oplock_q_entry * oplock_item;
|
struct oplock_q_entry *oplock_item;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
struct inode * inode;
|
struct inode *inode;
|
||||||
__u16 netfid;
|
__u16 netfid;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -863,7 +870,7 @@ static int cifs_oplock_thread(void * dummyarg)
|
||||||
oplock_item = list_entry(GlobalOplock_Q.next,
|
oplock_item = list_entry(GlobalOplock_Q.next,
|
||||||
struct oplock_q_entry, qhead);
|
struct oplock_q_entry, qhead);
|
||||||
if (oplock_item) {
|
if (oplock_item) {
|
||||||
cFYI(1,("found oplock item to write out"));
|
cFYI(1, ("found oplock item to write out"));
|
||||||
pTcon = oplock_item->tcon;
|
pTcon = oplock_item->tcon;
|
||||||
inode = oplock_item->pinode;
|
inode = oplock_item->pinode;
|
||||||
netfid = oplock_item->netfid;
|
netfid = oplock_item->netfid;
|
||||||
|
@ -876,7 +883,8 @@ static int cifs_oplock_thread(void * dummyarg)
|
||||||
/* mutex_lock(&inode->i_mutex);*/
|
/* mutex_lock(&inode->i_mutex);*/
|
||||||
if (S_ISREG(inode->i_mode)) {
|
if (S_ISREG(inode->i_mode)) {
|
||||||
rc = filemap_fdatawrite(inode->i_mapping);
|
rc = filemap_fdatawrite(inode->i_mapping);
|
||||||
if (CIFS_I(inode)->clientCanCacheRead == 0) {
|
if (CIFS_I(inode)->clientCanCacheRead
|
||||||
|
== 0) {
|
||||||
filemap_fdatawait(inode->i_mapping);
|
filemap_fdatawait(inode->i_mapping);
|
||||||
invalidate_remote_inode(inode);
|
invalidate_remote_inode(inode);
|
||||||
}
|
}
|
||||||
|
@ -885,9 +893,10 @@ static int cifs_oplock_thread(void * dummyarg)
|
||||||
/* mutex_unlock(&inode->i_mutex);*/
|
/* mutex_unlock(&inode->i_mutex);*/
|
||||||
if (rc)
|
if (rc)
|
||||||
CIFS_I(inode)->write_behind_rc = rc;
|
CIFS_I(inode)->write_behind_rc = rc;
|
||||||
cFYI(1,("Oplock flush inode %p rc %d",inode,rc));
|
cFYI(1, ("Oplock flush inode %p rc %d",
|
||||||
|
inode, rc));
|
||||||
|
|
||||||
/* releasing a stale oplock after recent reconnection
|
/* releasing stale oplock after recent reconnect
|
||||||
of smb session using a now incorrect file
|
of smb session using a now incorrect file
|
||||||
handle is not a data integrity issue but do
|
handle is not a data integrity issue but do
|
||||||
not bother sending an oplock release if session
|
not bother sending an oplock release if session
|
||||||
|
@ -898,7 +907,8 @@ static int cifs_oplock_thread(void * dummyarg)
|
||||||
0 /* len */ , 0 /* offset */, 0,
|
0 /* len */ , 0 /* offset */, 0,
|
||||||
0, LOCKING_ANDX_OPLOCK_RELEASE,
|
0, LOCKING_ANDX_OPLOCK_RELEASE,
|
||||||
0 /* wait flag */);
|
0 /* wait flag */);
|
||||||
cFYI(1,("Oplock release rc = %d ",rc));
|
cFYI(1,
|
||||||
|
("Oplock release rc = %d ", rc));
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
|
@ -910,7 +920,7 @@ static int cifs_oplock_thread(void * dummyarg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cifs_dnotify_thread(void * dummyarg)
|
static int cifs_dnotify_thread(void *dummyarg)
|
||||||
{
|
{
|
||||||
struct list_head *tmp;
|
struct list_head *tmp;
|
||||||
struct cifsSesInfo *ses;
|
struct cifsSesInfo *ses;
|
||||||
|
@ -957,7 +967,7 @@ init_cifs(void)
|
||||||
*/
|
*/
|
||||||
atomic_set(&sesInfoAllocCount, 0);
|
atomic_set(&sesInfoAllocCount, 0);
|
||||||
atomic_set(&tconInfoAllocCount, 0);
|
atomic_set(&tconInfoAllocCount, 0);
|
||||||
atomic_set(&tcpSesAllocCount,0);
|
atomic_set(&tcpSesAllocCount, 0);
|
||||||
atomic_set(&tcpSesReconnectCount, 0);
|
atomic_set(&tcpSesReconnectCount, 0);
|
||||||
atomic_set(&tconInfoReconnectCount, 0);
|
atomic_set(&tconInfoReconnectCount, 0);
|
||||||
|
|
||||||
|
@ -978,10 +988,10 @@ init_cifs(void)
|
||||||
|
|
||||||
if (cifs_max_pending < 2) {
|
if (cifs_max_pending < 2) {
|
||||||
cifs_max_pending = 2;
|
cifs_max_pending = 2;
|
||||||
cFYI(1,("cifs_max_pending set to min of 2"));
|
cFYI(1, ("cifs_max_pending set to min of 2"));
|
||||||
} else if (cifs_max_pending > 256) {
|
} else if (cifs_max_pending > 256) {
|
||||||
cifs_max_pending = 256;
|
cifs_max_pending = 256;
|
||||||
cFYI(1,("cifs_max_pending set to max of 256"));
|
cFYI(1, ("cifs_max_pending set to max of 256"));
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = cifs_init_inodecache();
|
rc = cifs_init_inodecache();
|
||||||
|
@ -1003,14 +1013,14 @@ init_cifs(void)
|
||||||
oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");
|
oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");
|
||||||
if (IS_ERR(oplockThread)) {
|
if (IS_ERR(oplockThread)) {
|
||||||
rc = PTR_ERR(oplockThread);
|
rc = PTR_ERR(oplockThread);
|
||||||
cERROR(1,("error %d create oplock thread", rc));
|
cERROR(1, ("error %d create oplock thread", rc));
|
||||||
goto out_unregister_filesystem;
|
goto out_unregister_filesystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
|
dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
|
||||||
if (IS_ERR(dnotifyThread)) {
|
if (IS_ERR(dnotifyThread)) {
|
||||||
rc = PTR_ERR(dnotifyThread);
|
rc = PTR_ERR(dnotifyThread);
|
||||||
cERROR(1,("error %d create dnotify thread", rc));
|
cERROR(1, ("error %d create dnotify thread", rc));
|
||||||
goto out_stop_oplock_thread;
|
goto out_stop_oplock_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1036,7 +1046,7 @@ init_cifs(void)
|
||||||
static void __exit
|
static void __exit
|
||||||
exit_cifs(void)
|
exit_cifs(void)
|
||||||
{
|
{
|
||||||
cFYI(0, ("In unregister ie exit_cifs"));
|
cFYI(0, ("exit_cifs"));
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
cifs_proc_clean();
|
cifs_proc_clean();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1051,7 +1061,8 @@ exit_cifs(void)
|
||||||
MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
|
MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
|
||||||
MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
|
MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
|
||||||
MODULE_DESCRIPTION
|
MODULE_DESCRIPTION
|
||||||
("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
|
("VFS to access servers complying with the SNIA CIFS Specification "
|
||||||
|
"e.g. Samba and Windows");
|
||||||
MODULE_VERSION(CIFS_VERSION);
|
MODULE_VERSION(CIFS_VERSION);
|
||||||
module_init(init_cifs)
|
module_init(init_cifs)
|
||||||
module_exit(exit_cifs)
|
module_exit(exit_cifs)
|
||||||
|
|
|
@ -45,7 +45,7 @@ extern void cifs_read_inode(struct inode *);
|
||||||
extern const struct inode_operations cifs_dir_inode_ops;
|
extern const struct inode_operations cifs_dir_inode_ops;
|
||||||
extern int cifs_create(struct inode *, struct dentry *, int,
|
extern int cifs_create(struct inode *, struct dentry *, int,
|
||||||
struct nameidata *);
|
struct nameidata *);
|
||||||
extern struct dentry * cifs_lookup(struct inode *, struct dentry *,
|
extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
|
||||||
struct nameidata *);
|
struct nameidata *);
|
||||||
extern int cifs_unlink(struct inode *, struct dentry *);
|
extern int cifs_unlink(struct inode *, struct dentry *);
|
||||||
extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
|
extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
|
||||||
|
@ -63,16 +63,16 @@ extern const struct inode_operations cifs_symlink_inode_ops;
|
||||||
|
|
||||||
/* Functions related to files and directories */
|
/* Functions related to files and directories */
|
||||||
extern const struct file_operations cifs_file_ops;
|
extern const struct file_operations cifs_file_ops;
|
||||||
extern const struct file_operations cifs_file_direct_ops; /* if directio mount */
|
extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
|
||||||
extern const struct file_operations cifs_file_nobrl_ops;
|
extern const struct file_operations cifs_file_nobrl_ops;
|
||||||
extern const struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */
|
extern const struct file_operations cifs_file_direct_nobrl_ops; /* no brlocks */
|
||||||
extern int cifs_open(struct inode *inode, struct file *file);
|
extern int cifs_open(struct inode *inode, struct file *file);
|
||||||
extern int cifs_close(struct inode *inode, struct file *file);
|
extern int cifs_close(struct inode *inode, struct file *file);
|
||||||
extern int cifs_closedir(struct inode *inode, struct file *file);
|
extern int cifs_closedir(struct inode *inode, struct file *file);
|
||||||
extern ssize_t cifs_user_read(struct file *file, char __user *read_data,
|
extern ssize_t cifs_user_read(struct file *file, char __user *read_data,
|
||||||
size_t read_size, loff_t * poffset);
|
size_t read_size, loff_t *poffset);
|
||||||
extern ssize_t cifs_user_write(struct file *file, const char __user *write_data,
|
extern ssize_t cifs_user_write(struct file *file, const char __user *write_data,
|
||||||
size_t write_size, loff_t * poffset);
|
size_t write_size, loff_t *poffset);
|
||||||
extern int cifs_lock(struct file *, int, struct file_lock *);
|
extern int cifs_lock(struct file *, int, struct file_lock *);
|
||||||
extern int cifs_fsync(struct file *, struct dentry *, int);
|
extern int cifs_fsync(struct file *, struct dentry *, int);
|
||||||
extern int cifs_flush(struct file *, fl_owner_t id);
|
extern int cifs_flush(struct file *, fl_owner_t id);
|
||||||
|
@ -88,7 +88,8 @@ extern struct dentry_operations cifs_ci_dentry_ops;
|
||||||
|
|
||||||
/* Functions related to symlinks */
|
/* Functions related to symlinks */
|
||||||
extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
|
extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
|
||||||
extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *);
|
extern void cifs_put_link(struct dentry *direntry,
|
||||||
|
struct nameidata *nd, void *);
|
||||||
extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
|
extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
|
||||||
int buflen);
|
int buflen);
|
||||||
extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
|
extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
|
||||||
|
@ -98,7 +99,7 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
|
||||||
size_t, int);
|
size_t, int);
|
||||||
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
|
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
|
||||||
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
|
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
|
||||||
extern int cifs_ioctl (struct inode * inode, struct file * filep,
|
extern int cifs_ioctl (struct inode *inode, struct file *filep,
|
||||||
unsigned int command, unsigned long arg);
|
unsigned int command, unsigned long arg);
|
||||||
#define CIFS_VERSION "1.49"
|
#define CIFS_VERSION "1.50"
|
||||||
#endif /* _CIFSFS_H */
|
#endif /* _CIFSFS_H */
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/cifsglob.h
|
* fs/cifs/cifsglob.h
|
||||||
*
|
*
|
||||||
* Copyright (C) International Business Machines Corp., 2002,2006
|
* Copyright (C) International Business Machines Corp., 2002,2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
* Jeremy Allison (jra@samba.org)
|
* Jeremy Allison (jra@samba.org)
|
||||||
*
|
*
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
|
#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
|
||||||
#define MAX_SERVER_SIZE 15
|
#define MAX_SERVER_SIZE 15
|
||||||
#define MAX_SHARE_SIZE 64 /* used to be 20 - this should still be enough */
|
#define MAX_SHARE_SIZE 64 /* used to be 20, this should still be enough */
|
||||||
#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
|
#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
|
||||||
termination then *2 for unicode versions */
|
termination then *2 for unicode versions */
|
||||||
#define MAX_PASSWORD_SIZE 16
|
#define MAX_PASSWORD_SIZE 16
|
||||||
|
@ -104,6 +104,17 @@ enum protocolEnum {
|
||||||
/* Netbios frames protocol not supported at this time */
|
/* Netbios frames protocol not supported at this time */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mac_key {
|
||||||
|
unsigned int len;
|
||||||
|
union {
|
||||||
|
char ntlm[CIFS_SESS_KEY_SIZE + 16];
|
||||||
|
struct {
|
||||||
|
char key[16];
|
||||||
|
struct ntlmv2_resp resp;
|
||||||
|
} ntlmv2;
|
||||||
|
} data;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*****************************************************************
|
*****************************************************************
|
||||||
* Except the CIFS PDUs themselves all the
|
* Except the CIFS PDUs themselves all the
|
||||||
|
@ -159,7 +170,8 @@ struct TCP_Server_Info {
|
||||||
/* 16th byte of RFC1001 workstation name is always null */
|
/* 16th byte of RFC1001 workstation name is always null */
|
||||||
char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
|
char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
|
||||||
__u32 sequence_number; /* needed for CIFS PDU signature */
|
__u32 sequence_number; /* needed for CIFS PDU signature */
|
||||||
char mac_signing_key[CIFS_SESS_KEY_SIZE + 16];
|
struct mac_key mac_signing_key;
|
||||||
|
char ntlmv2_hash[16];
|
||||||
unsigned long lstrp; /* when we got last response from this server */
|
unsigned long lstrp; /* when we got last response from this server */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -200,8 +212,8 @@ struct cifsSesInfo {
|
||||||
char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
|
char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
|
||||||
TCP names - will ipv6 and sctp addresses fit? */
|
TCP names - will ipv6 and sctp addresses fit? */
|
||||||
char userName[MAX_USERNAME_SIZE + 1];
|
char userName[MAX_USERNAME_SIZE + 1];
|
||||||
char * domainName;
|
char *domainName;
|
||||||
char * password;
|
char *password;
|
||||||
};
|
};
|
||||||
/* no more than one of the following three session flags may be set */
|
/* no more than one of the following three session flags may be set */
|
||||||
#define CIFS_SES_NT4 1
|
#define CIFS_SES_NT4 1
|
||||||
|
@ -269,7 +281,9 @@ struct cifsTconInfo {
|
||||||
FILE_SYSTEM_UNIX_INFO fsUnixInfo;
|
FILE_SYSTEM_UNIX_INFO fsUnixInfo;
|
||||||
unsigned retry:1;
|
unsigned retry:1;
|
||||||
unsigned nocase:1;
|
unsigned nocase:1;
|
||||||
/* BB add field for back pointer to sb struct? */
|
unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol
|
||||||
|
for this mount even if server would support */
|
||||||
|
/* BB add field for back pointer to sb struct(s)? */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -291,9 +305,9 @@ struct cifs_search_info {
|
||||||
__u16 entries_in_buffer;
|
__u16 entries_in_buffer;
|
||||||
__u16 info_level;
|
__u16 info_level;
|
||||||
__u32 resume_key;
|
__u32 resume_key;
|
||||||
char * ntwrk_buf_start;
|
char *ntwrk_buf_start;
|
||||||
char * srch_entries_start;
|
char *srch_entries_start;
|
||||||
char * presume_name;
|
char *presume_name;
|
||||||
unsigned int resume_name_len;
|
unsigned int resume_name_len;
|
||||||
unsigned endOfSearch:1;
|
unsigned endOfSearch:1;
|
||||||
unsigned emptyDir:1;
|
unsigned emptyDir:1;
|
||||||
|
@ -309,15 +323,15 @@ struct cifsFileInfo {
|
||||||
__u16 netfid; /* file id from remote */
|
__u16 netfid; /* file id from remote */
|
||||||
/* BB add lock scope info here if needed */ ;
|
/* BB add lock scope info here if needed */ ;
|
||||||
/* lock scope id (0 if none) */
|
/* lock scope id (0 if none) */
|
||||||
struct file * pfile; /* needed for writepage */
|
struct file *pfile; /* needed for writepage */
|
||||||
struct inode * pInode; /* needed for oplock break */
|
struct inode *pInode; /* needed for oplock break */
|
||||||
struct mutex lock_mutex;
|
struct mutex lock_mutex;
|
||||||
struct list_head llist; /* list of byte range locks we have. */
|
struct list_head llist; /* list of byte range locks we have. */
|
||||||
unsigned closePend:1; /* file is marked to close */
|
unsigned closePend:1; /* file is marked to close */
|
||||||
unsigned invalidHandle:1; /* file closed via session abend */
|
unsigned invalidHandle:1; /* file closed via session abend */
|
||||||
atomic_t wrtPending; /* handle in use - defer close */
|
atomic_t wrtPending; /* handle in use - defer close */
|
||||||
struct semaphore fh_sem; /* prevents reopen race after dead ses*/
|
struct semaphore fh_sem; /* prevents reopen race after dead ses*/
|
||||||
char * search_resume_name; /* BB removeme BB */
|
char *search_resume_name; /* BB removeme BB */
|
||||||
struct cifs_search_info srch_inf;
|
struct cifs_search_info srch_inf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -327,7 +341,7 @@ struct cifsFileInfo {
|
||||||
|
|
||||||
struct cifsInodeInfo {
|
struct cifsInodeInfo {
|
||||||
struct list_head lockList;
|
struct list_head lockList;
|
||||||
/* BB add in lists for dirty pages - i.e. write caching info for oplock */
|
/* BB add in lists for dirty pages i.e. write caching info for oplock */
|
||||||
struct list_head openFileList;
|
struct list_head openFileList;
|
||||||
int write_behind_rc;
|
int write_behind_rc;
|
||||||
__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
|
__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
|
||||||
|
@ -381,9 +395,9 @@ static inline void cifs_stats_bytes_read(struct cifsTconInfo *tcon,
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define cifs_stats_inc(field) do {} while(0)
|
#define cifs_stats_inc(field) do {} while (0)
|
||||||
#define cifs_stats_bytes_written(tcon, bytes) do {} while(0)
|
#define cifs_stats_bytes_written(tcon, bytes) do {} while (0)
|
||||||
#define cifs_stats_bytes_read(tcon, bytes) do {} while(0)
|
#define cifs_stats_bytes_read(tcon, bytes) do {} while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -410,8 +424,8 @@ struct mid_q_entry {
|
||||||
|
|
||||||
struct oplock_q_entry {
|
struct oplock_q_entry {
|
||||||
struct list_head qhead;
|
struct list_head qhead;
|
||||||
struct inode * pinode;
|
struct inode *pinode;
|
||||||
struct cifsTconInfo * tcon;
|
struct cifsTconInfo *tcon;
|
||||||
__u16 netfid;
|
__u16 netfid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -426,7 +440,7 @@ struct dir_notify_req {
|
||||||
__u16 netfid;
|
__u16 netfid;
|
||||||
__u32 filter; /* CompletionFilter (for multishot) */
|
__u32 filter; /* CompletionFilter (for multishot) */
|
||||||
int multishot;
|
int multishot;
|
||||||
struct file * pfile;
|
struct file *pfile;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MID_FREE 0
|
#define MID_FREE 0
|
||||||
|
|
|
@ -366,17 +366,19 @@ struct smb_hdr {
|
||||||
#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
|
#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Computer Name Length
|
* Computer Name Length (since Netbios name was length 16 with last byte 0x20)
|
||||||
|
* No longer as important, now that TCP names are more commonly used to
|
||||||
|
* resolve hosts.
|
||||||
*/
|
*/
|
||||||
#define CNLEN 15
|
#define CNLEN 15
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Share Name Length @S8A
|
* Share Name Length (SNLEN)
|
||||||
* Note: This length is limited by the SMB used to get @S8A
|
* Note: This length was limited by the SMB used to get
|
||||||
* the Share info. NetShareEnum only returns 13 @S8A
|
* the Share info. NetShareEnum only returned 13
|
||||||
* chars, including the null termination. @S8A
|
* chars, including the null termination.
|
||||||
|
* This was removed because it no longer is limiting.
|
||||||
*/
|
*/
|
||||||
#define SNLEN 12 /*@S8A */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Comment Length
|
* Comment Length
|
||||||
|
@ -712,6 +714,7 @@ typedef struct smb_com_findclose_req {
|
||||||
#define REQ_OPLOCK 0x00000002
|
#define REQ_OPLOCK 0x00000002
|
||||||
#define REQ_BATCHOPLOCK 0x00000004
|
#define REQ_BATCHOPLOCK 0x00000004
|
||||||
#define REQ_OPENDIRONLY 0x00000008
|
#define REQ_OPENDIRONLY 0x00000008
|
||||||
|
#define REQ_EXTENDED_INFO 0x00000010
|
||||||
|
|
||||||
typedef struct smb_com_open_req { /* also handles create */
|
typedef struct smb_com_open_req { /* also handles create */
|
||||||
struct smb_hdr hdr; /* wct = 24 */
|
struct smb_hdr hdr; /* wct = 24 */
|
||||||
|
@ -818,7 +821,8 @@ typedef struct smb_com_writex_req {
|
||||||
__le16 DataLengthLow;
|
__le16 DataLengthLow;
|
||||||
__le16 DataOffset;
|
__le16 DataOffset;
|
||||||
__le16 ByteCount;
|
__le16 ByteCount;
|
||||||
__u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
|
__u8 Pad; /* BB check for whether padded to DWORD
|
||||||
|
boundary and optimum performance here */
|
||||||
char Data[0];
|
char Data[0];
|
||||||
} __attribute__((packed)) WRITEX_REQ;
|
} __attribute__((packed)) WRITEX_REQ;
|
||||||
|
|
||||||
|
@ -837,7 +841,8 @@ typedef struct smb_com_write_req {
|
||||||
__le16 DataOffset;
|
__le16 DataOffset;
|
||||||
__le32 OffsetHigh;
|
__le32 OffsetHigh;
|
||||||
__le16 ByteCount;
|
__le16 ByteCount;
|
||||||
__u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
|
__u8 Pad; /* BB check for whether padded to DWORD
|
||||||
|
boundary and optimum performance here */
|
||||||
char Data[0];
|
char Data[0];
|
||||||
} __attribute__((packed)) WRITE_REQ;
|
} __attribute__((packed)) WRITE_REQ;
|
||||||
|
|
||||||
|
@ -896,7 +901,8 @@ typedef struct smb_com_read_rsp {
|
||||||
__le16 DataLengthHigh;
|
__le16 DataLengthHigh;
|
||||||
__u64 Reserved2;
|
__u64 Reserved2;
|
||||||
__u16 ByteCount;
|
__u16 ByteCount;
|
||||||
__u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
|
__u8 Pad; /* BB check for whether padded to DWORD
|
||||||
|
boundary and optimum performance here */
|
||||||
char Data[1];
|
char Data[1];
|
||||||
} __attribute__((packed)) READ_RSP;
|
} __attribute__((packed)) READ_RSP;
|
||||||
|
|
||||||
|
@ -1743,7 +1749,9 @@ typedef struct smb_com_transaction2_get_dfs_refer_req {
|
||||||
__u8 Reserved3;
|
__u8 Reserved3;
|
||||||
__le16 SubCommand; /* one setup word */
|
__le16 SubCommand; /* one setup word */
|
||||||
__le16 ByteCount;
|
__le16 ByteCount;
|
||||||
__u8 Pad[3]; /* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */
|
__u8 Pad[3]; /* Win2K has sent 0x0F01 (max response length
|
||||||
|
perhaps?) followed by one byte pad - doesn't
|
||||||
|
seem to matter though */
|
||||||
__le16 MaxReferralLevel;
|
__le16 MaxReferralLevel;
|
||||||
char RequestFileName[1];
|
char RequestFileName[1];
|
||||||
} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ;
|
} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ;
|
||||||
|
@ -1752,7 +1760,10 @@ typedef struct dfs_referral_level_3 {
|
||||||
__le16 VersionNumber;
|
__le16 VersionNumber;
|
||||||
__le16 ReferralSize;
|
__le16 ReferralSize;
|
||||||
__le16 ServerType; /* 0x0001 = CIFS server */
|
__le16 ServerType; /* 0x0001 = CIFS server */
|
||||||
__le16 ReferralFlags; /* or proximity - not clear which since always set to zero - SNIA spec says 0x01 means strip off PathConsumed chars before submitting RequestFileName to remote node */
|
__le16 ReferralFlags; /* or proximity - not clear which since it is
|
||||||
|
always set to zero - SNIA spec says 0x01
|
||||||
|
means strip off PathConsumed chars before
|
||||||
|
submitting RequestFileName to remote node */
|
||||||
__le16 TimeToLive;
|
__le16 TimeToLive;
|
||||||
__le16 Proximity;
|
__le16 Proximity;
|
||||||
__le16 DfsPathOffset;
|
__le16 DfsPathOffset;
|
||||||
|
@ -1778,11 +1789,13 @@ typedef struct smb_com_transaction_get_dfs_refer_rsp {
|
||||||
#define DFSREF_STORAGE_SERVER 0x0002
|
#define DFSREF_STORAGE_SERVER 0x0002
|
||||||
|
|
||||||
/* IOCTL information */
|
/* IOCTL information */
|
||||||
/* List of ioctl function codes that look to be of interest to remote clients like this. */
|
/*
|
||||||
/* Need to do some experimentation to make sure they all work remotely. */
|
* List of ioctl function codes that look to be of interest to remote clients
|
||||||
/* Some of the following such as the encryption/compression ones would be */
|
* like this one. Need to do some experimentation to make sure they all work
|
||||||
/* invoked from tools via a specialized hook into the VFS rather than via the */
|
* remotely. Some of the following, such as the encryption/compression ones
|
||||||
/* standard vfs entry points */
|
* would be invoked from tools via a specialized hook into the VFS rather
|
||||||
|
* than via the standard vfs entry points
|
||||||
|
*/
|
||||||
#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
|
#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
|
||||||
#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
|
#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
|
||||||
#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
|
#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
|
||||||
|
@ -1871,7 +1884,7 @@ typedef struct {
|
||||||
__le16 MajorVersionNumber;
|
__le16 MajorVersionNumber;
|
||||||
__le16 MinorVersionNumber;
|
__le16 MinorVersionNumber;
|
||||||
__le64 Capability;
|
__le64 Capability;
|
||||||
} __attribute__((packed)) FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
|
} __attribute__((packed)) FILE_SYSTEM_UNIX_INFO; /* Unix extension level 0x200*/
|
||||||
|
|
||||||
/* Version numbers for CIFS UNIX major and minor. */
|
/* Version numbers for CIFS UNIX major and minor. */
|
||||||
#define CIFS_UNIX_MAJOR_VERSION 1
|
#define CIFS_UNIX_MAJOR_VERSION 1
|
||||||
|
@ -1886,14 +1899,18 @@ typedef struct {
|
||||||
#define CIFS_UNIX_POSIX_PATH_OPS_CAP 0x00000020 /* Allow new POSIX path based
|
#define CIFS_UNIX_POSIX_PATH_OPS_CAP 0x00000020 /* Allow new POSIX path based
|
||||||
calls including posix open
|
calls including posix open
|
||||||
and posix unlink */
|
and posix unlink */
|
||||||
|
#define CIFS_UNIX_LARGE_READ_CAP 0x00000040 /* support reads >128K (up
|
||||||
|
to 0xFFFF00 */
|
||||||
|
#define CIFS_UNIX_LARGE_WRITE_CAP 0x00000080
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
/* Can not set pathnames cap yet until we send new posix create SMB since
|
/* Can not set pathnames cap yet until we send new posix create SMB since
|
||||||
otherwise server can treat such handles opened with older ntcreatex
|
otherwise server can treat such handles opened with older ntcreatex
|
||||||
(by a new client which knows how to send posix path ops)
|
(by a new client which knows how to send posix path ops)
|
||||||
as non-posix handles (can affect write behavior with byte range locks.
|
as non-posix handles (can affect write behavior with byte range locks.
|
||||||
We can add back in POSIX_PATH_OPS cap when Posix Create/Mkdir finished */
|
We can add back in POSIX_PATH_OPS cap when Posix Create/Mkdir finished */
|
||||||
/* #define CIFS_UNIX_CAP_MASK 0x0000003b */
|
/* #define CIFS_UNIX_CAP_MASK 0x000000fb */
|
||||||
#define CIFS_UNIX_CAP_MASK 0x0000001b
|
#define CIFS_UNIX_CAP_MASK 0x000000db
|
||||||
#else
|
#else
|
||||||
#define CIFS_UNIX_CAP_MASK 0x00000013
|
#define CIFS_UNIX_CAP_MASK 0x00000013
|
||||||
#endif /* CONFIG_CIFS_POSIX */
|
#endif /* CONFIG_CIFS_POSIX */
|
||||||
|
@ -2138,6 +2155,12 @@ typedef struct {
|
||||||
/* struct following varies based on requested level */
|
/* struct following varies based on requested level */
|
||||||
} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
|
} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
|
||||||
|
|
||||||
|
#define SMB_POSIX_UNLINK_FILE_TARGET 0
|
||||||
|
#define SMB_POSIX_UNLINK_DIRECTORY_TARGET 1
|
||||||
|
|
||||||
|
struct unlink_psx_rq { /* level 0x20a SetPathInfo */
|
||||||
|
__le16 type;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct file_internal_info {
|
struct file_internal_info {
|
||||||
__u64 UniqueId; /* inode number */
|
__u64 UniqueId; /* inode number */
|
||||||
|
@ -2291,7 +2314,7 @@ struct fealist {
|
||||||
struct data_blob {
|
struct data_blob {
|
||||||
__u8 *data;
|
__u8 *data;
|
||||||
size_t length;
|
size_t length;
|
||||||
void (*free) (struct data_blob * data_blob);
|
void (*free) (struct data_blob *data_blob);
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
|
@ -2357,8 +2380,10 @@ struct data_blob {
|
||||||
T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
|
T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
|
||||||
T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
|
T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
|
||||||
T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
|
T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
|
||||||
T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
|
T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) BB check for missing
|
||||||
Actually need QUERY_FILE_UNIX_INFO since has inode num
|
inode fields
|
||||||
|
Actually a need QUERY_FILE_UNIX_INFO
|
||||||
|
since has inode num
|
||||||
BB what about a) blksize/blkbits/blocks
|
BB what about a) blksize/blkbits/blocks
|
||||||
b) i_version
|
b) i_version
|
||||||
c) i_rdev
|
c) i_rdev
|
||||||
|
@ -2368,8 +2393,6 @@ struct data_blob {
|
||||||
T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
|
T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
|
||||||
TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
|
TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
|
||||||
T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
|
T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* xsymlink is a symlink format (used by MacOS) that can be used
|
/* xsymlink is a symlink format (used by MacOS) that can be used
|
||||||
|
@ -2405,7 +2428,8 @@ typedef struct file_xattr_info {
|
||||||
__u32 xattr_value_len;
|
__u32 xattr_value_len;
|
||||||
char xattr_name[0];
|
char xattr_name[0];
|
||||||
/* followed by xattr_value[xattr_value_len], no pad */
|
/* followed by xattr_value[xattr_value_len], no pad */
|
||||||
} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute, info level 0x205 */
|
} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute info
|
||||||
|
level 0x205 */
|
||||||
|
|
||||||
|
|
||||||
/* flags for chattr command */
|
/* flags for chattr command */
|
||||||
|
@ -2431,7 +2455,8 @@ typedef struct file_xattr_info {
|
||||||
typedef struct file_chattr_info {
|
typedef struct file_chattr_info {
|
||||||
__le64 mask; /* list of all possible attribute bits */
|
__le64 mask; /* list of all possible attribute bits */
|
||||||
__le64 mode; /* list of actual attribute bits on this inode */
|
__le64 mode; /* list of actual attribute bits on this inode */
|
||||||
} __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes (chattr, chflags) level 0x206 */
|
} __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes
|
||||||
|
(chattr, chflags) level 0x206 */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -64,19 +64,19 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr);
|
||||||
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
|
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
|
||||||
extern int decode_negTokenInit(unsigned char *security_blob, int length,
|
extern int decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
enum securityEnum *secType);
|
enum securityEnum *secType);
|
||||||
extern int cifs_inet_pton(int, char * source, void *dst);
|
extern int cifs_inet_pton(int, char *source, void *dst);
|
||||||
extern int map_smb_to_linux_error(struct smb_hdr *smb);
|
extern int map_smb_to_linux_error(struct smb_hdr *smb);
|
||||||
extern void header_assemble(struct smb_hdr *, char /* command */ ,
|
extern void header_assemble(struct smb_hdr *, char /* command */ ,
|
||||||
const struct cifsTconInfo *, int /* length of
|
const struct cifsTconInfo *, int /* length of
|
||||||
fixed section (word count) in two byte units */);
|
fixed section (word count) in two byte units */);
|
||||||
extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
|
extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
|
||||||
struct cifsSesInfo *ses,
|
struct cifsSesInfo *ses,
|
||||||
void ** request_buf);
|
void **request_buf);
|
||||||
extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
const int stage,
|
const int stage,
|
||||||
const struct nls_table *nls_cp);
|
const struct nls_table *nls_cp);
|
||||||
extern __u16 GetNextMid(struct TCP_Server_Info *server);
|
extern __u16 GetNextMid(struct TCP_Server_Info *server);
|
||||||
extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
|
extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16,
|
||||||
struct cifsTconInfo *);
|
struct cifsTconInfo *);
|
||||||
extern void DeleteOplockQEntry(struct oplock_q_entry *);
|
extern void DeleteOplockQEntry(struct oplock_q_entry *);
|
||||||
extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
|
extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
|
||||||
|
@ -90,7 +90,7 @@ extern int cifs_get_inode_info(struct inode **pinode,
|
||||||
struct super_block *sb, int xid);
|
struct super_block *sb, int xid);
|
||||||
extern int cifs_get_inode_info_unix(struct inode **pinode,
|
extern int cifs_get_inode_info_unix(struct inode **pinode,
|
||||||
const unsigned char *search_path,
|
const unsigned char *search_path,
|
||||||
struct super_block *sb,int xid);
|
struct super_block *sb, int xid);
|
||||||
|
|
||||||
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
|
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
|
||||||
const char *);
|
const char *);
|
||||||
|
@ -99,7 +99,7 @@ void cifs_proc_init(void);
|
||||||
void cifs_proc_clean(void);
|
void cifs_proc_clean(void);
|
||||||
|
|
||||||
extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
|
extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
|
||||||
struct nls_table * nls_info);
|
struct nls_table *nls_info);
|
||||||
extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
|
extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
|
||||||
|
|
||||||
extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
|
@ -108,11 +108,11 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
|
|
||||||
extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
|
||||||
const char *searchName, const struct nls_table *nls_codepage,
|
const char *searchName, const struct nls_table *nls_codepage,
|
||||||
__u16 *searchHandle, struct cifs_search_info * psrch_inf,
|
__u16 *searchHandle, struct cifs_search_info *psrch_inf,
|
||||||
int map, const char dirsep);
|
int map, const char dirsep);
|
||||||
|
|
||||||
extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
|
||||||
__u16 searchHandle, struct cifs_search_info * psrch_inf);
|
__u16 searchHandle, struct cifs_search_info *psrch_inf);
|
||||||
|
|
||||||
extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
|
extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
|
||||||
const __u16 search_handle);
|
const __u16 search_handle);
|
||||||
|
@ -124,7 +124,7 @@ extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
|
||||||
const struct nls_table *nls_codepage, int remap);
|
const struct nls_table *nls_codepage, int remap);
|
||||||
extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
|
extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
|
||||||
const unsigned char *searchName,
|
const unsigned char *searchName,
|
||||||
FILE_ALL_INFO * findData,
|
FILE_ALL_INFO *findData,
|
||||||
const struct nls_table *nls_codepage, int remap);
|
const struct nls_table *nls_codepage, int remap);
|
||||||
|
|
||||||
extern int CIFSSMBUnixQPathInfo(const int xid,
|
extern int CIFSSMBUnixQPathInfo(const int xid,
|
||||||
|
@ -146,10 +146,10 @@ extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
|
||||||
const char *old_path,
|
const char *old_path,
|
||||||
const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage,
|
||||||
unsigned int *pnum_referrals,
|
unsigned int *pnum_referrals,
|
||||||
unsigned char ** preferrals,
|
unsigned char **preferrals,
|
||||||
int remap);
|
int remap);
|
||||||
extern void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
|
extern void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
|
||||||
struct super_block * sb, struct smb_vol * vol);
|
struct super_block *sb, struct smb_vol *vol);
|
||||||
extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
|
||||||
struct kstatfs *FSData);
|
struct kstatfs *FSData);
|
||||||
extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon,
|
extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon,
|
||||||
|
@ -181,7 +181,7 @@ extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
|
||||||
const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage,
|
||||||
int remap_special_chars);
|
int remap_special_chars);
|
||||||
extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
|
||||||
__u64 size, __u16 fileHandle,__u32 opener_pid,
|
__u64 size, __u16 fileHandle, __u32 opener_pid,
|
||||||
int AllocSizeFlag);
|
int AllocSizeFlag);
|
||||||
extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
|
extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
|
||||||
char *full_path, __u64 mode, __u64 uid,
|
char *full_path, __u64 mode, __u64 uid,
|
||||||
|
@ -196,7 +196,10 @@ extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
|
||||||
extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
|
||||||
const char *name, const struct nls_table *nls_codepage,
|
const char *name, const struct nls_table *nls_codepage,
|
||||||
int remap_special_chars);
|
int remap_special_chars);
|
||||||
|
extern int CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon,
|
||||||
|
const char *name, __u16 type,
|
||||||
|
const struct nls_table *nls_codepage,
|
||||||
|
int remap_special_chars);
|
||||||
extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
|
||||||
const char *name,
|
const char *name,
|
||||||
const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage,
|
||||||
|
@ -205,8 +208,8 @@ extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
|
||||||
const char *fromName, const char *toName,
|
const char *fromName, const char *toName,
|
||||||
const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage,
|
||||||
int remap_special_chars);
|
int remap_special_chars);
|
||||||
extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
|
extern int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
|
||||||
int netfid, char * target_name,
|
int netfid, char *target_name,
|
||||||
const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage,
|
||||||
int remap_special_chars);
|
int remap_special_chars);
|
||||||
extern int CIFSCreateHardLink(const int xid,
|
extern int CIFSCreateHardLink(const int xid,
|
||||||
|
@ -255,7 +258,7 @@ extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
|
||||||
extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
|
||||||
const int netfid, unsigned int count,
|
const int netfid, unsigned int count,
|
||||||
const __u64 lseek, unsigned int *nbytes, char **buf,
|
const __u64 lseek, unsigned int *nbytes, char **buf,
|
||||||
int * return_buf_type);
|
int *return_buf_type);
|
||||||
extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
|
||||||
const int netfid, const unsigned int count,
|
const int netfid, const unsigned int count,
|
||||||
const __u64 lseek, unsigned int *nbytes,
|
const __u64 lseek, unsigned int *nbytes,
|
||||||
|
@ -270,9 +273,9 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
|
||||||
const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage,
|
||||||
int remap_special_chars);
|
int remap_special_chars);
|
||||||
extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
|
extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
|
||||||
const struct nls_table * codepage);
|
const struct nls_table *codepage);
|
||||||
extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
|
extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
|
||||||
const struct nls_table * cp, int mapChars);
|
const struct nls_table *cp, int mapChars);
|
||||||
|
|
||||||
extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
|
||||||
const __u16 netfid, const __u64 len,
|
const __u16 netfid, const __u64 len,
|
||||||
|
@ -291,19 +294,21 @@ extern void sesInfoFree(struct cifsSesInfo *);
|
||||||
extern struct cifsTconInfo *tconInfoAlloc(void);
|
extern struct cifsTconInfo *tconInfoAlloc(void);
|
||||||
extern void tconInfoFree(struct cifsTconInfo *);
|
extern void tconInfoFree(struct cifsTconInfo *);
|
||||||
|
|
||||||
extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *);
|
extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
|
||||||
extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
|
extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
|
||||||
__u32 *);
|
__u32 *);
|
||||||
extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
|
extern int cifs_verify_signature(struct smb_hdr *,
|
||||||
|
const struct mac_key *mac_key,
|
||||||
__u32 expected_sequence_number);
|
__u32 expected_sequence_number);
|
||||||
extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
|
extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
|
||||||
|
const char *pass);
|
||||||
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
|
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
|
||||||
const struct nls_table *);
|
const struct nls_table *);
|
||||||
extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * );
|
extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * );
|
||||||
extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
|
extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
|
||||||
const struct nls_table *);
|
const struct nls_table *);
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key);
|
extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key);
|
||||||
#endif /* CIFS_WEAK_PW_HASH */
|
#endif /* CIFS_WEAK_PW_HASH */
|
||||||
extern int CIFSSMBCopy(int xid,
|
extern int CIFSSMBCopy(int xid,
|
||||||
struct cifsTconInfo *source_tcon,
|
struct cifsTconInfo *source_tcon,
|
||||||
|
@ -313,27 +318,27 @@ extern int CIFSSMBCopy(int xid,
|
||||||
const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage,
|
||||||
int remap_special_chars);
|
int remap_special_chars);
|
||||||
extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
|
||||||
const int notify_subdirs,const __u16 netfid,
|
const int notify_subdirs, const __u16 netfid,
|
||||||
__u32 filter, struct file * file, int multishot,
|
__u32 filter, struct file *file, int multishot,
|
||||||
const struct nls_table *nls_codepage);
|
const struct nls_table *nls_codepage);
|
||||||
extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
|
extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
|
||||||
const unsigned char *searchName, char * EAData,
|
const unsigned char *searchName, char *EAData,
|
||||||
size_t bufsize, const struct nls_table *nls_codepage,
|
size_t bufsize, const struct nls_table *nls_codepage,
|
||||||
int remap_special_chars);
|
int remap_special_chars);
|
||||||
extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
|
extern ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
|
||||||
const unsigned char * searchName,const unsigned char * ea_name,
|
const unsigned char *searchName, const unsigned char *ea_name,
|
||||||
unsigned char * ea_value, size_t buf_size,
|
unsigned char *ea_value, size_t buf_size,
|
||||||
const struct nls_table *nls_codepage, int remap_special_chars);
|
const struct nls_table *nls_codepage, int remap_special_chars);
|
||||||
extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
|
||||||
const char *fileName, const char * ea_name,
|
const char *fileName, const char *ea_name,
|
||||||
const void * ea_value, const __u16 ea_value_len,
|
const void *ea_value, const __u16 ea_value_len,
|
||||||
const struct nls_table *nls_codepage, int remap_special_chars);
|
const struct nls_table *nls_codepage, int remap_special_chars);
|
||||||
extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
|
||||||
__u16 fid, char *acl_inf, const int buflen,
|
__u16 fid, char *acl_inf, const int buflen,
|
||||||
const int acl_type /* ACCESS vs. DEFAULT */);
|
const int acl_type /* ACCESS vs. DEFAULT */);
|
||||||
extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
|
||||||
const unsigned char *searchName,
|
const unsigned char *searchName,
|
||||||
char *acl_inf, const int buflen,const int acl_type,
|
char *acl_inf, const int buflen, const int acl_type,
|
||||||
const struct nls_table *nls_codepage, int remap_special_chars);
|
const struct nls_table *nls_codepage, int remap_special_chars);
|
||||||
extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
|
||||||
const unsigned char *fileName,
|
const unsigned char *fileName,
|
||||||
|
|
1019
fs/cifs/cifssmb.c
1019
fs/cifs/cifssmb.c
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -135,10 +135,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
char *full_path = NULL;
|
char *full_path = NULL;
|
||||||
FILE_ALL_INFO * buf = NULL;
|
FILE_ALL_INFO *buf = NULL;
|
||||||
struct inode *newinode = NULL;
|
struct inode *newinode = NULL;
|
||||||
struct cifsFileInfo * pCifsFile = NULL;
|
struct cifsFileInfo *pCifsFile = NULL;
|
||||||
struct cifsInodeInfo * pCifsInode;
|
struct cifsInodeInfo *pCifsInode;
|
||||||
int disposition = FILE_OVERWRITE_IF;
|
int disposition = FILE_OVERWRITE_IF;
|
||||||
int write_only = FALSE;
|
int write_only = FALSE;
|
||||||
|
|
||||||
|
@ -207,8 +207,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
} else {
|
} else {
|
||||||
/* If Open reported that we actually created a file
|
/* If Open reported that we actually created a file
|
||||||
then we now have to set the mode if possible */
|
then we now have to set the mode if possible */
|
||||||
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
|
if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
|
||||||
(oplock & CIFS_CREATE_ACTION)) {
|
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current->fs->umask;
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||||
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
|
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
|
||||||
|
@ -235,8 +234,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
/* Could set r/o dos attribute if mode & 0222 == 0 */
|
/* Could set r/o dos attribute if mode & 0222 == 0 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BB server might mask mode so we have to query for Unix case*/
|
/* server might mask mode so we have to query for it */
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
||||||
inode->i_sb, xid);
|
inode->i_sb, xid);
|
||||||
else {
|
else {
|
||||||
|
@ -264,7 +263,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
direntry->d_op = &cifs_dentry_ops;
|
direntry->d_op = &cifs_dentry_ops;
|
||||||
d_instantiate(direntry, newinode);
|
d_instantiate(direntry, newinode);
|
||||||
}
|
}
|
||||||
if ((nd->flags & LOOKUP_OPEN) == FALSE) {
|
if ((nd == NULL /* nfsd case - nfs srv does not set nd */) ||
|
||||||
|
((nd->flags & LOOKUP_OPEN) == FALSE)) {
|
||||||
/* mknod case - do not leave file open */
|
/* mknod case - do not leave file open */
|
||||||
CIFSSMBClose(xid, pTcon, fileHandle);
|
CIFSSMBClose(xid, pTcon, fileHandle);
|
||||||
} else if (newinode) {
|
} else if (newinode) {
|
||||||
|
@ -323,7 +323,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
char *full_path = NULL;
|
char *full_path = NULL;
|
||||||
struct inode * newinode = NULL;
|
struct inode *newinode = NULL;
|
||||||
|
|
||||||
if (!old_valid_dev(device_number))
|
if (!old_valid_dev(device_number))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -336,7 +336,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
full_path = build_path_from_dentry(direntry);
|
full_path = build_path_from_dentry(direntry);
|
||||||
if (full_path == NULL)
|
if (full_path == NULL)
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
else if (pTcon->ses->capabilities & CAP_UNIX) {
|
else if (pTcon->unix_ext) {
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current->fs->umask;
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||||
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
||||||
|
@ -490,7 +490,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
(" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
|
(" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
|
||||||
|
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = cifs_get_inode_info_unix(&newInode, full_path,
|
rc = cifs_get_inode_info_unix(&newInode, full_path,
|
||||||
parent_dir_inode->i_sb, xid);
|
parent_dir_inode->i_sb, xid);
|
||||||
else
|
else
|
||||||
|
|
|
@ -26,28 +26,41 @@
|
||||||
/*
|
/*
|
||||||
* See Documentation/filesystems/Exporting
|
* See Documentation/filesystems/Exporting
|
||||||
* and examples in fs/exportfs
|
* and examples in fs/exportfs
|
||||||
|
*
|
||||||
|
* Since cifs is a network file system, an "fsid" must be included for
|
||||||
|
* any nfs exports file entries which refer to cifs paths. In addition
|
||||||
|
* the cifs mount must be mounted with the "serverino" option (ie use stable
|
||||||
|
* server inode numbers instead of locally generated temporary ones).
|
||||||
|
* Although cifs inodes do not use generation numbers (have generation number
|
||||||
|
* of zero) - the inode number alone should be good enough for simple cases
|
||||||
|
* in which users want to export cifs shares with NFS. The decode and encode
|
||||||
|
* could be improved by using a new routine which expects 64 bit inode numbers
|
||||||
|
* instead of the default 32 bit routines in fs/exportfs
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/exportfs.h>
|
#include <linux/exportfs.h>
|
||||||
|
#include "cifsglob.h"
|
||||||
|
#include "cifs_debug.h"
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||||
|
|
||||||
static struct dentry *cifs_get_parent(struct dentry *dentry)
|
static struct dentry *cifs_get_parent(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
/* BB need to add code here eventually to enable export via NFSD */
|
/* BB need to add code here eventually to enable export via NFSD */
|
||||||
|
cFYI(1, ("get parent for %p", dentry));
|
||||||
return ERR_PTR(-EACCES);
|
return ERR_PTR(-EACCES);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct export_operations cifs_export_ops = {
|
struct export_operations cifs_export_ops = {
|
||||||
.get_parent = cifs_get_parent,
|
.get_parent = cifs_get_parent,
|
||||||
/* Following five export operations are unneeded so far and can default */
|
/* Following five export operations are unneeded so far and can default:
|
||||||
/* .get_dentry =
|
.get_dentry =
|
||||||
.get_name =
|
.get_name =
|
||||||
.find_exported_dentry =
|
.find_exported_dentry =
|
||||||
.decode_fh =
|
.decode_fh =
|
||||||
.encode_fs = */
|
.encode_fs = */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EXPERIMENTAL */
|
#endif /* EXPERIMENTAL */
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags)
|
||||||
return cifs_ntfy_flags;
|
return cifs_ntfy_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cifs_dir_notify(struct file * file, unsigned long arg)
|
int cifs_dir_notify(struct file *file, unsigned long arg)
|
||||||
{
|
{
|
||||||
int xid;
|
int xid;
|
||||||
int rc = -EINVAL;
|
int rc = -EINVAL;
|
||||||
|
|
141
fs/cifs/file.c
141
fs/cifs/file.c
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* vfs operations that deal with files
|
* vfs operations that deal with files
|
||||||
*
|
*
|
||||||
* Copyright (C) International Business Machines Corp., 2002,2003
|
* Copyright (C) International Business Machines Corp., 2002,2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
* Jeremy Allison (jra@samba.org)
|
* Jeremy Allison (jra@samba.org)
|
||||||
*
|
*
|
||||||
|
@ -57,7 +57,7 @@ static inline struct cifsFileInfo *cifs_init_private(
|
||||||
does not tell us which handle the write is for so there can
|
does not tell us which handle the write is for so there can
|
||||||
be a close (overlapping with write) of the filehandle that
|
be a close (overlapping with write) of the filehandle that
|
||||||
cifs_writepages chose to use */
|
cifs_writepages chose to use */
|
||||||
atomic_set(&private_data->wrtPending,0);
|
atomic_set(&private_data->wrtPending, 0);
|
||||||
|
|
||||||
return private_data;
|
return private_data;
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
|
||||||
}
|
}
|
||||||
|
|
||||||
client_can_cache:
|
client_can_cache:
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode,
|
rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode,
|
||||||
full_path, inode->i_sb, xid);
|
full_path, inode->i_sb, xid);
|
||||||
else
|
else
|
||||||
|
@ -212,7 +212,7 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
|
cFYI(1, ("inode = 0x%p file flags are 0x%x for %s",
|
||||||
inode, file->f_flags, full_path));
|
inode, file->f_flags, full_path));
|
||||||
desiredAccess = cifs_convert_flags(file->f_flags);
|
desiredAccess = cifs_convert_flags(file->f_flags);
|
||||||
|
|
||||||
|
@ -303,7 +303,7 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||||
if (oplock & CIFS_CREATE_ACTION) {
|
if (oplock & CIFS_CREATE_ACTION) {
|
||||||
/* time to set mode which we can not set earlier due to
|
/* time to set mode which we can not set earlier due to
|
||||||
problems creating new read-only files */
|
problems creating new read-only files */
|
||||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
|
if (pTcon->unix_ext) {
|
||||||
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
||||||
inode->i_mode,
|
inode->i_mode,
|
||||||
(__u64)-1, (__u64)-1, 0 /* dev */,
|
(__u64)-1, (__u64)-1, 0 /* dev */,
|
||||||
|
@ -345,7 +345,7 @@ static int cifs_reopen_file(struct file *file, int can_flush)
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
struct cifsFileInfo *pCifsFile;
|
struct cifsFileInfo *pCifsFile;
|
||||||
struct cifsInodeInfo *pCifsInode;
|
struct cifsInodeInfo *pCifsInode;
|
||||||
struct inode * inode;
|
struct inode *inode;
|
||||||
char *full_path = NULL;
|
char *full_path = NULL;
|
||||||
int desiredAccess;
|
int desiredAccess;
|
||||||
int disposition = FILE_OPEN;
|
int disposition = FILE_OPEN;
|
||||||
|
@ -372,7 +372,7 @@ static int cifs_reopen_file(struct file *file, int can_flush)
|
||||||
}
|
}
|
||||||
|
|
||||||
inode = file->f_path.dentry->d_inode;
|
inode = file->f_path.dentry->d_inode;
|
||||||
if(inode == NULL) {
|
if (inode == NULL) {
|
||||||
cERROR(1, ("inode not valid"));
|
cERROR(1, ("inode not valid"));
|
||||||
dump_stack();
|
dump_stack();
|
||||||
rc = -EBADF;
|
rc = -EBADF;
|
||||||
|
@ -396,7 +396,7 @@ reopen_error_exit:
|
||||||
}
|
}
|
||||||
|
|
||||||
cFYI(1, ("inode = 0x%p file flags 0x%x for %s",
|
cFYI(1, ("inode = 0x%p file flags 0x%x for %s",
|
||||||
inode, file->f_flags,full_path));
|
inode, file->f_flags, full_path));
|
||||||
desiredAccess = cifs_convert_flags(file->f_flags);
|
desiredAccess = cifs_convert_flags(file->f_flags);
|
||||||
|
|
||||||
if (oplockEnabled)
|
if (oplockEnabled)
|
||||||
|
@ -430,7 +430,7 @@ reopen_error_exit:
|
||||||
go to server to get inode info */
|
go to server to get inode info */
|
||||||
pCifsInode->clientCanCacheAll = FALSE;
|
pCifsInode->clientCanCacheAll = FALSE;
|
||||||
pCifsInode->clientCanCacheRead = FALSE;
|
pCifsInode->clientCanCacheRead = FALSE;
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = cifs_get_inode_info_unix(&inode,
|
rc = cifs_get_inode_info_unix(&inode,
|
||||||
full_path, inode->i_sb, xid);
|
full_path, inode->i_sb, xid);
|
||||||
else
|
else
|
||||||
|
@ -486,7 +486,7 @@ int cifs_close(struct inode *inode, struct file *file)
|
||||||
already closed */
|
already closed */
|
||||||
if (pTcon->tidStatus != CifsNeedReconnect) {
|
if (pTcon->tidStatus != CifsNeedReconnect) {
|
||||||
int timeout = 2;
|
int timeout = 2;
|
||||||
while((atomic_read(&pSMBFile->wrtPending) != 0)
|
while ((atomic_read(&pSMBFile->wrtPending) != 0)
|
||||||
&& (timeout < 1000) ) {
|
&& (timeout < 1000) ) {
|
||||||
/* Give write a better chance to get to
|
/* Give write a better chance to get to
|
||||||
server ahead of the close. We do not
|
server ahead of the close. We do not
|
||||||
|
@ -496,13 +496,14 @@ int cifs_close(struct inode *inode, struct file *file)
|
||||||
but this should give enough time to
|
but this should give enough time to
|
||||||
clear the socket */
|
clear the socket */
|
||||||
#ifdef CONFIG_CIFS_DEBUG2
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
cFYI(1,("close delay, write pending"));
|
cFYI(1, ("close delay, write pending"));
|
||||||
#endif /* DEBUG2 */
|
#endif /* DEBUG2 */
|
||||||
msleep(timeout);
|
msleep(timeout);
|
||||||
timeout *= 4;
|
timeout *= 4;
|
||||||
}
|
}
|
||||||
if(atomic_read(&pSMBFile->wrtPending))
|
if (atomic_read(&pSMBFile->wrtPending))
|
||||||
cERROR(1,("close with pending writes"));
|
cERROR(1,
|
||||||
|
("close with pending writes"));
|
||||||
rc = CIFSSMBClose(xid, pTcon,
|
rc = CIFSSMBClose(xid, pTcon,
|
||||||
pSMBFile->netfid);
|
pSMBFile->netfid);
|
||||||
}
|
}
|
||||||
|
@ -534,7 +535,7 @@ int cifs_close(struct inode *inode, struct file *file)
|
||||||
CIFS_I(inode)->clientCanCacheRead = FALSE;
|
CIFS_I(inode)->clientCanCacheRead = FALSE;
|
||||||
CIFS_I(inode)->clientCanCacheAll = FALSE;
|
CIFS_I(inode)->clientCanCacheAll = FALSE;
|
||||||
}
|
}
|
||||||
if ((rc ==0) && CIFS_I(inode)->write_behind_rc)
|
if ((rc == 0) && CIFS_I(inode)->write_behind_rc)
|
||||||
rc = CIFS_I(inode)->write_behind_rc;
|
rc = CIFS_I(inode)->write_behind_rc;
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -554,7 +555,8 @@ int cifs_closedir(struct inode *inode, struct file *file)
|
||||||
|
|
||||||
if (pCFileStruct) {
|
if (pCFileStruct) {
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
struct cifs_sb_info *cifs_sb =
|
||||||
|
CIFS_SB(file->f_path.dentry->d_sb);
|
||||||
|
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
|
|
||||||
|
@ -572,7 +574,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
|
||||||
if (ptmp) {
|
if (ptmp) {
|
||||||
cFYI(1, ("closedir free smb buf in srch struct"));
|
cFYI(1, ("closedir free smb buf in srch struct"));
|
||||||
pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
|
pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
|
||||||
if(pCFileStruct->srch_inf.smallBuf)
|
if (pCFileStruct->srch_inf.smallBuf)
|
||||||
cifs_small_buf_release(ptmp);
|
cifs_small_buf_release(ptmp);
|
||||||
else
|
else
|
||||||
cifs_buf_release(ptmp);
|
cifs_buf_release(ptmp);
|
||||||
|
@ -594,7 +596,8 @@ int cifs_closedir(struct inode *inode, struct file *file)
|
||||||
static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
|
static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
|
||||||
__u64 offset, __u8 lockType)
|
__u64 offset, __u8 lockType)
|
||||||
{
|
{
|
||||||
struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
|
struct cifsLockInfo *li =
|
||||||
|
kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
|
||||||
if (li == NULL)
|
if (li == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
li->offset = offset;
|
li->offset = offset;
|
||||||
|
@ -683,9 +686,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
||||||
account for negative length which we can not accept over the
|
account for negative length which we can not accept over the
|
||||||
wire */
|
wire */
|
||||||
if (IS_GETLK(cmd)) {
|
if (IS_GETLK(cmd)) {
|
||||||
if(posix_locking) {
|
if (posix_locking) {
|
||||||
int posix_lock_type;
|
int posix_lock_type;
|
||||||
if(lockType & LOCKING_ANDX_SHARED_LOCK)
|
if (lockType & LOCKING_ANDX_SHARED_LOCK)
|
||||||
posix_lock_type = CIFS_RDLCK;
|
posix_lock_type = CIFS_RDLCK;
|
||||||
else
|
else
|
||||||
posix_lock_type = CIFS_WRLCK;
|
posix_lock_type = CIFS_WRLCK;
|
||||||
|
@ -729,22 +732,24 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
||||||
|
|
||||||
if (posix_locking) {
|
if (posix_locking) {
|
||||||
int posix_lock_type;
|
int posix_lock_type;
|
||||||
if(lockType & LOCKING_ANDX_SHARED_LOCK)
|
if (lockType & LOCKING_ANDX_SHARED_LOCK)
|
||||||
posix_lock_type = CIFS_RDLCK;
|
posix_lock_type = CIFS_RDLCK;
|
||||||
else
|
else
|
||||||
posix_lock_type = CIFS_WRLCK;
|
posix_lock_type = CIFS_WRLCK;
|
||||||
|
|
||||||
if(numUnlock == 1)
|
if (numUnlock == 1)
|
||||||
posix_lock_type = CIFS_UNLCK;
|
posix_lock_type = CIFS_UNLCK;
|
||||||
|
|
||||||
rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
|
rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
|
||||||
length, pfLock,
|
length, pfLock,
|
||||||
posix_lock_type, wait_flag);
|
posix_lock_type, wait_flag);
|
||||||
} else {
|
} else {
|
||||||
struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data;
|
struct cifsFileInfo *fid =
|
||||||
|
(struct cifsFileInfo *)file->private_data;
|
||||||
|
|
||||||
if (numLock) {
|
if (numLock) {
|
||||||
rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
|
rc = CIFSSMBLock(xid, pTcon, netfid, length,
|
||||||
|
pfLock->fl_start,
|
||||||
0, numLock, lockType, wait_flag);
|
0, numLock, lockType, wait_flag);
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
|
@ -763,7 +768,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
||||||
list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
|
list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
|
||||||
if (pfLock->fl_start <= li->offset &&
|
if (pfLock->fl_start <= li->offset &&
|
||||||
length >= li->length) {
|
length >= li->length) {
|
||||||
stored_rc = CIFSSMBLock(xid, pTcon, netfid,
|
stored_rc = CIFSSMBLock(xid, pTcon,
|
||||||
|
netfid,
|
||||||
li->length, li->offset,
|
li->length, li->offset,
|
||||||
1, 0, li->type, FALSE);
|
1, 0, li->type, FALSE);
|
||||||
if (stored_rc)
|
if (stored_rc)
|
||||||
|
@ -898,7 +904,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
|
||||||
|
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
|
|
||||||
cFYI(1,("write %zd bytes to offset %lld of %s", write_size,
|
cFYI(1, ("write %zd bytes to offset %lld of %s", write_size,
|
||||||
*poffset, file->f_path.dentry->d_name.name));
|
*poffset, file->f_path.dentry->d_name.name));
|
||||||
|
|
||||||
if (file->private_data == NULL)
|
if (file->private_data == NULL)
|
||||||
|
@ -941,7 +947,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(experimEnabled || (pTcon->ses->server &&
|
if (experimEnabled || (pTcon->ses->server &&
|
||||||
((pTcon->ses->server->secMode &
|
((pTcon->ses->server->secMode &
|
||||||
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
||||||
== 0))) {
|
== 0))) {
|
||||||
|
@ -1009,8 +1015,8 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
|
||||||
the VFS or MM) should not happen but we had reports of on oops (due to
|
the VFS or MM) should not happen but we had reports of on oops (due to
|
||||||
it being zero) during stress testcases so we need to check for it */
|
it being zero) during stress testcases so we need to check for it */
|
||||||
|
|
||||||
if(cifs_inode == NULL) {
|
if (cifs_inode == NULL) {
|
||||||
cERROR(1,("Null inode passed to cifs_writeable_file"));
|
cERROR(1, ("Null inode passed to cifs_writeable_file"));
|
||||||
dump_stack();
|
dump_stack();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1024,13 +1030,14 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
|
||||||
(open_file->pfile->f_flags & O_WRONLY))) {
|
(open_file->pfile->f_flags & O_WRONLY))) {
|
||||||
atomic_inc(&open_file->wrtPending);
|
atomic_inc(&open_file->wrtPending);
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&GlobalSMBSeslock);
|
||||||
if((open_file->invalidHandle) &&
|
if ((open_file->invalidHandle) &&
|
||||||
(!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
|
(!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
|
||||||
rc = cifs_reopen_file(open_file->pfile, FALSE);
|
rc = cifs_reopen_file(open_file->pfile, FALSE);
|
||||||
/* if it fails, try another handle - might be */
|
/* if it fails, try another handle - might be */
|
||||||
/* dangerous to hold up writepages with retry */
|
/* dangerous to hold up writepages with retry */
|
||||||
if(rc) {
|
if (rc) {
|
||||||
cFYI(1,("failed on reopen file in wp"));
|
cFYI(1,
|
||||||
|
("failed on reopen file in wp"));
|
||||||
read_lock(&GlobalSMBSeslock);
|
read_lock(&GlobalSMBSeslock);
|
||||||
/* can not use this handle, no write
|
/* can not use this handle, no write
|
||||||
pending on this one after all */
|
pending on this one after all */
|
||||||
|
@ -1117,7 +1124,7 @@ static int cifs_writepages(struct address_space *mapping,
|
||||||
pgoff_t end;
|
pgoff_t end;
|
||||||
pgoff_t index;
|
pgoff_t index;
|
||||||
int range_whole = 0;
|
int range_whole = 0;
|
||||||
struct kvec * iov;
|
struct kvec *iov;
|
||||||
int len;
|
int len;
|
||||||
int n_iov = 0;
|
int n_iov = 0;
|
||||||
pgoff_t next;
|
pgoff_t next;
|
||||||
|
@ -1139,14 +1146,14 @@ static int cifs_writepages(struct address_space *mapping,
|
||||||
if (cifs_sb->wsize < PAGE_CACHE_SIZE)
|
if (cifs_sb->wsize < PAGE_CACHE_SIZE)
|
||||||
return generic_writepages(mapping, wbc);
|
return generic_writepages(mapping, wbc);
|
||||||
|
|
||||||
if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
|
if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
|
||||||
if(cifs_sb->tcon->ses->server->secMode &
|
if (cifs_sb->tcon->ses->server->secMode &
|
||||||
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
||||||
if(!experimEnabled)
|
if (!experimEnabled)
|
||||||
return generic_writepages(mapping, wbc);
|
return generic_writepages(mapping, wbc);
|
||||||
|
|
||||||
iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);
|
iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);
|
||||||
if(iov == NULL)
|
if (iov == NULL)
|
||||||
return generic_writepages(mapping, wbc);
|
return generic_writepages(mapping, wbc);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1279,7 +1286,7 @@ retry:
|
||||||
1);
|
1);
|
||||||
atomic_dec(&open_file->wrtPending);
|
atomic_dec(&open_file->wrtPending);
|
||||||
if (rc || bytes_written < bytes_to_write) {
|
if (rc || bytes_written < bytes_to_write) {
|
||||||
cERROR(1,("Write2 ret %d, written = %d",
|
cERROR(1, ("Write2 ret %d, wrote %d",
|
||||||
rc, bytes_written));
|
rc, bytes_written));
|
||||||
/* BB what if continued retry is
|
/* BB what if continued retry is
|
||||||
requested via mount flags? */
|
requested via mount flags? */
|
||||||
|
@ -1296,7 +1303,7 @@ retry:
|
||||||
/* BB investigate retry logic on temporary
|
/* BB investigate retry logic on temporary
|
||||||
server crash cases and how recovery works
|
server crash cases and how recovery works
|
||||||
when page marked as error */
|
when page marked as error */
|
||||||
if(rc)
|
if (rc)
|
||||||
SetPageError(page);
|
SetPageError(page);
|
||||||
kunmap(page);
|
kunmap(page);
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
|
@ -1326,7 +1333,7 @@ retry:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cifs_writepage(struct page* page, struct writeback_control *wbc)
|
static int cifs_writepage(struct page *page, struct writeback_control *wbc)
|
||||||
{
|
{
|
||||||
int rc = -EFAULT;
|
int rc = -EFAULT;
|
||||||
int xid;
|
int xid;
|
||||||
|
@ -1456,7 +1463,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
|
||||||
*/
|
*/
|
||||||
int cifs_flush(struct file *file, fl_owner_t id)
|
int cifs_flush(struct file *file, fl_owner_t id)
|
||||||
{
|
{
|
||||||
struct inode * inode = file->f_path.dentry->d_inode;
|
struct inode *inode = file->f_path.dentry->d_inode;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
/* Rather than do the steps manually:
|
/* Rather than do the steps manually:
|
||||||
|
@ -1472,7 +1479,7 @@ int cifs_flush(struct file *file, fl_owner_t id)
|
||||||
if (!rc) /* reset wb rc if we were able to write out dirty pages */
|
if (!rc) /* reset wb rc if we were able to write out dirty pages */
|
||||||
CIFS_I(inode)->write_behind_rc = 0;
|
CIFS_I(inode)->write_behind_rc = 0;
|
||||||
|
|
||||||
cFYI(1, ("Flush inode %p file %p rc %d",inode,file,rc));
|
cFYI(1, ("Flush inode %p file %p rc %d", inode, file, rc));
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1535,9 +1542,9 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
|
||||||
rc = -EFAULT;
|
rc = -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(buf_type == CIFS_SMALL_BUFFER)
|
if (buf_type == CIFS_SMALL_BUFFER)
|
||||||
cifs_small_buf_release(smb_read_data);
|
cifs_small_buf_release(smb_read_data);
|
||||||
else if(buf_type == CIFS_LARGE_BUFFER)
|
else if (buf_type == CIFS_LARGE_BUFFER)
|
||||||
cifs_buf_release(smb_read_data);
|
cifs_buf_release(smb_read_data);
|
||||||
smb_read_data = NULL;
|
smb_read_data = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1593,7 +1600,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
|
||||||
cifs_sb->rsize);
|
cifs_sb->rsize);
|
||||||
/* For windows me and 9x we do not want to request more
|
/* For windows me and 9x we do not want to request more
|
||||||
than it negotiated since it will refuse the read then */
|
than it negotiated since it will refuse the read then */
|
||||||
if((pTcon->ses) &&
|
if ((pTcon->ses) &&
|
||||||
!(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
|
!(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
|
||||||
current_read_size = min_t(const int, current_read_size,
|
current_read_size = min_t(const int, current_read_size,
|
||||||
pTcon->ses->server->maxBuf - 128);
|
pTcon->ses->server->maxBuf - 128);
|
||||||
|
@ -1669,7 +1676,7 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
target = kmap_atomic(page,KM_USER0);
|
target = kmap_atomic(page, KM_USER0);
|
||||||
|
|
||||||
if (PAGE_CACHE_SIZE > bytes_read) {
|
if (PAGE_CACHE_SIZE > bytes_read) {
|
||||||
memcpy(target, data, bytes_read);
|
memcpy(target, data, bytes_read);
|
||||||
|
@ -1703,7 +1710,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
int bytes_read = 0;
|
int bytes_read = 0;
|
||||||
unsigned int read_size,i;
|
unsigned int read_size, i;
|
||||||
char *smb_read_data = NULL;
|
char *smb_read_data = NULL;
|
||||||
struct smb_com_read_rsp *pSMBr;
|
struct smb_com_read_rsp *pSMBr;
|
||||||
struct pagevec lru_pvec;
|
struct pagevec lru_pvec;
|
||||||
|
@ -1720,7 +1727,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
|
|
||||||
pagevec_init(&lru_pvec, 0);
|
pagevec_init(&lru_pvec, 0);
|
||||||
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
|
cFYI(1, ("rpages: num pages %d", num_pages));
|
||||||
|
#endif
|
||||||
for (i = 0; i < num_pages; ) {
|
for (i = 0; i < num_pages; ) {
|
||||||
unsigned contig_pages;
|
unsigned contig_pages;
|
||||||
struct page *tmp_page;
|
struct page *tmp_page;
|
||||||
|
@ -1736,7 +1745,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
||||||
contig_pages = 0;
|
contig_pages = 0;
|
||||||
expected_index =
|
expected_index =
|
||||||
list_entry(page_list->prev, struct page, lru)->index;
|
list_entry(page_list->prev, struct page, lru)->index;
|
||||||
list_for_each_entry_reverse(tmp_page,page_list,lru) {
|
list_for_each_entry_reverse(tmp_page, page_list, lru) {
|
||||||
if (tmp_page->index == expected_index) {
|
if (tmp_page->index == expected_index) {
|
||||||
contig_pages++;
|
contig_pages++;
|
||||||
expected_index++;
|
expected_index++;
|
||||||
|
@ -1753,7 +1762,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
||||||
/* Read size needs to be in multiples of one page */
|
/* Read size needs to be in multiples of one page */
|
||||||
read_size = min_t(const unsigned int, read_size,
|
read_size = min_t(const unsigned int, read_size,
|
||||||
cifs_sb->rsize & PAGE_CACHE_MASK);
|
cifs_sb->rsize & PAGE_CACHE_MASK);
|
||||||
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
|
cFYI(1, ("rpages: read size 0x%x contiguous pages %d",
|
||||||
|
read_size, contig_pages));
|
||||||
|
#endif
|
||||||
rc = -EAGAIN;
|
rc = -EAGAIN;
|
||||||
while (rc == -EAGAIN) {
|
while (rc == -EAGAIN) {
|
||||||
if ((open_file->invalidHandle) &&
|
if ((open_file->invalidHandle) &&
|
||||||
|
@ -1769,11 +1781,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
||||||
&bytes_read, &smb_read_data,
|
&bytes_read, &smb_read_data,
|
||||||
&buf_type);
|
&buf_type);
|
||||||
/* BB more RC checks ? */
|
/* BB more RC checks ? */
|
||||||
if (rc== -EAGAIN) {
|
if (rc == -EAGAIN) {
|
||||||
if (smb_read_data) {
|
if (smb_read_data) {
|
||||||
if(buf_type == CIFS_SMALL_BUFFER)
|
if (buf_type == CIFS_SMALL_BUFFER)
|
||||||
cifs_small_buf_release(smb_read_data);
|
cifs_small_buf_release(smb_read_data);
|
||||||
else if(buf_type == CIFS_LARGE_BUFFER)
|
else if (buf_type == CIFS_LARGE_BUFFER)
|
||||||
cifs_buf_release(smb_read_data);
|
cifs_buf_release(smb_read_data);
|
||||||
smb_read_data = NULL;
|
smb_read_data = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1811,9 +1823,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (smb_read_data) {
|
if (smb_read_data) {
|
||||||
if(buf_type == CIFS_SMALL_BUFFER)
|
if (buf_type == CIFS_SMALL_BUFFER)
|
||||||
cifs_small_buf_release(smb_read_data);
|
cifs_small_buf_release(smb_read_data);
|
||||||
else if(buf_type == CIFS_LARGE_BUFFER)
|
else if (buf_type == CIFS_LARGE_BUFFER)
|
||||||
cifs_buf_release(smb_read_data);
|
cifs_buf_release(smb_read_data);
|
||||||
smb_read_data = NULL;
|
smb_read_data = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1824,9 +1836,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
||||||
|
|
||||||
/* need to free smb_read_data buf before exit */
|
/* need to free smb_read_data buf before exit */
|
||||||
if (smb_read_data) {
|
if (smb_read_data) {
|
||||||
if(buf_type == CIFS_SMALL_BUFFER)
|
if (buf_type == CIFS_SMALL_BUFFER)
|
||||||
cifs_small_buf_release(smb_read_data);
|
cifs_small_buf_release(smb_read_data);
|
||||||
else if(buf_type == CIFS_LARGE_BUFFER)
|
else if (buf_type == CIFS_LARGE_BUFFER)
|
||||||
cifs_buf_release(smb_read_data);
|
cifs_buf_release(smb_read_data);
|
||||||
smb_read_data = NULL;
|
smb_read_data = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1850,7 +1862,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto io_error;
|
goto io_error;
|
||||||
else
|
else
|
||||||
cFYI(1, ("Bytes read %d",rc));
|
cFYI(1, ("Bytes read %d", rc));
|
||||||
|
|
||||||
file->f_path.dentry->d_inode->i_atime =
|
file->f_path.dentry->d_inode->i_atime =
|
||||||
current_fs_time(file->f_path.dentry->d_inode->i_sb);
|
current_fs_time(file->f_path.dentry->d_inode->i_sb);
|
||||||
|
@ -1905,7 +1917,7 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
|
||||||
if (cifsInode)
|
if (cifsInode)
|
||||||
open_file = find_writable_file(cifsInode);
|
open_file = find_writable_file(cifsInode);
|
||||||
|
|
||||||
if(open_file) {
|
if (open_file) {
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
|
|
||||||
/* there is not actually a write pending so let
|
/* there is not actually a write pending so let
|
||||||
|
@ -1920,7 +1932,7 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i_size_read(&cifsInode->vfs_inode) < end_of_file)
|
if (i_size_read(&cifsInode->vfs_inode) < end_of_file)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1935,7 +1947,7 @@ static int cifs_prepare_write(struct file *file, struct page *page,
|
||||||
loff_t i_size;
|
loff_t i_size;
|
||||||
loff_t offset;
|
loff_t offset;
|
||||||
|
|
||||||
cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
|
cFYI(1, ("prepare write for page %p from %d to %d", page, from, to));
|
||||||
if (PageUptodate(page))
|
if (PageUptodate(page))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1955,14 +1967,7 @@ static int cifs_prepare_write(struct file *file, struct page *page,
|
||||||
* We don't need to read data beyond the end of the file.
|
* We don't need to read data beyond the end of the file.
|
||||||
* zero it, and set the page uptodate
|
* zero it, and set the page uptodate
|
||||||
*/
|
*/
|
||||||
void *kaddr = kmap_atomic(page, KM_USER0);
|
simple_prepare_write(file, page, from, to);
|
||||||
|
|
||||||
if (from)
|
|
||||||
memset(kaddr, 0, from);
|
|
||||||
if (to < PAGE_CACHE_SIZE)
|
|
||||||
memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
|
|
||||||
flush_dcache_page(page);
|
|
||||||
kunmap_atomic(kaddr, KM_USER0);
|
|
||||||
SetPageUptodate(page);
|
SetPageUptodate(page);
|
||||||
} else if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
|
} else if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
|
||||||
/* might as well read a page, it is fast enough */
|
/* might as well read a page, it is fast enough */
|
||||||
|
|
166
fs/cifs/inode.c
166
fs/cifs/inode.c
|
@ -103,7 +103,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||||
cifsInfo->time = jiffies;
|
cifsInfo->time = jiffies;
|
||||||
cFYI(1, ("New time %ld", cifsInfo->time));
|
cFYI(1, ("New time %ld", cifsInfo->time));
|
||||||
/* this is ok to set on every inode revalidate */
|
/* this is ok to set on every inode revalidate */
|
||||||
atomic_set(&cifsInfo->inUse,1);
|
atomic_set(&cifsInfo->inUse, 1);
|
||||||
|
|
||||||
inode->i_atime =
|
inode->i_atime =
|
||||||
cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
|
cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
|
||||||
|
@ -137,7 +137,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||||
} else {
|
} else {
|
||||||
/* safest to call it a file if we do not know */
|
/* safest to call it a file if we do not know */
|
||||||
inode->i_mode |= S_IFREG;
|
inode->i_mode |= S_IFREG;
|
||||||
cFYI(1,("unknown type %d",type));
|
cFYI(1, ("unknown type %d", type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
|
||||||
|
@ -215,7 +215,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_sfu_inode(struct inode * inode, __u64 size,
|
static int decode_sfu_inode(struct inode *inode, __u64 size,
|
||||||
const unsigned char *path,
|
const unsigned char *path,
|
||||||
struct cifs_sb_info *cifs_sb, int xid)
|
struct cifs_sb_info *cifs_sb, int xid)
|
||||||
{
|
{
|
||||||
|
@ -225,7 +225,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
|
||||||
struct cifsTconInfo *pTcon = cifs_sb->tcon;
|
struct cifsTconInfo *pTcon = cifs_sb->tcon;
|
||||||
char buf[24];
|
char buf[24];
|
||||||
unsigned int bytes_read;
|
unsigned int bytes_read;
|
||||||
char * pbuf;
|
char *pbuf;
|
||||||
|
|
||||||
pbuf = buf;
|
pbuf = buf;
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if (rc==0) {
|
if (rc == 0) {
|
||||||
int buf_type = CIFS_NO_BUFFER;
|
int buf_type = CIFS_NO_BUFFER;
|
||||||
/* Read header */
|
/* Read header */
|
||||||
rc = CIFSSMBRead(xid, pTcon,
|
rc = CIFSSMBRead(xid, pTcon,
|
||||||
|
@ -250,7 +250,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
|
||||||
&bytes_read, &pbuf, &buf_type);
|
&bytes_read, &pbuf, &buf_type);
|
||||||
if ((rc == 0) && (bytes_read >= 8)) {
|
if ((rc == 0) && (bytes_read >= 8)) {
|
||||||
if (memcmp("IntxBLK", pbuf, 8) == 0) {
|
if (memcmp("IntxBLK", pbuf, 8) == 0) {
|
||||||
cFYI(1,("Block device"));
|
cFYI(1, ("Block device"));
|
||||||
inode->i_mode |= S_IFBLK;
|
inode->i_mode |= S_IFBLK;
|
||||||
if (bytes_read == 24) {
|
if (bytes_read == 24) {
|
||||||
/* we have enough to decode dev num */
|
/* we have enough to decode dev num */
|
||||||
|
@ -261,7 +261,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
|
||||||
inode->i_rdev = MKDEV(mjr, mnr);
|
inode->i_rdev = MKDEV(mjr, mnr);
|
||||||
}
|
}
|
||||||
} else if (memcmp("IntxCHR", pbuf, 8) == 0) {
|
} else if (memcmp("IntxCHR", pbuf, 8) == 0) {
|
||||||
cFYI(1,("Char device"));
|
cFYI(1, ("Char device"));
|
||||||
inode->i_mode |= S_IFCHR;
|
inode->i_mode |= S_IFCHR;
|
||||||
if (bytes_read == 24) {
|
if (bytes_read == 24) {
|
||||||
/* we have enough to decode dev num */
|
/* we have enough to decode dev num */
|
||||||
|
@ -272,7 +272,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
|
||||||
inode->i_rdev = MKDEV(mjr, mnr);
|
inode->i_rdev = MKDEV(mjr, mnr);
|
||||||
}
|
}
|
||||||
} else if (memcmp("IntxLNK", pbuf, 7) == 0) {
|
} else if (memcmp("IntxLNK", pbuf, 7) == 0) {
|
||||||
cFYI(1,("Symlink"));
|
cFYI(1, ("Symlink"));
|
||||||
inode->i_mode |= S_IFLNK;
|
inode->i_mode |= S_IFLNK;
|
||||||
} else {
|
} else {
|
||||||
inode->i_mode |= S_IFREG; /* file? */
|
inode->i_mode |= S_IFREG; /* file? */
|
||||||
|
@ -285,12 +285,11 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
|
||||||
CIFSSMBClose(xid, pTcon, netfid);
|
CIFSSMBClose(xid, pTcon, netfid);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
|
#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
|
||||||
|
|
||||||
static int get_sfu_uid_mode(struct inode * inode,
|
static int get_sfu_uid_mode(struct inode *inode,
|
||||||
const unsigned char *path,
|
const unsigned char *path,
|
||||||
struct cifs_sb_info *cifs_sb, int xid)
|
struct cifs_sb_info *cifs_sb, int xid)
|
||||||
{
|
{
|
||||||
|
@ -307,9 +306,9 @@ static int get_sfu_uid_mode(struct inode * inode,
|
||||||
else if (rc > 3) {
|
else if (rc > 3) {
|
||||||
mode = le32_to_cpu(*((__le32 *)ea_value));
|
mode = le32_to_cpu(*((__le32 *)ea_value));
|
||||||
inode->i_mode &= ~SFBITS_MASK;
|
inode->i_mode &= ~SFBITS_MASK;
|
||||||
cFYI(1,("special bits 0%o org mode 0%o", mode, inode->i_mode));
|
cFYI(1, ("special bits 0%o org mode 0%o", mode, inode->i_mode));
|
||||||
inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode;
|
inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode;
|
||||||
cFYI(1,("special mode bits 0%o", mode));
|
cFYI(1, ("special mode bits 0%o", mode));
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -317,8 +316,6 @@ static int get_sfu_uid_mode(struct inode * inode,
|
||||||
#else
|
#else
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cifs_get_inode_info(struct inode **pinode,
|
int cifs_get_inode_info(struct inode **pinode,
|
||||||
|
@ -334,11 +331,11 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||||
int adjustTZ = FALSE;
|
int adjustTZ = FALSE;
|
||||||
|
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
cFYI(1,("Getting info on %s", search_path));
|
cFYI(1, ("Getting info on %s", search_path));
|
||||||
|
|
||||||
if ((pfindData == NULL) && (*pinode != NULL)) {
|
if ((pfindData == NULL) && (*pinode != NULL)) {
|
||||||
if (CIFS_I(*pinode)->clientCanCacheRead) {
|
if (CIFS_I(*pinode)->clientCanCacheRead) {
|
||||||
cFYI(1,("No need to revalidate cached inode sizes"));
|
cFYI(1, ("No need to revalidate cached inode sizes"));
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,7 +361,6 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
adjustTZ = TRUE;
|
adjustTZ = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
|
/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
@ -419,7 +415,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||||
there Windows server or network appliances for which
|
there Windows server or network appliances for which
|
||||||
IndexNumber field is not guaranteed unique? */
|
IndexNumber field is not guaranteed unique? */
|
||||||
|
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||||
int rc1 = 0;
|
int rc1 = 0;
|
||||||
__u64 inode_num;
|
__u64 inode_num;
|
||||||
|
|
||||||
|
@ -429,7 +425,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if (rc1) {
|
if (rc1) {
|
||||||
cFYI(1,("GetSrvInodeNum rc %d", rc1));
|
cFYI(1, ("GetSrvInodeNum rc %d", rc1));
|
||||||
/* BB EOPNOSUPP disable SERVER_INUM? */
|
/* BB EOPNOSUPP disable SERVER_INUM? */
|
||||||
} else /* do we need cast or hash to ino? */
|
} else /* do we need cast or hash to ino? */
|
||||||
(*pinode)->i_ino = inode_num;
|
(*pinode)->i_ino = inode_num;
|
||||||
|
@ -471,7 +467,8 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||||
/* new inode, can safely set these fields */
|
/* new inode, can safely set these fields */
|
||||||
inode->i_mode = cifs_sb->mnt_file_mode;
|
inode->i_mode = cifs_sb->mnt_file_mode;
|
||||||
else /* since we set the inode type below we need to mask off
|
else /* since we set the inode type below we need to mask off
|
||||||
to avoid strange results if type changes and both get orred in */
|
to avoid strange results if type changes and both
|
||||||
|
get orred in */
|
||||||
inode->i_mode &= ~S_IFMT;
|
inode->i_mode &= ~S_IFMT;
|
||||||
/* if (attr & ATTR_REPARSE) */
|
/* if (attr & ATTR_REPARSE) */
|
||||||
/* We no longer handle these as symlinks because we could not
|
/* We no longer handle these as symlinks because we could not
|
||||||
|
@ -494,9 +491,9 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||||
le64_to_cpu(pfindData->EndOfFile),
|
le64_to_cpu(pfindData->EndOfFile),
|
||||||
search_path,
|
search_path,
|
||||||
cifs_sb, xid)) {
|
cifs_sb, xid)) {
|
||||||
cFYI(1,("Unrecognized sfu inode type"));
|
cFYI(1, ("Unrecognized sfu inode type"));
|
||||||
}
|
}
|
||||||
cFYI(1,("sfu mode 0%o",inode->i_mode));
|
cFYI(1, ("sfu mode 0%o", inode->i_mode));
|
||||||
} else {
|
} else {
|
||||||
inode->i_mode |= S_IFREG;
|
inode->i_mode |= S_IFREG;
|
||||||
/* treat the dos attribute of read-only as read-only
|
/* treat the dos attribute of read-only as read-only
|
||||||
|
@ -517,7 +514,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||||
if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) {
|
if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) {
|
||||||
/* can not safely shrink the file size here if the
|
/* can not safely shrink the file size here if the
|
||||||
client is writing to it due to potential races */
|
client is writing to it due to potential races */
|
||||||
i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
|
i_size_write(inode, le64_to_cpu(pfindData->EndOfFile));
|
||||||
|
|
||||||
/* 512 bytes (2**9) is the fake blocksize that must be
|
/* 512 bytes (2**9) is the fake blocksize that must be
|
||||||
used for this calculation */
|
used for this calculation */
|
||||||
|
@ -540,7 +537,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||||
inode->i_gid = cifs_sb->mnt_gid;
|
inode->i_gid = cifs_sb->mnt_gid;
|
||||||
/* set so we do not keep refreshing these fields with
|
/* set so we do not keep refreshing these fields with
|
||||||
bad data after user has changed them in memory */
|
bad data after user has changed them in memory */
|
||||||
atomic_set(&cifsInfo->inUse,1);
|
atomic_set(&cifsInfo->inUse, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (S_ISREG(inode->i_mode)) {
|
if (S_ISREG(inode->i_mode)) {
|
||||||
|
@ -586,10 +583,11 @@ void cifs_read_inode(struct inode *inode)
|
||||||
|
|
||||||
cifs_sb = CIFS_SB(inode->i_sb);
|
cifs_sb = CIFS_SB(inode->i_sb);
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
|
|
||||||
cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
|
if (cifs_sb->tcon->unix_ext)
|
||||||
|
cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
|
||||||
else
|
else
|
||||||
cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
|
cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
|
||||||
/* can not call macro FreeXid here since in a void func */
|
/* can not call macro FreeXid here since in a void func */
|
||||||
_FreeXid(xid);
|
_FreeXid(xid);
|
||||||
}
|
}
|
||||||
|
@ -623,9 +621,21 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((pTcon->ses->capabilities & CAP_UNIX) &&
|
||||||
|
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||||
|
le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
|
||||||
|
rc = CIFSPOSIXDelFile(xid, pTcon, full_path,
|
||||||
|
SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
|
||||||
|
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
cFYI(1, ("posix del rc %d", rc));
|
||||||
|
if ((rc == 0) || (rc == -ENOENT))
|
||||||
|
goto psx_del_no_retry;
|
||||||
|
}
|
||||||
|
|
||||||
rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
|
rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
psx_del_no_retry:
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
if (direntry->d_inode)
|
if (direntry->d_inode)
|
||||||
drop_nlink(direntry->d_inode);
|
drop_nlink(direntry->d_inode);
|
||||||
|
@ -640,7 +650,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||||
&netfid, &oplock, NULL, cifs_sb->local_nls,
|
&netfid, &oplock, NULL, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if (rc==0) {
|
if (rc == 0) {
|
||||||
CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
|
CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
|
@ -685,7 +695,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if (rc==0) {
|
if (rc == 0) {
|
||||||
rc = CIFSSMBSetFileTimes(xid, pTcon,
|
rc = CIFSSMBSetFileTimes(xid, pTcon,
|
||||||
pinfo_buf,
|
pinfo_buf,
|
||||||
netfid);
|
netfid);
|
||||||
|
@ -694,7 +704,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||||
}
|
}
|
||||||
kfree(pinfo_buf);
|
kfree(pinfo_buf);
|
||||||
}
|
}
|
||||||
if (rc==0) {
|
if (rc == 0) {
|
||||||
rc = CIFSSMBDelFile(xid, pTcon, full_path,
|
rc = CIFSSMBDelFile(xid, pTcon, full_path,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
|
@ -714,7 +724,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if (rc==0) {
|
if (rc == 0) {
|
||||||
CIFSSMBRenameOpenFile(xid, pTcon,
|
CIFSSMBRenameOpenFile(xid, pTcon,
|
||||||
netfid, NULL,
|
netfid, NULL,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
|
@ -804,11 +814,11 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
|
||||||
/* safest to just call it a file */
|
/* safest to just call it a file */
|
||||||
*pobject_type = DT_REG;
|
*pobject_type = DT_REG;
|
||||||
tmp_inode->i_mode |= S_IFREG;
|
tmp_inode->i_mode |= S_IFREG;
|
||||||
cFYI(1,("unknown inode type %d",type));
|
cFYI(1, ("unknown inode type %d", type));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_DEBUG2
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
cFYI(1,("object type: %d", type));
|
cFYI(1, ("object type: %d", type));
|
||||||
#endif
|
#endif
|
||||||
tmp_inode->i_uid = le64_to_cpu(pData->Uid);
|
tmp_inode->i_uid = le64_to_cpu(pData->Uid);
|
||||||
tmp_inode->i_gid = le64_to_cpu(pData->Gid);
|
tmp_inode->i_gid = le64_to_cpu(pData->Gid);
|
||||||
|
@ -830,27 +840,28 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
|
||||||
cFYI(1, ("File inode"));
|
cFYI(1, ("File inode"));
|
||||||
tmp_inode->i_op = &cifs_file_inode_ops;
|
tmp_inode->i_op = &cifs_file_inode_ops;
|
||||||
|
|
||||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
||||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||||
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
|
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
|
||||||
else
|
else
|
||||||
tmp_inode->i_fop = &cifs_file_direct_ops;
|
tmp_inode->i_fop = &cifs_file_direct_ops;
|
||||||
|
|
||||||
} else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||||
tmp_inode->i_fop = &cifs_file_nobrl_ops;
|
tmp_inode->i_fop = &cifs_file_nobrl_ops;
|
||||||
else
|
else
|
||||||
tmp_inode->i_fop = &cifs_file_ops;
|
tmp_inode->i_fop = &cifs_file_ops;
|
||||||
|
|
||||||
if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
|
if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
|
||||||
(cifs_sb->tcon->ses->server->maxBuf <
|
(cifs_sb->tcon->ses->server->maxBuf <
|
||||||
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
|
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
|
||||||
tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
||||||
else
|
else
|
||||||
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
||||||
|
|
||||||
if(isNewInode)
|
if (isNewInode)
|
||||||
return; /* No sense invalidating pages for new inode since we
|
return; /* No sense invalidating pages for new inode
|
||||||
have not started caching readahead file data yet */
|
since we we have not started caching
|
||||||
|
readahead file data yet */
|
||||||
|
|
||||||
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
|
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
|
||||||
(local_size == tmp_inode->i_size)) {
|
(local_size == tmp_inode->i_size)) {
|
||||||
|
@ -897,13 +908,13 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((pTcon->ses->capabilities & CAP_UNIX) &&
|
if ((pTcon->ses->capabilities & CAP_UNIX) &&
|
||||||
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||||
le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
|
le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
|
||||||
u32 oplock = 0;
|
u32 oplock = 0;
|
||||||
FILE_UNIX_BASIC_INFO * pInfo =
|
FILE_UNIX_BASIC_INFO * pInfo =
|
||||||
kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
|
kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
|
||||||
if(pInfo == NULL) {
|
if (pInfo == NULL) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto mkdir_out;
|
goto mkdir_out;
|
||||||
}
|
}
|
||||||
|
@ -920,7 +931,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||||
int obj_type;
|
int obj_type;
|
||||||
if (pInfo->Type == -1) /* no return info - go query */
|
if (pInfo->Type == -1) /* no return info - go query */
|
||||||
goto mkdir_get_info;
|
goto mkdir_get_info;
|
||||||
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need to set uid/gid */
|
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
|
||||||
|
to set uid/gid */
|
||||||
inc_nlink(inode);
|
inc_nlink(inode);
|
||||||
if (pTcon->nocase)
|
if (pTcon->nocase)
|
||||||
direntry->d_op = &cifs_ci_dentry_ops;
|
direntry->d_op = &cifs_ci_dentry_ops;
|
||||||
|
@ -937,7 +949,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||||
newinode->i_ino =
|
newinode->i_ino =
|
||||||
(unsigned long)pInfo->UniqueId;
|
(unsigned long)pInfo->UniqueId;
|
||||||
} /* note ino incremented to unique num in new_inode */
|
} /* note ino incremented to unique num in new_inode */
|
||||||
if(inode->i_sb->s_flags & MS_NOATIME)
|
if (inode->i_sb->s_flags & MS_NOATIME)
|
||||||
newinode->i_flags |= S_NOATIME | S_NOCMTIME;
|
newinode->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||||
newinode->i_nlink = 2;
|
newinode->i_nlink = 2;
|
||||||
|
|
||||||
|
@ -949,11 +961,11 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||||
posix_fill_in_inode(direntry->d_inode,
|
posix_fill_in_inode(direntry->d_inode,
|
||||||
pInfo, &obj_type, 1 /* NewInode */);
|
pInfo, &obj_type, 1 /* NewInode */);
|
||||||
#ifdef CONFIG_CIFS_DEBUG2
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
cFYI(1,("instantiated dentry %p %s to inode %p",
|
cFYI(1, ("instantiated dentry %p %s to inode %p",
|
||||||
direntry, direntry->d_name.name, newinode));
|
direntry, direntry->d_name.name, newinode));
|
||||||
|
|
||||||
if(newinode->i_nlink != 2)
|
if (newinode->i_nlink != 2)
|
||||||
cFYI(1,("unexpected number of links %d",
|
cFYI(1, ("unexpected number of links %d",
|
||||||
newinode->i_nlink));
|
newinode->i_nlink));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -970,12 +982,12 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||||
} else {
|
} else {
|
||||||
mkdir_get_info:
|
mkdir_get_info:
|
||||||
inc_nlink(inode);
|
inc_nlink(inode);
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
||||||
inode->i_sb,xid);
|
inode->i_sb, xid);
|
||||||
else
|
else
|
||||||
rc = cifs_get_inode_info(&newinode, full_path, NULL,
|
rc = cifs_get_inode_info(&newinode, full_path, NULL,
|
||||||
inode->i_sb,xid);
|
inode->i_sb, xid);
|
||||||
|
|
||||||
if (pTcon->nocase)
|
if (pTcon->nocase)
|
||||||
direntry->d_op = &cifs_ci_dentry_ops;
|
direntry->d_op = &cifs_ci_dentry_ops;
|
||||||
|
@ -986,7 +998,7 @@ mkdir_get_info:
|
||||||
* failed to get it from the server or was set bogus */
|
* failed to get it from the server or was set bogus */
|
||||||
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
|
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
|
||||||
direntry->d_inode->i_nlink = 2;
|
direntry->d_inode->i_nlink = 2;
|
||||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
|
if (pTcon->unix_ext) {
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current->fs->umask;
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||||
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
||||||
|
@ -1009,10 +1021,10 @@ mkdir_get_info:
|
||||||
/* BB to be implemented via Windows secrty descriptors
|
/* BB to be implemented via Windows secrty descriptors
|
||||||
eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
|
eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
|
||||||
-1, -1, local_nls); */
|
-1, -1, local_nls); */
|
||||||
if(direntry->d_inode) {
|
if (direntry->d_inode) {
|
||||||
direntry->d_inode->i_mode = mode;
|
direntry->d_inode->i_mode = mode;
|
||||||
direntry->d_inode->i_mode |= S_IFDIR;
|
direntry->d_inode->i_mode |= S_IFDIR;
|
||||||
if(cifs_sb->mnt_cifs_flags &
|
if (cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_SET_UID) {
|
CIFS_MOUNT_SET_UID) {
|
||||||
direntry->d_inode->i_uid =
|
direntry->d_inode->i_uid =
|
||||||
current->fsuid;
|
current->fsuid;
|
||||||
|
@ -1056,7 +1068,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
drop_nlink(inode);
|
drop_nlink(inode);
|
||||||
spin_lock(&direntry->d_inode->i_lock);
|
spin_lock(&direntry->d_inode->i_lock);
|
||||||
i_size_write(direntry->d_inode,0);
|
i_size_write(direntry->d_inode, 0);
|
||||||
clear_nlink(direntry->d_inode);
|
clear_nlink(direntry->d_inode);
|
||||||
spin_unlock(&direntry->d_inode->i_lock);
|
spin_unlock(&direntry->d_inode->i_lock);
|
||||||
}
|
}
|
||||||
|
@ -1119,7 +1131,7 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
|
||||||
kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
|
kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
|
||||||
if (info_buf_source != NULL) {
|
if (info_buf_source != NULL) {
|
||||||
info_buf_target = info_buf_source + 1;
|
info_buf_target = info_buf_source + 1;
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
|
rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
|
||||||
info_buf_source,
|
info_buf_source,
|
||||||
cifs_sb_source->local_nls,
|
cifs_sb_source->local_nls,
|
||||||
|
@ -1174,7 +1186,7 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
|
||||||
cifs_sb_source->local_nls,
|
cifs_sb_source->local_nls,
|
||||||
cifs_sb_source->mnt_cifs_flags &
|
cifs_sb_source->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if (rc==0) {
|
if (rc == 0) {
|
||||||
rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
|
rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
|
||||||
cifs_sb_source->local_nls,
|
cifs_sb_source->local_nls,
|
||||||
cifs_sb_source->mnt_cifs_flags &
|
cifs_sb_source->mnt_cifs_flags &
|
||||||
|
@ -1247,9 +1259,9 @@ int cifs_revalidate(struct dentry *direntry)
|
||||||
local_mtime = direntry->d_inode->i_mtime;
|
local_mtime = direntry->d_inode->i_mtime;
|
||||||
local_size = direntry->d_inode->i_size;
|
local_size = direntry->d_inode->i_size;
|
||||||
|
|
||||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
|
if (cifs_sb->tcon->unix_ext) {
|
||||||
rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
|
rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
|
||||||
direntry->d_sb,xid);
|
direntry->d_sb, xid);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cFYI(1, ("error on getting revalidate info %d", rc));
|
cFYI(1, ("error on getting revalidate info %d", rc));
|
||||||
/* if (rc != -ENOENT)
|
/* if (rc != -ENOENT)
|
||||||
|
@ -1258,7 +1270,7 @@ int cifs_revalidate(struct dentry *direntry)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
|
rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
|
||||||
direntry->d_sb,xid);
|
direntry->d_sb, xid);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cFYI(1, ("error on getting revalidate info %d", rc));
|
cFYI(1, ("error on getting revalidate info %d", rc));
|
||||||
/* if (rc != -ENOENT)
|
/* if (rc != -ENOENT)
|
||||||
|
@ -1271,7 +1283,7 @@ int cifs_revalidate(struct dentry *direntry)
|
||||||
/* if not oplocked, we invalidate inode pages if mtime or file size
|
/* if not oplocked, we invalidate inode pages if mtime or file size
|
||||||
had changed on server */
|
had changed on server */
|
||||||
|
|
||||||
if (timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) &&
|
if (timespec_equal(&local_mtime, &direntry->d_inode->i_mtime) &&
|
||||||
(local_size == direntry->d_inode->i_size)) {
|
(local_size == direntry->d_inode->i_size)) {
|
||||||
cFYI(1, ("cifs_revalidate - inode unchanged"));
|
cFYI(1, ("cifs_revalidate - inode unchanged"));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1298,7 +1310,7 @@ int cifs_revalidate(struct dentry *direntry)
|
||||||
if (invalidate_inode) {
|
if (invalidate_inode) {
|
||||||
/* shrink_dcache not necessary now that cifs dentry ops
|
/* shrink_dcache not necessary now that cifs dentry ops
|
||||||
are exported for negative dentries */
|
are exported for negative dentries */
|
||||||
/* if(S_ISDIR(direntry->d_inode->i_mode))
|
/* if (S_ISDIR(direntry->d_inode->i_mode))
|
||||||
shrink_dcache_parent(direntry); */
|
shrink_dcache_parent(direntry); */
|
||||||
if (S_ISREG(direntry->d_inode->i_mode)) {
|
if (S_ISREG(direntry->d_inode->i_mode)) {
|
||||||
if (direntry->d_inode->i_mapping)
|
if (direntry->d_inode->i_mapping)
|
||||||
|
@ -1335,23 +1347,19 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
|
||||||
pgoff_t index = from >> PAGE_CACHE_SHIFT;
|
pgoff_t index = from >> PAGE_CACHE_SHIFT;
|
||||||
unsigned offset = from & (PAGE_CACHE_SIZE - 1);
|
unsigned offset = from & (PAGE_CACHE_SIZE - 1);
|
||||||
struct page *page;
|
struct page *page;
|
||||||
char *kaddr;
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
page = grab_cache_page(mapping, index);
|
page = grab_cache_page(mapping, index);
|
||||||
if (!page)
|
if (!page)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
kaddr = kmap_atomic(page, KM_USER0);
|
zero_user_page(page, offset, PAGE_CACHE_SIZE - offset, KM_USER0);
|
||||||
memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
|
|
||||||
flush_dcache_page(page);
|
|
||||||
kunmap_atomic(kaddr, KM_USER0);
|
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
page_cache_release(page);
|
page_cache_release(page);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cifs_vmtruncate(struct inode * inode, loff_t offset)
|
static int cifs_vmtruncate(struct inode *inode, loff_t offset)
|
||||||
{
|
{
|
||||||
struct address_space *mapping = inode->i_mapping;
|
struct address_space *mapping = inode->i_mapping;
|
||||||
unsigned long limit;
|
unsigned long limit;
|
||||||
|
@ -1424,7 +1432,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
|
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
|
||||||
/* check if we have permission to change attrs */
|
/* check if we have permission to change attrs */
|
||||||
rc = inode_change_ok(direntry->d_inode, attrs);
|
rc = inode_change_ok(direntry->d_inode, attrs);
|
||||||
if(rc < 0) {
|
if (rc < 0) {
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return rc;
|
return rc;
|
||||||
} else
|
} else
|
||||||
|
@ -1459,14 +1467,14 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||||
rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
|
rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
|
||||||
nfid, npid, FALSE);
|
nfid, npid, FALSE);
|
||||||
atomic_dec(&open_file->wrtPending);
|
atomic_dec(&open_file->wrtPending);
|
||||||
cFYI(1,("SetFSize for attrs rc = %d", rc));
|
cFYI(1, ("SetFSize for attrs rc = %d", rc));
|
||||||
if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
||||||
int bytes_written;
|
int bytes_written;
|
||||||
rc = CIFSSMBWrite(xid, pTcon,
|
rc = CIFSSMBWrite(xid, pTcon,
|
||||||
nfid, 0, attrs->ia_size,
|
nfid, 0, attrs->ia_size,
|
||||||
&bytes_written, NULL, NULL,
|
&bytes_written, NULL, NULL,
|
||||||
1 /* 45 seconds */);
|
1 /* 45 seconds */);
|
||||||
cFYI(1,("Wrt seteof rc %d", rc));
|
cFYI(1, ("Wrt seteof rc %d", rc));
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
|
@ -1482,7 +1490,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
|
cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
|
||||||
if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
||||||
__u16 netfid;
|
__u16 netfid;
|
||||||
int oplock = FALSE;
|
int oplock = FALSE;
|
||||||
|
|
||||||
|
@ -1493,14 +1501,14 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||||
NULL, cifs_sb->local_nls,
|
NULL, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if (rc==0) {
|
if (rc == 0) {
|
||||||
int bytes_written;
|
int bytes_written;
|
||||||
rc = CIFSSMBWrite(xid, pTcon,
|
rc = CIFSSMBWrite(xid, pTcon,
|
||||||
netfid, 0,
|
netfid, 0,
|
||||||
attrs->ia_size,
|
attrs->ia_size,
|
||||||
&bytes_written, NULL,
|
&bytes_written, NULL,
|
||||||
NULL, 1 /* 45 sec */);
|
NULL, 1 /* 45 sec */);
|
||||||
cFYI(1,("wrt seteof rc %d",rc));
|
cFYI(1, ("wrt seteof rc %d", rc));
|
||||||
CIFSSMBClose(xid, pTcon, netfid);
|
CIFSSMBClose(xid, pTcon, netfid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1535,7 +1543,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||||
mode = attrs->ia_mode;
|
mode = attrs->ia_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
|
if ((pTcon->unix_ext)
|
||||||
&& (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
|
&& (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
|
||||||
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
|
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
|
||||||
0 /* dev_t */, cifs_sb->local_nls,
|
0 /* dev_t */, cifs_sb->local_nls,
|
||||||
|
@ -1559,7 +1567,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||||
time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs &
|
time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs &
|
||||||
(~ATTR_READONLY));
|
(~ATTR_READONLY));
|
||||||
/* Windows ignores set to zero */
|
/* Windows ignores set to zero */
|
||||||
if(time_buf.Attributes == 0)
|
if (time_buf.Attributes == 0)
|
||||||
time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL);
|
time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL);
|
||||||
}
|
}
|
||||||
/* BB to be implemented -
|
/* BB to be implemented -
|
||||||
|
@ -1624,7 +1632,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||||
NULL, cifs_sb->local_nls,
|
NULL, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if (rc==0) {
|
if (rc == 0) {
|
||||||
rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
|
rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
|
||||||
netfid);
|
netfid);
|
||||||
CIFSSMBClose(xid, pTcon, netfid);
|
CIFSSMBClose(xid, pTcon, netfid);
|
||||||
|
@ -1642,7 +1650,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||||
and this check ensures that we are not being called from
|
and this check ensures that we are not being called from
|
||||||
sys_utimes in which case we ought to fail the call back to
|
sys_utimes in which case we ought to fail the call back to
|
||||||
the user when the server rejects the call */
|
the user when the server rejects the call */
|
||||||
if((rc) && (attrs->ia_valid &
|
if ((rc) && (attrs->ia_valid &
|
||||||
(ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
|
(ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
|
||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* vfs operations that deal with io control
|
* vfs operations that deal with io control
|
||||||
*
|
*
|
||||||
* Copyright (C) International Business Machines Corp., 2005
|
* Copyright (C) International Business Machines Corp., 2005,2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
|
#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
|
||||||
|
|
||||||
int cifs_ioctl (struct inode * inode, struct file * filep,
|
int cifs_ioctl (struct inode *inode, struct file *filep,
|
||||||
unsigned int command, unsigned long arg)
|
unsigned int command, unsigned long arg)
|
||||||
{
|
{
|
||||||
int rc = -ENOTTY; /* strange error - but the precedent */
|
int rc = -ENOTTY; /* strange error - but the precedent */
|
||||||
|
|
|
@ -50,12 +50,13 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
||||||
|
|
||||||
fromName = build_path_from_dentry(old_file);
|
fromName = build_path_from_dentry(old_file);
|
||||||
toName = build_path_from_dentry(direntry);
|
toName = build_path_from_dentry(direntry);
|
||||||
if((fromName == NULL) || (toName == NULL)) {
|
if ((fromName == NULL) || (toName == NULL)) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto cifs_hl_exit;
|
goto cifs_hl_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
|
/* if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)*/
|
||||||
|
if (pTcon->unix_ext)
|
||||||
rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
|
rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
|
||||||
cifs_sb_target->local_nls,
|
cifs_sb_target->local_nls,
|
||||||
cifs_sb_target->mnt_cifs_flags &
|
cifs_sb_target->mnt_cifs_flags &
|
||||||
|
@ -65,7 +66,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
||||||
cifs_sb_target->local_nls,
|
cifs_sb_target->local_nls,
|
||||||
cifs_sb_target->mnt_cifs_flags &
|
cifs_sb_target->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if((rc == -EIO) || (rc == -EINVAL))
|
if ((rc == -EIO) || (rc == -EINVAL))
|
||||||
rc = -EOPNOTSUPP;
|
rc = -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,9 +74,9 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
||||||
|
|
||||||
/* if source file is cached (oplocked) revalidate will not go to server
|
/* if source file is cached (oplocked) revalidate will not go to server
|
||||||
until the file is closed or oplock broken so update nlinks locally */
|
until the file is closed or oplock broken so update nlinks locally */
|
||||||
if(old_file->d_inode) {
|
if (old_file->d_inode) {
|
||||||
cifsInode = CIFS_I(old_file->d_inode);
|
cifsInode = CIFS_I(old_file->d_inode);
|
||||||
if(rc == 0) {
|
if (rc == 0) {
|
||||||
old_file->d_inode->i_nlink++;
|
old_file->d_inode->i_nlink++;
|
||||||
/* BB should we make this contingent on superblock flag NOATIME? */
|
/* BB should we make this contingent on superblock flag NOATIME? */
|
||||||
/* old_file->d_inode->i_ctime = CURRENT_TIME;*/
|
/* old_file->d_inode->i_ctime = CURRENT_TIME;*/
|
||||||
|
@ -109,7 +110,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
|
||||||
int rc = -EACCES;
|
int rc = -EACCES;
|
||||||
int xid;
|
int xid;
|
||||||
char *full_path = NULL;
|
char *full_path = NULL;
|
||||||
char * target_path = ERR_PTR(-ENOMEM);
|
char *target_path = ERR_PTR(-ENOMEM);
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
|
|
||||||
|
@ -129,13 +130,19 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
|
/* We could change this to:
|
||||||
|
if (pTcon->unix_ext)
|
||||||
|
but there does not seem any point in refusing to
|
||||||
|
get symlink info if we can, even if unix extensions
|
||||||
|
turned off for this mount */
|
||||||
|
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->ses->capabilities & CAP_UNIX)
|
||||||
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
|
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
|
||||||
target_path,
|
target_path,
|
||||||
PATH_MAX-1,
|
PATH_MAX-1,
|
||||||
cifs_sb->local_nls);
|
cifs_sb->local_nls);
|
||||||
else {
|
else {
|
||||||
|
/* BB add read reparse point symlink code here */
|
||||||
/* rc = CIFSSMBQueryReparseLinkInfo */
|
/* rc = CIFSSMBQueryReparseLinkInfo */
|
||||||
/* BB Add code to Query ReparsePoint info */
|
/* BB Add code to Query ReparsePoint info */
|
||||||
/* BB Add MAC style xsymlink check here if enabled */
|
/* BB Add MAC style xsymlink check here if enabled */
|
||||||
|
@ -176,7 +183,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
|
||||||
|
|
||||||
full_path = build_path_from_dentry(direntry);
|
full_path = build_path_from_dentry(direntry);
|
||||||
|
|
||||||
if(full_path == NULL) {
|
if (full_path == NULL) {
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -185,19 +192,20 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
|
||||||
cFYI(1, ("symname is %s", symname));
|
cFYI(1, ("symname is %s", symname));
|
||||||
|
|
||||||
/* BB what if DFS and this volume is on different share? BB */
|
/* BB what if DFS and this volume is on different share? BB */
|
||||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
|
rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
|
||||||
cifs_sb->local_nls);
|
cifs_sb->local_nls);
|
||||||
/* else
|
/* else
|
||||||
rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */
|
rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,
|
||||||
|
cifs_sb_target->local_nls); */
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
||||||
inode->i_sb,xid);
|
inode->i_sb, xid);
|
||||||
else
|
else
|
||||||
rc = cifs_get_inode_info(&newinode, full_path, NULL,
|
rc = cifs_get_inode_info(&newinode, full_path, NULL,
|
||||||
inode->i_sb,xid);
|
inode->i_sb, xid);
|
||||||
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d",
|
cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d",
|
||||||
|
@ -227,8 +235,8 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
char *full_path = NULL;
|
char *full_path = NULL;
|
||||||
char *tmp_path = NULL;
|
char *tmp_path = NULL;
|
||||||
char * tmpbuffer;
|
char *tmpbuffer;
|
||||||
unsigned char * referrals = NULL;
|
unsigned char *referrals = NULL;
|
||||||
int num_referrals = 0;
|
int num_referrals = 0;
|
||||||
int len;
|
int len;
|
||||||
__u16 fid;
|
__u16 fid;
|
||||||
|
@ -243,7 +251,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
|
||||||
full_path = build_path_from_dentry(direntry);
|
full_path = build_path_from_dentry(direntry);
|
||||||
/* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/
|
/* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/
|
||||||
|
|
||||||
if(full_path == NULL) {
|
if (full_path == NULL) {
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -251,70 +259,80 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
|
("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
|
||||||
full_path, inode, pBuffer, buflen));
|
full_path, inode, pBuffer, buflen));
|
||||||
if(buflen > PATH_MAX)
|
if (buflen > PATH_MAX)
|
||||||
len = PATH_MAX;
|
len = PATH_MAX;
|
||||||
else
|
else
|
||||||
len = buflen;
|
len = buflen;
|
||||||
tmpbuffer = kmalloc(len,GFP_KERNEL);
|
tmpbuffer = kmalloc(len, GFP_KERNEL);
|
||||||
if(tmpbuffer == NULL) {
|
if (tmpbuffer == NULL) {
|
||||||
kfree(full_path);
|
kfree(full_path);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
|
/* BB add read reparse point symlink code and
|
||||||
|
Unix extensions symlink code here BB */
|
||||||
|
/* We could disable this based on pTcon->unix_ext flag instead ... but why? */
|
||||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
|
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
|
||||||
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
|
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
|
||||||
tmpbuffer,
|
tmpbuffer,
|
||||||
len - 1,
|
len - 1,
|
||||||
cifs_sb->local_nls);
|
cifs_sb->local_nls);
|
||||||
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||||
cERROR(1,("SFU style symlinks not implemented yet"));
|
cERROR(1, ("SFU style symlinks not implemented yet"));
|
||||||
/* add open and read as in fs/cifs/inode.c */
|
/* add open and read as in fs/cifs/inode.c */
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
|
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
|
||||||
OPEN_REPARSE_POINT,&fid, &oplock, NULL,
|
OPEN_REPARSE_POINT, &fid, &oplock, NULL,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if(!rc) {
|
if (!rc) {
|
||||||
rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
|
rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
|
||||||
tmpbuffer,
|
tmpbuffer,
|
||||||
len - 1,
|
len - 1,
|
||||||
fid,
|
fid,
|
||||||
cifs_sb->local_nls);
|
cifs_sb->local_nls);
|
||||||
if(CIFSSMBClose(xid, pTcon, fid)) {
|
if (CIFSSMBClose(xid, pTcon, fid)) {
|
||||||
cFYI(1,("Error closing junction point (open for ioctl)"));
|
cFYI(1, ("Error closing junction point "
|
||||||
|
"(open for ioctl)"));
|
||||||
}
|
}
|
||||||
if(rc == -EIO) {
|
if (rc == -EIO) {
|
||||||
/* Query if DFS Junction */
|
/* Query if DFS Junction */
|
||||||
tmp_path =
|
tmp_path =
|
||||||
kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
|
kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (tmp_path) {
|
if (tmp_path) {
|
||||||
strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
|
strncpy(tmp_path, pTcon->treeName,
|
||||||
strncat(tmp_path, full_path, MAX_PATHCONF);
|
MAX_TREE_SIZE);
|
||||||
rc = get_dfs_path(xid, pTcon->ses, tmp_path,
|
strncat(tmp_path, full_path,
|
||||||
|
MAX_PATHCONF);
|
||||||
|
rc = get_dfs_path(xid, pTcon->ses,
|
||||||
|
tmp_path,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
&num_referrals, &referrals,
|
&num_referrals, &referrals,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
|
cFYI(1, ("Get DFS for %s rc = %d ",
|
||||||
if((num_referrals == 0) && (rc == 0))
|
tmp_path, rc));
|
||||||
|
if ((num_referrals == 0) && (rc == 0))
|
||||||
rc = -EACCES;
|
rc = -EACCES;
|
||||||
else {
|
else {
|
||||||
cFYI(1,("num referral: %d",num_referrals));
|
cFYI(1, ("num referral: %d",
|
||||||
if(referrals) {
|
num_referrals));
|
||||||
cFYI(1,("referral string: %s",referrals));
|
if (referrals) {
|
||||||
strncpy(tmpbuffer, referrals, len-1);
|
cFYI(1,("referral string: %s", referrals));
|
||||||
|
strncpy(tmpbuffer,
|
||||||
|
referrals,
|
||||||
|
len-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kfree(referrals);
|
kfree(referrals);
|
||||||
kfree(tmp_path);
|
kfree(tmp_path);
|
||||||
}
|
}
|
||||||
/* BB add code like else decode referrals then memcpy to
|
/* BB add code like else decode referrals
|
||||||
tmpbuffer and free referrals string array BB */
|
then memcpy to tmpbuffer and free referrals
|
||||||
|
string array BB */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ mdfour(unsigned char *out, unsigned char *in, int n)
|
||||||
|
|
||||||
while (n > 64) {
|
while (n > 64) {
|
||||||
copy64(M, in);
|
copy64(M, in);
|
||||||
mdfour64(M,&A,&B, &C, &D);
|
mdfour64(M, &A, &B, &C, &D);
|
||||||
in += 64;
|
in += 64;
|
||||||
n -= 64;
|
n -= 64;
|
||||||
}
|
}
|
||||||
|
|
159
fs/cifs/misc.c
159
fs/cifs/misc.c
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/misc.c
|
* fs/cifs/misc.c
|
||||||
*
|
*
|
||||||
* Copyright (C) International Business Machines Corp., 2002,2005
|
* Copyright (C) International Business Machines Corp., 2002,2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
extern mempool_t *cifs_sm_req_poolp;
|
extern mempool_t *cifs_sm_req_poolp;
|
||||||
extern mempool_t *cifs_req_poolp;
|
extern mempool_t *cifs_req_poolp;
|
||||||
extern struct task_struct * oplockThread;
|
extern struct task_struct *oplockThread;
|
||||||
|
|
||||||
/* The xid serves as a useful identifier for each incoming vfs request,
|
/* The xid serves as a useful identifier for each incoming vfs request,
|
||||||
in a similar way to the mid which is useful to track each sent smb,
|
in a similar way to the mid which is useful to track each sent smb,
|
||||||
|
@ -47,10 +47,12 @@ _GetXid(void)
|
||||||
|
|
||||||
spin_lock(&GlobalMid_Lock);
|
spin_lock(&GlobalMid_Lock);
|
||||||
GlobalTotalActiveXid++;
|
GlobalTotalActiveXid++;
|
||||||
|
|
||||||
|
/* keep high water mark for number of simultaneous ops in filesystem */
|
||||||
if (GlobalTotalActiveXid > GlobalMaxActiveXid)
|
if (GlobalTotalActiveXid > GlobalMaxActiveXid)
|
||||||
GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */
|
GlobalMaxActiveXid = GlobalTotalActiveXid;
|
||||||
if(GlobalTotalActiveXid > 65000)
|
if (GlobalTotalActiveXid > 65000)
|
||||||
cFYI(1,("warning: more than 65000 requests active"));
|
cFYI(1, ("warning: more than 65000 requests active"));
|
||||||
xid = GlobalCurrentXid++;
|
xid = GlobalCurrentXid++;
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
return xid;
|
return xid;
|
||||||
|
@ -60,7 +62,7 @@ void
|
||||||
_FreeXid(unsigned int xid)
|
_FreeXid(unsigned int xid)
|
||||||
{
|
{
|
||||||
spin_lock(&GlobalMid_Lock);
|
spin_lock(&GlobalMid_Lock);
|
||||||
/* if(GlobalTotalActiveXid == 0)
|
/* if (GlobalTotalActiveXid == 0)
|
||||||
BUG(); */
|
BUG(); */
|
||||||
GlobalTotalActiveXid--;
|
GlobalTotalActiveXid--;
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
|
@ -148,8 +150,8 @@ cifs_buf_get(void)
|
||||||
but it may be more efficient to always alloc same size
|
but it may be more efficient to always alloc same size
|
||||||
albeit slightly larger than necessary and maxbuffersize
|
albeit slightly larger than necessary and maxbuffersize
|
||||||
defaults to this and can not be bigger */
|
defaults to this and can not be bigger */
|
||||||
ret_buf =
|
ret_buf = (struct smb_hdr *) mempool_alloc(cifs_req_poolp,
|
||||||
(struct smb_hdr *) mempool_alloc(cifs_req_poolp, GFP_KERNEL | GFP_NOFS);
|
GFP_KERNEL | GFP_NOFS);
|
||||||
|
|
||||||
/* clear the first few header bytes */
|
/* clear the first few header bytes */
|
||||||
/* for most paths, more is cleared in header_assemble */
|
/* for most paths, more is cleared in header_assemble */
|
||||||
|
@ -172,7 +174,7 @@ cifs_buf_release(void *buf_to_free)
|
||||||
/* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
|
/* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mempool_free(buf_to_free,cifs_req_poolp);
|
mempool_free(buf_to_free, cifs_req_poolp);
|
||||||
|
|
||||||
atomic_dec(&bufAllocCount);
|
atomic_dec(&bufAllocCount);
|
||||||
return;
|
return;
|
||||||
|
@ -187,8 +189,8 @@ cifs_small_buf_get(void)
|
||||||
but it may be more efficient to always alloc same size
|
but it may be more efficient to always alloc same size
|
||||||
albeit slightly larger than necessary and maxbuffersize
|
albeit slightly larger than necessary and maxbuffersize
|
||||||
defaults to this and can not be bigger */
|
defaults to this and can not be bigger */
|
||||||
ret_buf =
|
ret_buf = (struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp,
|
||||||
(struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp, GFP_KERNEL | GFP_NOFS);
|
GFP_KERNEL | GFP_NOFS);
|
||||||
if (ret_buf) {
|
if (ret_buf) {
|
||||||
/* No need to clear memory here, cleared in header assemble */
|
/* No need to clear memory here, cleared in header assemble */
|
||||||
/* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
|
/* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
|
||||||
|
@ -209,7 +211,7 @@ cifs_small_buf_release(void *buf_to_free)
|
||||||
cFYI(1, ("Null buffer passed to cifs_small_buf_release"));
|
cFYI(1, ("Null buffer passed to cifs_small_buf_release"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mempool_free(buf_to_free,cifs_sm_req_poolp);
|
mempool_free(buf_to_free, cifs_sm_req_poolp);
|
||||||
|
|
||||||
atomic_dec(&smBufAllocCount);
|
atomic_dec(&smBufAllocCount);
|
||||||
return;
|
return;
|
||||||
|
@ -242,7 +244,7 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
|
||||||
__u16 last_mid;
|
__u16 last_mid;
|
||||||
int collision;
|
int collision;
|
||||||
|
|
||||||
if(server == NULL)
|
if (server == NULL)
|
||||||
return mid;
|
return mid;
|
||||||
|
|
||||||
spin_lock(&GlobalMid_Lock);
|
spin_lock(&GlobalMid_Lock);
|
||||||
|
@ -255,12 +257,12 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
|
||||||
takes longer than the 64 thousand requests before it
|
takes longer than the 64 thousand requests before it
|
||||||
(and it would also have to have been a request that
|
(and it would also have to have been a request that
|
||||||
did not time out) */
|
did not time out) */
|
||||||
while(server->CurrentMid != last_mid) {
|
while (server->CurrentMid != last_mid) {
|
||||||
struct list_head *tmp;
|
struct list_head *tmp;
|
||||||
struct mid_q_entry *mid_entry;
|
struct mid_q_entry *mid_entry;
|
||||||
|
|
||||||
collision = 0;
|
collision = 0;
|
||||||
if(server->CurrentMid == 0)
|
if (server->CurrentMid == 0)
|
||||||
server->CurrentMid++;
|
server->CurrentMid++;
|
||||||
|
|
||||||
list_for_each(tmp, &server->pending_mid_q) {
|
list_for_each(tmp, &server->pending_mid_q) {
|
||||||
|
@ -273,7 +275,7 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(collision == 0) {
|
if (collision == 0) {
|
||||||
mid = server->CurrentMid;
|
mid = server->CurrentMid;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -290,11 +292,11 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
||||||
const struct cifsTconInfo *treeCon, int word_count
|
const struct cifsTconInfo *treeCon, int word_count
|
||||||
/* length of fixed section (word count) in two byte units */)
|
/* length of fixed section (word count) in two byte units */)
|
||||||
{
|
{
|
||||||
struct list_head* temp_item;
|
struct list_head *temp_item;
|
||||||
struct cifsSesInfo * ses;
|
struct cifsSesInfo *ses;
|
||||||
char *temp = (char *) buffer;
|
char *temp = (char *) buffer;
|
||||||
|
|
||||||
memset(temp,0,256); /* bigger than MAX_CIFS_HDR_SIZE */
|
memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */
|
||||||
|
|
||||||
buffer->smb_buf_length =
|
buffer->smb_buf_length =
|
||||||
(2 * word_count) + sizeof (struct smb_hdr) -
|
(2 * word_count) + sizeof (struct smb_hdr) -
|
||||||
|
@ -325,7 +327,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
||||||
/* Uid is not converted */
|
/* Uid is not converted */
|
||||||
buffer->Uid = treeCon->ses->Suid;
|
buffer->Uid = treeCon->ses->Suid;
|
||||||
buffer->Mid = GetNextMid(treeCon->ses->server);
|
buffer->Mid = GetNextMid(treeCon->ses->server);
|
||||||
if(multiuser_mount != 0) {
|
if (multiuser_mount != 0) {
|
||||||
/* For the multiuser case, there are few obvious technically */
|
/* For the multiuser case, there are few obvious technically */
|
||||||
/* possible mechanisms to match the local linux user (uid) */
|
/* possible mechanisms to match the local linux user (uid) */
|
||||||
/* to a valid remote smb user (smb_uid): */
|
/* to a valid remote smb user (smb_uid): */
|
||||||
|
@ -350,19 +352,20 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
||||||
/* BB Add support for establishing new tCon and SMB Session */
|
/* BB Add support for establishing new tCon and SMB Session */
|
||||||
/* with userid/password pairs found on the smb session */
|
/* with userid/password pairs found on the smb session */
|
||||||
/* for other target tcp/ip addresses BB */
|
/* for other target tcp/ip addresses BB */
|
||||||
if(current->fsuid != treeCon->ses->linux_uid) {
|
if (current->fsuid != treeCon->ses->linux_uid) {
|
||||||
cFYI(1,("Multiuser mode and UID did not match tcon uid"));
|
cFYI(1, ("Multiuser mode and UID "
|
||||||
|
"did not match tcon uid"));
|
||||||
read_lock(&GlobalSMBSeslock);
|
read_lock(&GlobalSMBSeslock);
|
||||||
list_for_each(temp_item, &GlobalSMBSessionList) {
|
list_for_each(temp_item, &GlobalSMBSessionList) {
|
||||||
ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
|
ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
|
||||||
if(ses->linux_uid == current->fsuid) {
|
if (ses->linux_uid == current->fsuid) {
|
||||||
if(ses->server == treeCon->ses->server) {
|
if (ses->server == treeCon->ses->server) {
|
||||||
cFYI(1,("found matching uid substitute right smb_uid"));
|
cFYI(1, ("found matching uid substitute right smb_uid"));
|
||||||
buffer->Uid = ses->Suid;
|
buffer->Uid = ses->Suid;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
/* BB eventually call cifs_setup_session here */
|
/* BB eventually call cifs_setup_session here */
|
||||||
cFYI(1,("local UID found but smb sess with this server does not exist"));
|
cFYI(1, ("local UID found but no smb sess with this server exists"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,8 +377,8 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
||||||
buffer->Flags2 |= SMBFLG2_DFS;
|
buffer->Flags2 |= SMBFLG2_DFS;
|
||||||
if (treeCon->nocase)
|
if (treeCon->nocase)
|
||||||
buffer->Flags |= SMBFLG_CASELESS;
|
buffer->Flags |= SMBFLG_CASELESS;
|
||||||
if((treeCon->ses) && (treeCon->ses->server))
|
if ((treeCon->ses) && (treeCon->ses->server))
|
||||||
if(treeCon->ses->server->secMode &
|
if (treeCon->ses->server->secMode &
|
||||||
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
||||||
buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
||||||
}
|
}
|
||||||
|
@ -392,14 +395,14 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
|
||||||
and that the message ids match */
|
and that the message ids match */
|
||||||
if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
|
if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
|
||||||
(mid == smb->Mid)) {
|
(mid == smb->Mid)) {
|
||||||
if(smb->Flags & SMBFLG_RESPONSE)
|
if (smb->Flags & SMBFLG_RESPONSE)
|
||||||
return 0;
|
return 0;
|
||||||
else {
|
else {
|
||||||
/* only one valid case where server sends us request */
|
/* only one valid case where server sends us request */
|
||||||
if(smb->Command == SMB_COM_LOCKING_ANDX)
|
if (smb->Command == SMB_COM_LOCKING_ANDX)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
cERROR(1, ("Rcvd Request not response"));
|
cERROR(1, ("Received Request not response"));
|
||||||
}
|
}
|
||||||
} else { /* bad signature or mid */
|
} else { /* bad signature or mid */
|
||||||
if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
|
if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
|
||||||
|
@ -428,7 +431,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((length == sizeof(struct smb_hdr) + 1) &&
|
} else if ((length == sizeof(struct smb_hdr) + 1) &&
|
||||||
(smb->WordCount == 0)) {
|
(smb->WordCount == 0)) {
|
||||||
char * tmp = (char *)smb;
|
char *tmp = (char *)smb;
|
||||||
/* Need to work around a bug in two servers here */
|
/* Need to work around a bug in two servers here */
|
||||||
/* First, check if the part of bcc they sent was zero */
|
/* First, check if the part of bcc they sent was zero */
|
||||||
if (tmp[sizeof(struct smb_hdr)] == 0) {
|
if (tmp[sizeof(struct smb_hdr)] == 0) {
|
||||||
|
@ -442,7 +445,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
|
||||||
tmp[sizeof(struct smb_hdr)+1] = 0;
|
tmp[sizeof(struct smb_hdr)+1] = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
cERROR(1,("rcvd invalid byte count (bcc)"));
|
cERROR(1, ("rcvd invalid byte count (bcc)"));
|
||||||
} else {
|
} else {
|
||||||
cERROR(1, ("Length less than smb header size"));
|
cERROR(1, ("Length less than smb header size"));
|
||||||
}
|
}
|
||||||
|
@ -458,16 +461,17 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
|
||||||
return 1;
|
return 1;
|
||||||
clc_len = smbCalcSize_LE(smb);
|
clc_len = smbCalcSize_LE(smb);
|
||||||
|
|
||||||
if(4 + len != length) {
|
if (4 + len != length) {
|
||||||
cERROR(1, ("Length read does not match RFC1001 length %d",len));
|
cERROR(1, ("Length read does not match RFC1001 length %d",
|
||||||
|
len));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (4 + len != clc_len) {
|
if (4 + len != clc_len) {
|
||||||
/* check if bcc wrapped around for large read responses */
|
/* check if bcc wrapped around for large read responses */
|
||||||
if((len > 64 * 1024) && (len > clc_len)) {
|
if ((len > 64 * 1024) && (len > clc_len)) {
|
||||||
/* check if lengths match mod 64K */
|
/* check if lengths match mod 64K */
|
||||||
if(((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
|
if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
|
||||||
return 0; /* bcc wrapped */
|
return 0; /* bcc wrapped */
|
||||||
}
|
}
|
||||||
cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d",
|
cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d",
|
||||||
|
@ -483,7 +487,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
|
||||||
but server says length is 0x21 bytes too long as if the server
|
but server says length is 0x21 bytes too long as if the server
|
||||||
forget to reset the smb rfc1001 length when it reset the
|
forget to reset the smb rfc1001 length when it reset the
|
||||||
wct and bcc to minimum size and drop the t2 parms and data */
|
wct and bcc to minimum size and drop the t2 parms and data */
|
||||||
if((4+len > clc_len) && (len <= clc_len + 512))
|
if ((4+len > clc_len) && (len <= clc_len + 512))
|
||||||
return 0;
|
return 0;
|
||||||
else {
|
else {
|
||||||
cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d",
|
cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d",
|
||||||
|
@ -496,46 +500,48 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
|
||||||
int
|
int
|
||||||
is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
||||||
{
|
{
|
||||||
struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
|
struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
|
||||||
struct list_head *tmp;
|
struct list_head *tmp;
|
||||||
struct list_head *tmp1;
|
struct list_head *tmp1;
|
||||||
struct cifsTconInfo *tcon;
|
struct cifsTconInfo *tcon;
|
||||||
struct cifsFileInfo *netfile;
|
struct cifsFileInfo *netfile;
|
||||||
|
|
||||||
cFYI(1,("Checking for oplock break or dnotify response"));
|
cFYI(1, ("Checking for oplock break or dnotify response"));
|
||||||
if((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
|
if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
|
||||||
(pSMB->hdr.Flags & SMBFLG_RESPONSE)) {
|
(pSMB->hdr.Flags & SMBFLG_RESPONSE)) {
|
||||||
struct smb_com_transaction_change_notify_rsp * pSMBr =
|
struct smb_com_transaction_change_notify_rsp *pSMBr =
|
||||||
(struct smb_com_transaction_change_notify_rsp *)buf;
|
(struct smb_com_transaction_change_notify_rsp *)buf;
|
||||||
struct file_notify_information * pnotify;
|
struct file_notify_information *pnotify;
|
||||||
__u32 data_offset = 0;
|
__u32 data_offset = 0;
|
||||||
if(pSMBr->ByteCount > sizeof(struct file_notify_information)) {
|
if (pSMBr->ByteCount > sizeof(struct file_notify_information)) {
|
||||||
data_offset = le32_to_cpu(pSMBr->DataOffset);
|
data_offset = le32_to_cpu(pSMBr->DataOffset);
|
||||||
|
|
||||||
pnotify = (struct file_notify_information *)
|
pnotify = (struct file_notify_information *)
|
||||||
((char *)&pSMBr->hdr.Protocol + data_offset);
|
((char *)&pSMBr->hdr.Protocol + data_offset);
|
||||||
cFYI(1,("dnotify on %s Action: 0x%x",pnotify->FileName,
|
cFYI(1, ("dnotify on %s Action: 0x%x",
|
||||||
|
pnotify->FileName,
|
||||||
pnotify->Action)); /* BB removeme BB */
|
pnotify->Action)); /* BB removeme BB */
|
||||||
/* cifs_dump_mem("Rcvd notify Data: ",buf,
|
/* cifs_dump_mem("Rcvd notify Data: ",buf,
|
||||||
sizeof(struct smb_hdr)+60); */
|
sizeof(struct smb_hdr)+60); */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
if(pSMBr->hdr.Status.CifsError) {
|
if (pSMBr->hdr.Status.CifsError) {
|
||||||
cFYI(1,("notify err 0x%d",pSMBr->hdr.Status.CifsError));
|
cFYI(1, ("notify err 0x%d",
|
||||||
|
pSMBr->hdr.Status.CifsError));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
|
if (pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if(pSMB->hdr.Flags & SMBFLG_RESPONSE) {
|
if (pSMB->hdr.Flags & SMBFLG_RESPONSE) {
|
||||||
/* no sense logging error on invalid handle on oplock
|
/* no sense logging error on invalid handle on oplock
|
||||||
break - harmless race between close request and oplock
|
break - harmless race between close request and oplock
|
||||||
break response is expected from time to time writing out
|
break response is expected from time to time writing out
|
||||||
large dirty files cached on the client */
|
large dirty files cached on the client */
|
||||||
if ((NT_STATUS_INVALID_HANDLE) ==
|
if ((NT_STATUS_INVALID_HANDLE) ==
|
||||||
le32_to_cpu(pSMB->hdr.Status.CifsError)) {
|
le32_to_cpu(pSMB->hdr.Status.CifsError)) {
|
||||||
cFYI(1,("invalid handle on oplock break"));
|
cFYI(1, ("invalid handle on oplock break"));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} else if (ERRbadfid ==
|
} else if (ERRbadfid ==
|
||||||
le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
|
le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
|
||||||
|
@ -544,11 +550,12 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
||||||
return FALSE; /* on valid oplock brk we get "request" */
|
return FALSE; /* on valid oplock brk we get "request" */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(pSMB->hdr.WordCount != 8)
|
if (pSMB->hdr.WordCount != 8)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
|
cFYI(1, ("oplock type 0x%d level 0x%d",
|
||||||
if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
|
pSMB->LockType, pSMB->OplockLevel));
|
||||||
|
if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* look up tcon based on tid & uid */
|
/* look up tcon based on tid & uid */
|
||||||
|
@ -557,36 +564,38 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
||||||
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
||||||
if ((tcon->tid == buf->Tid) && (srv == tcon->ses->server)) {
|
if ((tcon->tid == buf->Tid) && (srv == tcon->ses->server)) {
|
||||||
cifs_stats_inc(&tcon->num_oplock_brks);
|
cifs_stats_inc(&tcon->num_oplock_brks);
|
||||||
list_for_each(tmp1,&tcon->openFileList){
|
list_for_each(tmp1, &tcon->openFileList) {
|
||||||
netfile = list_entry(tmp1,struct cifsFileInfo,
|
netfile = list_entry(tmp1, struct cifsFileInfo,
|
||||||
tlist);
|
tlist);
|
||||||
if(pSMB->Fid == netfile->netfid) {
|
if (pSMB->Fid == netfile->netfid) {
|
||||||
struct cifsInodeInfo *pCifsInode;
|
struct cifsInodeInfo *pCifsInode;
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&GlobalSMBSeslock);
|
||||||
cFYI(1,("file id match, oplock break"));
|
cFYI(1,
|
||||||
|
("file id match, oplock break"));
|
||||||
pCifsInode =
|
pCifsInode =
|
||||||
CIFS_I(netfile->pInode);
|
CIFS_I(netfile->pInode);
|
||||||
pCifsInode->clientCanCacheAll = FALSE;
|
pCifsInode->clientCanCacheAll = FALSE;
|
||||||
if(pSMB->OplockLevel == 0)
|
if (pSMB->OplockLevel == 0)
|
||||||
pCifsInode->clientCanCacheRead
|
pCifsInode->clientCanCacheRead
|
||||||
= FALSE;
|
= FALSE;
|
||||||
pCifsInode->oplockPending = TRUE;
|
pCifsInode->oplockPending = TRUE;
|
||||||
AllocOplockQEntry(netfile->pInode,
|
AllocOplockQEntry(netfile->pInode,
|
||||||
netfile->netfid,
|
netfile->netfid,
|
||||||
tcon);
|
tcon);
|
||||||
cFYI(1,("about to wake up oplock thd"));
|
cFYI(1,
|
||||||
if(oplockThread)
|
("about to wake up oplock thread"));
|
||||||
|
if (oplockThread)
|
||||||
wake_up_process(oplockThread);
|
wake_up_process(oplockThread);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&GlobalSMBSeslock);
|
||||||
cFYI(1,("No matching file for oplock break"));
|
cFYI(1, ("No matching file for oplock break"));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&GlobalSMBSeslock);
|
||||||
cFYI(1,("Can not process oplock break for non-existent connection"));
|
cFYI(1, ("Can not process oplock break for non-existent connection"));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,13 +652,13 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
|
||||||
only legal in POSIX-like OS (if they are present in the string). Path
|
only legal in POSIX-like OS (if they are present in the string). Path
|
||||||
names are little endian 16 bit Unicode on the wire */
|
names are little endian 16 bit Unicode on the wire */
|
||||||
int
|
int
|
||||||
cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
|
cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
|
||||||
const struct nls_table * cp)
|
const struct nls_table *cp)
|
||||||
{
|
{
|
||||||
int i,j,len;
|
int i, j, len;
|
||||||
__u16 src_char;
|
__u16 src_char;
|
||||||
|
|
||||||
for(i = 0, j = 0; i < maxlen; i++) {
|
for (i = 0, j = 0; i < maxlen; i++) {
|
||||||
src_char = le16_to_cpu(source[i]);
|
src_char = le16_to_cpu(source[i]);
|
||||||
switch (src_char) {
|
switch (src_char) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -681,7 +690,7 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
|
||||||
default:
|
default:
|
||||||
len = cp->uni2char(src_char, &target[j],
|
len = cp->uni2char(src_char, &target[j],
|
||||||
NLS_MAX_CHARSET_SIZE);
|
NLS_MAX_CHARSET_SIZE);
|
||||||
if(len > 0) {
|
if (len > 0) {
|
||||||
j += len;
|
j += len;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
@ -690,7 +699,7 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
|
||||||
}
|
}
|
||||||
j++;
|
j++;
|
||||||
/* make sure we do not overrun callers allocated temp buffer */
|
/* make sure we do not overrun callers allocated temp buffer */
|
||||||
if(j >= (2 * NAME_MAX))
|
if (j >= (2 * NAME_MAX))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cUCS_out:
|
cUCS_out:
|
||||||
|
@ -703,18 +712,18 @@ cUCS_out:
|
||||||
only legal in POSIX-like OS (if they are present in the string). Path
|
only legal in POSIX-like OS (if they are present in the string). Path
|
||||||
names are little endian 16 bit Unicode on the wire */
|
names are little endian 16 bit Unicode on the wire */
|
||||||
int
|
int
|
||||||
cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
|
cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
|
||||||
const struct nls_table * cp, int mapChars)
|
const struct nls_table *cp, int mapChars)
|
||||||
{
|
{
|
||||||
int i,j,charlen;
|
int i, j, charlen;
|
||||||
int len_remaining = maxlen;
|
int len_remaining = maxlen;
|
||||||
char src_char;
|
char src_char;
|
||||||
__u16 temp;
|
__u16 temp;
|
||||||
|
|
||||||
if(!mapChars)
|
if (!mapChars)
|
||||||
return cifs_strtoUCS(target, source, PATH_MAX, cp);
|
return cifs_strtoUCS(target, source, PATH_MAX, cp);
|
||||||
|
|
||||||
for(i = 0, j = 0; i < maxlen; j++) {
|
for (i = 0, j = 0; i < maxlen; j++) {
|
||||||
src_char = source[i];
|
src_char = source[i];
|
||||||
switch (src_char) {
|
switch (src_char) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -749,7 +758,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
|
||||||
len_remaining, &temp);
|
len_remaining, &temp);
|
||||||
/* if no match, use question mark, which
|
/* if no match, use question mark, which
|
||||||
at least in some cases servers as wild card */
|
at least in some cases servers as wild card */
|
||||||
if(charlen < 1) {
|
if (charlen < 1) {
|
||||||
target[j] = cpu_to_le16(0x003f);
|
target[j] = cpu_to_le16(0x003f);
|
||||||
charlen = 1;
|
charlen = 1;
|
||||||
} else
|
} else
|
||||||
|
@ -758,7 +767,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
|
||||||
/* character may take more than one byte in the
|
/* character may take more than one byte in the
|
||||||
the source string, but will take exactly two
|
the source string, but will take exactly two
|
||||||
bytes in the target string */
|
bytes in the target string */
|
||||||
i+= charlen;
|
i += charlen;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
i++; /* move to next char in source string */
|
i++; /* move to next char in source string */
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
* Error mapping routines from Samba libsmb/errormap.c
|
* Error mapping routines from Samba libsmb/errormap.c
|
||||||
* Copyright (C) Andrew Tridgell 2001
|
* Copyright (C) Andrew Tridgell 2001
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
@ -30,9 +29,7 @@
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <asm/div64.h>
|
#include <asm/div64.h>
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
|
||||||
#include <linux/inet.h>
|
#include <linux/inet.h>
|
||||||
#endif
|
|
||||||
#include "cifsfs.h"
|
#include "cifsfs.h"
|
||||||
#include "cifspdu.h"
|
#include "cifspdu.h"
|
||||||
#include "cifsglob.h"
|
#include "cifsglob.h"
|
||||||
|
@ -67,22 +64,22 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
|
||||||
{ERRbadshare, -ETXTBSY},
|
{ERRbadshare, -ETXTBSY},
|
||||||
{ERRlock, -EACCES},
|
{ERRlock, -EACCES},
|
||||||
{ERRunsup, -EINVAL},
|
{ERRunsup, -EINVAL},
|
||||||
{ERRnosuchshare,-ENXIO},
|
{ERRnosuchshare, -ENXIO},
|
||||||
{ERRfilexists, -EEXIST},
|
{ERRfilexists, -EEXIST},
|
||||||
{ERRinvparm, -EINVAL},
|
{ERRinvparm, -EINVAL},
|
||||||
{ERRdiskfull, -ENOSPC},
|
{ERRdiskfull, -ENOSPC},
|
||||||
{ERRinvname, -ENOENT},
|
{ERRinvname, -ENOENT},
|
||||||
{ERRinvlevel,-EOPNOTSUPP},
|
{ERRinvlevel, -EOPNOTSUPP},
|
||||||
{ERRdirnotempty, -ENOTEMPTY},
|
{ERRdirnotempty, -ENOTEMPTY},
|
||||||
{ERRnotlocked, -ENOLCK},
|
{ERRnotlocked, -ENOLCK},
|
||||||
{ERRcancelviolation, -ENOLCK},
|
{ERRcancelviolation, -ENOLCK},
|
||||||
{ERRalreadyexists, -EEXIST},
|
{ERRalreadyexists, -EEXIST},
|
||||||
{ERRmoredata, -EOVERFLOW},
|
{ERRmoredata, -EOVERFLOW},
|
||||||
{ERReasnotsupported,-EOPNOTSUPP},
|
{ERReasnotsupported, -EOPNOTSUPP},
|
||||||
{ErrQuota, -EDQUOT},
|
{ErrQuota, -EDQUOT},
|
||||||
{ErrNotALink, -ENOLINK},
|
{ErrNotALink, -ENOLINK},
|
||||||
{ERRnetlogonNotStarted,-ENOPROTOOPT},
|
{ERRnetlogonNotStarted, -ENOPROTOOPT},
|
||||||
{ErrTooManyLinks,-EMLINK},
|
{ErrTooManyLinks, -EMLINK},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -133,85 +130,24 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
|
||||||
/* returns 0 if invalid address */
|
/* returns 0 if invalid address */
|
||||||
|
|
||||||
int
|
int
|
||||||
cifs_inet_pton(int address_family, char *cp,void *dst)
|
cifs_inet_pton(int address_family, char *cp, void *dst)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* calculate length by finding first slash or NULL */
|
/* calculate length by finding first slash or NULL */
|
||||||
/* BB Should we convert '/' slash to '\' here since it seems already done
|
/* BB Should we convert '/' slash to '\' here since it seems already
|
||||||
before this */
|
* done before this */
|
||||||
if( address_family == AF_INET ){
|
if ( address_family == AF_INET ) {
|
||||||
ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL);
|
ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL);
|
||||||
} else if( address_family == AF_INET6 ){
|
} else if ( address_family == AF_INET6 ) {
|
||||||
ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL);
|
ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_CIFS_DEBUG2
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
cFYI(1,("address conversion returned %d for %s", ret, cp));
|
cFYI(1, ("address conversion returned %d for %s", ret, cp));
|
||||||
#endif
|
#endif
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
return ret;
|
return ret;
|
||||||
#else
|
|
||||||
int value;
|
|
||||||
int digit;
|
|
||||||
int i;
|
|
||||||
char temp;
|
|
||||||
char bytes[4];
|
|
||||||
char *end = bytes;
|
|
||||||
static const int addr_class_max[4] =
|
|
||||||
{ 0xffffffff, 0xffffff, 0xffff, 0xff };
|
|
||||||
|
|
||||||
if(address_family != AF_INET)
|
|
||||||
return -EAFNOSUPPORT;
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
bytes[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = *cp;
|
|
||||||
|
|
||||||
while (TRUE) {
|
|
||||||
if (!isdigit(temp))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
value = 0;
|
|
||||||
digit = 0;
|
|
||||||
for (;;) {
|
|
||||||
if (isascii(temp) && isdigit(temp)) {
|
|
||||||
value = (value * 10) + temp - '0';
|
|
||||||
temp = *++cp;
|
|
||||||
digit = 1;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (temp == '.') {
|
|
||||||
if ((end > bytes + 2) || (value > 255))
|
|
||||||
return 0;
|
|
||||||
*end++ = value;
|
|
||||||
temp = *++cp;
|
|
||||||
} else if (temp == ':') {
|
|
||||||
cFYI(1,("IPv6 addresses not supported for CIFS mounts yet"));
|
|
||||||
return -1;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check for last characters */
|
|
||||||
if (temp != '\0' && (!isascii(temp) || !isspace(temp)))
|
|
||||||
if (temp != '\\') {
|
|
||||||
if (temp != '/')
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
(*cp = '\\'); /* switch the slash the expected way */
|
|
||||||
}
|
|
||||||
if (value > addr_class_max[end - bytes])
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
*((__be32 *)dst) = *((__be32 *) bytes) | htonl(value);
|
|
||||||
return 1; /* success */
|
|
||||||
#endif /* EXPERIMENTAL */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
@ -393,8 +329,8 @@ static const struct {
|
||||||
ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
|
ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
|
||||||
ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
|
ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
|
||||||
/* { This NT error code was 'sqashed'
|
/* { This NT error code was 'sqashed'
|
||||||
from NT_STATUS_INSUFFICIENT_RESOURCES to NT_STATUS_INSUFF_SERVER_RESOURCES
|
from NT_STATUS_INSUFFICIENT_RESOURCES to
|
||||||
during the session setup } */
|
NT_STATUS_INSUFF_SERVER_RESOURCES during the session setup } */
|
||||||
{
|
{
|
||||||
ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
|
ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
|
||||||
ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
|
ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
|
||||||
|
@ -638,8 +574,8 @@ static const struct {
|
||||||
ERRDOS, 19, NT_STATUS_TOO_LATE}, {
|
ERRDOS, 19, NT_STATUS_TOO_LATE}, {
|
||||||
ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
|
ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
|
||||||
/* { This NT error code was 'sqashed'
|
/* { This NT error code was 'sqashed'
|
||||||
from NT_STATUS_NO_TRUST_SAM_ACCOUNT to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
|
from NT_STATUS_NO_TRUST_SAM_ACCOUNT to
|
||||||
during the session setup } */
|
NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE during the session setup } */
|
||||||
{
|
{
|
||||||
ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
|
ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
|
||||||
ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
|
ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
|
||||||
|
@ -789,7 +725,7 @@ cifs_print_status(__u32 status_code)
|
||||||
if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
|
if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
|
||||||
(status_code & 0xFFFFFF)) {
|
(status_code & 0xFFFFFF)) {
|
||||||
printk(KERN_NOTICE "Status code returned 0x%08x %s\n",
|
printk(KERN_NOTICE "Status code returned 0x%08x %s\n",
|
||||||
status_code,nt_errs[idx].nt_errstr);
|
status_code, nt_errs[idx].nt_errstr);
|
||||||
}
|
}
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
@ -832,9 +768,10 @@ map_smb_to_linux_error(struct smb_hdr *smb)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
|
if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
|
||||||
/* translate the newer STATUS codes to old style errors and then to POSIX errors */
|
/* translate the newer STATUS codes to old style SMB errors
|
||||||
|
* and then to POSIX errors */
|
||||||
__u32 err = le32_to_cpu(smb->Status.CifsError);
|
__u32 err = le32_to_cpu(smb->Status.CifsError);
|
||||||
if(cifsFYI & CIFS_RC)
|
if (cifsFYI & CIFS_RC)
|
||||||
cifs_print_status(err);
|
cifs_print_status(err);
|
||||||
ntstatus_to_dos(err, &smberrclass, &smberrcode);
|
ntstatus_to_dos(err, &smberrclass, &smberrcode);
|
||||||
} else {
|
} else {
|
||||||
|
@ -845,18 +782,19 @@ map_smb_to_linux_error(struct smb_hdr *smb)
|
||||||
/* old style errors */
|
/* old style errors */
|
||||||
|
|
||||||
/* DOS class smb error codes - map DOS */
|
/* DOS class smb error codes - map DOS */
|
||||||
if (smberrclass == ERRDOS) { /* one byte field no need to byte reverse */
|
if (smberrclass == ERRDOS) { /* 1 byte field no need to byte reverse */
|
||||||
for (i = 0;
|
for (i = 0;
|
||||||
i <
|
i <
|
||||||
sizeof (mapping_table_ERRDOS) /
|
sizeof (mapping_table_ERRDOS) /
|
||||||
sizeof (struct smb_to_posix_error); i++) {
|
sizeof (struct smb_to_posix_error); i++) {
|
||||||
if (mapping_table_ERRDOS[i].smb_err == 0)
|
if (mapping_table_ERRDOS[i].smb_err == 0)
|
||||||
break;
|
break;
|
||||||
else if (mapping_table_ERRDOS[i].smb_err == smberrcode) {
|
else if (mapping_table_ERRDOS[i].smb_err ==
|
||||||
|
smberrcode) {
|
||||||
rc = mapping_table_ERRDOS[i].posix_code;
|
rc = mapping_table_ERRDOS[i].posix_code;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* else try the next error mapping one to see if it will match */
|
/* else try next error mapping one to see if match */
|
||||||
}
|
}
|
||||||
} else if (smberrclass == ERRSRV) { /* server class of error codes */
|
} else if (smberrclass == ERRSRV) { /* server class of error codes */
|
||||||
for (i = 0;
|
for (i = 0;
|
||||||
|
@ -865,18 +803,21 @@ map_smb_to_linux_error(struct smb_hdr *smb)
|
||||||
sizeof (struct smb_to_posix_error); i++) {
|
sizeof (struct smb_to_posix_error); i++) {
|
||||||
if (mapping_table_ERRSRV[i].smb_err == 0)
|
if (mapping_table_ERRSRV[i].smb_err == 0)
|
||||||
break;
|
break;
|
||||||
else if (mapping_table_ERRSRV[i].smb_err == smberrcode) {
|
else if (mapping_table_ERRSRV[i].smb_err ==
|
||||||
|
smberrcode) {
|
||||||
rc = mapping_table_ERRSRV[i].posix_code;
|
rc = mapping_table_ERRSRV[i].posix_code;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* else try the next error mapping one to see if it will match */
|
/* else try next error mapping to see if match */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* else ERRHRD class errors or junk - return EIO */
|
/* else ERRHRD class errors or junk - return EIO */
|
||||||
|
|
||||||
cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc));
|
cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!",
|
||||||
|
smberrcode, rc));
|
||||||
|
|
||||||
/* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */
|
/* generic corrective action e.g. reconnect SMB session on
|
||||||
|
* ERRbaduid could be added */
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -946,20 +887,20 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
|
||||||
SMB_TIME * st = (SMB_TIME *)&time;
|
SMB_TIME * st = (SMB_TIME *)&time;
|
||||||
SMB_DATE * sd = (SMB_DATE *)&date;
|
SMB_DATE * sd = (SMB_DATE *)&date;
|
||||||
|
|
||||||
cFYI(1,("date %d time %d",date, time));
|
cFYI(1, ("date %d time %d", date, time));
|
||||||
|
|
||||||
sec = 2 * st->TwoSeconds;
|
sec = 2 * st->TwoSeconds;
|
||||||
min = st->Minutes;
|
min = st->Minutes;
|
||||||
if((sec > 59) || (min > 59))
|
if ((sec > 59) || (min > 59))
|
||||||
cERROR(1,("illegal time min %d sec %d", min, sec));
|
cERROR(1, ("illegal time min %d sec %d", min, sec));
|
||||||
sec += (min * 60);
|
sec += (min * 60);
|
||||||
sec += 60 * 60 * st->Hours;
|
sec += 60 * 60 * st->Hours;
|
||||||
if(st->Hours > 24)
|
if (st->Hours > 24)
|
||||||
cERROR(1,("illegal hours %d",st->Hours));
|
cERROR(1, ("illegal hours %d", st->Hours));
|
||||||
days = sd->Day;
|
days = sd->Day;
|
||||||
month = sd->Month;
|
month = sd->Month;
|
||||||
if((days > 31) || (month > 12))
|
if ((days > 31) || (month > 12))
|
||||||
cERROR(1,("illegal date, month %d day: %d", month, days));
|
cERROR(1, ("illegal date, month %d day: %d", month, days));
|
||||||
month -= 1;
|
month -= 1;
|
||||||
days += total_days_of_prev_months[month];
|
days += total_days_of_prev_months[month];
|
||||||
days += 3652; /* account for difference in days between 1980 and 1970 */
|
days += 3652; /* account for difference in days between 1980 and 1970 */
|
||||||
|
@ -972,11 +913,11 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
|
||||||
consider 2 special case years, ie the years 2000 and 2100, and only
|
consider 2 special case years, ie the years 2000 and 2100, and only
|
||||||
adjust for the lack of leap year for the year 2100, as 2000 was a
|
adjust for the lack of leap year for the year 2100, as 2000 was a
|
||||||
leap year (divisable by 400) */
|
leap year (divisable by 400) */
|
||||||
if(year >= 120) /* the year 2100 */
|
if (year >= 120) /* the year 2100 */
|
||||||
days = days - 1; /* do not count leap year for the year 2100 */
|
days = days - 1; /* do not count leap year for the year 2100 */
|
||||||
|
|
||||||
/* adjust for leap year where we are still before leap day */
|
/* adjust for leap year where we are still before leap day */
|
||||||
if(year != 120)
|
if (year != 120)
|
||||||
days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0);
|
days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0);
|
||||||
sec += 24 * 60 * 60 * days;
|
sec += 24 * 60 * 60 * days;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/ntlmssp.h
|
* fs/cifs/ntlmssp.h
|
||||||
*
|
*
|
||||||
* Copyright (c) International Business Machines Corp., 2002,2006
|
* Copyright (c) International Business Machines Corp., 2002,2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
@ -27,18 +27,18 @@
|
||||||
#define UnknownMessage cpu_to_le32(8)
|
#define UnknownMessage cpu_to_le32(8)
|
||||||
|
|
||||||
/* Negotiate Flags */
|
/* Negotiate Flags */
|
||||||
#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode
|
#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are in unicode */
|
||||||
#define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM
|
#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */
|
||||||
#define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm
|
#define NTLMSSP_REQUEST_TARGET 0x04 /* Server return its auth realm */
|
||||||
#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability
|
#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signature capability */
|
||||||
#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality
|
#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */
|
||||||
#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
|
#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
|
||||||
#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
|
#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Sign/seal use LM session key */
|
||||||
#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication
|
#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */
|
||||||
#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
|
#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
|
||||||
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
|
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
|
||||||
#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 // client/server on same machine
|
#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server on same machine */
|
||||||
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 // Sign for all security levels
|
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign for all security levels */
|
||||||
#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
|
#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
|
||||||
#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
|
#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
|
||||||
#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
|
#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
|
||||||
|
|
|
@ -34,24 +34,23 @@
|
||||||
#ifdef CONFIG_CIFS_DEBUG2
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
static void dump_cifs_file_struct(struct file *file, char *label)
|
static void dump_cifs_file_struct(struct file *file, char *label)
|
||||||
{
|
{
|
||||||
struct cifsFileInfo * cf;
|
struct cifsFileInfo *cf;
|
||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
cf = file->private_data;
|
cf = file->private_data;
|
||||||
if (cf == NULL) {
|
if (cf == NULL) {
|
||||||
cFYI(1,("empty cifs private file data"));
|
cFYI(1, ("empty cifs private file data"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cf->invalidHandle) {
|
if (cf->invalidHandle) {
|
||||||
cFYI(1,("invalid handle"));
|
cFYI(1, ("invalid handle"));
|
||||||
}
|
}
|
||||||
if (cf->srch_inf.endOfSearch) {
|
if (cf->srch_inf.endOfSearch) {
|
||||||
cFYI(1,("end of search"));
|
cFYI(1, ("end of search"));
|
||||||
}
|
}
|
||||||
if (cf->srch_inf.emptyDir) {
|
if (cf->srch_inf.emptyDir) {
|
||||||
cFYI(1,("empty dir"));
|
cFYI(1, ("empty dir"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* DEBUG2 */
|
#endif /* DEBUG2 */
|
||||||
|
@ -73,7 +72,8 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
|
||||||
qstring->hash = full_name_hash(qstring->name, qstring->len);
|
qstring->hash = full_name_hash(qstring->name, qstring->len);
|
||||||
tmp_dentry = d_lookup(file->f_path.dentry, qstring);
|
tmp_dentry = d_lookup(file->f_path.dentry, qstring);
|
||||||
if (tmp_dentry) {
|
if (tmp_dentry) {
|
||||||
cFYI(0, ("existing dentry with inode 0x%p", tmp_dentry->d_inode));
|
cFYI(0, ("existing dentry with inode 0x%p",
|
||||||
|
tmp_dentry->d_inode));
|
||||||
*ptmp_inode = tmp_dentry->d_inode;
|
*ptmp_inode = tmp_dentry->d_inode;
|
||||||
/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
|
/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
|
||||||
if (*ptmp_inode == NULL) {
|
if (*ptmp_inode == NULL) {
|
||||||
|
@ -87,7 +87,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
|
||||||
} else {
|
} else {
|
||||||
tmp_dentry = d_alloc(file->f_path.dentry, qstring);
|
tmp_dentry = d_alloc(file->f_path.dentry, qstring);
|
||||||
if (tmp_dentry == NULL) {
|
if (tmp_dentry == NULL) {
|
||||||
cERROR(1,("Failed allocating dentry"));
|
cERROR(1, ("Failed allocating dentry"));
|
||||||
*ptmp_inode = NULL;
|
*ptmp_inode = NULL;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AdjustForTZ(struct cifsTconInfo * tcon, struct inode * inode)
|
static void AdjustForTZ(struct cifsTconInfo *tcon, struct inode *inode)
|
||||||
{
|
{
|
||||||
if ((tcon) && (tcon->ses) && (tcon->ses->server)) {
|
if ((tcon) && (tcon->ses) && (tcon->ses->server)) {
|
||||||
inode->i_ctime.tv_sec += tcon->ses->server->timeAdj;
|
inode->i_ctime.tv_sec += tcon->ses->server->timeAdj;
|
||||||
|
@ -121,7 +121,7 @@ static void AdjustForTZ(struct cifsTconInfo * tcon, struct inode * inode)
|
||||||
|
|
||||||
|
|
||||||
static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
||||||
char * buf, int *pobject_type, int isNewInode)
|
char *buf, int *pobject_type, int isNewInode)
|
||||||
{
|
{
|
||||||
loff_t local_size;
|
loff_t local_size;
|
||||||
struct timespec local_mtime;
|
struct timespec local_mtime;
|
||||||
|
@ -254,7 +254,6 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
||||||
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
|
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
|
||||||
else
|
else
|
||||||
tmp_inode->i_fop = &cifs_file_direct_ops;
|
tmp_inode->i_fop = &cifs_file_direct_ops;
|
||||||
|
|
||||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||||
tmp_inode->i_fop = &cifs_file_nobrl_ops;
|
tmp_inode->i_fop = &cifs_file_nobrl_ops;
|
||||||
else
|
else
|
||||||
|
@ -353,7 +352,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
|
||||||
/* safest to just call it a file */
|
/* safest to just call it a file */
|
||||||
*pobject_type = DT_REG;
|
*pobject_type = DT_REG;
|
||||||
tmp_inode->i_mode |= S_IFREG;
|
tmp_inode->i_mode |= S_IFREG;
|
||||||
cFYI(1,("unknown inode type %d",type));
|
cFYI(1, ("unknown inode type %d", type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
|
||||||
|
@ -400,8 +399,9 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
|
||||||
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
||||||
|
|
||||||
if (isNewInode)
|
if (isNewInode)
|
||||||
return; /* No sense invalidating pages for new inode since we
|
return; /* No sense invalidating pages for new inode
|
||||||
have not started caching readahead file data yet */
|
since we have not started caching readahead
|
||||||
|
file data for it yet */
|
||||||
|
|
||||||
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
|
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
|
||||||
(local_size == tmp_inode->i_size)) {
|
(local_size == tmp_inode->i_size)) {
|
||||||
|
@ -429,14 +429,14 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
|
||||||
static int initiate_cifs_search(const int xid, struct file *file)
|
static int initiate_cifs_search(const int xid, struct file *file)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
char * full_path;
|
char *full_path;
|
||||||
struct cifsFileInfo * cifsFile;
|
struct cifsFileInfo *cifsFile;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
|
|
||||||
if (file->private_data == NULL) {
|
if (file->private_data == NULL) {
|
||||||
file->private_data =
|
file->private_data =
|
||||||
kzalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
|
kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file->private_data == NULL)
|
if (file->private_data == NULL)
|
||||||
|
@ -463,7 +463,9 @@ static int initiate_cifs_search(const int xid, struct file *file)
|
||||||
|
|
||||||
ffirst_retry:
|
ffirst_retry:
|
||||||
/* test for Unix extensions */
|
/* test for Unix extensions */
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX) {
|
/* but now check for them on the share/mount not on the SMB session */
|
||||||
|
/* if (pTcon->ses->capabilities & CAP_UNIX) { */
|
||||||
|
if (pTcon->unix_ext) {
|
||||||
cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
|
cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
|
||||||
} else if ((pTcon->ses->capabilities &
|
} else if ((pTcon->ses->capabilities &
|
||||||
(CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
|
(CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
|
||||||
|
@ -474,7 +476,7 @@ ffirst_retry:
|
||||||
cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
|
cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls,
|
rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls,
|
||||||
&cifsFile->netfid, &cifsFile->srch_inf,
|
&cifsFile->netfid, &cifsFile->srch_inf,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
|
CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
|
||||||
|
@ -495,17 +497,17 @@ static int cifs_unicode_bytelen(char *str)
|
||||||
int len;
|
int len;
|
||||||
__le16 * ustr = (__le16 *)str;
|
__le16 * ustr = (__le16 *)str;
|
||||||
|
|
||||||
for(len=0;len <= PATH_MAX;len++) {
|
for (len = 0; len <= PATH_MAX; len++) {
|
||||||
if (ustr[len] == 0)
|
if (ustr[len] == 0)
|
||||||
return len << 1;
|
return len << 1;
|
||||||
}
|
}
|
||||||
cFYI(1,("Unicode string longer than PATH_MAX found"));
|
cFYI(1, ("Unicode string longer than PATH_MAX found"));
|
||||||
return len << 1;
|
return len << 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
|
static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
|
||||||
{
|
{
|
||||||
char * new_entry;
|
char *new_entry;
|
||||||
FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
|
FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
|
||||||
|
|
||||||
if (level == SMB_FIND_FILE_INFO_STANDARD) {
|
if (level == SMB_FIND_FILE_INFO_STANDARD) {
|
||||||
|
@ -516,7 +518,7 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
|
||||||
pfData->FileNameLength;
|
pfData->FileNameLength;
|
||||||
} else
|
} else
|
||||||
new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
|
new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
|
||||||
cFYI(1,("new entry %p old entry %p",new_entry,old_entry));
|
cFYI(1, ("new entry %p old entry %p", new_entry, old_entry));
|
||||||
/* validate that new_entry is not past end of SMB */
|
/* validate that new_entry is not past end of SMB */
|
||||||
if (new_entry >= end_of_smb) {
|
if (new_entry >= end_of_smb) {
|
||||||
cERROR(1,
|
cERROR(1,
|
||||||
|
@ -524,10 +526,10 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
|
||||||
new_entry, end_of_smb, old_entry));
|
new_entry, end_of_smb, old_entry));
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
|
} else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
|
||||||
(new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb)) ||
|
(new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
|
||||||
((level != SMB_FIND_FILE_INFO_STANDARD) &&
|
|| ((level != SMB_FIND_FILE_INFO_STANDARD) &&
|
||||||
(new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
|
(new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
|
||||||
cERROR(1,("search entry %p extends after end of SMB %p",
|
cERROR(1, ("search entry %p extends after end of SMB %p",
|
||||||
new_entry, end_of_smb));
|
new_entry, end_of_smb));
|
||||||
return NULL;
|
return NULL;
|
||||||
} else
|
} else
|
||||||
|
@ -541,7 +543,7 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
|
||||||
static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
|
static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
char * filename = NULL;
|
char *filename = NULL;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
|
if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
|
||||||
|
@ -582,7 +584,8 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
|
||||||
filename = &pFindData->FileName[0];
|
filename = &pFindData->FileName[0];
|
||||||
len = pFindData->FileNameLength;
|
len = pFindData->FileNameLength;
|
||||||
} else {
|
} else {
|
||||||
cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level));
|
cFYI(1, ("Unknown findfirst level %d",
|
||||||
|
cfile->srch_inf.info_level));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filename) {
|
if (filename) {
|
||||||
|
@ -595,7 +598,7 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
|
||||||
} else if (len == 4) {
|
} else if (len == 4) {
|
||||||
/* check for .. */
|
/* check for .. */
|
||||||
if ((ufilename[0] == UNICODE_DOT)
|
if ((ufilename[0] == UNICODE_DOT)
|
||||||
&&(ufilename[1] == UNICODE_DOT))
|
&& (ufilename[1] == UNICODE_DOT))
|
||||||
rc = 2;
|
rc = 2;
|
||||||
}
|
}
|
||||||
} else /* ASCII */ {
|
} else /* ASCII */ {
|
||||||
|
@ -603,7 +606,7 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
|
||||||
if (filename[0] == '.')
|
if (filename[0] == '.')
|
||||||
rc = 1;
|
rc = 1;
|
||||||
} else if (len == 2) {
|
} else if (len == 2) {
|
||||||
if((filename[0] == '.') && (filename[1] == '.'))
|
if ((filename[0] == '.') && (filename[1] == '.'))
|
||||||
rc = 2;
|
rc = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -614,7 +617,7 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
|
||||||
|
|
||||||
/* Check if directory that we are searching has changed so we can decide
|
/* Check if directory that we are searching has changed so we can decide
|
||||||
whether we can use the cached search results from the previous search */
|
whether we can use the cached search results from the previous search */
|
||||||
static int is_dir_changed(struct file * file)
|
static int is_dir_changed(struct file *file)
|
||||||
{
|
{
|
||||||
struct inode *inode = file->f_path.dentry->d_inode;
|
struct inode *inode = file->f_path.dentry->d_inode;
|
||||||
struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
|
struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
|
||||||
|
@ -639,7 +642,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||||
int pos_in_buf = 0;
|
int pos_in_buf = 0;
|
||||||
loff_t first_entry_in_buffer;
|
loff_t first_entry_in_buffer;
|
||||||
loff_t index_to_find = file->f_pos;
|
loff_t index_to_find = file->f_pos;
|
||||||
struct cifsFileInfo * cifsFile = file->private_data;
|
struct cifsFileInfo *cifsFile = file->private_data;
|
||||||
/* check if index in the buffer */
|
/* check if index in the buffer */
|
||||||
|
|
||||||
if ((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
|
if ((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
|
||||||
|
@ -664,13 +667,13 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||||
is_dir_changed(file)) ||
|
is_dir_changed(file)) ||
|
||||||
(index_to_find < first_entry_in_buffer)) {
|
(index_to_find < first_entry_in_buffer)) {
|
||||||
/* close and restart search */
|
/* close and restart search */
|
||||||
cFYI(1,("search backing up - close and restart search"));
|
cFYI(1, ("search backing up - close and restart search"));
|
||||||
cifsFile->invalidHandle = TRUE;
|
cifsFile->invalidHandle = TRUE;
|
||||||
CIFSFindClose(xid, pTcon, cifsFile->netfid);
|
CIFSFindClose(xid, pTcon, cifsFile->netfid);
|
||||||
kfree(cifsFile->search_resume_name);
|
kfree(cifsFile->search_resume_name);
|
||||||
cifsFile->search_resume_name = NULL;
|
cifsFile->search_resume_name = NULL;
|
||||||
if (cifsFile->srch_inf.ntwrk_buf_start) {
|
if (cifsFile->srch_inf.ntwrk_buf_start) {
|
||||||
cFYI(1,("freeing SMB ff cache buf on search rewind"));
|
cFYI(1, ("freeing SMB ff cache buf on search rewind"));
|
||||||
if (cifsFile->srch_inf.smallBuf)
|
if (cifsFile->srch_inf.smallBuf)
|
||||||
cifs_small_buf_release(cifsFile->srch_inf.
|
cifs_small_buf_release(cifsFile->srch_inf.
|
||||||
ntwrk_buf_start);
|
ntwrk_buf_start);
|
||||||
|
@ -678,17 +681,18 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||||
cifs_buf_release(cifsFile->srch_inf.
|
cifs_buf_release(cifsFile->srch_inf.
|
||||||
ntwrk_buf_start);
|
ntwrk_buf_start);
|
||||||
}
|
}
|
||||||
rc = initiate_cifs_search(xid,file);
|
rc = initiate_cifs_search(xid, file);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cFYI(1,("error %d reinitiating a search on rewind",rc));
|
cFYI(1, ("error %d reinitiating a search on rewind",
|
||||||
|
rc));
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
|
while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
|
||||||
(rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){
|
(rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)) {
|
||||||
cFYI(1,("calling findnext2"));
|
cFYI(1, ("calling findnext2"));
|
||||||
rc = CIFSFindNext(xid,pTcon,cifsFile->netfid,
|
rc = CIFSFindNext(xid, pTcon, cifsFile->netfid,
|
||||||
&cifsFile->srch_inf);
|
&cifsFile->srch_inf);
|
||||||
if (rc)
|
if (rc)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
@ -697,8 +701,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||||
/* we found the buffer that contains the entry */
|
/* we found the buffer that contains the entry */
|
||||||
/* scan and find it */
|
/* scan and find it */
|
||||||
int i;
|
int i;
|
||||||
char * current_entry;
|
char *current_entry;
|
||||||
char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
|
char *end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
|
||||||
smbCalcSize((struct smb_hdr *)
|
smbCalcSize((struct smb_hdr *)
|
||||||
cifsFile->srch_inf.ntwrk_buf_start);
|
cifsFile->srch_inf.ntwrk_buf_start);
|
||||||
|
|
||||||
|
@ -706,28 +710,28 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||||
first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
|
first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
|
||||||
- cifsFile->srch_inf.entries_in_buffer;
|
- cifsFile->srch_inf.entries_in_buffer;
|
||||||
pos_in_buf = index_to_find - first_entry_in_buffer;
|
pos_in_buf = index_to_find - first_entry_in_buffer;
|
||||||
cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
|
cFYI(1, ("found entry - pos_in_buf %d", pos_in_buf));
|
||||||
|
|
||||||
for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
|
for (i=0; (i < (pos_in_buf)) && (current_entry != NULL); i++) {
|
||||||
/* go entry by entry figuring out which is first */
|
/* go entry by entry figuring out which is first */
|
||||||
current_entry = nxt_dir_entry(current_entry,end_of_smb,
|
current_entry = nxt_dir_entry(current_entry, end_of_smb,
|
||||||
cifsFile->srch_inf.info_level);
|
cifsFile->srch_inf.info_level);
|
||||||
}
|
}
|
||||||
if((current_entry == NULL) && (i < pos_in_buf)) {
|
if ((current_entry == NULL) && (i < pos_in_buf)) {
|
||||||
/* BB fixme - check if we should flag this error */
|
/* BB fixme - check if we should flag this error */
|
||||||
cERROR(1,("reached end of buf searching for pos in buf"
|
cERROR(1, ("reached end of buf searching for pos in buf"
|
||||||
" %d index to find %lld rc %d",
|
" %d index to find %lld rc %d",
|
||||||
pos_in_buf,index_to_find,rc));
|
pos_in_buf, index_to_find, rc));
|
||||||
}
|
}
|
||||||
rc = 0;
|
rc = 0;
|
||||||
*ppCurrentEntry = current_entry;
|
*ppCurrentEntry = current_entry;
|
||||||
} else {
|
} else {
|
||||||
cFYI(1,("index not in buffer - could not findnext into it"));
|
cFYI(1, ("index not in buffer - could not findnext into it"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
|
if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
|
||||||
cFYI(1,("can not return entries pos_in_buf beyond last entry"));
|
cFYI(1, ("can not return entries pos_in_buf beyond last"));
|
||||||
*num_to_ret = 0;
|
*num_to_ret = 0;
|
||||||
} else
|
} else
|
||||||
*num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
|
*num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
|
||||||
|
@ -738,81 +742,81 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||||
/* inode num, inode type and filename returned */
|
/* inode num, inode type and filename returned */
|
||||||
static int cifs_get_name_from_search_buf(struct qstr *pqst,
|
static int cifs_get_name_from_search_buf(struct qstr *pqst,
|
||||||
char *current_entry, __u16 level, unsigned int unicode,
|
char *current_entry, __u16 level, unsigned int unicode,
|
||||||
struct cifs_sb_info * cifs_sb, int max_len, ino_t *pinum)
|
struct cifs_sb_info *cifs_sb, int max_len, ino_t *pinum)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned int len = 0;
|
unsigned int len = 0;
|
||||||
char * filename;
|
char *filename;
|
||||||
struct nls_table * nlt = cifs_sb->local_nls;
|
struct nls_table *nlt = cifs_sb->local_nls;
|
||||||
|
|
||||||
*pinum = 0;
|
*pinum = 0;
|
||||||
|
|
||||||
if(level == SMB_FIND_FILE_UNIX) {
|
if (level == SMB_FIND_FILE_UNIX) {
|
||||||
FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
|
FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
|
||||||
|
|
||||||
filename = &pFindData->FileName[0];
|
filename = &pFindData->FileName[0];
|
||||||
if(unicode) {
|
if (unicode) {
|
||||||
len = cifs_unicode_bytelen(filename);
|
len = cifs_unicode_bytelen(filename);
|
||||||
} else {
|
} else {
|
||||||
/* BB should we make this strnlen of PATH_MAX? */
|
/* BB should we make this strnlen of PATH_MAX? */
|
||||||
len = strnlen(filename, PATH_MAX);
|
len = strnlen(filename, PATH_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BB fixme - hash low and high 32 bits if not 64 bit arch BB fixme */
|
/* BB fixme - hash low and high 32 bits if not 64 bit arch BB */
|
||||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
|
||||||
*pinum = pFindData->UniqueId;
|
*pinum = pFindData->UniqueId;
|
||||||
} else if(level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
||||||
FILE_DIRECTORY_INFO * pFindData =
|
FILE_DIRECTORY_INFO *pFindData =
|
||||||
(FILE_DIRECTORY_INFO *)current_entry;
|
(FILE_DIRECTORY_INFO *)current_entry;
|
||||||
filename = &pFindData->FileName[0];
|
filename = &pFindData->FileName[0];
|
||||||
len = le32_to_cpu(pFindData->FileNameLength);
|
len = le32_to_cpu(pFindData->FileNameLength);
|
||||||
} else if(level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
|
} else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
|
||||||
FILE_FULL_DIRECTORY_INFO * pFindData =
|
FILE_FULL_DIRECTORY_INFO *pFindData =
|
||||||
(FILE_FULL_DIRECTORY_INFO *)current_entry;
|
(FILE_FULL_DIRECTORY_INFO *)current_entry;
|
||||||
filename = &pFindData->FileName[0];
|
filename = &pFindData->FileName[0];
|
||||||
len = le32_to_cpu(pFindData->FileNameLength);
|
len = le32_to_cpu(pFindData->FileNameLength);
|
||||||
} else if(level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
|
} else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
|
||||||
SEARCH_ID_FULL_DIR_INFO * pFindData =
|
SEARCH_ID_FULL_DIR_INFO *pFindData =
|
||||||
(SEARCH_ID_FULL_DIR_INFO *)current_entry;
|
(SEARCH_ID_FULL_DIR_INFO *)current_entry;
|
||||||
filename = &pFindData->FileName[0];
|
filename = &pFindData->FileName[0];
|
||||||
len = le32_to_cpu(pFindData->FileNameLength);
|
len = le32_to_cpu(pFindData->FileNameLength);
|
||||||
*pinum = pFindData->UniqueId;
|
*pinum = pFindData->UniqueId;
|
||||||
} else if(level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
|
} else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
|
||||||
FILE_BOTH_DIRECTORY_INFO * pFindData =
|
FILE_BOTH_DIRECTORY_INFO *pFindData =
|
||||||
(FILE_BOTH_DIRECTORY_INFO *)current_entry;
|
(FILE_BOTH_DIRECTORY_INFO *)current_entry;
|
||||||
filename = &pFindData->FileName[0];
|
filename = &pFindData->FileName[0];
|
||||||
len = le32_to_cpu(pFindData->FileNameLength);
|
len = le32_to_cpu(pFindData->FileNameLength);
|
||||||
} else if(level == SMB_FIND_FILE_INFO_STANDARD) {
|
} else if (level == SMB_FIND_FILE_INFO_STANDARD) {
|
||||||
FIND_FILE_STANDARD_INFO * pFindData =
|
FIND_FILE_STANDARD_INFO * pFindData =
|
||||||
(FIND_FILE_STANDARD_INFO *)current_entry;
|
(FIND_FILE_STANDARD_INFO *)current_entry;
|
||||||
filename = &pFindData->FileName[0];
|
filename = &pFindData->FileName[0];
|
||||||
/* one byte length, no name conversion */
|
/* one byte length, no name conversion */
|
||||||
len = (unsigned int)pFindData->FileNameLength;
|
len = (unsigned int)pFindData->FileNameLength;
|
||||||
} else {
|
} else {
|
||||||
cFYI(1,("Unknown findfirst level %d",level));
|
cFYI(1, ("Unknown findfirst level %d", level));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(len > max_len) {
|
if (len > max_len) {
|
||||||
cERROR(1,("bad search response length %d past smb end", len));
|
cERROR(1, ("bad search response length %d past smb end", len));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(unicode) {
|
if (unicode) {
|
||||||
/* BB fixme - test with long names */
|
/* BB fixme - test with long names */
|
||||||
/* Note converted filename can be longer than in unicode */
|
/* Note converted filename can be longer than in unicode */
|
||||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
|
||||||
pqst->len = cifs_convertUCSpath((char *)pqst->name,
|
pqst->len = cifs_convertUCSpath((char *)pqst->name,
|
||||||
(__le16 *)filename, len/2, nlt);
|
(__le16 *)filename, len/2, nlt);
|
||||||
else
|
else
|
||||||
pqst->len = cifs_strfromUCS_le((char *)pqst->name,
|
pqst->len = cifs_strfromUCS_le((char *)pqst->name,
|
||||||
(__le16 *)filename,len/2,nlt);
|
(__le16 *)filename, len/2, nlt);
|
||||||
} else {
|
} else {
|
||||||
pqst->name = filename;
|
pqst->name = filename;
|
||||||
pqst->len = len;
|
pqst->len = len;
|
||||||
}
|
}
|
||||||
pqst->hash = full_name_hash(pqst->name,pqst->len);
|
pqst->hash = full_name_hash(pqst->name, pqst->len);
|
||||||
/* cFYI(1,("filldir on %s",pqst->name)); */
|
/* cFYI(1, ("filldir on %s",pqst->name)); */
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,49 +825,50 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct qstr qstring;
|
struct qstr qstring;
|
||||||
struct cifsFileInfo * pCifsF;
|
struct cifsFileInfo *pCifsF;
|
||||||
unsigned obj_type;
|
unsigned obj_type;
|
||||||
ino_t inum;
|
ino_t inum;
|
||||||
struct cifs_sb_info * cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct inode *tmp_inode;
|
struct inode *tmp_inode;
|
||||||
struct dentry *tmp_dentry;
|
struct dentry *tmp_dentry;
|
||||||
|
|
||||||
/* get filename and len into qstring */
|
/* get filename and len into qstring */
|
||||||
/* get dentry */
|
/* get dentry */
|
||||||
/* decide whether to create and populate ionde */
|
/* decide whether to create and populate ionde */
|
||||||
if((direntry == NULL) || (file == NULL))
|
if ((direntry == NULL) || (file == NULL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
pCifsF = file->private_data;
|
pCifsF = file->private_data;
|
||||||
|
|
||||||
if((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
|
if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
rc = cifs_entry_is_dot(pfindEntry,pCifsF);
|
rc = cifs_entry_is_dot(pfindEntry, pCifsF);
|
||||||
/* skip . and .. since we added them first */
|
/* skip . and .. since we added them first */
|
||||||
if(rc != 0)
|
if (rc != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
||||||
|
|
||||||
qstring.name = scratch_buf;
|
qstring.name = scratch_buf;
|
||||||
rc = cifs_get_name_from_search_buf(&qstring,pfindEntry,
|
rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
|
||||||
pCifsF->srch_inf.info_level,
|
pCifsF->srch_inf.info_level,
|
||||||
pCifsF->srch_inf.unicode,cifs_sb,
|
pCifsF->srch_inf.unicode, cifs_sb,
|
||||||
max_len,
|
max_len,
|
||||||
&inum /* returned */);
|
&inum /* returned */);
|
||||||
|
|
||||||
if(rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
rc = construct_dentry(&qstring,file,&tmp_inode, &tmp_dentry);
|
rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry);
|
||||||
if((tmp_inode == NULL) || (tmp_dentry == NULL))
|
if ((tmp_inode == NULL) || (tmp_dentry == NULL))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if(rc) {
|
if (rc) {
|
||||||
/* inode created, we need to hash it with right inode number */
|
/* inode created, we need to hash it with right inode number */
|
||||||
if(inum != 0) {
|
if (inum != 0) {
|
||||||
/* BB fixme - hash the 2 32 quantities bits together if necessary BB */
|
/* BB fixme - hash the 2 32 quantities bits together if
|
||||||
|
* necessary BB */
|
||||||
tmp_inode->i_ino = inum;
|
tmp_inode->i_ino = inum;
|
||||||
}
|
}
|
||||||
insert_inode_hash(tmp_inode);
|
insert_inode_hash(tmp_inode);
|
||||||
|
@ -872,27 +877,27 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
|
||||||
/* we pass in rc below, indicating whether it is a new inode,
|
/* we pass in rc below, indicating whether it is a new inode,
|
||||||
so we can figure out whether to invalidate the inode cached
|
so we can figure out whether to invalidate the inode cached
|
||||||
data if the file has changed */
|
data if the file has changed */
|
||||||
if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
|
if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
|
||||||
unix_fill_in_inode(tmp_inode,
|
unix_fill_in_inode(tmp_inode,
|
||||||
(FILE_UNIX_INFO *)pfindEntry,
|
(FILE_UNIX_INFO *)pfindEntry,
|
||||||
&obj_type, rc);
|
&obj_type, rc);
|
||||||
else if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
|
else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
|
||||||
fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */,
|
fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */,
|
||||||
pfindEntry, &obj_type, rc);
|
pfindEntry, &obj_type, rc);
|
||||||
else
|
else
|
||||||
fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc);
|
fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc);
|
||||||
|
|
||||||
if(rc) /* new inode - needs to be tied to dentry */ {
|
if (rc) /* new inode - needs to be tied to dentry */ {
|
||||||
d_instantiate(tmp_dentry, tmp_inode);
|
d_instantiate(tmp_dentry, tmp_inode);
|
||||||
if(rc == 2)
|
if (rc == 2)
|
||||||
d_rehash(tmp_dentry);
|
d_rehash(tmp_dentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,
|
rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
|
||||||
tmp_inode->i_ino,obj_type);
|
tmp_inode->i_ino, obj_type);
|
||||||
if(rc) {
|
if (rc) {
|
||||||
cFYI(1,("filldir rc = %d",rc));
|
cFYI(1, ("filldir rc = %d", rc));
|
||||||
/* we can not return filldir errors to the caller
|
/* we can not return filldir errors to the caller
|
||||||
since they are "normal" when the stat blocksize
|
since they are "normal" when the stat blocksize
|
||||||
is too small - we return remapped error instead */
|
is too small - we return remapped error instead */
|
||||||
|
@ -909,57 +914,57 @@ static int cifs_save_resume_key(const char *current_entry,
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned int len = 0;
|
unsigned int len = 0;
|
||||||
__u16 level;
|
__u16 level;
|
||||||
char * filename;
|
char *filename;
|
||||||
|
|
||||||
if((cifsFile == NULL) || (current_entry == NULL))
|
if ((cifsFile == NULL) || (current_entry == NULL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
level = cifsFile->srch_inf.info_level;
|
level = cifsFile->srch_inf.info_level;
|
||||||
|
|
||||||
if(level == SMB_FIND_FILE_UNIX) {
|
if (level == SMB_FIND_FILE_UNIX) {
|
||||||
FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
|
FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
|
||||||
|
|
||||||
filename = &pFindData->FileName[0];
|
filename = &pFindData->FileName[0];
|
||||||
if(cifsFile->srch_inf.unicode) {
|
if (cifsFile->srch_inf.unicode) {
|
||||||
len = cifs_unicode_bytelen(filename);
|
len = cifs_unicode_bytelen(filename);
|
||||||
} else {
|
} else {
|
||||||
/* BB should we make this strnlen of PATH_MAX? */
|
/* BB should we make this strnlen of PATH_MAX? */
|
||||||
len = strnlen(filename, PATH_MAX);
|
len = strnlen(filename, PATH_MAX);
|
||||||
}
|
}
|
||||||
cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
|
cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
|
||||||
} else if(level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
||||||
FILE_DIRECTORY_INFO * pFindData =
|
FILE_DIRECTORY_INFO *pFindData =
|
||||||
(FILE_DIRECTORY_INFO *)current_entry;
|
(FILE_DIRECTORY_INFO *)current_entry;
|
||||||
filename = &pFindData->FileName[0];
|
filename = &pFindData->FileName[0];
|
||||||
len = le32_to_cpu(pFindData->FileNameLength);
|
len = le32_to_cpu(pFindData->FileNameLength);
|
||||||
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
||||||
} else if(level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
|
} else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
|
||||||
FILE_FULL_DIRECTORY_INFO * pFindData =
|
FILE_FULL_DIRECTORY_INFO *pFindData =
|
||||||
(FILE_FULL_DIRECTORY_INFO *)current_entry;
|
(FILE_FULL_DIRECTORY_INFO *)current_entry;
|
||||||
filename = &pFindData->FileName[0];
|
filename = &pFindData->FileName[0];
|
||||||
len = le32_to_cpu(pFindData->FileNameLength);
|
len = le32_to_cpu(pFindData->FileNameLength);
|
||||||
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
||||||
} else if(level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
|
} else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
|
||||||
SEARCH_ID_FULL_DIR_INFO * pFindData =
|
SEARCH_ID_FULL_DIR_INFO *pFindData =
|
||||||
(SEARCH_ID_FULL_DIR_INFO *)current_entry;
|
(SEARCH_ID_FULL_DIR_INFO *)current_entry;
|
||||||
filename = &pFindData->FileName[0];
|
filename = &pFindData->FileName[0];
|
||||||
len = le32_to_cpu(pFindData->FileNameLength);
|
len = le32_to_cpu(pFindData->FileNameLength);
|
||||||
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
||||||
} else if(level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
|
} else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
|
||||||
FILE_BOTH_DIRECTORY_INFO * pFindData =
|
FILE_BOTH_DIRECTORY_INFO *pFindData =
|
||||||
(FILE_BOTH_DIRECTORY_INFO *)current_entry;
|
(FILE_BOTH_DIRECTORY_INFO *)current_entry;
|
||||||
filename = &pFindData->FileName[0];
|
filename = &pFindData->FileName[0];
|
||||||
len = le32_to_cpu(pFindData->FileNameLength);
|
len = le32_to_cpu(pFindData->FileNameLength);
|
||||||
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
||||||
} else if(level == SMB_FIND_FILE_INFO_STANDARD) {
|
} else if (level == SMB_FIND_FILE_INFO_STANDARD) {
|
||||||
FIND_FILE_STANDARD_INFO * pFindData =
|
FIND_FILE_STANDARD_INFO *pFindData =
|
||||||
(FIND_FILE_STANDARD_INFO *)current_entry;
|
(FIND_FILE_STANDARD_INFO *)current_entry;
|
||||||
filename = &pFindData->FileName[0];
|
filename = &pFindData->FileName[0];
|
||||||
/* one byte length, no name conversion */
|
/* one byte length, no name conversion */
|
||||||
len = (unsigned int)pFindData->FileNameLength;
|
len = (unsigned int)pFindData->FileNameLength;
|
||||||
cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
|
cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
|
||||||
} else {
|
} else {
|
||||||
cFYI(1,("Unknown findfirst level %d",level));
|
cFYI(1, ("Unknown findfirst level %d", level));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
cifsFile->srch_inf.resume_name_len = len;
|
cifsFile->srch_inf.resume_name_len = len;
|
||||||
|
@ -970,21 +975,21 @@ static int cifs_save_resume_key(const char *current_entry,
|
||||||
int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int xid,i;
|
int xid, i;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
struct cifsFileInfo *cifsFile = NULL;
|
struct cifsFileInfo *cifsFile = NULL;
|
||||||
char * current_entry;
|
char *current_entry;
|
||||||
int num_to_fill = 0;
|
int num_to_fill = 0;
|
||||||
char * tmp_buf = NULL;
|
char *tmp_buf = NULL;
|
||||||
char * end_of_smb;
|
char *end_of_smb;
|
||||||
int max_len;
|
int max_len;
|
||||||
|
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
|
|
||||||
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
if(pTcon == NULL)
|
if (pTcon == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch ((int) file->f_pos) {
|
switch ((int) file->f_pos) {
|
||||||
|
@ -1010,22 +1015,22 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||||
if it before then restart search
|
if it before then restart search
|
||||||
if after then keep searching till find it */
|
if after then keep searching till find it */
|
||||||
|
|
||||||
if(file->private_data == NULL) {
|
if (file->private_data == NULL) {
|
||||||
rc = initiate_cifs_search(xid,file);
|
rc = initiate_cifs_search(xid, file);
|
||||||
cFYI(1,("initiate cifs search rc %d",rc));
|
cFYI(1, ("initiate cifs search rc %d", rc));
|
||||||
if(rc) {
|
if (rc) {
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(file->private_data == NULL) {
|
if (file->private_data == NULL) {
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
cifsFile = file->private_data;
|
cifsFile = file->private_data;
|
||||||
if (cifsFile->srch_inf.endOfSearch) {
|
if (cifsFile->srch_inf.endOfSearch) {
|
||||||
if(cifsFile->srch_inf.emptyDir) {
|
if (cifsFile->srch_inf.emptyDir) {
|
||||||
cFYI(1, ("End of search, empty dir"));
|
cFYI(1, ("End of search, empty dir"));
|
||||||
rc = 0;
|
rc = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -1037,19 +1042,19 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||||
kfree(cifsFile->search_resume_name);
|
kfree(cifsFile->search_resume_name);
|
||||||
cifsFile->search_resume_name = NULL; */
|
cifsFile->search_resume_name = NULL; */
|
||||||
|
|
||||||
rc = find_cifs_entry(xid,pTcon, file,
|
rc = find_cifs_entry(xid, pTcon, file,
|
||||||
¤t_entry,&num_to_fill);
|
¤t_entry, &num_to_fill);
|
||||||
if(rc) {
|
if (rc) {
|
||||||
cFYI(1,("fce error %d",rc));
|
cFYI(1, ("fce error %d", rc));
|
||||||
goto rddir2_exit;
|
goto rddir2_exit;
|
||||||
} else if (current_entry != NULL) {
|
} else if (current_entry != NULL) {
|
||||||
cFYI(1,("entry %lld found",file->f_pos));
|
cFYI(1, ("entry %lld found", file->f_pos));
|
||||||
} else {
|
} else {
|
||||||
cFYI(1,("could not find entry"));
|
cFYI(1, ("could not find entry"));
|
||||||
goto rddir2_exit;
|
goto rddir2_exit;
|
||||||
}
|
}
|
||||||
cFYI(1,("loop through %d times filling dir for net buf %p",
|
cFYI(1, ("loop through %d times filling dir for net buf %p",
|
||||||
num_to_fill,cifsFile->srch_inf.ntwrk_buf_start));
|
num_to_fill, cifsFile->srch_inf.ntwrk_buf_start));
|
||||||
max_len = smbCalcSize((struct smb_hdr *)
|
max_len = smbCalcSize((struct smb_hdr *)
|
||||||
cifsFile->srch_inf.ntwrk_buf_start);
|
cifsFile->srch_inf.ntwrk_buf_start);
|
||||||
end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
|
end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
|
||||||
|
@ -1059,8 +1064,8 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||||
such multibyte target UTF-8 characters. cifs_unicode.c,
|
such multibyte target UTF-8 characters. cifs_unicode.c,
|
||||||
which actually does the conversion, has the same limit */
|
which actually does the conversion, has the same limit */
|
||||||
tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL);
|
tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL);
|
||||||
for(i=0;(i<num_to_fill) && (rc == 0);i++) {
|
for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
|
||||||
if(current_entry == NULL) {
|
if (current_entry == NULL) {
|
||||||
/* evaluate whether this case is an error */
|
/* evaluate whether this case is an error */
|
||||||
cERROR(1,("past end of SMB num to fill %d i %d",
|
cERROR(1,("past end of SMB num to fill %d i %d",
|
||||||
num_to_fill, i));
|
num_to_fill, i));
|
||||||
|
@ -1070,17 +1075,17 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||||
we want to check for that here? */
|
we want to check for that here? */
|
||||||
rc = cifs_filldir(current_entry, file,
|
rc = cifs_filldir(current_entry, file,
|
||||||
filldir, direntry, tmp_buf, max_len);
|
filldir, direntry, tmp_buf, max_len);
|
||||||
if(rc == -EOVERFLOW) {
|
if (rc == -EOVERFLOW) {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
file->f_pos++;
|
file->f_pos++;
|
||||||
if(file->f_pos ==
|
if (file->f_pos ==
|
||||||
cifsFile->srch_inf.index_of_last_entry) {
|
cifsFile->srch_inf.index_of_last_entry) {
|
||||||
cFYI(1,("last entry in buf at pos %lld %s",
|
cFYI(1, ("last entry in buf at pos %lld %s",
|
||||||
file->f_pos,tmp_buf));
|
file->f_pos, tmp_buf));
|
||||||
cifs_save_resume_key(current_entry,cifsFile);
|
cifs_save_resume_key(current_entry, cifsFile);
|
||||||
break;
|
break;
|
||||||
} else
|
} else
|
||||||
current_entry =
|
current_entry =
|
||||||
|
|
151
fs/cifs/sess.c
151
fs/cifs/sess.c
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* SMB/CIFS session setup handling routines
|
* SMB/CIFS session setup handling routines
|
||||||
*
|
*
|
||||||
* Copyright (c) International Business Machines Corp., 2006
|
* Copyright (c) International Business Machines Corp., 2006, 2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
@ -51,7 +51,8 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
|
||||||
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
|
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
|
||||||
CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
|
CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
|
||||||
|
|
||||||
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
if (ses->server->secMode &
|
||||||
|
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
||||||
pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
||||||
|
|
||||||
if (ses->capabilities & CAP_UNICODE) {
|
if (ses->capabilities & CAP_UNICODE) {
|
||||||
|
@ -74,10 +75,10 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
|
||||||
return capabilities;
|
return capabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
|
||||||
const struct nls_table * nls_cp)
|
const struct nls_table *nls_cp)
|
||||||
{
|
{
|
||||||
char * bcc_ptr = *pbcc_area;
|
char *bcc_ptr = *pbcc_area;
|
||||||
int bytes_ret = 0;
|
int bytes_ret = 0;
|
||||||
|
|
||||||
/* BB FIXME add check that strings total less
|
/* BB FIXME add check that strings total less
|
||||||
|
@ -89,7 +90,7 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
||||||
bcc_ptr++;
|
bcc_ptr++;
|
||||||
} */
|
} */
|
||||||
/* copy user */
|
/* copy user */
|
||||||
if(ses->userName == NULL) {
|
if (ses->userName == NULL) {
|
||||||
/* null user mount */
|
/* null user mount */
|
||||||
*bcc_ptr = 0;
|
*bcc_ptr = 0;
|
||||||
*(bcc_ptr+1) = 0;
|
*(bcc_ptr+1) = 0;
|
||||||
|
@ -100,7 +101,7 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
||||||
bcc_ptr += 2 * bytes_ret;
|
bcc_ptr += 2 * bytes_ret;
|
||||||
bcc_ptr += 2; /* account for null termination */
|
bcc_ptr += 2; /* account for null termination */
|
||||||
/* copy domain */
|
/* copy domain */
|
||||||
if(ses->domainName == NULL) {
|
if (ses->domainName == NULL) {
|
||||||
/* Sending null domain better than using a bogus domain name (as
|
/* Sending null domain better than using a bogus domain name (as
|
||||||
we did briefly in 2.6.18) since server will use its default */
|
we did briefly in 2.6.18) since server will use its default */
|
||||||
*bcc_ptr = 0;
|
*bcc_ptr = 0;
|
||||||
|
@ -129,15 +130,15 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
||||||
*pbcc_area = bcc_ptr;
|
*pbcc_area = bcc_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
|
||||||
const struct nls_table * nls_cp)
|
const struct nls_table *nls_cp)
|
||||||
{
|
{
|
||||||
char * bcc_ptr = *pbcc_area;
|
char *bcc_ptr = *pbcc_area;
|
||||||
|
|
||||||
/* copy user */
|
/* copy user */
|
||||||
/* BB what about null user mounts - check that we do this BB */
|
/* BB what about null user mounts - check that we do this BB */
|
||||||
/* copy user */
|
/* copy user */
|
||||||
if(ses->userName == NULL) {
|
if (ses->userName == NULL) {
|
||||||
/* BB what about null user mounts - check that we do this BB */
|
/* BB what about null user mounts - check that we do this BB */
|
||||||
} else { /* 300 should be long enough for any conceivable user name */
|
} else { /* 300 should be long enough for any conceivable user name */
|
||||||
strncpy(bcc_ptr, ses->userName, 300);
|
strncpy(bcc_ptr, ses->userName, 300);
|
||||||
|
@ -149,7 +150,7 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
||||||
|
|
||||||
/* copy domain */
|
/* copy domain */
|
||||||
|
|
||||||
if(ses->domainName != NULL) {
|
if (ses->domainName != NULL) {
|
||||||
strncpy(bcc_ptr, ses->domainName, 256);
|
strncpy(bcc_ptr, ses->domainName, 256);
|
||||||
bcc_ptr += strnlen(ses->domainName, 256);
|
bcc_ptr += strnlen(ses->domainName, 256);
|
||||||
} /* else we will send a null domain name
|
} /* else we will send a null domain name
|
||||||
|
@ -170,16 +171,17 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
||||||
*pbcc_area = bcc_ptr;
|
*pbcc_area = bcc_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
|
static int decode_unicode_ssetup(char **pbcc_area, int bleft,
|
||||||
const struct nls_table * nls_cp)
|
struct cifsSesInfo *ses,
|
||||||
|
const struct nls_table *nls_cp)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int words_left, len;
|
int words_left, len;
|
||||||
char * data = *pbcc_area;
|
char *data = *pbcc_area;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cFYI(1,("bleft %d",bleft));
|
cFYI(1, ("bleft %d", bleft));
|
||||||
|
|
||||||
|
|
||||||
/* SMB header is unaligned, so cifs servers word align start of
|
/* SMB header is unaligned, so cifs servers word align start of
|
||||||
|
@ -198,14 +200,14 @@ static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInf
|
||||||
/* We look for obvious messed up bcc or strings in response so we do not go off
|
/* We look for obvious messed up bcc or strings in response so we do not go off
|
||||||
the end since (at least) WIN2K and Windows XP have a major bug in not null
|
the end since (at least) WIN2K and Windows XP have a major bug in not null
|
||||||
terminating last Unicode string in response */
|
terminating last Unicode string in response */
|
||||||
if(len >= words_left)
|
if (len >= words_left)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if(ses->serverOS)
|
if (ses->serverOS)
|
||||||
kfree(ses->serverOS);
|
kfree(ses->serverOS);
|
||||||
/* UTF-8 string will not grow more than four times as big as UCS-16 */
|
/* UTF-8 string will not grow more than four times as big as UCS-16 */
|
||||||
ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
|
ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
|
||||||
if(ses->serverOS != NULL) {
|
if (ses->serverOS != NULL) {
|
||||||
cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
|
cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
|
||||||
nls_cp);
|
nls_cp);
|
||||||
}
|
}
|
||||||
|
@ -215,17 +217,17 @@ static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInf
|
||||||
/* save off server network operating system */
|
/* save off server network operating system */
|
||||||
len = UniStrnlen((wchar_t *) data, words_left);
|
len = UniStrnlen((wchar_t *) data, words_left);
|
||||||
|
|
||||||
if(len >= words_left)
|
if (len >= words_left)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if(ses->serverNOS)
|
if (ses->serverNOS)
|
||||||
kfree(ses->serverNOS);
|
kfree(ses->serverNOS);
|
||||||
ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
|
ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
|
||||||
if(ses->serverNOS != NULL) {
|
if (ses->serverNOS != NULL) {
|
||||||
cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
|
cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
|
||||||
nls_cp);
|
nls_cp);
|
||||||
if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) {
|
if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) {
|
||||||
cFYI(1,("NT4 server"));
|
cFYI(1, ("NT4 server"));
|
||||||
ses->flags |= CIFS_SES_NT4;
|
ses->flags |= CIFS_SES_NT4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,13 +237,13 @@ static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInf
|
||||||
/* save off server domain */
|
/* save off server domain */
|
||||||
len = UniStrnlen((wchar_t *) data, words_left);
|
len = UniStrnlen((wchar_t *) data, words_left);
|
||||||
|
|
||||||
if(len > words_left)
|
if (len > words_left)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if(ses->serverDomain)
|
if (ses->serverDomain)
|
||||||
kfree(ses->serverDomain);
|
kfree(ses->serverDomain);
|
||||||
ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
|
ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
|
||||||
if(ses->serverDomain != NULL) {
|
if (ses->serverDomain != NULL) {
|
||||||
cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
|
cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
|
||||||
nls_cp);
|
nls_cp);
|
||||||
ses->serverDomain[2*len] = 0;
|
ses->serverDomain[2*len] = 0;
|
||||||
|
@ -250,32 +252,33 @@ static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInf
|
||||||
data += 2 * (len + 1);
|
data += 2 * (len + 1);
|
||||||
words_left -= len + 1;
|
words_left -= len + 1;
|
||||||
|
|
||||||
cFYI(1,("words left: %d",words_left));
|
cFYI(1, ("words left: %d", words_left));
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
|
static int decode_ascii_ssetup(char **pbcc_area, int bleft,
|
||||||
const struct nls_table * nls_cp)
|
struct cifsSesInfo *ses,
|
||||||
|
const struct nls_table *nls_cp)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int len;
|
int len;
|
||||||
char * bcc_ptr = *pbcc_area;
|
char *bcc_ptr = *pbcc_area;
|
||||||
|
|
||||||
cFYI(1,("decode sessetup ascii. bleft %d", bleft));
|
cFYI(1, ("decode sessetup ascii. bleft %d", bleft));
|
||||||
|
|
||||||
len = strnlen(bcc_ptr, bleft);
|
len = strnlen(bcc_ptr, bleft);
|
||||||
if(len >= bleft)
|
if (len >= bleft)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if(ses->serverOS)
|
if (ses->serverOS)
|
||||||
kfree(ses->serverOS);
|
kfree(ses->serverOS);
|
||||||
|
|
||||||
ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
|
ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
|
||||||
if(ses->serverOS)
|
if (ses->serverOS)
|
||||||
strncpy(ses->serverOS, bcc_ptr, len);
|
strncpy(ses->serverOS, bcc_ptr, len);
|
||||||
if(strncmp(ses->serverOS, "OS/2",4) == 0) {
|
if (strncmp(ses->serverOS, "OS/2", 4) == 0) {
|
||||||
cFYI(1,("OS/2 server"));
|
cFYI(1, ("OS/2 server"));
|
||||||
ses->flags |= CIFS_SES_OS2;
|
ses->flags |= CIFS_SES_OS2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,21 +286,21 @@ static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo
|
||||||
bleft -= len + 1;
|
bleft -= len + 1;
|
||||||
|
|
||||||
len = strnlen(bcc_ptr, bleft);
|
len = strnlen(bcc_ptr, bleft);
|
||||||
if(len >= bleft)
|
if (len >= bleft)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if(ses->serverNOS)
|
if (ses->serverNOS)
|
||||||
kfree(ses->serverNOS);
|
kfree(ses->serverNOS);
|
||||||
|
|
||||||
ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
|
ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
|
||||||
if(ses->serverNOS)
|
if (ses->serverNOS)
|
||||||
strncpy(ses->serverNOS, bcc_ptr, len);
|
strncpy(ses->serverNOS, bcc_ptr, len);
|
||||||
|
|
||||||
bcc_ptr += len + 1;
|
bcc_ptr += len + 1;
|
||||||
bleft -= len + 1;
|
bleft -= len + 1;
|
||||||
|
|
||||||
len = strnlen(bcc_ptr, bleft);
|
len = strnlen(bcc_ptr, bleft);
|
||||||
if(len > bleft)
|
if (len > bleft)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
/* No domain field in LANMAN case. Domain is
|
/* No domain field in LANMAN case. Domain is
|
||||||
|
@ -305,7 +308,7 @@ static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo
|
||||||
/* BB For newer servers which do not support Unicode,
|
/* BB For newer servers which do not support Unicode,
|
||||||
but thus do return domain here we could add parsing
|
but thus do return domain here we could add parsing
|
||||||
for it later, but it is not very important */
|
for it later, but it is not very important */
|
||||||
cFYI(1,("ascii: bytes left %d",bleft));
|
cFYI(1, ("ascii: bytes left %d", bleft));
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -328,13 +331,13 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
__u16 action;
|
__u16 action;
|
||||||
int bytes_remaining;
|
int bytes_remaining;
|
||||||
|
|
||||||
if(ses == NULL)
|
if (ses == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
type = ses->server->secType;
|
type = ses->server->secType;
|
||||||
|
|
||||||
cFYI(1,("sess setup type %d",type));
|
cFYI(1, ("sess setup type %d", type));
|
||||||
if(type == LANMAN) {
|
if (type == LANMAN) {
|
||||||
#ifndef CONFIG_CIFS_WEAK_PW_HASH
|
#ifndef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
/* LANMAN and plaintext are less secure and off by default.
|
/* LANMAN and plaintext are less secure and off by default.
|
||||||
So we make this explicitly be turned on in kconfig (in the
|
So we make this explicitly be turned on in kconfig (in the
|
||||||
|
@ -344,15 +347,15 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
#endif
|
#endif
|
||||||
wct = 10; /* lanman 2 style sessionsetup */
|
wct = 10; /* lanman 2 style sessionsetup */
|
||||||
} else if((type == NTLM) || (type == NTLMv2)) {
|
} else if ((type == NTLM) || (type == NTLMv2)) {
|
||||||
/* For NTLMv2 failures eventually may need to retry NTLM */
|
/* For NTLMv2 failures eventually may need to retry NTLM */
|
||||||
wct = 13; /* old style NTLM sessionsetup */
|
wct = 13; /* old style NTLM sessionsetup */
|
||||||
} else /* same size for negotiate or auth, NTLMSSP or extended security */
|
} else /* same size: negotiate or auth, NTLMSSP or extended security */
|
||||||
wct = 12;
|
wct = 12;
|
||||||
|
|
||||||
rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
|
rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
|
||||||
(void **)&smb_buf);
|
(void **)&smb_buf);
|
||||||
if(rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
pSMB = (SESSION_SETUP_ANDX *)smb_buf;
|
pSMB = (SESSION_SETUP_ANDX *)smb_buf;
|
||||||
|
@ -373,7 +376,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
|
|
||||||
ses->flags &= ~CIFS_SES_LANMAN;
|
ses->flags &= ~CIFS_SES_LANMAN;
|
||||||
|
|
||||||
if(type == LANMAN) {
|
if (type == LANMAN) {
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
char lnm_session_key[CIFS_SESS_KEY_SIZE];
|
char lnm_session_key[CIFS_SESS_KEY_SIZE];
|
||||||
|
|
||||||
|
@ -397,7 +400,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
changed to do higher than lanman dialect and
|
changed to do higher than lanman dialect and
|
||||||
we reconnected would we ever calc signing_key? */
|
we reconnected would we ever calc signing_key? */
|
||||||
|
|
||||||
cFYI(1,("Negotiating LANMAN setting up strings"));
|
cFYI(1, ("Negotiating LANMAN setting up strings"));
|
||||||
/* Unicode not allowed for LANMAN dialects */
|
/* Unicode not allowed for LANMAN dialects */
|
||||||
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||||
#endif
|
#endif
|
||||||
|
@ -414,17 +417,17 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
SMBNTencrypt(ses->password, ses->server->cryptKey,
|
SMBNTencrypt(ses->password, ses->server->cryptKey,
|
||||||
ntlm_session_key);
|
ntlm_session_key);
|
||||||
|
|
||||||
if(first_time) /* should this be moved into common code
|
if (first_time) /* should this be moved into common code
|
||||||
with similar ntlmv2 path? */
|
with similar ntlmv2 path? */
|
||||||
cifs_calculate_mac_key(ses->server->mac_signing_key,
|
cifs_calculate_mac_key(&ses->server->mac_signing_key,
|
||||||
ntlm_session_key, ses->password);
|
ntlm_session_key, ses->password);
|
||||||
/* copy session key */
|
/* copy session key */
|
||||||
|
|
||||||
memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
|
memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
|
||||||
bcc_ptr += CIFS_SESS_KEY_SIZE;
|
bcc_ptr += CIFS_SESS_KEY_SIZE;
|
||||||
memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
|
memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
|
||||||
bcc_ptr += CIFS_SESS_KEY_SIZE;
|
bcc_ptr += CIFS_SESS_KEY_SIZE;
|
||||||
if(ses->capabilities & CAP_UNICODE) {
|
if (ses->capabilities & CAP_UNICODE) {
|
||||||
/* unicode strings must be word aligned */
|
/* unicode strings must be word aligned */
|
||||||
if (iov[0].iov_len % 2) {
|
if (iov[0].iov_len % 2) {
|
||||||
*bcc_ptr = 0;
|
*bcc_ptr = 0;
|
||||||
|
@ -434,13 +437,13 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
} else
|
} else
|
||||||
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||||
} else if (type == NTLMv2) {
|
} else if (type == NTLMv2) {
|
||||||
char * v2_sess_key =
|
char *v2_sess_key =
|
||||||
kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
|
kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
|
||||||
|
|
||||||
/* BB FIXME change all users of v2_sess_key to
|
/* BB FIXME change all users of v2_sess_key to
|
||||||
struct ntlmv2_resp */
|
struct ntlmv2_resp */
|
||||||
|
|
||||||
if(v2_sess_key == NULL) {
|
if (v2_sess_key == NULL) {
|
||||||
cifs_small_buf_release(smb_buf);
|
cifs_small_buf_release(smb_buf);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -456,7 +459,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
|
|
||||||
/* calculate session key */
|
/* calculate session key */
|
||||||
setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
|
setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
|
||||||
if(first_time) /* should this be moved into common code
|
if (first_time) /* should this be moved into common code
|
||||||
with similar ntlmv2 path? */
|
with similar ntlmv2 path? */
|
||||||
/* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
|
/* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
|
||||||
response BB FIXME, v2_sess_key); */
|
response BB FIXME, v2_sess_key); */
|
||||||
|
@ -465,11 +468,12 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
|
|
||||||
/* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
|
/* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
|
||||||
bcc_ptr += LM2_SESS_KEY_SIZE; */
|
bcc_ptr += LM2_SESS_KEY_SIZE; */
|
||||||
memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp));
|
memcpy(bcc_ptr, (char *)v2_sess_key,
|
||||||
|
sizeof(struct ntlmv2_resp));
|
||||||
bcc_ptr += sizeof(struct ntlmv2_resp);
|
bcc_ptr += sizeof(struct ntlmv2_resp);
|
||||||
kfree(v2_sess_key);
|
kfree(v2_sess_key);
|
||||||
if(ses->capabilities & CAP_UNICODE) {
|
if (ses->capabilities & CAP_UNICODE) {
|
||||||
if(iov[0].iov_len % 2) {
|
if (iov[0].iov_len % 2) {
|
||||||
*bcc_ptr = 0;
|
*bcc_ptr = 0;
|
||||||
} bcc_ptr++;
|
} bcc_ptr++;
|
||||||
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||||
|
@ -492,16 +496,16 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
|
rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
|
||||||
/* SMB request buf freed in SendReceive2 */
|
/* SMB request buf freed in SendReceive2 */
|
||||||
|
|
||||||
cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
|
cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
|
||||||
if(rc)
|
if (rc)
|
||||||
goto ssetup_exit;
|
goto ssetup_exit;
|
||||||
|
|
||||||
pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
|
pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
|
||||||
smb_buf = (struct smb_hdr *)iov[0].iov_base;
|
smb_buf = (struct smb_hdr *)iov[0].iov_base;
|
||||||
|
|
||||||
if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
|
if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
cERROR(1,("bad word count %d", smb_buf->WordCount));
|
cERROR(1, ("bad word count %d", smb_buf->WordCount));
|
||||||
goto ssetup_exit;
|
goto ssetup_exit;
|
||||||
}
|
}
|
||||||
action = le16_to_cpu(pSMB->resp.Action);
|
action = le16_to_cpu(pSMB->resp.Action);
|
||||||
|
@ -514,12 +518,12 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
bytes_remaining = BCC(smb_buf);
|
bytes_remaining = BCC(smb_buf);
|
||||||
bcc_ptr = pByteArea(smb_buf);
|
bcc_ptr = pByteArea(smb_buf);
|
||||||
|
|
||||||
if(smb_buf->WordCount == 4) {
|
if (smb_buf->WordCount == 4) {
|
||||||
__u16 blob_len;
|
__u16 blob_len;
|
||||||
blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
|
blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
|
||||||
bcc_ptr += blob_len;
|
bcc_ptr += blob_len;
|
||||||
if(blob_len > bytes_remaining) {
|
if (blob_len > bytes_remaining) {
|
||||||
cERROR(1,("bad security blob length %d", blob_len));
|
cERROR(1, ("bad security blob length %d", blob_len));
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto ssetup_exit;
|
goto ssetup_exit;
|
||||||
}
|
}
|
||||||
|
@ -527,18 +531,19 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BB check if Unicode and decode strings */
|
/* BB check if Unicode and decode strings */
|
||||||
if(smb_buf->Flags2 & SMBFLG2_UNICODE)
|
if (smb_buf->Flags2 & SMBFLG2_UNICODE)
|
||||||
rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
|
rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
|
||||||
ses, nls_cp);
|
ses, nls_cp);
|
||||||
else
|
else
|
||||||
rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
|
rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining,
|
||||||
|
ses, nls_cp);
|
||||||
|
|
||||||
ssetup_exit:
|
ssetup_exit:
|
||||||
kfree(str_area);
|
kfree(str_area);
|
||||||
if(resp_buf_type == CIFS_SMALL_BUFFER) {
|
if (resp_buf_type == CIFS_SMALL_BUFFER) {
|
||||||
cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
|
cFYI(1, ("ssetup freeing small buf %p", iov[0].iov_base));
|
||||||
cifs_small_buf_release(iov[0].iov_base);
|
cifs_small_buf_release(iov[0].iov_base);
|
||||||
} else if(resp_buf_type == CIFS_LARGE_BUFFER)
|
} else if (resp_buf_type == CIFS_LARGE_BUFFER)
|
||||||
cifs_buf_release(iov[0].iov_base);
|
cifs_buf_release(iov[0].iov_base);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -153,7 +153,7 @@ static uchar sbox[8][4][16] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
permute(char *out, char *in, uchar * p, int n)
|
permute(char *out, char *in, uchar *p, int n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
|
@ -202,18 +202,18 @@ dohash(char *out, char *in, char *key, int forw)
|
||||||
char *rl;
|
char *rl;
|
||||||
|
|
||||||
/* Have to reduce stack usage */
|
/* Have to reduce stack usage */
|
||||||
pk1 = kmalloc(56+56+64+64,GFP_KERNEL);
|
pk1 = kmalloc(56+56+64+64, GFP_KERNEL);
|
||||||
if(pk1 == NULL)
|
if (pk1 == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ki = kmalloc(16*48, GFP_KERNEL);
|
ki = kmalloc(16*48, GFP_KERNEL);
|
||||||
if(ki == NULL) {
|
if (ki == NULL) {
|
||||||
kfree(pk1);
|
kfree(pk1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cd = pk1 + 56;
|
cd = pk1 + 56;
|
||||||
pd1= cd + 56;
|
pd1 = cd + 56;
|
||||||
rl = pd1 + 64;
|
rl = pd1 + 64;
|
||||||
|
|
||||||
permute(pk1, key, perm1, 56);
|
permute(pk1, key, perm1, 56);
|
||||||
|
@ -247,7 +247,7 @@ dohash(char *out, char *in, char *key, int forw)
|
||||||
char *r2; /* r2[32] */
|
char *r2; /* r2[32] */
|
||||||
|
|
||||||
er = kmalloc(48+48+32+32+32, GFP_KERNEL);
|
er = kmalloc(48+48+32+32+32, GFP_KERNEL);
|
||||||
if(er == NULL) {
|
if (er == NULL) {
|
||||||
kfree(pk1);
|
kfree(pk1);
|
||||||
kfree(ki);
|
kfree(ki);
|
||||||
return;
|
return;
|
||||||
|
@ -327,8 +327,8 @@ smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
|
||||||
char *keyb; /* keyb[64] */
|
char *keyb; /* keyb[64] */
|
||||||
unsigned char key2[8];
|
unsigned char key2[8];
|
||||||
|
|
||||||
outb = kmalloc(64 * 3,GFP_KERNEL);
|
outb = kmalloc(64 * 3, GFP_KERNEL);
|
||||||
if(outb == NULL)
|
if (outb == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
inb = outb + 64;
|
inb = outb + 64;
|
||||||
|
|
|
@ -74,8 +74,8 @@ SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
|
||||||
|
|
||||||
SMBOWFencrypt(p21, c8, p24);
|
SMBOWFencrypt(p21, c8, p24);
|
||||||
|
|
||||||
memset(p14,0,15);
|
memset(p14, 0, 15);
|
||||||
memset(p21,0,21);
|
memset(p21, 0, 21);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Routines for Windows NT MD4 Hash functions. */
|
/* Routines for Windows NT MD4 Hash functions. */
|
||||||
|
@ -97,7 +97,7 @@ _my_wcslen(__u16 * str)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
|
_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
|
||||||
{ /* not a very good conversion routine - change/fix */
|
{ /* BB not a very good conversion routine - change/fix */
|
||||||
int i;
|
int i;
|
||||||
__u16 val;
|
__u16 val;
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16)
|
||||||
__u16 wpwd[129];
|
__u16 wpwd[129];
|
||||||
|
|
||||||
/* Password cannot be longer than 128 characters */
|
/* Password cannot be longer than 128 characters */
|
||||||
if(passwd) {
|
if (passwd) {
|
||||||
len = strlen((char *) passwd);
|
len = strlen((char *) passwd);
|
||||||
if (len > 128) {
|
if (len > 128) {
|
||||||
len = 128;
|
len = 128;
|
||||||
|
@ -138,7 +138,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16)
|
||||||
len = _my_wcslen(wpwd) * sizeof (__u16);
|
len = _my_wcslen(wpwd) * sizeof (__u16);
|
||||||
|
|
||||||
mdfour(p16, (unsigned char *) wpwd, len);
|
mdfour(p16, (unsigned char *) wpwd, len);
|
||||||
memset(wpwd,0,129 * 2);
|
memset(wpwd, 0, 129 * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* currently unused */
|
#if 0 /* currently unused */
|
||||||
|
@ -178,14 +178,14 @@ ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
|
||||||
const char *domain_n, unsigned char kr_buf[16],
|
const char *domain_n, unsigned char kr_buf[16],
|
||||||
const struct nls_table *nls_codepage)
|
const struct nls_table *nls_codepage)
|
||||||
{
|
{
|
||||||
wchar_t * user_u;
|
wchar_t *user_u;
|
||||||
wchar_t * dom_u;
|
wchar_t *dom_u;
|
||||||
int user_l, domain_l;
|
int user_l, domain_l;
|
||||||
struct HMACMD5Context ctx;
|
struct HMACMD5Context ctx;
|
||||||
|
|
||||||
/* might as well do one alloc to hold both (user_u and dom_u) */
|
/* might as well do one alloc to hold both (user_u and dom_u) */
|
||||||
user_u = kmalloc(2048 * sizeof(wchar_t),GFP_KERNEL);
|
user_u = kmalloc(2048 * sizeof(wchar_t), GFP_KERNEL);
|
||||||
if(user_u == NULL)
|
if (user_u == NULL)
|
||||||
return;
|
return;
|
||||||
dom_u = user_u + 1024;
|
dom_u = user_u + 1024;
|
||||||
|
|
||||||
|
@ -256,8 +256,8 @@ SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
|
||||||
#if 0
|
#if 0
|
||||||
static void
|
static void
|
||||||
SMBOWFencrypt_ntv2(const unsigned char kr[16],
|
SMBOWFencrypt_ntv2(const unsigned char kr[16],
|
||||||
const struct data_blob * srv_chal,
|
const struct data_blob *srv_chal,
|
||||||
const struct data_blob * cli_chal, unsigned char resp_buf[16])
|
const struct data_blob *cli_chal, unsigned char resp_buf[16])
|
||||||
{
|
{
|
||||||
struct HMACMD5Context ctx;
|
struct HMACMD5Context ctx;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/transport.c
|
* fs/cifs/transport.c
|
||||||
*
|
*
|
||||||
* Copyright (C) International Business Machines Corp., 2002,2005
|
* Copyright (C) International Business Machines Corp., 2002,2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
* Jeremy Allison (jra@samba.org) 2006.
|
* Jeremy Allison (jra@samba.org) 2006.
|
||||||
*
|
*
|
||||||
|
@ -86,7 +86,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
|
||||||
list_del(&midEntry->qhead);
|
list_del(&midEntry->qhead);
|
||||||
atomic_dec(&midCount);
|
atomic_dec(&midCount);
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
if(midEntry->largeBuf)
|
if (midEntry->largeBuf)
|
||||||
cifs_buf_release(midEntry->resp_buf);
|
cifs_buf_release(midEntry->resp_buf);
|
||||||
else
|
else
|
||||||
cifs_small_buf_release(midEntry->resp_buf);
|
cifs_small_buf_release(midEntry->resp_buf);
|
||||||
|
@ -94,8 +94,8 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
|
||||||
now = jiffies;
|
now = jiffies;
|
||||||
/* commands taking longer than one second are indications that
|
/* commands taking longer than one second are indications that
|
||||||
something is wrong, unless it is quite a slow link or server */
|
something is wrong, unless it is quite a slow link or server */
|
||||||
if((now - midEntry->when_alloc) > HZ) {
|
if ((now - midEntry->when_alloc) > HZ) {
|
||||||
if((cifsFYI & CIFS_TIMER) &&
|
if ((cifsFYI & CIFS_TIMER) &&
|
||||||
(midEntry->command != SMB_COM_LOCKING_ANDX)) {
|
(midEntry->command != SMB_COM_LOCKING_ANDX)) {
|
||||||
printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
|
printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
|
||||||
midEntry->command, midEntry->mid);
|
midEntry->command, midEntry->mid);
|
||||||
|
@ -110,10 +110,10 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct oplock_q_entry *
|
struct oplock_q_entry *
|
||||||
AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
|
AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon)
|
||||||
{
|
{
|
||||||
struct oplock_q_entry *temp;
|
struct oplock_q_entry *temp;
|
||||||
if ((pinode== NULL) || (tcon == NULL)) {
|
if ((pinode == NULL) || (tcon == NULL)) {
|
||||||
cERROR(1, ("Null parms passed to AllocOplockQEntry"));
|
cERROR(1, ("Null parms passed to AllocOplockQEntry"));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
|
void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry)
|
||||||
{
|
{
|
||||||
spin_lock(&GlobalMid_Lock);
|
spin_lock(&GlobalMid_Lock);
|
||||||
/* should we check if list empty first? */
|
/* should we check if list empty first? */
|
||||||
|
@ -152,7 +152,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
|
||||||
struct kvec iov;
|
struct kvec iov;
|
||||||
unsigned len = smb_buf_length + 4;
|
unsigned len = smb_buf_length + 4;
|
||||||
|
|
||||||
if(ssocket == NULL)
|
if (ssocket == NULL)
|
||||||
return -ENOTSOCK; /* BB eventually add reconnect code here */
|
return -ENOTSOCK; /* BB eventually add reconnect code here */
|
||||||
iov.iov_base = smb_buffer;
|
iov.iov_base = smb_buffer;
|
||||||
iov.iov_len = len;
|
iov.iov_len = len;
|
||||||
|
@ -179,7 +179,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
|
||||||
/* smaller timeout here than send2 since smaller size */
|
/* smaller timeout here than send2 since smaller size */
|
||||||
/* Although it may not be required, this also is smaller
|
/* Although it may not be required, this also is smaller
|
||||||
oplock break time */
|
oplock break time */
|
||||||
if(i > 12) {
|
if (i > 12) {
|
||||||
cERROR(1,
|
cERROR(1,
|
||||||
("sends on sock %p stuck for 7 seconds",
|
("sends on sock %p stuck for 7 seconds",
|
||||||
ssocket));
|
ssocket));
|
||||||
|
@ -199,7 +199,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
cERROR(1,("Error %d sending data on socket to server", rc));
|
cERROR(1, ("Error %d sending data on socket to server", rc));
|
||||||
} else {
|
} else {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
|
||||||
int first_vec = 0;
|
int first_vec = 0;
|
||||||
unsigned int smb_buf_length = smb_buffer->smb_buf_length;
|
unsigned int smb_buf_length = smb_buffer->smb_buf_length;
|
||||||
|
|
||||||
if(ssocket == NULL)
|
if (ssocket == NULL)
|
||||||
return -ENOTSOCK; /* BB eventually add reconnect code here */
|
return -ENOTSOCK; /* BB eventually add reconnect code here */
|
||||||
|
|
||||||
smb_msg.msg_name = sin;
|
smb_msg.msg_name = sin;
|
||||||
|
@ -252,7 +252,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
|
||||||
n_vec - first_vec, total_len);
|
n_vec - first_vec, total_len);
|
||||||
if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
|
if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
|
||||||
i++;
|
i++;
|
||||||
if(i >= 14) {
|
if (i >= 14) {
|
||||||
cERROR(1,
|
cERROR(1,
|
||||||
("sends on sock %p stuck for 15 seconds",
|
("sends on sock %p stuck for 15 seconds",
|
||||||
ssocket));
|
ssocket));
|
||||||
|
@ -269,10 +269,10 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
|
||||||
WARN_ON(rc > total_len);
|
WARN_ON(rc > total_len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(rc == 0) {
|
if (rc == 0) {
|
||||||
/* should never happen, letting socket clear before
|
/* should never happen, letting socket clear before
|
||||||
retrying is our only obvious option here */
|
retrying is our only obvious option here */
|
||||||
cERROR(1,("tcp sent no data"));
|
cERROR(1, ("tcp sent no data"));
|
||||||
msleep(500);
|
msleep(500);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -295,7 +295,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
cERROR(1,("Error %d sending data on socket to server", rc));
|
cERROR(1, ("Error %d sending data on socket to server", rc));
|
||||||
} else
|
} else
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
|
||||||
|
@ -308,13 +308,13 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
|
||||||
|
|
||||||
static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
|
static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
|
||||||
{
|
{
|
||||||
if(long_op == -1) {
|
if (long_op == -1) {
|
||||||
/* oplock breaks must not be held up */
|
/* oplock breaks must not be held up */
|
||||||
atomic_inc(&ses->server->inFlight);
|
atomic_inc(&ses->server->inFlight);
|
||||||
} else {
|
} else {
|
||||||
spin_lock(&GlobalMid_Lock);
|
spin_lock(&GlobalMid_Lock);
|
||||||
while(1) {
|
while (1) {
|
||||||
if(atomic_read(&ses->server->inFlight) >=
|
if (atomic_read(&ses->server->inFlight) >=
|
||||||
cifs_max_pending){
|
cifs_max_pending){
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
#ifdef CONFIG_CIFS_STATS2
|
#ifdef CONFIG_CIFS_STATS2
|
||||||
|
@ -328,13 +328,13 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
|
||||||
#endif
|
#endif
|
||||||
spin_lock(&GlobalMid_Lock);
|
spin_lock(&GlobalMid_Lock);
|
||||||
} else {
|
} else {
|
||||||
if(ses->server->tcpStatus == CifsExiting) {
|
if (ses->server->tcpStatus == CifsExiting) {
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* can not count locking commands against total since
|
/* can not count locking commands against total
|
||||||
they are allowed to block on server */
|
as they are allowed to block on server */
|
||||||
|
|
||||||
/* update # of requests on the wire to server */
|
/* update # of requests on the wire to server */
|
||||||
if (long_op < 3)
|
if (long_op < 3)
|
||||||
|
@ -353,11 +353,11 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
|
||||||
if (ses->server->tcpStatus == CifsExiting) {
|
if (ses->server->tcpStatus == CifsExiting) {
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
} else if (ses->server->tcpStatus == CifsNeedReconnect) {
|
} else if (ses->server->tcpStatus == CifsNeedReconnect) {
|
||||||
cFYI(1,("tcp session dead - return to caller to retry"));
|
cFYI(1, ("tcp session dead - return to caller to retry"));
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
} else if (ses->status != CifsGood) {
|
} else if (ses->status != CifsGood) {
|
||||||
/* check if SMB session is bad because we are setting it up */
|
/* check if SMB session is bad because we are setting it up */
|
||||||
if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
|
if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
|
||||||
(in_buf->Command != SMB_COM_NEGOTIATE)) {
|
(in_buf->Command != SMB_COM_NEGOTIATE)) {
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
} /* else ok - we are setting up session */
|
} /* else ok - we are setting up session */
|
||||||
|
@ -407,7 +407,7 @@ static int wait_for_response(struct cifsSesInfo *ses,
|
||||||
lrt += time_to_wait;
|
lrt += time_to_wait;
|
||||||
if (time_after(jiffies, lrt)) {
|
if (time_after(jiffies, lrt)) {
|
||||||
/* No replies for time_to_wait. */
|
/* No replies for time_to_wait. */
|
||||||
cERROR(1,("server not responding"));
|
cERROR(1, ("server not responding"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -418,7 +418,7 @@ static int wait_for_response(struct cifsSesInfo *ses,
|
||||||
|
|
||||||
int
|
int
|
||||||
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
|
struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
|
||||||
const int long_op)
|
const int long_op)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
@ -431,11 +431,11 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
|
|
||||||
if ((ses == NULL) || (ses->server == NULL)) {
|
if ((ses == NULL) || (ses->server == NULL)) {
|
||||||
cifs_small_buf_release(in_buf);
|
cifs_small_buf_release(in_buf);
|
||||||
cERROR(1,("Null session"));
|
cERROR(1, ("Null session"));
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ses->server->tcpStatus == CifsExiting) {
|
if (ses->server->tcpStatus == CifsExiting) {
|
||||||
cifs_small_buf_release(in_buf);
|
cifs_small_buf_release(in_buf);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
@ -482,7 +482,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
up(&ses->server->tcpSem);
|
up(&ses->server->tcpSem);
|
||||||
cifs_small_buf_release(in_buf);
|
cifs_small_buf_release(in_buf);
|
||||||
|
|
||||||
if(rc < 0)
|
if (rc < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (long_op == -1)
|
if (long_op == -1)
|
||||||
|
@ -511,10 +511,10 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
receive_len = midQ->resp_buf->smb_buf_length;
|
receive_len = midQ->resp_buf->smb_buf_length;
|
||||||
} else {
|
} else {
|
||||||
cERROR(1,("No response to cmd %d mid %d",
|
cERROR(1, ("No response to cmd %d mid %d",
|
||||||
midQ->command, midQ->mid));
|
midQ->command, midQ->mid));
|
||||||
if(midQ->midState == MID_REQUEST_SUBMITTED) {
|
if (midQ->midState == MID_REQUEST_SUBMITTED) {
|
||||||
if(ses->server->tcpStatus == CifsExiting)
|
if (ses->server->tcpStatus == CifsExiting)
|
||||||
rc = -EHOSTDOWN;
|
rc = -EHOSTDOWN;
|
||||||
else {
|
else {
|
||||||
ses->server->tcpStatus = CifsNeedReconnect;
|
ses->server->tcpStatus = CifsNeedReconnect;
|
||||||
|
@ -523,9 +523,9 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc != -EHOSTDOWN) {
|
if (rc != -EHOSTDOWN) {
|
||||||
if(midQ->midState == MID_RETRY_NEEDED) {
|
if (midQ->midState == MID_RETRY_NEEDED) {
|
||||||
rc = -EAGAIN;
|
rc = -EAGAIN;
|
||||||
cFYI(1,("marking request for retry"));
|
cFYI(1, ("marking request for retry"));
|
||||||
} else {
|
} else {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
}
|
}
|
||||||
|
@ -547,7 +547,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
(midQ->midState == MID_RESPONSE_RECEIVED)) {
|
(midQ->midState == MID_RESPONSE_RECEIVED)) {
|
||||||
|
|
||||||
iov[0].iov_base = (char *)midQ->resp_buf;
|
iov[0].iov_base = (char *)midQ->resp_buf;
|
||||||
if(midQ->largeBuf)
|
if (midQ->largeBuf)
|
||||||
*pRespBufType = CIFS_LARGE_BUFFER;
|
*pRespBufType = CIFS_LARGE_BUFFER;
|
||||||
else
|
else
|
||||||
*pRespBufType = CIFS_SMALL_BUFFER;
|
*pRespBufType = CIFS_SMALL_BUFFER;
|
||||||
|
@ -555,14 +555,14 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
|
|
||||||
dump_smb(midQ->resp_buf, 80);
|
dump_smb(midQ->resp_buf, 80);
|
||||||
/* convert the length into a more usable form */
|
/* convert the length into a more usable form */
|
||||||
if((receive_len > 24) &&
|
if ((receive_len > 24) &&
|
||||||
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
||||||
SECMODE_SIGN_ENABLED))) {
|
SECMODE_SIGN_ENABLED))) {
|
||||||
rc = cifs_verify_signature(midQ->resp_buf,
|
rc = cifs_verify_signature(midQ->resp_buf,
|
||||||
ses->server->mac_signing_key,
|
&ses->server->mac_signing_key,
|
||||||
midQ->sequence_number+1);
|
midQ->sequence_number+1);
|
||||||
if(rc) {
|
if (rc) {
|
||||||
cERROR(1,("Unexpected SMB signature"));
|
cERROR(1, ("Unexpected SMB signature"));
|
||||||
/* BB FIXME add code to kill session */
|
/* BB FIXME add code to kill session */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -582,7 +582,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
by DeleteMidQEntry */
|
by DeleteMidQEntry */
|
||||||
} else {
|
} else {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
cFYI(1,("Bad MID state?"));
|
cFYI(1, ("Bad MID state?"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,15 +605,15 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
struct mid_q_entry *midQ;
|
struct mid_q_entry *midQ;
|
||||||
|
|
||||||
if (ses == NULL) {
|
if (ses == NULL) {
|
||||||
cERROR(1,("Null smb session"));
|
cERROR(1, ("Null smb session"));
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
if(ses->server == NULL) {
|
if (ses->server == NULL) {
|
||||||
cERROR(1,("Null tcp session"));
|
cERROR(1, ("Null tcp session"));
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ses->server->tcpStatus == CifsExiting)
|
if (ses->server->tcpStatus == CifsExiting)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
/* Ensure that we do not send more than 50 overlapping requests
|
/* Ensure that we do not send more than 50 overlapping requests
|
||||||
|
@ -664,7 +664,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
#endif
|
#endif
|
||||||
up(&ses->server->tcpSem);
|
up(&ses->server->tcpSem);
|
||||||
|
|
||||||
if(rc < 0)
|
if (rc < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (long_op == -1)
|
if (long_op == -1)
|
||||||
|
@ -692,10 +692,10 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
receive_len = midQ->resp_buf->smb_buf_length;
|
receive_len = midQ->resp_buf->smb_buf_length;
|
||||||
} else {
|
} else {
|
||||||
cERROR(1,("No response for cmd %d mid %d",
|
cERROR(1, ("No response for cmd %d mid %d",
|
||||||
midQ->command, midQ->mid));
|
midQ->command, midQ->mid));
|
||||||
if(midQ->midState == MID_REQUEST_SUBMITTED) {
|
if (midQ->midState == MID_REQUEST_SUBMITTED) {
|
||||||
if(ses->server->tcpStatus == CifsExiting)
|
if (ses->server->tcpStatus == CifsExiting)
|
||||||
rc = -EHOSTDOWN;
|
rc = -EHOSTDOWN;
|
||||||
else {
|
else {
|
||||||
ses->server->tcpStatus = CifsNeedReconnect;
|
ses->server->tcpStatus = CifsNeedReconnect;
|
||||||
|
@ -704,9 +704,9 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc != -EHOSTDOWN) {
|
if (rc != -EHOSTDOWN) {
|
||||||
if(midQ->midState == MID_RETRY_NEEDED) {
|
if (midQ->midState == MID_RETRY_NEEDED) {
|
||||||
rc = -EAGAIN;
|
rc = -EAGAIN;
|
||||||
cFYI(1,("marking request for retry"));
|
cFYI(1, ("marking request for retry"));
|
||||||
} else {
|
} else {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
}
|
}
|
||||||
|
@ -734,14 +734,14 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
|
|
||||||
dump_smb(out_buf, 92);
|
dump_smb(out_buf, 92);
|
||||||
/* convert the length into a more usable form */
|
/* convert the length into a more usable form */
|
||||||
if((receive_len > 24) &&
|
if ((receive_len > 24) &&
|
||||||
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
||||||
SECMODE_SIGN_ENABLED))) {
|
SECMODE_SIGN_ENABLED))) {
|
||||||
rc = cifs_verify_signature(out_buf,
|
rc = cifs_verify_signature(out_buf,
|
||||||
ses->server->mac_signing_key,
|
&ses->server->mac_signing_key,
|
||||||
midQ->sequence_number+1);
|
midQ->sequence_number+1);
|
||||||
if(rc) {
|
if (rc) {
|
||||||
cERROR(1,("Unexpected SMB signature"));
|
cERROR(1, ("Unexpected SMB signature"));
|
||||||
/* BB FIXME add code to kill session */
|
/* BB FIXME add code to kill session */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -759,7 +759,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
|
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
|
||||||
} else {
|
} else {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
cERROR(1,("Bad MID state?"));
|
cERROR(1, ("Bad MID state?"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -832,17 +832,17 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
||||||
struct cifsSesInfo *ses;
|
struct cifsSesInfo *ses;
|
||||||
|
|
||||||
if (tcon == NULL || tcon->ses == NULL) {
|
if (tcon == NULL || tcon->ses == NULL) {
|
||||||
cERROR(1,("Null smb session"));
|
cERROR(1, ("Null smb session"));
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
ses = tcon->ses;
|
ses = tcon->ses;
|
||||||
|
|
||||||
if(ses->server == NULL) {
|
if (ses->server == NULL) {
|
||||||
cERROR(1,("Null tcp session"));
|
cERROR(1, ("Null tcp session"));
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ses->server->tcpStatus == CifsExiting)
|
if (ses->server->tcpStatus == CifsExiting)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
/* Ensure that we do not send more than 50 overlapping requests
|
/* Ensure that we do not send more than 50 overlapping requests
|
||||||
|
@ -887,7 +887,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
||||||
#endif
|
#endif
|
||||||
up(&ses->server->tcpSem);
|
up(&ses->server->tcpSem);
|
||||||
|
|
||||||
if(rc < 0) {
|
if (rc < 0) {
|
||||||
DeleteMidQEntry(midQ);
|
DeleteMidQEntry(midQ);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -928,7 +928,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait 5 seconds for the response. */
|
/* Wait 5 seconds for the response. */
|
||||||
if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ)==0) {
|
if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
|
||||||
/* We got the response - restart system call. */
|
/* We got the response - restart system call. */
|
||||||
rstart = 1;
|
rstart = 1;
|
||||||
}
|
}
|
||||||
|
@ -939,10 +939,10 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
receive_len = midQ->resp_buf->smb_buf_length;
|
receive_len = midQ->resp_buf->smb_buf_length;
|
||||||
} else {
|
} else {
|
||||||
cERROR(1,("No response for cmd %d mid %d",
|
cERROR(1, ("No response for cmd %d mid %d",
|
||||||
midQ->command, midQ->mid));
|
midQ->command, midQ->mid));
|
||||||
if(midQ->midState == MID_REQUEST_SUBMITTED) {
|
if (midQ->midState == MID_REQUEST_SUBMITTED) {
|
||||||
if(ses->server->tcpStatus == CifsExiting)
|
if (ses->server->tcpStatus == CifsExiting)
|
||||||
rc = -EHOSTDOWN;
|
rc = -EHOSTDOWN;
|
||||||
else {
|
else {
|
||||||
ses->server->tcpStatus = CifsNeedReconnect;
|
ses->server->tcpStatus = CifsNeedReconnect;
|
||||||
|
@ -951,9 +951,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc != -EHOSTDOWN) {
|
if (rc != -EHOSTDOWN) {
|
||||||
if(midQ->midState == MID_RETRY_NEEDED) {
|
if (midQ->midState == MID_RETRY_NEEDED) {
|
||||||
rc = -EAGAIN;
|
rc = -EAGAIN;
|
||||||
cFYI(1,("marking request for retry"));
|
cFYI(1, ("marking request for retry"));
|
||||||
} else {
|
} else {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
}
|
}
|
||||||
|
@ -978,14 +978,14 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
||||||
|
|
||||||
dump_smb(out_buf, 92);
|
dump_smb(out_buf, 92);
|
||||||
/* convert the length into a more usable form */
|
/* convert the length into a more usable form */
|
||||||
if((receive_len > 24) &&
|
if ((receive_len > 24) &&
|
||||||
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
||||||
SECMODE_SIGN_ENABLED))) {
|
SECMODE_SIGN_ENABLED))) {
|
||||||
rc = cifs_verify_signature(out_buf,
|
rc = cifs_verify_signature(out_buf,
|
||||||
ses->server->mac_signing_key,
|
&ses->server->mac_signing_key,
|
||||||
midQ->sequence_number+1);
|
midQ->sequence_number+1);
|
||||||
if(rc) {
|
if (rc) {
|
||||||
cERROR(1,("Unexpected SMB signature"));
|
cERROR(1, ("Unexpected SMB signature"));
|
||||||
/* BB FIXME add code to kill session */
|
/* BB FIXME add code to kill session */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1003,7 +1003,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
||||||
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
|
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
|
||||||
} else {
|
} else {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
cERROR(1,("Bad MID state?"));
|
cERROR(1, ("Bad MID state?"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DeleteMidQEntry(midQ);
|
DeleteMidQEntry(midQ);
|
||||||
|
|
185
fs/cifs/xattr.c
185
fs/cifs/xattr.c
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/xattr.c
|
* fs/cifs/xattr.c
|
||||||
*
|
*
|
||||||
* Copyright (c) International Business Machines Corp., 2003
|
* Copyright (c) International Business Machines Corp., 2003, 2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
@ -40,22 +40,22 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cifs_removexattr(struct dentry * direntry, const char * ea_name)
|
int cifs_removexattr(struct dentry *direntry, const char *ea_name)
|
||||||
{
|
{
|
||||||
int rc = -EOPNOTSUPP;
|
int rc = -EOPNOTSUPP;
|
||||||
#ifdef CONFIG_CIFS_XATTR
|
#ifdef CONFIG_CIFS_XATTR
|
||||||
int xid;
|
int xid;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
struct super_block * sb;
|
struct super_block *sb;
|
||||||
char * full_path;
|
char *full_path;
|
||||||
|
|
||||||
if(direntry == NULL)
|
if (direntry == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
if(direntry->d_inode == NULL)
|
if (direntry->d_inode == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
sb = direntry->d_inode->i_sb;
|
sb = direntry->d_inode->i_sb;
|
||||||
if(sb == NULL)
|
if (sb == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
|
|
||||||
|
@ -63,24 +63,26 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name)
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
|
|
||||||
full_path = build_path_from_dentry(direntry);
|
full_path = build_path_from_dentry(direntry);
|
||||||
if(full_path == NULL) {
|
if (full_path == NULL) {
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
if(ea_name == NULL) {
|
if (ea_name == NULL) {
|
||||||
cFYI(1,("Null xattr names not supported"));
|
cFYI(1, ("Null xattr names not supported"));
|
||||||
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)
|
} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5)
|
||||||
&& (strncmp(ea_name,CIFS_XATTR_OS2_PREFIX,4))) {
|
&& (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4))) {
|
||||||
cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
|
cFYI(1,
|
||||||
|
("illegal xattr request %s (only user namespace supported)",
|
||||||
|
ea_name));
|
||||||
/* BB what if no namespace prefix? */
|
/* BB what if no namespace prefix? */
|
||||||
/* Should we just pass them to server, except for
|
/* Should we just pass them to server, except for
|
||||||
system and perhaps security prefixes? */
|
system and perhaps security prefixes? */
|
||||||
} else {
|
} else {
|
||||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||||
goto remove_ea_exit;
|
goto remove_ea_exit;
|
||||||
|
|
||||||
ea_name+=5; /* skip past user. prefix */
|
ea_name += 5; /* skip past user. prefix */
|
||||||
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL,
|
rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL,
|
||||||
(__u16)0, cifs_sb->local_nls,
|
(__u16)0, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
}
|
}
|
||||||
|
@ -91,23 +93,23 @@ remove_ea_exit:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cifs_setxattr(struct dentry * direntry, const char * ea_name,
|
int cifs_setxattr(struct dentry *direntry, const char *ea_name,
|
||||||
const void * ea_value, size_t value_size, int flags)
|
const void *ea_value, size_t value_size, int flags)
|
||||||
{
|
{
|
||||||
int rc = -EOPNOTSUPP;
|
int rc = -EOPNOTSUPP;
|
||||||
#ifdef CONFIG_CIFS_XATTR
|
#ifdef CONFIG_CIFS_XATTR
|
||||||
int xid;
|
int xid;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
struct super_block * sb;
|
struct super_block *sb;
|
||||||
char * full_path;
|
char *full_path;
|
||||||
|
|
||||||
if(direntry == NULL)
|
if (direntry == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
if(direntry->d_inode == NULL)
|
if (direntry->d_inode == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
sb = direntry->d_inode->i_sb;
|
sb = direntry->d_inode->i_sb;
|
||||||
if(sb == NULL)
|
if (sb == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
|
|
||||||
|
@ -115,7 +117,7 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
|
|
||||||
full_path = build_path_from_dentry(direntry);
|
full_path = build_path_from_dentry(direntry);
|
||||||
if(full_path == NULL) {
|
if (full_path == NULL) {
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -125,63 +127,65 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
|
||||||
/* if proc/fs/cifs/streamstoxattr is set then
|
/* if proc/fs/cifs/streamstoxattr is set then
|
||||||
search server for EAs or streams to
|
search server for EAs or streams to
|
||||||
returns as xattrs */
|
returns as xattrs */
|
||||||
if(value_size > MAX_EA_VALUE_SIZE) {
|
if (value_size > MAX_EA_VALUE_SIZE) {
|
||||||
cFYI(1,("size of EA value too large"));
|
cFYI(1, ("size of EA value too large"));
|
||||||
kfree(full_path);
|
kfree(full_path);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ea_name == NULL) {
|
if (ea_name == NULL) {
|
||||||
cFYI(1,("Null xattr names not supported"));
|
cFYI(1, ("Null xattr names not supported"));
|
||||||
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
|
} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) {
|
||||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||||
goto set_ea_exit;
|
goto set_ea_exit;
|
||||||
if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
|
if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) {
|
||||||
cFYI(1,("attempt to set cifs inode metadata"));
|
cFYI(1, ("attempt to set cifs inode metadata"));
|
||||||
}
|
}
|
||||||
ea_name += 5; /* skip past user. prefix */
|
ea_name += 5; /* skip past user. prefix */
|
||||||
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
|
rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
|
||||||
(__u16)value_size, cifs_sb->local_nls,
|
(__u16)value_size, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
|
} else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) {
|
||||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||||
goto set_ea_exit;
|
goto set_ea_exit;
|
||||||
|
|
||||||
ea_name += 4; /* skip past os2. prefix */
|
ea_name += 4; /* skip past os2. prefix */
|
||||||
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
|
rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
|
||||||
(__u16)value_size, cifs_sb->local_nls,
|
(__u16)value_size, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
} else {
|
} else {
|
||||||
int temp;
|
int temp;
|
||||||
temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
|
temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
|
||||||
strlen(POSIX_ACL_XATTR_ACCESS));
|
strlen(POSIX_ACL_XATTR_ACCESS));
|
||||||
if (temp == 0) {
|
if (temp == 0) {
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
if(sb->s_flags & MS_POSIXACL)
|
if (sb->s_flags & MS_POSIXACL)
|
||||||
rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
|
rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
|
||||||
ea_value, (const int)value_size,
|
ea_value, (const int)value_size,
|
||||||
ACL_TYPE_ACCESS,cifs_sb->local_nls,
|
ACL_TYPE_ACCESS, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
cFYI(1,("set POSIX ACL rc %d",rc));
|
cFYI(1, ("set POSIX ACL rc %d", rc));
|
||||||
#else
|
#else
|
||||||
cFYI(1,("set POSIX ACL not supported"));
|
cFYI(1, ("set POSIX ACL not supported"));
|
||||||
#endif
|
#endif
|
||||||
} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
|
} else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
|
||||||
|
strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
if(sb->s_flags & MS_POSIXACL)
|
if (sb->s_flags & MS_POSIXACL)
|
||||||
rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
|
rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
|
||||||
ea_value, (const int)value_size,
|
ea_value, (const int)value_size,
|
||||||
ACL_TYPE_DEFAULT, cifs_sb->local_nls,
|
ACL_TYPE_DEFAULT, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
cFYI(1,("set POSIX default ACL rc %d",rc));
|
cFYI(1, ("set POSIX default ACL rc %d", rc));
|
||||||
#else
|
#else
|
||||||
cFYI(1,("set default POSIX ACL not supported"));
|
cFYI(1, ("set default POSIX ACL not supported"));
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
cFYI(1,("illegal xattr request %s (only user namespace supported)",ea_name));
|
cFYI(1, ("illegal xattr request %s (only user namespace"
|
||||||
|
" supported)", ea_name));
|
||||||
/* BB what if no namespace prefix? */
|
/* BB what if no namespace prefix? */
|
||||||
/* Should we just pass them to server, except for
|
/* Should we just pass them to server, except for
|
||||||
system and perhaps security prefixes? */
|
system and perhaps security prefixes? */
|
||||||
|
@ -195,23 +199,23 @@ set_ea_exit:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
|
ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
|
||||||
void * ea_value, size_t buf_size)
|
void *ea_value, size_t buf_size)
|
||||||
{
|
{
|
||||||
ssize_t rc = -EOPNOTSUPP;
|
ssize_t rc = -EOPNOTSUPP;
|
||||||
#ifdef CONFIG_CIFS_XATTR
|
#ifdef CONFIG_CIFS_XATTR
|
||||||
int xid;
|
int xid;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
struct super_block * sb;
|
struct super_block *sb;
|
||||||
char * full_path;
|
char *full_path;
|
||||||
|
|
||||||
if(direntry == NULL)
|
if (direntry == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
if(direntry->d_inode == NULL)
|
if (direntry->d_inode == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
sb = direntry->d_inode->i_sb;
|
sb = direntry->d_inode->i_sb;
|
||||||
if(sb == NULL)
|
if (sb == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
|
@ -220,38 +224,38 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
|
|
||||||
full_path = build_path_from_dentry(direntry);
|
full_path = build_path_from_dentry(direntry);
|
||||||
if(full_path == NULL) {
|
if (full_path == NULL) {
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
/* return dos attributes as pseudo xattr */
|
/* return dos attributes as pseudo xattr */
|
||||||
/* return alt name if available as pseudo attr */
|
/* return alt name if available as pseudo attr */
|
||||||
if(ea_name == NULL) {
|
if (ea_name == NULL) {
|
||||||
cFYI(1,("Null xattr names not supported"));
|
cFYI(1, ("Null xattr names not supported"));
|
||||||
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
|
} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) {
|
||||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||||
goto get_ea_exit;
|
goto get_ea_exit;
|
||||||
|
|
||||||
if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
|
if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) {
|
||||||
cFYI(1,("attempt to query cifs inode metadata"));
|
cFYI(1, ("attempt to query cifs inode metadata"));
|
||||||
/* revalidate/getattr then populate from inode */
|
/* revalidate/getattr then populate from inode */
|
||||||
} /* BB add else when above is implemented */
|
} /* BB add else when above is implemented */
|
||||||
ea_name += 5; /* skip past user. prefix */
|
ea_name += 5; /* skip past user. prefix */
|
||||||
rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
|
rc = CIFSSMBQueryEA(xid, pTcon, full_path, ea_name, ea_value,
|
||||||
buf_size, cifs_sb->local_nls,
|
buf_size, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
|
} else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) {
|
||||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||||
goto get_ea_exit;
|
goto get_ea_exit;
|
||||||
|
|
||||||
ea_name += 4; /* skip past os2. prefix */
|
ea_name += 4; /* skip past os2. prefix */
|
||||||
rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
|
rc = CIFSSMBQueryEA(xid, pTcon, full_path, ea_name, ea_value,
|
||||||
buf_size, cifs_sb->local_nls,
|
buf_size, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
} else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
|
} else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
|
||||||
strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
|
strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
if(sb->s_flags & MS_POSIXACL)
|
if (sb->s_flags & MS_POSIXACL)
|
||||||
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
|
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
|
||||||
ea_value, buf_size, ACL_TYPE_ACCESS,
|
ea_value, buf_size, ACL_TYPE_ACCESS,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
|
@ -272,30 +276,31 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
|
||||||
CIFSSMBClose(xid, pTcon, fid);
|
CIFSSMBClose(xid, pTcon, fid);
|
||||||
}
|
}
|
||||||
} */ /* BB enable after fixing up return data */
|
} */ /* BB enable after fixing up return data */
|
||||||
|
|
||||||
#else
|
#else
|
||||||
cFYI(1,("query POSIX ACL not supported yet"));
|
cFYI(1, ("query POSIX ACL not supported yet"));
|
||||||
#endif /* CONFIG_CIFS_POSIX */
|
#endif /* CONFIG_CIFS_POSIX */
|
||||||
} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,
|
} else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
|
||||||
strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
|
strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
if(sb->s_flags & MS_POSIXACL)
|
if (sb->s_flags & MS_POSIXACL)
|
||||||
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
|
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
|
||||||
ea_value, buf_size, ACL_TYPE_DEFAULT,
|
ea_value, buf_size, ACL_TYPE_DEFAULT,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
#else
|
#else
|
||||||
cFYI(1,("query POSIX default ACL not supported yet"));
|
cFYI(1, ("query POSIX default ACL not supported yet"));
|
||||||
#endif
|
#endif
|
||||||
} else if(strncmp(ea_name,
|
} else if (strncmp(ea_name,
|
||||||
CIFS_XATTR_TRUSTED_PREFIX,XATTR_TRUSTED_PREFIX_LEN) == 0) {
|
CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) {
|
||||||
cFYI(1,("Trusted xattr namespace not supported yet"));
|
cFYI(1, ("Trusted xattr namespace not supported yet"));
|
||||||
} else if(strncmp(ea_name,
|
} else if (strncmp(ea_name,
|
||||||
CIFS_XATTR_SECURITY_PREFIX,XATTR_SECURITY_PREFIX_LEN) == 0) {
|
CIFS_XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) {
|
||||||
cFYI(1,("Security xattr namespace not supported yet"));
|
cFYI(1, ("Security xattr namespace not supported yet"));
|
||||||
} else {
|
} else {
|
||||||
cFYI(1,("illegal xattr name request %s (only user namespace supported)",ea_name));
|
cFYI(1,
|
||||||
|
("illegal xattr request %s (only user namespace supported)",
|
||||||
|
ea_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We could add an additional check for streams ie
|
/* We could add an additional check for streams ie
|
||||||
|
@ -303,7 +308,7 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
|
||||||
search server for EAs or streams to
|
search server for EAs or streams to
|
||||||
returns as xattrs */
|
returns as xattrs */
|
||||||
|
|
||||||
if(rc == -EINVAL)
|
if (rc == -EINVAL)
|
||||||
rc = -EOPNOTSUPP;
|
rc = -EOPNOTSUPP;
|
||||||
|
|
||||||
get_ea_exit:
|
get_ea_exit:
|
||||||
|
@ -313,34 +318,34 @@ get_ea_exit:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
|
ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
|
||||||
{
|
{
|
||||||
ssize_t rc = -EOPNOTSUPP;
|
ssize_t rc = -EOPNOTSUPP;
|
||||||
#ifdef CONFIG_CIFS_XATTR
|
#ifdef CONFIG_CIFS_XATTR
|
||||||
int xid;
|
int xid;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
struct super_block * sb;
|
struct super_block *sb;
|
||||||
char * full_path;
|
char *full_path;
|
||||||
|
|
||||||
if(direntry == NULL)
|
if (direntry == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
if(direntry->d_inode == NULL)
|
if (direntry->d_inode == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
sb = direntry->d_inode->i_sb;
|
sb = direntry->d_inode->i_sb;
|
||||||
if(sb == NULL)
|
if (sb == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
cifs_sb = CIFS_SB(sb);
|
cifs_sb = CIFS_SB(sb);
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
|
|
||||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
|
|
||||||
full_path = build_path_from_dentry(direntry);
|
full_path = build_path_from_dentry(direntry);
|
||||||
if(full_path == NULL) {
|
if (full_path == NULL) {
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -350,7 +355,7 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
|
||||||
/* if proc/fs/cifs/streamstoxattr is set then
|
/* if proc/fs/cifs/streamstoxattr is set then
|
||||||
search server for EAs or streams to
|
search server for EAs or streams to
|
||||||
returns as xattrs */
|
returns as xattrs */
|
||||||
rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size,
|
rc = CIFSSMBQAllEAs(xid, pTcon, full_path, data, buf_size,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
|
Loading…
Add table
Reference in a new issue