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:
Коммит
789c56b7f7
|
@ -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
|
||||
------------
|
||||
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
|
||||
gids on the server do not match those of the client. Make "sec=none"
|
||||
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
|
||||
------------
|
||||
|
|
|
@ -301,10 +301,21 @@ A partial list of the supported mount options follows:
|
|||
during the local client kernel build will be used.
|
||||
If server does not support Unicode, this parameter is
|
||||
unused.
|
||||
rsize default read size (usually 16K)
|
||||
wsize default write size (usually 16K, 32K is often better over GigE)
|
||||
maximum wsize currently allowed by CIFS is 57344 (14 4096 byte
|
||||
pages)
|
||||
rsize default read size (usually 16K). The client currently
|
||||
can not use rsize larger than CIFSMaxBufSize. CIFSMaxBufSize
|
||||
defaults to 16K and may be changed (from 8K to the maximum
|
||||
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
|
||||
server may still consider the 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
|
||||
target machine done by the server software (of the server
|
||||
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
|
||||
make it easier to spot hardlinked files (as they will have
|
||||
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
|
||||
single share (since inode numbers on the servers might not
|
||||
be unique if multiple filesystems are mounted under the same
|
||||
shared higher level directory). Note that this requires that
|
||||
the server support the CIFS Unix Extensions as other servers
|
||||
do not return a unique IndexNumber on SMB FindFirst (most
|
||||
servers return zero as the IndexNumber). Parameter has no
|
||||
effect to Windows servers and others which do not support the
|
||||
CIFS Unix Extensions.
|
||||
shared higher level directory). Note that some older
|
||||
(e.g. pre-Windows 2000) do not support returning UniqueIDs
|
||||
or the CIFS Unix Extensions equivalent and for those
|
||||
this mount option will have no effect. Exporting cifs mounts
|
||||
under nfsd requires this mount option on the cifs mount.
|
||||
noserverino Client generates inode numbers (rather than using the actual one
|
||||
from the server) by default.
|
||||
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
|
||||
|
||||
Two other experimental features are under development and to test
|
||||
require enabling CONFIG_CIFS_EXPERIMENTAL
|
||||
Two other experimental features are under development. To test these
|
||||
requires enabling CONFIG_CIFS_EXPERIMENTAL
|
||||
|
||||
More efficient write operations
|
||||
ipv6 enablement
|
||||
|
||||
DNOTIFY fcntl: needed for support of directory change
|
||||
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)
|
||||
|
||||
e) More testing of NTLMv2 authentication (mostly implemented - double check
|
||||
that NTLMv2 signing works, also need to cleanup now unneeded SessSetup code in
|
||||
fs/cifs/connect.c)
|
||||
e) Cleanup now unneeded SessSetup code in
|
||||
fs/cifs/connect.c and add back in NTLMSSP code if any servers
|
||||
need it
|
||||
|
||||
f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
|
||||
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
|
||||
server not cifs client problem) and has not been reproduced recently.
|
||||
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
|
||||
==================
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
/*
|
||||
* The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
|
||||
* turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2000 RP Internet (www.rpi.net.au).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -80,7 +80,7 @@
|
|||
static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
|
||||
static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
|
||||
|
||||
/*
|
||||
/*
|
||||
* ASN.1 context.
|
||||
*/
|
||||
struct asn1_ctx {
|
||||
|
@ -190,7 +190,7 @@ asn1_header_decode(struct asn1_ctx *ctx,
|
|||
unsigned char **eoc,
|
||||
unsigned int *cls, unsigned int *con, unsigned int *tag)
|
||||
{
|
||||
unsigned int def = 0;
|
||||
unsigned int def = 0;
|
||||
unsigned int len = 0;
|
||||
|
||||
if (!asn1_id_decode(ctx, cls, con, tag))
|
||||
|
@ -331,7 +331,7 @@ static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
|
|||
*integer |= ch;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char
|
||||
asn1_octets_decode(struct asn1_ctx *ctx,
|
||||
|
@ -376,7 +376,7 @@ asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
static int
|
||||
asn1_oid_decode(struct asn1_ctx *ctx,
|
||||
unsigned char *eoc, unsigned long **oid, unsigned int *len)
|
||||
{
|
||||
|
@ -459,7 +459,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
|||
unsigned int cls, con, tag, oidlen, rc;
|
||||
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); */
|
||||
|
||||
|
@ -498,7 +498,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
|||
return 0;
|
||||
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|
||||
|| (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));
|
||||
return 0;
|
||||
}
|
||||
|
@ -508,7 +509,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
|||
return 0;
|
||||
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|
||||
|| (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));
|
||||
return 0;
|
||||
}
|
||||
|
@ -540,32 +542,34 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
|||
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
|
||||
if (!rc) {
|
||||
cFYI(1,
|
||||
("Error 1 decoding negTokenInit header exit 2"));
|
||||
("Error decoding negTokenInit hdr exit2"));
|
||||
return 0;
|
||||
}
|
||||
if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
|
||||
rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
|
||||
if(rc) {
|
||||
if (rc) {
|
||||
cFYI(1,
|
||||
("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
|
||||
oidlen, *oid, *(oid + 1), *(oid + 2),
|
||||
*(oid + 3)));
|
||||
rc = compare_oid(oid, oidlen, NTLMSSP_OID,
|
||||
NTLMSSP_OID_LEN);
|
||||
("OID len = %d oid = 0x%lx 0x%lx "
|
||||
"0x%lx 0x%lx",
|
||||
oidlen, *oid, *(oid + 1),
|
||||
*(oid + 2), *(oid + 3)));
|
||||
rc = compare_oid(oid, oidlen,
|
||||
NTLMSSP_OID, NTLMSSP_OID_LEN);
|
||||
kfree(oid);
|
||||
if (rc)
|
||||
use_ntlmssp = TRUE;
|
||||
}
|
||||
} 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) {
|
||||
cFYI(1,
|
||||
("Error decoding last part of negTokenInit exit 3"));
|
||||
("Error decoding last part negTokenInit exit3"));
|
||||
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,
|
||||
("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
|
||||
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) {
|
||||
cFYI(1,
|
||||
("Error decoding last part of negTokenInit exit 5"));
|
||||
("Error decoding last part negTokenInit exit5"));
|
||||
return 0;
|
||||
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|
||||
|| (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) {
|
||||
cFYI(1,
|
||||
("Error decoding last part of negTokenInit exit 7"));
|
||||
("Error decoding last part negTokenInit exit 7"));
|
||||
return 0;
|
||||
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
|
||||
cFYI(1,
|
||||
|
@ -594,20 +598,21 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
|||
}
|
||||
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
||||
cFYI(1,
|
||||
("Error decoding last part of negTokenInit exit 9"));
|
||||
("Error decoding last part negTokenInit exit9"));
|
||||
return 0;
|
||||
} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
|
||||
|| (tag != ASN1_GENSTR)) {
|
||||
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));
|
||||
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)
|
||||
*secType = Kerberos
|
||||
/* if (use_kerberos)
|
||||
*secType = Kerberos
|
||||
else */
|
||||
if (use_ntlmssp) {
|
||||
*secType = NTLMSSP;
|
||||
|
|
|
@ -58,7 +58,7 @@ cifs_dump_mem(char *label, void *data, int length)
|
|||
}
|
||||
|
||||
#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",
|
||||
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 mid_q_entry * mid_entry;
|
||||
struct mid_q_entry *mid_entry;
|
||||
|
||||
if (server == NULL)
|
||||
return;
|
||||
|
@ -114,12 +114,12 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
|||
{
|
||||
struct list_head *tmp;
|
||||
struct list_head *tmp1;
|
||||
struct mid_q_entry * mid_entry;
|
||||
struct mid_q_entry *mid_entry;
|
||||
struct cifsSesInfo *ses;
|
||||
struct cifsTconInfo *tcon;
|
||||
int i;
|
||||
int length = 0;
|
||||
char * original_buf = buf;
|
||||
char *original_buf = buf;
|
||||
|
||||
*beginBuffer = buf + offset;
|
||||
|
||||
|
@ -145,7 +145,6 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
|||
(ses->serverNOS == NULL)) {
|
||||
buf += sprintf(buf, "\nentry for %s not fully "
|
||||
"displayed\n\t", ses->serverName);
|
||||
|
||||
} else {
|
||||
length =
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -43,6 +43,6 @@ struct cifs_sb_info {
|
|||
mode_t mnt_dir_mode;
|
||||
int mnt_cifs_flags;
|
||||
int prepathlen;
|
||||
char * prepath;
|
||||
char *prepath;
|
||||
};
|
||||
#endif /* _CIFS_FS_SB_H */
|
||||
|
|
|
@ -66,7 +66,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len,
|
|||
{
|
||||
int charlen;
|
||||
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) {
|
||||
|
||||
|
|
|
@ -5,20 +5,20 @@
|
|||
* Convert a unicode character to upper or lower case using
|
||||
* 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
|
||||
* 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*
|
||||
|
@ -70,7 +70,7 @@ int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
|
|||
* Address of the first string
|
||||
*/
|
||||
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 */
|
||||
|
||||
|
@ -88,7 +88,7 @@ UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
|
|||
* or NULL if the character is not in the string
|
||||
*/
|
||||
static inline wchar_t *
|
||||
UniStrchr(const wchar_t * ucs, wchar_t uc)
|
||||
UniStrchr(const wchar_t *ucs, wchar_t uc)
|
||||
{
|
||||
while ((*ucs != uc) && *ucs)
|
||||
ucs++;
|
||||
|
@ -107,7 +107,7 @@ UniStrchr(const wchar_t * ucs, wchar_t uc)
|
|||
* > 0: First string is greater than second
|
||||
*/
|
||||
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) {
|
||||
ucs1++;
|
||||
|
@ -120,7 +120,7 @@ UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
|
|||
* UniStrcpy: Copy a string
|
||||
*/
|
||||
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 */
|
||||
|
||||
|
@ -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)
|
||||
*/
|
||||
static inline size_t
|
||||
UniStrlen(const wchar_t * ucs1)
|
||||
UniStrlen(const wchar_t *ucs1)
|
||||
{
|
||||
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
|
||||
UniStrnlen(const wchar_t * ucs1, int maxlen)
|
||||
UniStrnlen(const wchar_t *ucs1, int maxlen)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
|
@ -161,7 +162,7 @@ UniStrnlen(const wchar_t * ucs1, int maxlen)
|
|||
* UniStrncat: Concatenate length limited string
|
||||
*/
|
||||
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 */
|
||||
|
||||
|
@ -179,7 +180,7 @@ UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
|
|||
* UniStrncmp: Compare length limited string
|
||||
*/
|
||||
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)
|
||||
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
|
||||
*/
|
||||
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)
|
||||
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
|
||||
*/
|
||||
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;
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
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;
|
||||
|
||||
|
@ -247,7 +248,7 @@ UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
|
|||
* NULL if no matching string is found
|
||||
*/
|
||||
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 *anchor2 = ucs2;
|
||||
|
@ -297,7 +298,7 @@ UniToupper(register wchar_t uc)
|
|||
* UniStrupr: Upper case a unicode string
|
||||
*/
|
||||
static inline wchar_t *
|
||||
UniStrupr(register wchar_t * upin)
|
||||
UniStrupr(register wchar_t *upin)
|
||||
{
|
||||
register wchar_t *up;
|
||||
|
||||
|
@ -338,7 +339,7 @@ UniTolower(wchar_t uc)
|
|||
* UniStrlwr: Lower case a unicode string
|
||||
*/
|
||||
static inline wchar_t *
|
||||
UniStrlwr(register wchar_t * upin)
|
||||
UniStrlwr(register wchar_t *upin)
|
||||
{
|
||||
register wchar_t *up;
|
||||
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* uniupr.h - Unicode compressed case ranges
|
||||
|
@ -53,7 +53,7 @@ signed char CifsUniUpperTable[512] = {
|
|||
0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
|
||||
-1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
|
||||
0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
|
||||
-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
|
||||
-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
|
||||
0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
|
||||
0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include <linux/fs.h>
|
||||
#include "cifspdu.h"
|
||||
#include "cifsglob.h"
|
||||
#include "cifsglob.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "md5.h"
|
||||
#include "cifs_unicode.h"
|
||||
|
@ -29,54 +29,57 @@
|
|||
#include <linux/ctype.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 */
|
||||
/* 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
|
||||
sequence number before this function is called */
|
||||
|
||||
extern void mdfour(unsigned char *out, unsigned char *in, int n);
|
||||
extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
|
||||
extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
|
||||
unsigned char *p24);
|
||||
|
||||
static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu,
|
||||
const char * key, char * signature)
|
||||
unsigned char *p24);
|
||||
|
||||
static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
|
||||
const struct mac_key *key, char *signature)
|
||||
{
|
||||
struct MD5Context context;
|
||||
|
||||
if((cifs_pdu == NULL) || (signature == NULL))
|
||||
if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
MD5Init(&context);
|
||||
MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
|
||||
MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
|
||||
MD5Final(signature,&context);
|
||||
MD5Update(&context, (char *)&key->data, key->len);
|
||||
MD5Update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
|
||||
|
||||
MD5Final(signature, &context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
|
||||
__u32 * pexpected_response_sequence_number)
|
||||
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
|
||||
__u32 *pexpected_response_sequence_number)
|
||||
{
|
||||
int rc = 0;
|
||||
char smb_signature[20];
|
||||
|
||||
if((cifs_pdu == NULL) || (server == NULL))
|
||||
if ((cifs_pdu == NULL) || (server == NULL))
|
||||
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.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)
|
||||
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);
|
||||
|
@ -84,115 +87,119 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
|
||||
const char * key, char * signature)
|
||||
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))
|
||||
if ((iov == NULL) || (signature == NULL) || (key == 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"));
|
||||
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)
|
||||
} 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
|
||||
/* 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 (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);
|
||||
MD5Update(&context, iov[0].iov_base+4,
|
||||
iov[0].iov_len-4);
|
||||
} else
|
||||
MD5Update(&context,iov[i].iov_base, iov[i].iov_len);
|
||||
MD5Update(&context, iov[i].iov_base, iov[i].iov_len);
|
||||
}
|
||||
|
||||
MD5Final(signature,&context);
|
||||
MD5Final(signature, &context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cifs_sign_smb2(struct kvec * iov, int n_vec, struct TCP_Server_Info *server,
|
||||
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;
|
||||
struct smb_hdr *cifs_pdu = iov[0].iov_base;
|
||||
|
||||
if((cifs_pdu == NULL) || (server == NULL))
|
||||
if ((cifs_pdu == NULL) || (server == NULL))
|
||||
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 =
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
cifs_pdu->Signature.Sequence.SequenceNumber =
|
||||
cpu_to_le32(server->sequence_number);
|
||||
cifs_pdu->Signature.Sequence.Reserved = 0;
|
||||
cifs_pdu->Signature.Sequence.Reserved = 0;
|
||||
|
||||
*pexpected_response_sequence_number = server->sequence_number++;
|
||||
server->sequence_number++;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
*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,
|
||||
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;
|
||||
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 char * mac_key,
|
||||
__u32 expected_sequence_number)
|
||||
int cifs_verify_signature(struct smb_hdr *cifs_pdu,
|
||||
const struct mac_key *mac_key,
|
||||
__u32 expected_sequence_number)
|
||||
{
|
||||
unsigned int rc;
|
||||
char server_response_sig[8];
|
||||
char what_we_think_sig_should_be[20];
|
||||
|
||||
if((cifs_pdu == NULL) || (mac_key == NULL))
|
||||
if ((cifs_pdu == NULL) || (mac_key == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
|
||||
return 0;
|
||||
|
||||
if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
|
||||
struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu;
|
||||
if(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
|
||||
struct smb_com_lock_req *pSMB =
|
||||
(struct smb_com_lock_req *)cifs_pdu;
|
||||
if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* BB what if signatures are supposed to be on for session but server does not
|
||||
send one? BB */
|
||||
|
||||
/* BB what if signatures are supposed to be on for session but
|
||||
server does not send one? BB */
|
||||
|
||||
/* Do not need to verify session setups with signature "BSRSPYL " */
|
||||
if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
|
||||
cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
|
||||
if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
|
||||
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
|
||||
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;
|
||||
|
||||
rc = cifs_calculate_signature(cifs_pdu, mac_key,
|
||||
what_we_think_sig_should_be);
|
||||
|
||||
if(rc)
|
||||
if (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;
|
||||
else
|
||||
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 */
|
||||
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];
|
||||
if ((key == NULL) || (rn == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
E_md4hash(password, temp_key);
|
||||
mdfour(key,temp_key,16);
|
||||
memcpy(key+16,rn, CIFS_SESS_KEY_SIZE);
|
||||
mdfour(key->data.ntlm, temp_key, 16);
|
||||
memcpy(key->data.ntlm+16, rn, CIFS_SESS_KEY_SIZE);
|
||||
key->len = 40;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses,
|
||||
const struct nls_table * nls_info)
|
||||
int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *ses,
|
||||
const struct nls_table *nls_info)
|
||||
{
|
||||
char temp_hash[16];
|
||||
struct HMACMD5Context ctx;
|
||||
char * ucase_buf;
|
||||
__le16 * unicode_buf;
|
||||
unsigned int i,user_name_len,dom_name_len;
|
||||
char *ucase_buf;
|
||||
__le16 *unicode_buf;
|
||||
unsigned int i, user_name_len, dom_name_len;
|
||||
|
||||
if(ses == NULL)
|
||||
if (ses == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
E_md4hash(ses->password, temp_hash);
|
||||
|
||||
hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
|
||||
user_name_len = strlen(ses->userName);
|
||||
if(user_name_len > MAX_USERNAME_SIZE)
|
||||
if (user_name_len > MAX_USERNAME_SIZE)
|
||||
return -EINVAL;
|
||||
if(ses->domainName == NULL)
|
||||
if (ses->domainName == NULL)
|
||||
return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
|
||||
dom_name_len = strlen(ses->domainName);
|
||||
if(dom_name_len > MAX_USERNAME_SIZE)
|
||||
if (dom_name_len > MAX_USERNAME_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
|
||||
if(ucase_buf == NULL)
|
||||
if (ucase_buf == NULL)
|
||||
return -ENOMEM;
|
||||
unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
|
||||
if(unicode_buf == NULL) {
|
||||
if (unicode_buf == NULL) {
|
||||
kfree(ucase_buf);
|
||||
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] = 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;
|
||||
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] = 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;
|
||||
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(unicode_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#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;
|
||||
char password_with_pad[CIFS_ENCPWD_SIZE];
|
||||
|
||||
if(ses->server == NULL)
|
||||
if (ses->server == NULL)
|
||||
return;
|
||||
|
||||
memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
|
||||
if(ses->password)
|
||||
if (ses->password)
|
||||
strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
|
||||
|
||||
if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
|
||||
if(extended_security & CIFSSEC_MAY_PLNTXT) {
|
||||
memcpy(lnm_session_key, password_with_pad, CIFS_ENCPWD_SIZE);
|
||||
if ((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
|
||||
if (extended_security & CIFSSEC_MAY_PLNTXT) {
|
||||
memcpy(lnm_session_key, password_with_pad,
|
||||
CIFS_ENCPWD_SIZE);
|
||||
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
|
||||
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]);
|
||||
}
|
||||
|
||||
|
@ -307,19 +319,19 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
|
|||
}
|
||||
#endif /* CIFS_WEAK_PW_HASH */
|
||||
|
||||
static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
|
||||
const struct nls_table * nls_cp)
|
||||
static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
|
||||
const struct nls_table *nls_cp)
|
||||
{
|
||||
int rc = 0;
|
||||
int len;
|
||||
char nt_hash[16];
|
||||
struct HMACMD5Context * pctxt;
|
||||
wchar_t * user;
|
||||
wchar_t * domain;
|
||||
struct HMACMD5Context *pctxt;
|
||||
wchar_t *user;
|
||||
wchar_t *domain;
|
||||
|
||||
pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
|
||||
|
||||
if(pctxt == NULL)
|
||||
if (pctxt == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* calculate md4 hash of password */
|
||||
|
@ -331,41 +343,45 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
|
|||
/* convert ses->userName to unicode and uppercase */
|
||||
len = strlen(ses->userName);
|
||||
user = kmalloc(2 + (len * 2), GFP_KERNEL);
|
||||
if(user == NULL)
|
||||
if (user == NULL)
|
||||
goto calc_exit_2;
|
||||
len = cifs_strtoUCS(user, ses->userName, len, nls_cp);
|
||||
UniStrupr(user);
|
||||
hmac_md5_update((char *)user, 2*len, pctxt);
|
||||
|
||||
/* convert ses->domainName to unicode and uppercase */
|
||||
if(ses->domainName) {
|
||||
if (ses->domainName) {
|
||||
len = strlen(ses->domainName);
|
||||
|
||||
domain = kmalloc(2 + (len * 2), GFP_KERNEL);
|
||||
if(domain == NULL)
|
||||
domain = kmalloc(2 + (len * 2), GFP_KERNEL);
|
||||
if (domain == NULL)
|
||||
goto calc_exit_1;
|
||||
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);
|
||||
|
||||
|
||||
kfree(domain);
|
||||
}
|
||||
calc_exit_1:
|
||||
kfree(user);
|
||||
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 */
|
||||
hmac_md5_final(ses->server->mac_signing_key, pctxt);
|
||||
hmac_md5_final(ses->server->ntlmv2_hash, pctxt);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
|
||||
const struct nls_table * nls_cp)
|
||||
void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
|
||||
const struct nls_table *nls_cp)
|
||||
{
|
||||
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->reserved = 0;
|
||||
|
@ -379,21 +395,31 @@ void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
|
|||
|
||||
/* calculate buf->ntlmv2_hash */
|
||||
rc = calc_ntlmv2_hash(ses, nls_cp);
|
||||
if(rc)
|
||||
cERROR(1,("could not get v2 hash rc %d",rc));
|
||||
if (rc)
|
||||
cERROR(1, ("could not get v2 hash rc %d", rc));
|
||||
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;
|
||||
/* rest of v2 struct already generated */
|
||||
memcpy(v2_session_response + 8, ses->server->cryptKey,8);
|
||||
hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context);
|
||||
memcpy(v2_session_response + 8, ses->server->cryptKey, 8);
|
||||
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);
|
||||
|
||||
hmac_md5_final(v2_session_response,&context);
|
||||
hmac_md5_final(v2_session_response, &context);
|
||||
/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
|
||||
}
|
||||
|
|
197
fs/cifs/cifsfs.c
197
fs/cifs/cifsfs.c
|
@ -64,23 +64,27 @@ unsigned int multiuser_mount = 0;
|
|||
unsigned int extended_security = CIFSSEC_DEF;
|
||||
/* unsigned int ntlmv2_support = 0; */
|
||||
unsigned int sign_CIFS_PDUs = 1;
|
||||
extern struct task_struct * oplockThread; /* remove sparse warning */
|
||||
struct task_struct * oplockThread = NULL;
|
||||
extern struct task_struct *oplockThread; /* remove sparse warning */
|
||||
struct task_struct *oplockThread = NULL;
|
||||
/* 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;
|
||||
unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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_req_poolp;
|
||||
|
@ -95,10 +99,10 @@ cifs_read_super(struct super_block *sb, void *data,
|
|||
struct inode *inode;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
int rc = 0;
|
||||
|
||||
|
||||
/* BB should we make this contingent on mount parm? */
|
||||
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);
|
||||
if (cifs_sb == NULL)
|
||||
return -ENOMEM;
|
||||
|
@ -114,12 +118,9 @@ cifs_read_super(struct super_block *sb, void *data,
|
|||
|
||||
sb->s_magic = CIFS_MAGIC_NUMBER;
|
||||
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)
|
||||
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
|
||||
sb->s_qcop = &cifs_quotactl_ops;
|
||||
#endif
|
||||
|
@ -139,6 +140,13 @@ cifs_read_super(struct super_block *sb, void *data,
|
|||
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;
|
||||
|
||||
out_no_root:
|
||||
|
@ -149,7 +157,7 @@ out_no_root:
|
|||
out_mount_failed:
|
||||
if (cifs_sb) {
|
||||
if (cifs_sb->local_nls)
|
||||
unload_nls(cifs_sb->local_nls);
|
||||
unload_nls(cifs_sb->local_nls);
|
||||
kfree(cifs_sb);
|
||||
}
|
||||
return rc;
|
||||
|
@ -164,10 +172,10 @@ cifs_put_super(struct super_block *sb)
|
|||
cFYI(1, ("In cifs_put_super"));
|
||||
cifs_sb = CIFS_SB(sb);
|
||||
if (cifs_sb == NULL) {
|
||||
cFYI(1,("Empty cifs superblock info passed to unmount"));
|
||||
cFYI(1, ("Empty cifs superblock info passed to unmount"));
|
||||
return;
|
||||
}
|
||||
rc = cifs_umount(sb, cifs_sb);
|
||||
rc = cifs_umount(sb, cifs_sb);
|
||||
if (rc) {
|
||||
cERROR(1, ("cifs_umount failed with return code %d", rc));
|
||||
}
|
||||
|
@ -180,7 +188,7 @@ static int
|
|||
cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
{
|
||||
struct super_block *sb = dentry->d_sb;
|
||||
int xid;
|
||||
int xid;
|
||||
int rc = -EOPNOTSUPP;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
|
@ -193,7 +201,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
|||
buf->f_type = CIFS_MAGIC_NUMBER;
|
||||
|
||||
/* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
|
||||
buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would
|
||||
buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would
|
||||
presumably be total path, but note
|
||||
that some servers (includinng Samba 3)
|
||||
have a shorter maximum path */
|
||||
|
@ -217,8 +225,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
|||
bypassed it because we detected that this was an older LANMAN sess */
|
||||
if (rc)
|
||||
rc = SMBOldQFSInfo(xid, pTcon, buf);
|
||||
/*
|
||||
int f_type;
|
||||
/* int f_type;
|
||||
__fsid_t f_fsid;
|
||||
int f_namelen; */
|
||||
/* 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? */
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -235,10 +242,10 @@ static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
|
|||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
|
||||
return 0;
|
||||
} else /* file mode might have been restricted at mount time
|
||||
on the client (above and beyond ACL on servers) for
|
||||
} else /* file mode might have been restricted at mount time
|
||||
on the client (above and beyond ACL on servers) for
|
||||
servers which do not support setting and viewing mode bits,
|
||||
so allowing client to check permissions is useful */
|
||||
so allowing client to check permissions is useful */
|
||||
return generic_permission(inode, mask, NULL);
|
||||
}
|
||||
|
||||
|
@ -267,7 +274,7 @@ cifs_alloc_inode(struct super_block *sb)
|
|||
cifs_inode->clientCanCacheRead = FALSE;
|
||||
cifs_inode->clientCanCacheAll = FALSE;
|
||||
cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
|
||||
|
||||
|
||||
/* Can not set i_flags here - they get immediately overwritten
|
||||
to zero by the VFS */
|
||||
/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/
|
||||
|
@ -309,26 +316,26 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
|
|||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
|
||||
seq_printf(s, ",posixpaths");
|
||||
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);
|
||||
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, ",rsize=%d",cifs_sb->rsize);
|
||||
seq_printf(s, ",wsize=%d",cifs_sb->wsize);
|
||||
seq_printf(s, ",rsize=%d", cifs_sb->rsize);
|
||||
seq_printf(s, ",wsize=%d", cifs_sb->wsize);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_QUOTA
|
||||
int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
|
||||
struct fs_disk_quota * pdquota)
|
||||
int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid,
|
||||
struct fs_disk_quota *pdquota)
|
||||
{
|
||||
int xid;
|
||||
int rc = 0;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifsTconInfo *pTcon;
|
||||
|
||||
|
||||
if (cifs_sb)
|
||||
pTcon = cifs_sb->tcon;
|
||||
else
|
||||
|
@ -337,7 +344,7 @@ int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
|
|||
|
||||
xid = GetXid();
|
||||
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 {
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -346,8 +353,8 @@ int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
|
|||
return rc;
|
||||
}
|
||||
|
||||
int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
|
||||
struct fs_disk_quota * pdquota)
|
||||
int cifs_xquota_get(struct super_block *sb, int quota_type, qid_t qid,
|
||||
struct fs_disk_quota *pdquota)
|
||||
{
|
||||
int xid;
|
||||
int rc = 0;
|
||||
|
@ -361,7 +368,7 @@ int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
|
|||
|
||||
xid = GetXid();
|
||||
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 {
|
||||
rc = -EIO;
|
||||
}
|
||||
|
@ -370,9 +377,9 @@ int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
|
|||
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;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifsTconInfo *pTcon;
|
||||
|
@ -384,7 +391,7 @@ int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
|
|||
|
||||
xid = GetXid();
|
||||
if (pTcon) {
|
||||
cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
|
||||
cFYI(1, ("flags: 0x%x operation: 0x%x", flags, operation));
|
||||
} else {
|
||||
rc = -EIO;
|
||||
}
|
||||
|
@ -393,7 +400,7 @@ int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
|
|||
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 rc = 0;
|
||||
|
@ -407,7 +414,7 @@ int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
|
|||
}
|
||||
xid = GetXid();
|
||||
if (pTcon) {
|
||||
cFYI(1,("pqstats %p",qstats));
|
||||
cFYI(1, ("pqstats %p", qstats));
|
||||
} else {
|
||||
rc = -EIO;
|
||||
}
|
||||
|
@ -424,10 +431,10 @@ static struct quotactl_ops cifs_quotactl_ops = {
|
|||
};
|
||||
#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 cifsTconInfo * tcon;
|
||||
struct cifsTconInfo *tcon;
|
||||
|
||||
if (!(flags & MNT_FORCE))
|
||||
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_notify_requests(tcon); */
|
||||
if (tcon->ses && tcon->ses->server)
|
||||
{
|
||||
cFYI(1,("wake up tasks now - umount begin not complete"));
|
||||
if (tcon->ses && tcon->ses->server) {
|
||||
cFYI(1, ("wake up tasks now - umount begin not complete"));
|
||||
wake_up_all(&tcon->ses->server->request_q);
|
||||
wake_up_all(&tcon->ses->server->response_q);
|
||||
msleep(1); /* yield */
|
||||
|
@ -480,10 +486,11 @@ static const struct super_operations cifs_super_ops = {
|
|||
.statfs = cifs_statfs,
|
||||
.alloc_inode = cifs_alloc_inode,
|
||||
.destroy_inode = cifs_destroy_inode,
|
||||
/* .drop_inode = generic_delete_inode,
|
||||
.delete_inode = cifs_delete_inode, *//* Do not need the above two functions
|
||||
unless later we add lazy close of inodes or unless the kernel forgets to call
|
||||
us with the same number of releases (closes) as opens */
|
||||
/* .drop_inode = generic_delete_inode,
|
||||
.delete_inode = cifs_delete_inode, */ /* Do not need above two
|
||||
functions unless later we add lazy close of inodes or unless the
|
||||
kernel forgets to call us with the same number of releases (closes)
|
||||
as opens */
|
||||
.show_options = cifs_show_options,
|
||||
.umount_begin = cifs_umount_begin,
|
||||
.remount_fs = cifs_remount,
|
||||
|
@ -586,11 +593,11 @@ const struct inode_operations cifs_file_inode_ops = {
|
|||
.getxattr = cifs_getxattr,
|
||||
.listxattr = cifs_listxattr,
|
||||
.removexattr = cifs_removexattr,
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
const struct inode_operations cifs_symlink_inode_ops = {
|
||||
.readlink = generic_readlink,
|
||||
.readlink = generic_readlink,
|
||||
.follow_link = cifs_follow_link,
|
||||
.put_link = cifs_put_link,
|
||||
.permission = cifs_permission,
|
||||
|
@ -602,7 +609,7 @@ const struct inode_operations cifs_symlink_inode_ops = {
|
|||
.getxattr = cifs_getxattr,
|
||||
.listxattr = cifs_listxattr,
|
||||
.removexattr = cifs_removexattr,
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
const struct file_operations cifs_file_ops = {
|
||||
|
@ -628,7 +635,7 @@ const struct file_operations cifs_file_ops = {
|
|||
};
|
||||
|
||||
const struct file_operations cifs_file_direct_ops = {
|
||||
/* no mmap, no aio, no readv -
|
||||
/* no mmap, no aio, no readv -
|
||||
BB reevaluate whether they can be done with directio, no cache */
|
||||
.read = cifs_user_read,
|
||||
.write = cifs_user_write,
|
||||
|
@ -668,7 +675,7 @@ const struct file_operations cifs_file_nobrl_ops = {
|
|||
};
|
||||
|
||||
const struct file_operations cifs_file_direct_nobrl_ops = {
|
||||
/* no mmap, no aio, no readv -
|
||||
/* no mmap, no aio, no readv -
|
||||
BB reevaluate whether they can be done with directio, no cache */
|
||||
.read = cifs_user_read,
|
||||
.write = cifs_user_write,
|
||||
|
@ -693,11 +700,11 @@ const struct file_operations cifs_dir_ops = {
|
|||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
.dir_notify = cifs_dir_notify,
|
||||
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
||||
.ioctl = cifs_ioctl,
|
||||
.ioctl = cifs_ioctl,
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
|
@ -749,7 +756,7 @@ cifs_init_request_bufs(void)
|
|||
cifs_min_rcv = 1;
|
||||
else if (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,
|
||||
|
@ -762,25 +769,25 @@ cifs_init_request_bufs(void)
|
|||
/* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and
|
||||
almost all handle based requests (but not write response, nor is it
|
||||
sufficient for path based requests). A smaller size would have
|
||||
been more efficient (compacting multiple slab items on one 4k page)
|
||||
been more efficient (compacting multiple slab items on one 4k page)
|
||||
for the case in which debug was on, but this larger size allows
|
||||
more SMBs to use small buffer alloc and is still much more
|
||||
efficient to alloc 1 per page off the slab compared to 17K (5page)
|
||||
efficient to alloc 1 per page off the slab compared to 17K (5page)
|
||||
alloc of large cifs buffers even when page debugging is on */
|
||||
cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
|
||||
MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN,
|
||||
MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN,
|
||||
NULL, NULL);
|
||||
if (cifs_sm_req_cachep == NULL) {
|
||||
mempool_destroy(cifs_req_poolp);
|
||||
kmem_cache_destroy(cifs_req_cachep);
|
||||
return -ENOMEM;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (cifs_min_small < 2)
|
||||
cifs_min_small = 2;
|
||||
else if (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,
|
||||
|
@ -841,42 +848,43 @@ cifs_destroy_mids(void)
|
|||
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 inode * inode;
|
||||
struct inode *inode;
|
||||
__u16 netfid;
|
||||
int rc;
|
||||
|
||||
set_freezable();
|
||||
do {
|
||||
if (try_to_freeze())
|
||||
if (try_to_freeze())
|
||||
continue;
|
||||
|
||||
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
if (list_empty(&GlobalOplock_Q)) {
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(39*HZ);
|
||||
} else {
|
||||
oplock_item = list_entry(GlobalOplock_Q.next,
|
||||
oplock_item = list_entry(GlobalOplock_Q.next,
|
||||
struct oplock_q_entry, qhead);
|
||||
if (oplock_item) {
|
||||
cFYI(1,("found oplock item to write out"));
|
||||
cFYI(1, ("found oplock item to write out"));
|
||||
pTcon = oplock_item->tcon;
|
||||
inode = oplock_item->pinode;
|
||||
netfid = oplock_item->netfid;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
DeleteOplockQEntry(oplock_item);
|
||||
/* can not grab inode sem here since it would
|
||||
deadlock when oplock received on delete
|
||||
deadlock when oplock received on delete
|
||||
since vfs_unlink holds the i_mutex across
|
||||
the call */
|
||||
/* mutex_lock(&inode->i_mutex);*/
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
rc = filemap_fdatawrite(inode->i_mapping);
|
||||
if (CIFS_I(inode)->clientCanCacheRead == 0) {
|
||||
if (CIFS_I(inode)->clientCanCacheRead
|
||||
== 0) {
|
||||
filemap_fdatawait(inode->i_mapping);
|
||||
invalidate_remote_inode(inode);
|
||||
}
|
||||
|
@ -885,20 +893,22 @@ static int cifs_oplock_thread(void * dummyarg)
|
|||
/* mutex_unlock(&inode->i_mutex);*/
|
||||
if (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
|
||||
of smb session using a now incorrect file
|
||||
handle is not a data integrity issue but do
|
||||
not bother sending an oplock release if session
|
||||
to server still is disconnected since oplock
|
||||
/* releasing stale oplock after recent reconnect
|
||||
of smb session using a now incorrect file
|
||||
handle is not a data integrity issue but do
|
||||
not bother sending an oplock release if session
|
||||
to server still is disconnected since oplock
|
||||
already released by the server in that case */
|
||||
if (pTcon->tidStatus != CifsNeedReconnect) {
|
||||
rc = CIFSSMBLock(0, pTcon, netfid,
|
||||
0 /* len */ , 0 /* offset */, 0,
|
||||
0 /* len */ , 0 /* offset */, 0,
|
||||
0, LOCKING_ANDX_OPLOCK_RELEASE,
|
||||
0 /* wait flag */);
|
||||
cFYI(1,("Oplock release rc = %d ",rc));
|
||||
cFYI(1,
|
||||
("Oplock release rc = %d ", rc));
|
||||
}
|
||||
} else
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
|
@ -910,7 +920,7 @@ static int cifs_oplock_thread(void * dummyarg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cifs_dnotify_thread(void * dummyarg)
|
||||
static int cifs_dnotify_thread(void *dummyarg)
|
||||
{
|
||||
struct list_head *tmp;
|
||||
struct cifsSesInfo *ses;
|
||||
|
@ -925,9 +935,9 @@ static int cifs_dnotify_thread(void * dummyarg)
|
|||
to be woken up and wakeq so the
|
||||
thread can wake up and error out */
|
||||
list_for_each(tmp, &GlobalSMBSessionList) {
|
||||
ses = list_entry(tmp, struct cifsSesInfo,
|
||||
ses = list_entry(tmp, struct cifsSesInfo,
|
||||
cifsSessionList);
|
||||
if (ses && ses->server &&
|
||||
if (ses && ses->server &&
|
||||
atomic_read(&ses->server->inFlight))
|
||||
wake_up_all(&ses->server->response_q);
|
||||
}
|
||||
|
@ -951,13 +961,13 @@ init_cifs(void)
|
|||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
INIT_LIST_HEAD(&GlobalDnotifyReqList);
|
||||
INIT_LIST_HEAD(&GlobalDnotifyRsp_Q);
|
||||
#endif
|
||||
#endif
|
||||
/*
|
||||
* Initialize Global counters
|
||||
*/
|
||||
atomic_set(&sesInfoAllocCount, 0);
|
||||
atomic_set(&tconInfoAllocCount, 0);
|
||||
atomic_set(&tcpSesAllocCount,0);
|
||||
atomic_set(&tcpSesAllocCount, 0);
|
||||
atomic_set(&tcpSesReconnectCount, 0);
|
||||
atomic_set(&tconInfoReconnectCount, 0);
|
||||
|
||||
|
@ -978,10 +988,10 @@ init_cifs(void)
|
|||
|
||||
if (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) {
|
||||
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();
|
||||
|
@ -1003,14 +1013,14 @@ init_cifs(void)
|
|||
oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");
|
||||
if (IS_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;
|
||||
}
|
||||
|
||||
dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
|
||||
if (IS_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;
|
||||
}
|
||||
|
||||
|
@ -1036,7 +1046,7 @@ init_cifs(void)
|
|||
static void __exit
|
||||
exit_cifs(void)
|
||||
{
|
||||
cFYI(0, ("In unregister ie exit_cifs"));
|
||||
cFYI(0, ("exit_cifs"));
|
||||
#ifdef CONFIG_PROC_FS
|
||||
cifs_proc_clean();
|
||||
#endif
|
||||
|
@ -1049,9 +1059,10 @@ exit_cifs(void)
|
|||
}
|
||||
|
||||
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
|
||||
("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_init(init_cifs)
|
||||
module_exit(exit_cifs)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _CIFSFS_H
|
||||
|
@ -43,9 +43,9 @@ extern void cifs_read_inode(struct inode *);
|
|||
|
||||
/* Functions related to inodes */
|
||||
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 *);
|
||||
extern struct dentry * cifs_lookup(struct inode *, struct dentry *,
|
||||
extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
|
||||
struct nameidata *);
|
||||
extern int cifs_unlink(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 */
|
||||
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_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_close(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,
|
||||
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,
|
||||
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_fsync(struct file *, struct dentry *, int);
|
||||
extern int cifs_flush(struct file *, fl_owner_t id);
|
||||
|
@ -88,8 +88,9 @@ extern struct dentry_operations cifs_ci_dentry_ops;
|
|||
|
||||
/* Functions related to symlinks */
|
||||
extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
|
||||
extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *);
|
||||
extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
|
||||
extern void cifs_put_link(struct dentry *direntry,
|
||||
struct nameidata *nd, void *);
|
||||
extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
|
||||
int buflen);
|
||||
extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
|
||||
const char *symname);
|
||||
|
@ -98,7 +99,7 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
|
|||
size_t, int);
|
||||
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, 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);
|
||||
#define CIFS_VERSION "1.49"
|
||||
#define CIFS_VERSION "1.50"
|
||||
#endif /* _CIFSFS_H */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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)
|
||||
* Jeremy Allison (jra@samba.org)
|
||||
*
|
||||
|
@ -14,7 +14,7 @@
|
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU Lesser General Public License for more details.
|
||||
*
|
||||
*
|
||||
*/
|
||||
#include <linux/in.h>
|
||||
#include <linux/in6.h>
|
||||
|
@ -28,7 +28,7 @@
|
|||
|
||||
#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
|
||||
#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
|
||||
termination then *2 for unicode versions */
|
||||
#define MAX_PASSWORD_SIZE 16
|
||||
|
@ -38,13 +38,13 @@
|
|||
/*
|
||||
* MAX_REQ is the maximum number of requests that WE will send
|
||||
* on one socket concurently. It also matches the most common
|
||||
* value of max multiplex returned by servers. We may
|
||||
* value of max multiplex returned by servers. We may
|
||||
* eventually want to use the negotiated value (in case
|
||||
* future servers can handle more) when we are more confident that
|
||||
* we will not have problems oveloading the socket with pending
|
||||
* write data.
|
||||
*/
|
||||
#define CIFS_MAX_REQ 50
|
||||
#define CIFS_MAX_REQ 50
|
||||
|
||||
#define SERVER_NAME_LENGTH 15
|
||||
#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
|
||||
|
@ -104,6 +104,17 @@ enum protocolEnum {
|
|||
/* 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
|
||||
|
@ -120,13 +131,13 @@ struct TCP_Server_Info {
|
|||
struct sockaddr_in sockAddr;
|
||||
struct sockaddr_in6 sockAddr6;
|
||||
} addr;
|
||||
wait_queue_head_t response_q;
|
||||
wait_queue_head_t response_q;
|
||||
wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
|
||||
struct list_head pending_mid_q;
|
||||
void *Server_NlsInfo; /* BB - placeholder for future NLS info */
|
||||
unsigned short server_codepage; /* codepage for the server */
|
||||
unsigned long ip_address; /* IP addr for the server if known */
|
||||
enum protocolEnum protocolType;
|
||||
enum protocolEnum protocolType;
|
||||
char versionMajor;
|
||||
char versionMinor;
|
||||
unsigned svlocal:1; /* local server or remote */
|
||||
|
@ -159,14 +170,15 @@ struct TCP_Server_Info {
|
|||
/* 16th byte of RFC1001 workstation name is always null */
|
||||
char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
|
||||
__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 */
|
||||
};
|
||||
|
||||
/*
|
||||
* The following is our shortcut to user information. We surface the uid,
|
||||
* and name. We always get the password on the fly in case it
|
||||
* has changed. We also hang a list of sessions owned by this user off here.
|
||||
* has changed. We also hang a list of sessions owned by this user off here.
|
||||
*/
|
||||
struct cifsUidInfo {
|
||||
struct list_head userList;
|
||||
|
@ -197,11 +209,11 @@ struct cifsSesInfo {
|
|||
int Suid; /* remote smb uid */
|
||||
uid_t linux_uid; /* local Linux uid */
|
||||
int capabilities;
|
||||
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? */
|
||||
char userName[MAX_USERNAME_SIZE + 1];
|
||||
char * domainName;
|
||||
char * password;
|
||||
char *domainName;
|
||||
char *password;
|
||||
};
|
||||
/* no more than one of the following three session flags may be set */
|
||||
#define CIFS_SES_NT4 1
|
||||
|
@ -213,7 +225,7 @@ struct cifsSesInfo {
|
|||
#define CIFS_SES_LANMAN 8
|
||||
/*
|
||||
* there is one of these for each connection to a resource on a particular
|
||||
* session
|
||||
* session
|
||||
*/
|
||||
struct cifsTconInfo {
|
||||
struct list_head cifsConnectionList;
|
||||
|
@ -269,7 +281,9 @@ struct cifsTconInfo {
|
|||
FILE_SYSTEM_UNIX_INFO fsUnixInfo;
|
||||
unsigned retry: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 info_level;
|
||||
__u32 resume_key;
|
||||
char * ntwrk_buf_start;
|
||||
char * srch_entries_start;
|
||||
char * presume_name;
|
||||
char *ntwrk_buf_start;
|
||||
char *srch_entries_start;
|
||||
char *presume_name;
|
||||
unsigned int resume_name_len;
|
||||
unsigned endOfSearch:1;
|
||||
unsigned emptyDir:1;
|
||||
|
@ -309,15 +323,15 @@ struct cifsFileInfo {
|
|||
__u16 netfid; /* file id from remote */
|
||||
/* BB add lock scope info here if needed */ ;
|
||||
/* lock scope id (0 if none) */
|
||||
struct file * pfile; /* needed for writepage */
|
||||
struct inode * pInode; /* needed for oplock break */
|
||||
struct file *pfile; /* needed for writepage */
|
||||
struct inode *pInode; /* needed for oplock break */
|
||||
struct mutex lock_mutex;
|
||||
struct list_head llist; /* list of byte range locks we have. */
|
||||
unsigned closePend:1; /* file is marked to close */
|
||||
unsigned invalidHandle:1; /* file closed via session abend */
|
||||
atomic_t wrtPending; /* handle in use - defer close */
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -327,7 +341,7 @@ struct cifsFileInfo {
|
|||
|
||||
struct cifsInodeInfo {
|
||||
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;
|
||||
int write_behind_rc;
|
||||
__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
|
||||
|
||||
#define cifs_stats_inc(field) 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_inc(field) do {} while (0)
|
||||
#define cifs_stats_bytes_written(tcon, bytes) do {} while (0)
|
||||
#define cifs_stats_bytes_read(tcon, bytes) do {} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -410,8 +424,8 @@ struct mid_q_entry {
|
|||
|
||||
struct oplock_q_entry {
|
||||
struct list_head qhead;
|
||||
struct inode * pinode;
|
||||
struct cifsTconInfo * tcon;
|
||||
struct inode *pinode;
|
||||
struct cifsTconInfo *tcon;
|
||||
__u16 netfid;
|
||||
};
|
||||
|
||||
|
@ -426,7 +440,7 @@ struct dir_notify_req {
|
|||
__u16 netfid;
|
||||
__u32 filter; /* CompletionFilter (for multishot) */
|
||||
int multishot;
|
||||
struct file * pfile;
|
||||
struct file *pfile;
|
||||
};
|
||||
|
||||
#define MID_FREE 0
|
||||
|
@ -464,7 +478,7 @@ require use of the stronger protocol */
|
|||
#define CIFSSEC_MUST_LANMAN 0x10010
|
||||
#define CIFSSEC_MUST_PLNTXT 0x20020
|
||||
#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
|
||||
#else
|
||||
#else
|
||||
#define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */
|
||||
#endif /* WEAK_PW_HASH */
|
||||
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
|
||||
|
@ -502,7 +516,7 @@ require use of the stronger protocol */
|
|||
* ----------
|
||||
* sesSem operations on smb session
|
||||
* tconSem operations on tree connection
|
||||
* fh_sem file handle reconnection operations
|
||||
* fh_sem file handle reconnection operations
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
@ -515,7 +529,7 @@ require use of the stronger protocol */
|
|||
/*
|
||||
* The list of servers that did not respond with NT LM 0.12.
|
||||
* This list helps improve performance and eliminate the messages indicating
|
||||
* that we had a communications error talking to the server in this list.
|
||||
* that we had a communications error talking to the server in this list.
|
||||
*/
|
||||
/* Feature not supported */
|
||||
/* GLOBAL_EXTERN struct servers_not_supported *NotSuppList; */
|
||||
|
@ -568,12 +582,12 @@ GLOBAL_EXTERN atomic_t midCount;
|
|||
/* Misc globals */
|
||||
GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
|
||||
to be established on existing mount if we
|
||||
have the uid/password or Kerberos credential
|
||||
have the uid/password or Kerberos credential
|
||||
or equivalent for current user */
|
||||
GLOBAL_EXTERN unsigned int oplockEnabled;
|
||||
GLOBAL_EXTERN unsigned int experimEnabled;
|
||||
GLOBAL_EXTERN unsigned int lookupCacheEnabled;
|
||||
GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
|
||||
GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
|
||||
with more secure ntlmssp2 challenge/resp */
|
||||
GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
|
||||
GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
|
||||
|
|
|
@ -144,7 +144,7 @@
|
|||
#define SMBOPEN_OAPPEND 0x0001
|
||||
|
||||
/*
|
||||
* SMB flag definitions
|
||||
* SMB flag definitions
|
||||
*/
|
||||
#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock smb */
|
||||
#define SMBFLG_RCV_POSTED 0x02 /* obsolete */
|
||||
|
@ -157,9 +157,9 @@
|
|||
#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
|
||||
|
||||
/*
|
||||
* SMB flag2 definitions
|
||||
* SMB flag2 definitions
|
||||
*/
|
||||
#define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1) /* can send long (non-8.3)
|
||||
#define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1) /* can send long (non-8.3)
|
||||
path names in response */
|
||||
#define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
|
||||
#define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
|
||||
|
@ -260,7 +260,7 @@
|
|||
#define ATTR_SPARSE 0x0200
|
||||
#define ATTR_REPARSE 0x0400
|
||||
#define ATTR_COMPRESSED 0x0800
|
||||
#define ATTR_OFFLINE 0x1000 /* ie file not immediately available -
|
||||
#define ATTR_OFFLINE 0x1000 /* ie file not immediately available -
|
||||
on offline storage */
|
||||
#define ATTR_NOT_CONTENT_INDEXED 0x2000
|
||||
#define ATTR_ENCRYPTED 0x4000
|
||||
|
@ -300,7 +300,7 @@
|
|||
#define CREATE_DELETE_ON_CLOSE 0x00001000
|
||||
#define CREATE_OPEN_BY_ID 0x00002000
|
||||
#define OPEN_REPARSE_POINT 0x00200000
|
||||
#define CREATE_OPTIONS_MASK 0x007FFFFF
|
||||
#define CREATE_OPTIONS_MASK 0x007FFFFF
|
||||
#define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */
|
||||
|
||||
/* ImpersonationLevel flags */
|
||||
|
@ -366,17 +366,19 @@ struct smb_hdr {
|
|||
#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
|
||||
|
||||
/*
|
||||
* Share Name Length @S8A
|
||||
* Note: This length is limited by the SMB used to get @S8A
|
||||
* the Share info. NetShareEnum only returns 13 @S8A
|
||||
* chars, including the null termination. @S8A
|
||||
* Share Name Length (SNLEN)
|
||||
* Note: This length was limited by the SMB used to get
|
||||
* the Share info. NetShareEnum only returned 13
|
||||
* chars, including the null termination.
|
||||
* This was removed because it no longer is limiting.
|
||||
*/
|
||||
#define SNLEN 12 /*@S8A */
|
||||
|
||||
/*
|
||||
* Comment Length
|
||||
|
@ -394,8 +396,8 @@ struct smb_hdr {
|
|||
*
|
||||
* The Naming convention is the lower case version of the
|
||||
* smb command code name for the struct and this is typedef to the
|
||||
* uppercase version of the same name with the prefix SMB_ removed
|
||||
* for brevity. Although typedefs are not commonly used for
|
||||
* uppercase version of the same name with the prefix SMB_ removed
|
||||
* for brevity. Although typedefs are not commonly used for
|
||||
* structure definitions in the Linux kernel, their use in the
|
||||
* CIFS standards document, which this code is based on, may
|
||||
* make this one of the cases where typedefs for structures make
|
||||
|
@ -403,7 +405,7 @@ struct smb_hdr {
|
|||
* Typedefs can always be removed later if they are too distracting
|
||||
* and they are only used for the CIFSs PDUs themselves, not
|
||||
* internal cifs vfs structures
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct negotiate_req {
|
||||
|
@ -511,7 +513,7 @@ typedef union smb_com_session_setup_andx {
|
|||
unsigned char SecurityBlob[1]; /* followed by */
|
||||
/* STRING NativeOS */
|
||||
/* STRING NativeLanMan */
|
||||
} __attribute__((packed)) req; /* NTLM request format (with
|
||||
} __attribute__((packed)) req; /* NTLM request format (with
|
||||
extended security */
|
||||
|
||||
struct { /* request format */
|
||||
|
@ -549,7 +551,7 @@ typedef union smb_com_session_setup_andx {
|
|||
/* unsigned char * NativeOS; */
|
||||
/* unsigned char * NativeLanMan; */
|
||||
/* unsigned char * PrimaryDomain; */
|
||||
} __attribute__((packed)) resp; /* NTLM response
|
||||
} __attribute__((packed)) resp; /* NTLM response
|
||||
(with or without extended sec) */
|
||||
|
||||
struct { /* request format */
|
||||
|
@ -618,7 +620,7 @@ struct ntlmv2_resp {
|
|||
#define CAP_NT_SMBS 0x00000010
|
||||
#define CAP_STATUS32 0x00000040
|
||||
#define CAP_LEVEL_II_OPLOCKS 0x00000080
|
||||
#define CAP_NT_FIND 0x00000200 /* reserved should be zero
|
||||
#define CAP_NT_FIND 0x00000200 /* reserved should be zero
|
||||
(because NT_SMBs implies the same thing?) */
|
||||
#define CAP_BULK_TRANSFER 0x20000000
|
||||
#define CAP_EXTENDED_SECURITY 0x80000000
|
||||
|
@ -676,7 +678,7 @@ typedef struct smb_com_logoff_andx_rsp {
|
|||
__u16 ByteCount;
|
||||
} __attribute__((packed)) LOGOFF_ANDX_RSP;
|
||||
|
||||
typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on
|
||||
typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on
|
||||
tree_connect PDU to effect disconnect */
|
||||
/* tdis is probably simplest SMB PDU */
|
||||
struct {
|
||||
|
@ -712,6 +714,7 @@ typedef struct smb_com_findclose_req {
|
|||
#define REQ_OPLOCK 0x00000002
|
||||
#define REQ_BATCHOPLOCK 0x00000004
|
||||
#define REQ_OPENDIRONLY 0x00000008
|
||||
#define REQ_EXTENDED_INFO 0x00000010
|
||||
|
||||
typedef struct smb_com_open_req { /* also handles create */
|
||||
struct smb_hdr hdr; /* wct = 24 */
|
||||
|
@ -799,27 +802,28 @@ typedef struct smb_com_openx_rsp {
|
|||
__u32 FileId;
|
||||
__u16 Reserved;
|
||||
__u16 ByteCount;
|
||||
} __attribute__((packed)) OPENX_RSP;
|
||||
} __attribute__((packed)) OPENX_RSP;
|
||||
|
||||
/* For encoding of POSIX Open Request - see trans2 function 0x209 data struct */
|
||||
|
||||
/* Legacy write request for older servers */
|
||||
typedef struct smb_com_writex_req {
|
||||
struct smb_hdr hdr; /* wct = 12 */
|
||||
__u8 AndXCommand;
|
||||
__u8 AndXReserved;
|
||||
__le16 AndXOffset;
|
||||
__u16 Fid;
|
||||
__le32 OffsetLow;
|
||||
__u32 Reserved; /* Timeout */
|
||||
__le16 WriteMode; /* 1 = write through */
|
||||
__le16 Remaining;
|
||||
__le16 Reserved2;
|
||||
__le16 DataLengthLow;
|
||||
__le16 DataOffset;
|
||||
__le16 ByteCount;
|
||||
__u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
|
||||
char Data[0];
|
||||
struct smb_hdr hdr; /* wct = 12 */
|
||||
__u8 AndXCommand;
|
||||
__u8 AndXReserved;
|
||||
__le16 AndXOffset;
|
||||
__u16 Fid;
|
||||
__le32 OffsetLow;
|
||||
__u32 Reserved; /* Timeout */
|
||||
__le16 WriteMode; /* 1 = write through */
|
||||
__le16 Remaining;
|
||||
__le16 Reserved2;
|
||||
__le16 DataLengthLow;
|
||||
__le16 DataOffset;
|
||||
__le16 ByteCount;
|
||||
__u8 Pad; /* BB check for whether padded to DWORD
|
||||
boundary and optimum performance here */
|
||||
char Data[0];
|
||||
} __attribute__((packed)) WRITEX_REQ;
|
||||
|
||||
typedef struct smb_com_write_req {
|
||||
|
@ -837,7 +841,8 @@ typedef struct smb_com_write_req {
|
|||
__le16 DataOffset;
|
||||
__le32 OffsetHigh;
|
||||
__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];
|
||||
} __attribute__((packed)) WRITE_REQ;
|
||||
|
||||
|
@ -855,17 +860,17 @@ typedef struct smb_com_write_rsp {
|
|||
|
||||
/* legacy read request for older servers */
|
||||
typedef struct smb_com_readx_req {
|
||||
struct smb_hdr hdr; /* wct = 10 */
|
||||
__u8 AndXCommand;
|
||||
__u8 AndXReserved;
|
||||
__le16 AndXOffset;
|
||||
__u16 Fid;
|
||||
__le32 OffsetLow;
|
||||
__le16 MaxCount;
|
||||
__le16 MinCount; /* obsolete */
|
||||
__le32 Reserved;
|
||||
__le16 Remaining;
|
||||
__le16 ByteCount;
|
||||
struct smb_hdr hdr; /* wct = 10 */
|
||||
__u8 AndXCommand;
|
||||
__u8 AndXReserved;
|
||||
__le16 AndXOffset;
|
||||
__u16 Fid;
|
||||
__le32 OffsetLow;
|
||||
__le16 MaxCount;
|
||||
__le16 MinCount; /* obsolete */
|
||||
__le32 Reserved;
|
||||
__le16 Remaining;
|
||||
__le16 ByteCount;
|
||||
} __attribute__((packed)) READX_REQ;
|
||||
|
||||
typedef struct smb_com_read_req {
|
||||
|
@ -896,7 +901,8 @@ typedef struct smb_com_read_rsp {
|
|||
__le16 DataLengthHigh;
|
||||
__u64 Reserved2;
|
||||
__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];
|
||||
} __attribute__((packed)) READ_RSP;
|
||||
|
||||
|
@ -967,7 +973,7 @@ typedef struct smb_com_rename_req {
|
|||
#define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */
|
||||
#define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */
|
||||
#define COPY_VERIFY_WRITES 0x0010
|
||||
#define COPY_TREE 0x0020
|
||||
#define COPY_TREE 0x0020
|
||||
|
||||
typedef struct smb_com_copy_req {
|
||||
struct smb_hdr hdr; /* wct = 3 */
|
||||
|
@ -975,7 +981,7 @@ typedef struct smb_com_copy_req {
|
|||
__le16 OpenFunction;
|
||||
__le16 Flags;
|
||||
__le16 ByteCount;
|
||||
__u8 BufferFormat; /* 4 = ASCII or Unicode */
|
||||
__u8 BufferFormat; /* 4 = ASCII or Unicode */
|
||||
unsigned char OldFileName[1];
|
||||
/* followed by __u8 BufferFormat2 */
|
||||
/* followed by NewFileName string */
|
||||
|
@ -1083,28 +1089,28 @@ typedef struct smb_com_setattr_rsp {
|
|||
|
||||
/*******************************************************/
|
||||
/* NT Transact structure defintions follow */
|
||||
/* Currently only ioctl, acl (get security descriptor) */
|
||||
/* Currently only ioctl, acl (get security descriptor) */
|
||||
/* and notify are implemented */
|
||||
/*******************************************************/
|
||||
typedef struct smb_com_ntransact_req {
|
||||
struct smb_hdr hdr; /* wct >= 19 */
|
||||
__u8 MaxSetupCount;
|
||||
__u16 Reserved;
|
||||
__le32 TotalParameterCount;
|
||||
__le32 TotalDataCount;
|
||||
__le32 MaxParameterCount;
|
||||
__le32 MaxDataCount;
|
||||
__le32 ParameterCount;
|
||||
__le32 ParameterOffset;
|
||||
__le32 DataCount;
|
||||
__le32 DataOffset;
|
||||
__u8 SetupCount; /* four setup words follow subcommand */
|
||||
/* SNIA spec incorrectly included spurious pad here */
|
||||
__le16 SubCommand; /* 2 = IOCTL/FSCTL */
|
||||
/* SetupCount words follow then */
|
||||
__le16 ByteCount;
|
||||
__u8 Pad[3];
|
||||
__u8 Parms[0];
|
||||
struct smb_hdr hdr; /* wct >= 19 */
|
||||
__u8 MaxSetupCount;
|
||||
__u16 Reserved;
|
||||
__le32 TotalParameterCount;
|
||||
__le32 TotalDataCount;
|
||||
__le32 MaxParameterCount;
|
||||
__le32 MaxDataCount;
|
||||
__le32 ParameterCount;
|
||||
__le32 ParameterOffset;
|
||||
__le32 DataCount;
|
||||
__le32 DataOffset;
|
||||
__u8 SetupCount; /* four setup words follow subcommand */
|
||||
/* SNIA spec incorrectly included spurious pad here */
|
||||
__le16 SubCommand; /* 2 = IOCTL/FSCTL */
|
||||
/* SetupCount words follow then */
|
||||
__le16 ByteCount;
|
||||
__u8 Pad[3];
|
||||
__u8 Parms[0];
|
||||
} __attribute__((packed)) NTRANSACT_REQ;
|
||||
|
||||
typedef struct smb_com_ntransact_rsp {
|
||||
|
@ -1120,7 +1126,7 @@ typedef struct smb_com_ntransact_rsp {
|
|||
__le32 DataDisplacement;
|
||||
__u8 SetupCount; /* 0 */
|
||||
__u16 ByteCount;
|
||||
/* __u8 Pad[3]; */
|
||||
/* __u8 Pad[3]; */
|
||||
/* parms and data follow */
|
||||
} __attribute__((packed)) NTRANSACT_RSP;
|
||||
|
||||
|
@ -1215,7 +1221,7 @@ typedef struct smb_com_transaction_change_notify_req {
|
|||
/* __u8 Data[1];*/
|
||||
} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ;
|
||||
|
||||
/* BB eventually change to use generic ntransact rsp struct
|
||||
/* BB eventually change to use generic ntransact rsp struct
|
||||
and validation routine */
|
||||
typedef struct smb_com_transaction_change_notify_rsp {
|
||||
struct smb_hdr hdr; /* wct = 18 */
|
||||
|
@ -1262,7 +1268,7 @@ struct file_notify_information {
|
|||
__le32 Action;
|
||||
__le32 FileNameLength;
|
||||
__u8 FileName[0];
|
||||
} __attribute__((packed));
|
||||
} __attribute__((packed));
|
||||
|
||||
struct reparse_data {
|
||||
__u32 ReparseTag;
|
||||
|
@ -1331,7 +1337,7 @@ struct trans2_resp {
|
|||
__u8 Reserved1;
|
||||
/* SetupWords[SetupCount];
|
||||
__u16 ByteCount;
|
||||
__u16 Reserved2;*/
|
||||
__u16 Reserved2;*/
|
||||
/* data area follows */
|
||||
} __attribute__((packed));
|
||||
|
||||
|
@ -1370,9 +1376,9 @@ struct smb_t2_rsp {
|
|||
#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
|
||||
#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
|
||||
#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
|
||||
#define SMB_QUERY_FILE_POSITION_INFO 0x3f6
|
||||
#define SMB_QUERY_FILE_POSITION_INFO 0x3f6
|
||||
#define SMB_QUERY_FILE_MODE_INFO 0x3f8
|
||||
#define SMB_QUERY_FILE_ALGN_INFO 0x3f9
|
||||
#define SMB_QUERY_FILE_ALGN_INFO 0x3f9
|
||||
|
||||
|
||||
#define SMB_SET_FILE_BASIC_INFO 0x101
|
||||
|
@ -1506,35 +1512,35 @@ struct smb_com_transaction2_sfi_req {
|
|||
__u16 Pad1;
|
||||
__u16 Fid;
|
||||
__le16 InformationLevel;
|
||||
__u16 Reserved4;
|
||||
__u16 Reserved4;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct smb_com_transaction2_sfi_rsp {
|
||||
struct smb_hdr hdr; /* wct = 10 + SetupCount */
|
||||
struct trans2_resp t2;
|
||||
__u16 ByteCount;
|
||||
__u16 Reserved2; /* parameter word reserved -
|
||||
__u16 Reserved2; /* parameter word reserved -
|
||||
present for infolevels > 100 */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct smb_t2_qfi_req {
|
||||
struct smb_hdr hdr;
|
||||
struct trans2_req t2;
|
||||
struct smb_hdr hdr;
|
||||
struct trans2_req t2;
|
||||
__u8 Pad;
|
||||
__u16 Fid;
|
||||
__le16 InformationLevel;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct smb_t2_qfi_rsp {
|
||||
struct smb_hdr hdr; /* wct = 10 + SetupCount */
|
||||
struct trans2_resp t2;
|
||||
__u16 ByteCount;
|
||||
__u16 Reserved2; /* parameter word reserved -
|
||||
present for infolevels > 100 */
|
||||
struct smb_hdr hdr; /* wct = 10 + SetupCount */
|
||||
struct trans2_resp t2;
|
||||
__u16 ByteCount;
|
||||
__u16 Reserved2; /* parameter word reserved -
|
||||
present for infolevels > 100 */
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* Flags on T2 FINDFIRST and FINDNEXT
|
||||
* Flags on T2 FINDFIRST and FINDNEXT
|
||||
*/
|
||||
#define CIFS_SEARCH_CLOSE_ALWAYS 0x0001
|
||||
#define CIFS_SEARCH_CLOSE_AT_END 0x0002
|
||||
|
@ -1743,7 +1749,9 @@ typedef struct smb_com_transaction2_get_dfs_refer_req {
|
|||
__u8 Reserved3;
|
||||
__le16 SubCommand; /* one setup word */
|
||||
__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;
|
||||
char RequestFileName[1];
|
||||
} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ;
|
||||
|
@ -1752,7 +1760,10 @@ typedef struct dfs_referral_level_3 {
|
|||
__le16 VersionNumber;
|
||||
__le16 ReferralSize;
|
||||
__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 Proximity;
|
||||
__le16 DfsPathOffset;
|
||||
|
@ -1778,11 +1789,13 @@ typedef struct smb_com_transaction_get_dfs_refer_rsp {
|
|||
#define DFSREF_STORAGE_SERVER 0x0002
|
||||
|
||||
/* 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. */
|
||||
/* Some of the following such as the encryption/compression ones would be */
|
||||
/* invoked from tools via a specialized hook into the VFS rather than via the */
|
||||
/* standard vfs entry points */
|
||||
/*
|
||||
* List of ioctl function codes that look to be of interest to remote clients
|
||||
* like this one. Need to do some experimentation to make sure they all work
|
||||
* remotely. Some of the following, such as the encryption/compression ones
|
||||
* 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_2 0x00090004
|
||||
#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
|
||||
|
@ -1811,7 +1824,7 @@ typedef struct smb_com_transaction_get_dfs_refer_rsp {
|
|||
/*
|
||||
************************************************************************
|
||||
* All structs for everything above the SMB PDUs themselves
|
||||
* (such as the T2 level specific data) go here
|
||||
* (such as the T2 level specific data) go here
|
||||
************************************************************************
|
||||
*/
|
||||
|
||||
|
@ -1857,7 +1870,7 @@ typedef struct {
|
|||
__le64 FreeAllocationUnits;
|
||||
__le32 SectorsPerAllocationUnit;
|
||||
__le32 BytesPerSector;
|
||||
} __attribute__((packed)) FILE_SYSTEM_INFO; /* size info, level 0x103 */
|
||||
} __attribute__((packed)) FILE_SYSTEM_INFO; /* size info, level 0x103 */
|
||||
|
||||
typedef struct {
|
||||
__le32 fsid;
|
||||
|
@ -1871,7 +1884,7 @@ typedef struct {
|
|||
__le16 MajorVersionNumber;
|
||||
__le16 MinorVersionNumber;
|
||||
__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. */
|
||||
#define CIFS_UNIX_MAJOR_VERSION 1
|
||||
|
@ -1885,16 +1898,20 @@ typedef struct {
|
|||
#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */
|
||||
#define CIFS_UNIX_POSIX_PATH_OPS_CAP 0x00000020 /* Allow new POSIX path based
|
||||
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
|
||||
/* Can not set pathnames cap yet until we send new posix create SMB since
|
||||
otherwise server can treat such handles opened with older ntcreatex
|
||||
(by a new client which knows how to send posix path ops)
|
||||
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 */
|
||||
/* #define CIFS_UNIX_CAP_MASK 0x0000003b */
|
||||
#define CIFS_UNIX_CAP_MASK 0x0000001b
|
||||
#else
|
||||
/* #define CIFS_UNIX_CAP_MASK 0x000000fb */
|
||||
#define CIFS_UNIX_CAP_MASK 0x000000db
|
||||
#else
|
||||
#define CIFS_UNIX_CAP_MASK 0x00000013
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
|
||||
|
@ -1904,10 +1921,10 @@ typedef struct {
|
|||
typedef struct {
|
||||
/* For undefined recommended transfer size return -1 in that field */
|
||||
__le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
|
||||
__le32 BlockSize;
|
||||
__le32 BlockSize;
|
||||
/* The next three fields are in terms of the block size.
|
||||
(above). If block size is unknown, 4096 would be a
|
||||
reasonable block size for a server to report.
|
||||
reasonable block size for a server to report.
|
||||
Note that returning the blocks/blocksavail removes need
|
||||
to make a second call (to QFSInfo level 0x103 to get this info.
|
||||
UserBlockAvail is typically less than or equal to BlocksAvail,
|
||||
|
@ -2062,9 +2079,9 @@ struct file_alt_name_info {
|
|||
|
||||
struct file_stream_info {
|
||||
__le32 number_of_streams; /* BB check sizes and verify location */
|
||||
/* followed by info on streams themselves
|
||||
/* followed by info on streams themselves
|
||||
u64 size;
|
||||
u64 allocation_size
|
||||
u64 allocation_size
|
||||
stream info */
|
||||
}; /* level 0x109 */
|
||||
|
||||
|
@ -2083,7 +2100,7 @@ struct cifs_posix_ace { /* access control entry (ACE) */
|
|||
__u8 cifs_e_tag;
|
||||
__u8 cifs_e_perm;
|
||||
__le64 cifs_uid; /* or gid */
|
||||
} __attribute__((packed));
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cifs_posix_acl { /* access conrol list (ACL) */
|
||||
__le16 version;
|
||||
|
@ -2138,6 +2155,12 @@ typedef struct {
|
|||
/* struct following varies based on requested level */
|
||||
} __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 {
|
||||
__u64 UniqueId; /* inode number */
|
||||
|
@ -2154,7 +2177,7 @@ struct file_attrib_tag {
|
|||
|
||||
|
||||
/********************************************************/
|
||||
/* FindFirst/FindNext transact2 data buffer formats */
|
||||
/* FindFirst/FindNext transact2 data buffer formats */
|
||||
/********************************************************/
|
||||
|
||||
typedef struct {
|
||||
|
@ -2232,7 +2255,7 @@ typedef struct {
|
|||
__le64 EndOfFile;
|
||||
__le64 AllocationSize;
|
||||
__le32 ExtFileAttributes;
|
||||
__le32 FileNameLength;
|
||||
__le32 FileNameLength;
|
||||
__le32 EaSize; /* length of the xattrs */
|
||||
__u8 ShortNameLength;
|
||||
__u8 Reserved;
|
||||
|
@ -2259,7 +2282,7 @@ typedef struct {
|
|||
struct win_dev {
|
||||
unsigned char type[8]; /* IntxCHR or IntxBLK */
|
||||
__le64 major;
|
||||
__le64 minor;
|
||||
__le64 minor;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct gea {
|
||||
|
@ -2291,36 +2314,36 @@ struct fealist {
|
|||
struct data_blob {
|
||||
__u8 *data;
|
||||
size_t length;
|
||||
void (*free) (struct data_blob * data_blob);
|
||||
void (*free) (struct data_blob *data_blob);
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
/*
|
||||
/*
|
||||
For better POSIX semantics from Linux client, (even better
|
||||
than the existing CIFS Unix Extensions) we need updated PDUs for:
|
||||
|
||||
|
||||
1) PosixCreateX - to set and return the mode, inode#, device info and
|
||||
perhaps add a CreateDevice - to create Pipes and other special .inodes
|
||||
Also note POSIX open flags
|
||||
2) Close - to return the last write time to do cache across close
|
||||
2) Close - to return the last write time to do cache across close
|
||||
more safely
|
||||
3) FindFirst return unique inode number - what about resume key, two
|
||||
3) FindFirst return unique inode number - what about resume key, two
|
||||
forms short (matches readdir) and full (enough info to cache inodes)
|
||||
4) Mkdir - set mode
|
||||
|
||||
And under consideration:
|
||||
|
||||
And under consideration:
|
||||
5) FindClose2 (return nanosecond timestamp ??)
|
||||
6) Use nanosecond timestamps throughout all time fields if
|
||||
6) Use nanosecond timestamps throughout all time fields if
|
||||
corresponding attribute flag is set
|
||||
7) sendfile - handle based copy
|
||||
8) Direct i/o
|
||||
9) Misc fcntls?
|
||||
|
||||
|
||||
what about fixing 64 bit alignment
|
||||
|
||||
|
||||
There are also various legacy SMB/CIFS requests used as is
|
||||
|
||||
|
||||
From existing Lanman and NTLM dialects:
|
||||
--------------------------------------
|
||||
NEGOTIATE
|
||||
|
@ -2341,48 +2364,48 @@ struct data_blob {
|
|||
(BB verify that never need to set allocation size)
|
||||
SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via
|
||||
Unix ext?)
|
||||
|
||||
|
||||
COPY (note support for copy across directories) - FUTURE, OPTIONAL
|
||||
setting/getting OS/2 EAs - FUTURE (BB can this handle
|
||||
setting Linux xattrs perfectly) - OPTIONAL
|
||||
dnotify - FUTURE, OPTIONAL
|
||||
quota - FUTURE, OPTIONAL
|
||||
|
||||
Note that various requests implemented for NT interop such as
|
||||
|
||||
Note that various requests implemented for NT interop such as
|
||||
NT_TRANSACT (IOCTL) QueryReparseInfo
|
||||
are unneeded to servers compliant with the CIFS POSIX extensions
|
||||
|
||||
|
||||
From CIFS Unix Extensions:
|
||||
-------------------------
|
||||
T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
|
||||
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_BASIC) - BB check for missing inode fields
|
||||
Actually need QUERY_FILE_UNIX_INFO since has inode num
|
||||
BB what about a) blksize/blkbits/blocks
|
||||
T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) BB check for missing
|
||||
inode fields
|
||||
Actually a need QUERY_FILE_UNIX_INFO
|
||||
since has inode num
|
||||
BB what about a) blksize/blkbits/blocks
|
||||
b) i_version
|
||||
c) i_rdev
|
||||
d) notify mask?
|
||||
e) generation
|
||||
f) size_seqcount
|
||||
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
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/* xsymlink is a symlink format (used by MacOS) that can be used
|
||||
to save symlink info in a regular file when
|
||||
to save symlink info in a regular file when
|
||||
mounted to operating systems that do not
|
||||
support the cifs Unix extensions or EAs (for xattr
|
||||
based symlinks). For such a file to be recognized
|
||||
as containing symlink data:
|
||||
as containing symlink data:
|
||||
|
||||
1) file size must be 1067,
|
||||
1) file size must be 1067,
|
||||
2) signature must begin file data,
|
||||
3) length field must be set to ASCII representation
|
||||
of a number which is less than or equal to 1024,
|
||||
of a number which is less than or equal to 1024,
|
||||
4) md5 must match that of the path data */
|
||||
|
||||
struct xsymlink {
|
||||
|
@ -2393,10 +2416,10 @@ struct xsymlink {
|
|||
char length[4];
|
||||
char cr1; /* \n */
|
||||
/* md5 of valid subset of path ie path[0] through path[length-1] */
|
||||
__u8 md5[32];
|
||||
__u8 md5[32];
|
||||
char cr2; /* \n */
|
||||
/* if room left, then end with \n then 0x20s by convention but not required */
|
||||
char path[1024];
|
||||
char path[1024];
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef struct file_xattr_info {
|
||||
|
@ -2405,7 +2428,8 @@ typedef struct file_xattr_info {
|
|||
__u32 xattr_value_len;
|
||||
char xattr_name[0];
|
||||
/* 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 */
|
||||
|
@ -2431,8 +2455,9 @@ typedef struct file_xattr_info {
|
|||
typedef struct file_chattr_info {
|
||||
__le64 mask; /* list of all possible attribute bits */
|
||||
__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
|
||||
|
||||
#endif /* _CIFSPDU_H */
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _CIFSPROTO_H
|
||||
#define _CIFSPROTO_H
|
||||
|
@ -49,9 +49,9 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
|
|||
struct smb_hdr * /* out */ ,
|
||||
int * /* bytes returned */ , const int long_op);
|
||||
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
|
||||
struct kvec *, int /* nvec to send */,
|
||||
struct kvec *, int /* nvec to send */,
|
||||
int * /* type of buf returned */ , const int long_op);
|
||||
extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
|
||||
extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
|
||||
struct cifsTconInfo *,
|
||||
struct smb_hdr * /* input */ ,
|
||||
struct smb_hdr * /* out */ ,
|
||||
|
@ -64,19 +64,19 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr);
|
|||
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
|
||||
extern int decode_negTokenInit(unsigned char *security_blob, int length,
|
||||
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 void header_assemble(struct smb_hdr *, char /* command */ ,
|
||||
const struct cifsTconInfo *, int /* length of
|
||||
fixed section (word count) in two byte units */);
|
||||
extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
|
||||
struct cifsSesInfo *ses,
|
||||
void ** request_buf);
|
||||
void **request_buf);
|
||||
extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||
const int stage,
|
||||
const int stage,
|
||||
const struct nls_table *nls_cp);
|
||||
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 *);
|
||||
extern void DeleteOplockQEntry(struct oplock_q_entry *);
|
||||
extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
|
||||
|
@ -85,12 +85,12 @@ extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
|
|||
extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
|
||||
|
||||
extern int cifs_get_inode_info(struct inode **pinode,
|
||||
const unsigned char *search_path,
|
||||
const unsigned char *search_path,
|
||||
FILE_ALL_INFO * pfile_info,
|
||||
struct super_block *sb, int xid);
|
||||
extern int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
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 *,
|
||||
const char *);
|
||||
|
@ -98,8 +98,8 @@ extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
|
|||
void cifs_proc_init(void);
|
||||
void cifs_proc_clean(void);
|
||||
|
||||
extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
|
||||
struct nls_table * nls_info);
|
||||
extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
|
||||
struct nls_table *nls_info);
|
||||
extern int CIFSSMBNegotiate(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,
|
||||
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);
|
||||
|
||||
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,
|
||||
const __u16 search_handle);
|
||||
|
@ -123,9 +123,9 @@ extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
|
|||
int legacy /* whether to use old info level */,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
|
||||
const unsigned char *searchName,
|
||||
FILE_ALL_INFO * findData,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
const unsigned char *searchName,
|
||||
FILE_ALL_INFO *findData,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
|
||||
extern int CIFSSMBUnixQPathInfo(const int xid,
|
||||
struct cifsTconInfo *tcon,
|
||||
|
@ -143,13 +143,13 @@ extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
|
|||
const char *old_path,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
|
||||
const char *old_path,
|
||||
const char *old_path,
|
||||
const struct nls_table *nls_codepage,
|
||||
unsigned int *pnum_referrals,
|
||||
unsigned char ** preferrals,
|
||||
unsigned int *pnum_referrals,
|
||||
unsigned char **preferrals,
|
||||
int remap);
|
||||
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,
|
||||
struct kstatfs *FSData);
|
||||
extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon,
|
||||
|
@ -181,11 +181,11 @@ extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
|
|||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
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);
|
||||
extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
|
||||
char *full_path, __u64 mode, __u64 uid,
|
||||
__u64 gid, dev_t dev,
|
||||
__u64 gid, dev_t dev,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
|
||||
|
@ -196,7 +196,10 @@ extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
|
|||
extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
|
||||
const char *name, const struct nls_table *nls_codepage,
|
||||
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,
|
||||
const char *name,
|
||||
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 struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
|
||||
int netfid, char * target_name,
|
||||
extern int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
|
||||
int netfid, char *target_name,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSCreateHardLink(const int xid,
|
||||
|
@ -217,7 +220,7 @@ extern int CIFSCreateHardLink(const int xid,
|
|||
extern int CIFSUnixCreateHardLink(const int xid,
|
||||
struct cifsTconInfo *tcon,
|
||||
const char *fromName, const char *toName,
|
||||
const struct nls_table *nls_codepage,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSUnixCreateSymLink(const int xid,
|
||||
struct cifsTconInfo *tcon,
|
||||
|
@ -228,7 +231,7 @@ extern int CIFSSMBUnixQuerySymLink(const int xid,
|
|||
const unsigned char *searchName,
|
||||
char *syminfo, const int buflen,
|
||||
const struct nls_table *nls_codepage);
|
||||
extern int CIFSSMBQueryReparseLinkInfo(const int xid,
|
||||
extern int CIFSSMBQueryReparseLinkInfo(const int xid,
|
||||
struct cifsTconInfo *tcon,
|
||||
const unsigned char *searchName,
|
||||
char *symlinkinfo, const int buflen, __u16 fid,
|
||||
|
@ -244,35 +247,35 @@ extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
|
|||
const int access_flags, const int omode,
|
||||
__u16 * netfid, int *pOplock, FILE_ALL_INFO *,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon,
|
||||
extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon,
|
||||
u32 posix_flags, __u64 mode, __u16 * netfid,
|
||||
FILE_UNIX_BASIC_INFO *pRetData,
|
||||
__u32 *pOplock, const char *name,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
|
||||
const int smb_file_id);
|
||||
|
||||
extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
|
||||
const int netfid, unsigned int count,
|
||||
const __u64 lseek, unsigned int *nbytes, char **buf,
|
||||
int * return_buf_type);
|
||||
const int netfid, unsigned int count,
|
||||
const __u64 lseek, unsigned int *nbytes, char **buf,
|
||||
int *return_buf_type);
|
||||
extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
|
||||
const int netfid, const unsigned int count,
|
||||
const __u64 lseek, unsigned int *nbytes,
|
||||
const char *buf, const char __user *ubuf,
|
||||
const char *buf, const char __user *ubuf,
|
||||
const int long_op);
|
||||
extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
|
||||
const int netfid, const unsigned int count,
|
||||
const __u64 offset, unsigned int *nbytes,
|
||||
const __u64 offset, unsigned int *nbytes,
|
||||
struct kvec *iov, const int nvec, const int long_op);
|
||||
extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
|
||||
const unsigned char *searchName, __u64 * inode_number,
|
||||
const struct nls_table *nls_codepage,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
|
||||
const struct nls_table * codepage);
|
||||
extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
|
||||
const struct nls_table * cp, int mapChars);
|
||||
const struct nls_table *codepage);
|
||||
extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
|
||||
const struct nls_table *cp, int mapChars);
|
||||
|
||||
extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
|
||||
const __u16 netfid, const __u64 len,
|
||||
|
@ -281,7 +284,7 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
|
|||
const int waitFlag);
|
||||
extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
|
||||
const __u16 smb_file_id, const int get_flag,
|
||||
const __u64 len, struct file_lock *,
|
||||
const __u64 len, struct file_lock *,
|
||||
const __u16 lock_type, const int waitFlag);
|
||||
extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
|
||||
extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
|
||||
|
@ -291,54 +294,56 @@ extern void sesInfoFree(struct cifsSesInfo *);
|
|||
extern struct cifsTconInfo *tconInfoAlloc(void);
|
||||
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 *,
|
||||
__u32 *);
|
||||
extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
|
||||
__u32 expected_sequence_number);
|
||||
extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
|
||||
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
|
||||
extern int cifs_verify_signature(struct smb_hdr *,
|
||||
const struct mac_key *mac_key,
|
||||
__u32 expected_sequence_number);
|
||||
extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
|
||||
const char *pass);
|
||||
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
|
||||
const struct nls_table *);
|
||||
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 *);
|
||||
#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 */
|
||||
extern int CIFSSMBCopy(int xid,
|
||||
struct cifsTconInfo *source_tcon,
|
||||
const char *fromName,
|
||||
const __u16 target_tid,
|
||||
const char *toName, const int flags,
|
||||
const struct nls_table *nls_codepage,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
|
||||
const int notify_subdirs,const __u16 netfid,
|
||||
__u32 filter, struct file * file, int multishot,
|
||||
extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
|
||||
const int notify_subdirs, const __u16 netfid,
|
||||
__u32 filter, struct file *file, int multishot,
|
||||
const struct nls_table *nls_codepage);
|
||||
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,
|
||||
int remap_special_chars);
|
||||
extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
|
||||
const unsigned char * searchName,const unsigned char * ea_name,
|
||||
unsigned char * ea_value, size_t buf_size,
|
||||
extern ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
|
||||
const unsigned char *searchName, const unsigned char *ea_name,
|
||||
unsigned char *ea_value, size_t buf_size,
|
||||
const struct nls_table *nls_codepage, int remap_special_chars);
|
||||
extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
|
||||
const char *fileName, const char * ea_name,
|
||||
const void * ea_value, const __u16 ea_value_len,
|
||||
extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
|
||||
const char *fileName, const char *ea_name,
|
||||
const void *ea_value, const __u16 ea_value_len,
|
||||
const struct nls_table *nls_codepage, int remap_special_chars);
|
||||
extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
|
||||
__u16 fid, char *acl_inf, const int buflen,
|
||||
const int acl_type /* ACCESS vs. DEFAULT */);
|
||||
extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
|
||||
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);
|
||||
extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
|
||||
const unsigned char *fileName,
|
||||
const char *local_acl, const int buflen, const int acl_type,
|
||||
const struct nls_table *nls_codepage, int remap_special_chars);
|
||||
extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
|
||||
const int netfid, __u64 * pExtAttrBits, __u64 *pMask);
|
||||
const int netfid, __u64 * pExtAttrBits, __u64 *pMask);
|
||||
#endif /* _CIFSPROTO_H */
|
||||
|
|
1617
fs/cifs/cifssmb.c
1617
fs/cifs/cifssmb.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
1262
fs/cifs/connect.c
1262
fs/cifs/connect.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -135,10 +135,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
|||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
char *full_path = NULL;
|
||||
FILE_ALL_INFO * buf = NULL;
|
||||
FILE_ALL_INFO *buf = NULL;
|
||||
struct inode *newinode = NULL;
|
||||
struct cifsFileInfo * pCifsFile = NULL;
|
||||
struct cifsInodeInfo * pCifsInode;
|
||||
struct cifsFileInfo *pCifsFile = NULL;
|
||||
struct cifsInodeInfo *pCifsInode;
|
||||
int disposition = FILE_OVERWRITE_IF;
|
||||
int write_only = FALSE;
|
||||
|
||||
|
@ -207,8 +207,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
|||
} else {
|
||||
/* If Open reported that we actually created a file
|
||||
then we now have to set the mode if possible */
|
||||
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
|
||||
(oplock & CIFS_CREATE_ACTION)) {
|
||||
if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
|
||||
mode &= ~current->fs->umask;
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||
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 */
|
||||
}
|
||||
|
||||
/* BB server might mask mode so we have to query for Unix case*/
|
||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
||||
/* server might mask mode so we have to query for it */
|
||||
if (pTcon->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
||||
inode->i_sb, xid);
|
||||
else {
|
||||
|
@ -264,7 +263,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
|||
direntry->d_op = &cifs_dentry_ops;
|
||||
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 */
|
||||
CIFSSMBClose(xid, pTcon, fileHandle);
|
||||
} 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 cifsTconInfo *pTcon;
|
||||
char *full_path = NULL;
|
||||
struct inode * newinode = NULL;
|
||||
struct inode *newinode = NULL;
|
||||
|
||||
if (!old_valid_dev(device_number))
|
||||
return -EINVAL;
|
||||
|
@ -336,7 +336,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
|||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL)
|
||||
rc = -ENOMEM;
|
||||
else if (pTcon->ses->capabilities & CAP_UNIX) {
|
||||
else if (pTcon->unix_ext) {
|
||||
mode &= ~current->fs->umask;
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
||||
|
@ -490,7 +490,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
|||
cFYI(1,
|
||||
(" 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,
|
||||
parent_dir_inode->i_sb, xid);
|
||||
else
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* Common Internet FileSystem (CIFS) client
|
||||
*
|
||||
*
|
||||
* Operations related to support for exporting files via NFSD
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
|
@ -22,32 +22,45 @@
|
|||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* See Documentation/filesystems/Exporting
|
||||
* 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/exportfs.h>
|
||||
|
||||
#include "cifsglob.h"
|
||||
#include "cifs_debug.h"
|
||||
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
|
||||
static struct dentry *cifs_get_parent(struct dentry *dentry)
|
||||
{
|
||||
/* BB need to add code here eventually to enable export via NFSD */
|
||||
return ERR_PTR(-EACCES);
|
||||
/* BB need to add code here eventually to enable export via NFSD */
|
||||
cFYI(1, ("get parent for %p", dentry));
|
||||
return ERR_PTR(-EACCES);
|
||||
}
|
||||
|
||||
|
||||
struct export_operations cifs_export_ops = {
|
||||
.get_parent = cifs_get_parent,
|
||||
/* Following five export operations are unneeded so far and can default */
|
||||
/* .get_dentry =
|
||||
.get_name =
|
||||
.find_exported_dentry =
|
||||
.decode_fh =
|
||||
.encode_fs = */
|
||||
};
|
||||
|
||||
.get_parent = cifs_get_parent,
|
||||
/* Following five export operations are unneeded so far and can default:
|
||||
.get_dentry =
|
||||
.get_name =
|
||||
.find_exported_dentry =
|
||||
.decode_fh =
|
||||
.encode_fs = */
|
||||
};
|
||||
|
||||
#endif /* EXPERIMENTAL */
|
||||
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_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 rc = -EINVAL;
|
||||
|
|
287
fs/cifs/file.c
287
fs/cifs/file.c
|
@ -2,8 +2,8 @@
|
|||
* fs/cifs/file.c
|
||||
*
|
||||
* 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)
|
||||
* Jeremy Allison (jra@samba.org)
|
||||
*
|
||||
|
@ -45,7 +45,7 @@ static inline struct cifsFileInfo *cifs_init_private(
|
|||
{
|
||||
memset(private_data, 0, sizeof(struct cifsFileInfo));
|
||||
private_data->netfid = netfid;
|
||||
private_data->pid = current->tgid;
|
||||
private_data->pid = current->tgid;
|
||||
init_MUTEX(&private_data->fh_sem);
|
||||
mutex_init(&private_data->lock_mutex);
|
||||
INIT_LIST_HEAD(&private_data->llist);
|
||||
|
@ -57,7 +57,7 @@ static inline struct cifsFileInfo *cifs_init_private(
|
|||
does not tell us which handle the write is for so there can
|
||||
be a close (overlapping with write) of the filehandle that
|
||||
cifs_writepages chose to use */
|
||||
atomic_set(&private_data->wrtPending,0);
|
||||
atomic_set(&private_data->wrtPending, 0);
|
||||
|
||||
return private_data;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
|
|||
in the list so we do not have to walk the
|
||||
list to search for one in prepare_write */
|
||||
if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
|
||||
list_add_tail(&pCifsFile->flist,
|
||||
list_add_tail(&pCifsFile->flist,
|
||||
&pCifsInode->openFileList);
|
||||
} else {
|
||||
list_add(&pCifsFile->flist,
|
||||
|
@ -138,7 +138,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
|
|||
}
|
||||
|
||||
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,
|
||||
full_path, inode->i_sb, xid);
|
||||
else
|
||||
|
@ -189,7 +189,7 @@ int cifs_open(struct inode *inode, struct file *file)
|
|||
|
||||
/* needed for writepage */
|
||||
pCifsFile->pfile = file;
|
||||
|
||||
|
||||
file->private_data = pCifsFile;
|
||||
break;
|
||||
}
|
||||
|
@ -212,15 +212,15 @@ int cifs_open(struct inode *inode, struct file *file)
|
|||
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));
|
||||
desiredAccess = cifs_convert_flags(file->f_flags);
|
||||
|
||||
/*********************************************************************
|
||||
* open flag mapping table:
|
||||
*
|
||||
*
|
||||
* POSIX Flag CIFS Disposition
|
||||
* ---------- ----------------
|
||||
* ---------- ----------------
|
||||
* O_CREAT FILE_OPEN_IF
|
||||
* O_CREAT | O_EXCL FILE_CREATE
|
||||
* O_CREAT | O_TRUNC FILE_OVERWRITE_IF
|
||||
|
@ -228,12 +228,12 @@ int cifs_open(struct inode *inode, struct file *file)
|
|||
* none of the above FILE_OPEN
|
||||
*
|
||||
* Note that there is not a direct match between disposition
|
||||
* FILE_SUPERSEDE (ie create whether or not file exists although
|
||||
* FILE_SUPERSEDE (ie create whether or not file exists although
|
||||
* O_CREAT | O_TRUNC is similar but truncates the existing
|
||||
* file rather than creating a new file as FILE_SUPERSEDE does
|
||||
* (which uses the attributes / metadata passed in on open call)
|
||||
*?
|
||||
*? O_SYNC is a reasonable match to CIFS writethrough flag
|
||||
*? O_SYNC is a reasonable match to CIFS writethrough flag
|
||||
*? and the read write flags match reasonably. O_LARGEFILE
|
||||
*? is irrelevant because largefile support is always used
|
||||
*? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
|
||||
|
@ -253,8 +253,8 @@ int cifs_open(struct inode *inode, struct file *file)
|
|||
and calling get_inode_info with returned buf (at least helps
|
||||
non-Unix server case) */
|
||||
|
||||
/* BB we can not do this if this is the second open of a file
|
||||
and the first handle has writebehind data, we might be
|
||||
/* BB we can not do this if this is the second open of a file
|
||||
and the first handle has writebehind data, we might be
|
||||
able to simply do a filemap_fdatawrite/filemap_fdatawait first */
|
||||
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
||||
if (!buf) {
|
||||
|
@ -263,7 +263,7 @@ int cifs_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
|
||||
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
|
||||
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
|
||||
desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
|
||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
|
||||
& CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
|
@ -300,15 +300,15 @@ int cifs_open(struct inode *inode, struct file *file)
|
|||
write_unlock(&GlobalSMBSeslock);
|
||||
}
|
||||
|
||||
if (oplock & CIFS_CREATE_ACTION) {
|
||||
if (oplock & CIFS_CREATE_ACTION) {
|
||||
/* time to set mode which we can not set earlier due to
|
||||
problems creating new read-only files */
|
||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
|
||||
if (pTcon->unix_ext) {
|
||||
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
||||
inode->i_mode,
|
||||
(__u64)-1, (__u64)-1, 0 /* dev */,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
} else {
|
||||
/* BB implement via Windows security descriptors eg
|
||||
|
@ -345,7 +345,7 @@ static int cifs_reopen_file(struct file *file, int can_flush)
|
|||
struct cifsTconInfo *pTcon;
|
||||
struct cifsFileInfo *pCifsFile;
|
||||
struct cifsInodeInfo *pCifsInode;
|
||||
struct inode * inode;
|
||||
struct inode *inode;
|
||||
char *full_path = NULL;
|
||||
int desiredAccess;
|
||||
int disposition = FILE_OPEN;
|
||||
|
@ -372,13 +372,13 @@ static int cifs_reopen_file(struct file *file, int can_flush)
|
|||
}
|
||||
|
||||
inode = file->f_path.dentry->d_inode;
|
||||
if(inode == NULL) {
|
||||
if (inode == NULL) {
|
||||
cERROR(1, ("inode not valid"));
|
||||
dump_stack();
|
||||
rc = -EBADF;
|
||||
goto reopen_error_exit;
|
||||
}
|
||||
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
pTcon = cifs_sb->tcon;
|
||||
|
||||
|
@ -396,7 +396,7 @@ reopen_error_exit:
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
if (oplockEnabled)
|
||||
|
@ -405,14 +405,14 @@ reopen_error_exit:
|
|||
oplock = FALSE;
|
||||
|
||||
/* Can not refresh inode by passing in file_info buf to be returned
|
||||
by SMBOpen and then calling get_inode_info with returned buf
|
||||
since file might have write behind data that needs to be flushed
|
||||
by SMBOpen and then calling get_inode_info with returned buf
|
||||
since file might have write behind data that needs to be flushed
|
||||
and server version of file size can be stale. If we knew for sure
|
||||
that inode was not dirty locally we could do this */
|
||||
|
||||
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
|
||||
CREATE_NOT_DIR, &netfid, &oplock, NULL,
|
||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc) {
|
||||
up(&pCifsFile->fh_sem);
|
||||
|
@ -430,7 +430,7 @@ reopen_error_exit:
|
|||
go to server to get inode info */
|
||||
pCifsInode->clientCanCacheAll = FALSE;
|
||||
pCifsInode->clientCanCacheRead = FALSE;
|
||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
||||
if (pTcon->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&inode,
|
||||
full_path, inode->i_sb, xid);
|
||||
else
|
||||
|
@ -486,23 +486,24 @@ int cifs_close(struct inode *inode, struct file *file)
|
|||
already closed */
|
||||
if (pTcon->tidStatus != CifsNeedReconnect) {
|
||||
int timeout = 2;
|
||||
while((atomic_read(&pSMBFile->wrtPending) != 0)
|
||||
while ((atomic_read(&pSMBFile->wrtPending) != 0)
|
||||
&& (timeout < 1000) ) {
|
||||
/* Give write a better chance to get to
|
||||
server ahead of the close. We do not
|
||||
want to add a wait_q here as it would
|
||||
increase the memory utilization as
|
||||
the struct would be in each open file,
|
||||
but this should give enough time to
|
||||
but this should give enough time to
|
||||
clear the socket */
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
cFYI(1,("close delay, write pending"));
|
||||
cFYI(1, ("close delay, write pending"));
|
||||
#endif /* DEBUG2 */
|
||||
msleep(timeout);
|
||||
timeout *= 4;
|
||||
}
|
||||
if(atomic_read(&pSMBFile->wrtPending))
|
||||
cERROR(1,("close with pending writes"));
|
||||
if (atomic_read(&pSMBFile->wrtPending))
|
||||
cERROR(1,
|
||||
("close with pending writes"));
|
||||
rc = CIFSSMBClose(xid, pTcon,
|
||||
pSMBFile->netfid);
|
||||
}
|
||||
|
@ -534,7 +535,7 @@ int cifs_close(struct inode *inode, struct file *file)
|
|||
CIFS_I(inode)->clientCanCacheRead = 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;
|
||||
FreeXid(xid);
|
||||
return rc;
|
||||
|
@ -554,7 +555,8 @@ int cifs_closedir(struct inode *inode, struct file *file)
|
|||
|
||||
if (pCFileStruct) {
|
||||
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;
|
||||
|
||||
|
@ -572,7 +574,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
|
|||
if (ptmp) {
|
||||
cFYI(1, ("closedir free smb buf in srch struct"));
|
||||
pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
|
||||
if(pCFileStruct->srch_inf.smallBuf)
|
||||
if (pCFileStruct->srch_inf.smallBuf)
|
||||
cifs_small_buf_release(ptmp);
|
||||
else
|
||||
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,
|
||||
__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)
|
||||
return -ENOMEM;
|
||||
li->offset = offset;
|
||||
|
@ -625,8 +628,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
|||
|
||||
cFYI(1, ("Lock parm: 0x%x flockflags: "
|
||||
"0x%x flocktype: 0x%x start: %lld end: %lld",
|
||||
cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
|
||||
pfLock->fl_end));
|
||||
cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
|
||||
pfLock->fl_end));
|
||||
|
||||
if (pfLock->fl_flags & FL_POSIX)
|
||||
cFYI(1, ("Posix"));
|
||||
|
@ -641,7 +644,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
|||
"not implemented yet"));
|
||||
if (pfLock->fl_flags & FL_LEASE)
|
||||
cFYI(1, ("Lease on file - not implemented yet"));
|
||||
if (pfLock->fl_flags &
|
||||
if (pfLock->fl_flags &
|
||||
(~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
|
||||
cFYI(1, ("Unknown lock flags 0x%x", pfLock->fl_flags));
|
||||
|
||||
|
@ -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
|
||||
wire */
|
||||
if (IS_GETLK(cmd)) {
|
||||
if(posix_locking) {
|
||||
if (posix_locking) {
|
||||
int posix_lock_type;
|
||||
if(lockType & LOCKING_ANDX_SHARED_LOCK)
|
||||
if (lockType & LOCKING_ANDX_SHARED_LOCK)
|
||||
posix_lock_type = CIFS_RDLCK;
|
||||
else
|
||||
posix_lock_type = CIFS_WRLCK;
|
||||
|
@ -700,7 +703,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
|||
rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
|
||||
0, 1, lockType, 0 /* wait flag */ );
|
||||
if (rc == 0) {
|
||||
rc = CIFSSMBLock(xid, pTcon, netfid, length,
|
||||
rc = CIFSSMBLock(xid, pTcon, netfid, length,
|
||||
pfLock->fl_start, 1 /* numUnlock */ ,
|
||||
0 /* numLock */ , lockType,
|
||||
0 /* wait flag */ );
|
||||
|
@ -729,22 +732,24 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
|||
|
||||
if (posix_locking) {
|
||||
int posix_lock_type;
|
||||
if(lockType & LOCKING_ANDX_SHARED_LOCK)
|
||||
if (lockType & LOCKING_ANDX_SHARED_LOCK)
|
||||
posix_lock_type = CIFS_RDLCK;
|
||||
else
|
||||
posix_lock_type = CIFS_WRLCK;
|
||||
|
||||
if(numUnlock == 1)
|
||||
|
||||
if (numUnlock == 1)
|
||||
posix_lock_type = CIFS_UNLCK;
|
||||
|
||||
rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
|
||||
length, pfLock,
|
||||
posix_lock_type, wait_flag);
|
||||
} else {
|
||||
struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data;
|
||||
struct cifsFileInfo *fid =
|
||||
(struct cifsFileInfo *)file->private_data;
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
if (pfLock->fl_start <= li->offset &&
|
||||
length >= li->length) {
|
||||
stored_rc = CIFSSMBLock(xid, pTcon, netfid,
|
||||
stored_rc = CIFSSMBLock(xid, pTcon,
|
||||
netfid,
|
||||
li->length, li->offset,
|
||||
1, 0, li->type, FALSE);
|
||||
if (stored_rc)
|
||||
|
@ -805,7 +811,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
|
|||
if (file->private_data == NULL)
|
||||
return -EBADF;
|
||||
open_file = (struct cifsFileInfo *) file->private_data;
|
||||
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
if (*poffset > file->f_path.dentry->d_inode->i_size)
|
||||
|
@ -824,7 +830,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
|
|||
and blocked, and the file has been freed on us while
|
||||
we blocked so return what we managed to write */
|
||||
return total_written;
|
||||
}
|
||||
}
|
||||
if (open_file->closePend) {
|
||||
FreeXid(xid);
|
||||
if (total_written)
|
||||
|
@ -867,8 +873,8 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
|
|||
/* since the write may have blocked check these pointers again */
|
||||
if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) {
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
/* Do not update local mtime - server will set its actual value on write
|
||||
* inode->i_ctime = inode->i_mtime =
|
||||
/* Do not update local mtime - server will set its actual value on write
|
||||
* inode->i_ctime = inode->i_mtime =
|
||||
* current_fs_time(inode->i_sb);*/
|
||||
if (total_written > 0) {
|
||||
spin_lock(&inode->i_lock);
|
||||
|
@ -877,7 +883,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
|
|||
*poffset);
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
mark_inode_dirty_sync(file->f_path.dentry->d_inode);
|
||||
mark_inode_dirty_sync(file->f_path.dentry->d_inode);
|
||||
}
|
||||
FreeXid(xid);
|
||||
return total_written;
|
||||
|
@ -898,13 +904,13 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
|
|||
|
||||
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));
|
||||
|
||||
if (file->private_data == NULL)
|
||||
return -EBADF;
|
||||
open_file = (struct cifsFileInfo *)file->private_data;
|
||||
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
if (*poffset > file->f_path.dentry->d_inode->i_size)
|
||||
|
@ -921,10 +927,10 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
|
|||
FreeXid(xid);
|
||||
/* if we have gotten here we have written some data
|
||||
and blocked, and the file has been freed on us
|
||||
while we blocked so return what we managed to
|
||||
while we blocked so return what we managed to
|
||||
write */
|
||||
return total_written;
|
||||
}
|
||||
}
|
||||
if (open_file->closePend) {
|
||||
FreeXid(xid);
|
||||
if (total_written)
|
||||
|
@ -935,14 +941,14 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
|
|||
if (open_file->invalidHandle) {
|
||||
/* we could deadlock if we called
|
||||
filemap_fdatawait from here so tell
|
||||
reopen_file not to flush data to
|
||||
reopen_file not to flush data to
|
||||
server now */
|
||||
rc = cifs_reopen_file(file, FALSE);
|
||||
if (rc != 0)
|
||||
break;
|
||||
}
|
||||
if(experimEnabled || (pTcon->ses->server &&
|
||||
((pTcon->ses->server->secMode &
|
||||
if (experimEnabled || (pTcon->ses->server &&
|
||||
((pTcon->ses->server->secMode &
|
||||
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
||||
== 0))) {
|
||||
struct kvec iov[2];
|
||||
|
@ -976,7 +982,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
|
|||
}
|
||||
} else
|
||||
*poffset += bytes_written;
|
||||
long_op = FALSE; /* subsequent writes fast -
|
||||
long_op = FALSE; /* subsequent writes fast -
|
||||
15 seconds is plenty */
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
it being zero) during stress testcases so we need to check for it */
|
||||
|
||||
if(cifs_inode == NULL) {
|
||||
cERROR(1,("Null inode passed to cifs_writeable_file"));
|
||||
if (cifs_inode == NULL) {
|
||||
cERROR(1, ("Null inode passed to cifs_writeable_file"));
|
||||
dump_stack();
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1024,13 +1030,14 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
|
|||
(open_file->pfile->f_flags & O_WRONLY))) {
|
||||
atomic_inc(&open_file->wrtPending);
|
||||
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 */) {
|
||||
rc = cifs_reopen_file(open_file->pfile, FALSE);
|
||||
/* if it fails, try another handle - might be */
|
||||
/* dangerous to hold up writepages with retry */
|
||||
if(rc) {
|
||||
cFYI(1,("failed on reopen file in wp"));
|
||||
if (rc) {
|
||||
cFYI(1,
|
||||
("failed on reopen file in wp"));
|
||||
read_lock(&GlobalSMBSeslock);
|
||||
/* can not use this handle, no write
|
||||
pending on this one after all */
|
||||
|
@ -1082,7 +1089,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
|
|||
|
||||
/* check to make sure that we are not extending the file */
|
||||
if (mapping->host->i_size - offset < (loff_t)to)
|
||||
to = (unsigned)(mapping->host->i_size - offset);
|
||||
to = (unsigned)(mapping->host->i_size - offset);
|
||||
|
||||
open_file = find_writable_file(CIFS_I(mapping->host));
|
||||
if (open_file) {
|
||||
|
@ -1116,8 +1123,8 @@ static int cifs_writepages(struct address_space *mapping,
|
|||
int done = 0;
|
||||
pgoff_t end;
|
||||
pgoff_t index;
|
||||
int range_whole = 0;
|
||||
struct kvec * iov;
|
||||
int range_whole = 0;
|
||||
struct kvec *iov;
|
||||
int len;
|
||||
int n_iov = 0;
|
||||
pgoff_t next;
|
||||
|
@ -1131,7 +1138,7 @@ static int cifs_writepages(struct address_space *mapping,
|
|||
int xid;
|
||||
|
||||
cifs_sb = CIFS_SB(mapping->host->i_sb);
|
||||
|
||||
|
||||
/*
|
||||
* If wsize is smaller that the page cache size, default to writing
|
||||
* one page at a time via cifs_writepage
|
||||
|
@ -1139,14 +1146,14 @@ static int cifs_writepages(struct address_space *mapping,
|
|||
if (cifs_sb->wsize < PAGE_CACHE_SIZE)
|
||||
return generic_writepages(mapping, wbc);
|
||||
|
||||
if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
|
||||
if(cifs_sb->tcon->ses->server->secMode &
|
||||
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
||||
if(!experimEnabled)
|
||||
if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
|
||||
if (cifs_sb->tcon->ses->server->secMode &
|
||||
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
||||
if (!experimEnabled)
|
||||
return generic_writepages(mapping, wbc);
|
||||
|
||||
iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);
|
||||
if(iov == NULL)
|
||||
if (iov == NULL)
|
||||
return generic_writepages(mapping, wbc);
|
||||
|
||||
|
||||
|
@ -1279,7 +1286,7 @@ retry:
|
|||
1);
|
||||
atomic_dec(&open_file->wrtPending);
|
||||
if (rc || bytes_written < bytes_to_write) {
|
||||
cERROR(1,("Write2 ret %d, written = %d",
|
||||
cERROR(1, ("Write2 ret %d, wrote %d",
|
||||
rc, bytes_written));
|
||||
/* BB what if continued retry is
|
||||
requested via mount flags? */
|
||||
|
@ -1295,8 +1302,8 @@ retry:
|
|||
success rc but too little data written? */
|
||||
/* BB investigate retry logic on temporary
|
||||
server crash cases and how recovery works
|
||||
when page marked as error */
|
||||
if(rc)
|
||||
when page marked as error */
|
||||
if (rc)
|
||||
SetPageError(page);
|
||||
kunmap(page);
|
||||
unlock_page(page);
|
||||
|
@ -1326,7 +1333,7 @@ retry:
|
|||
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 xid;
|
||||
|
@ -1334,7 +1341,7 @@ static int cifs_writepage(struct page* page, struct writeback_control *wbc)
|
|||
xid = GetXid();
|
||||
/* BB add check for wbc flags */
|
||||
page_cache_get(page);
|
||||
if (!PageUptodate(page)) {
|
||||
if (!PageUptodate(page)) {
|
||||
cFYI(1, ("ppw - page not up to date"));
|
||||
}
|
||||
|
||||
|
@ -1348,7 +1355,7 @@ static int cifs_writepage(struct page* page, struct writeback_control *wbc)
|
|||
* Just unlocking the page will cause the radix tree tag-bits
|
||||
* to fail to update with the state of the page correctly.
|
||||
*/
|
||||
set_page_writeback(page);
|
||||
set_page_writeback(page);
|
||||
rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
|
||||
SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
|
||||
unlock_page(page);
|
||||
|
@ -1368,7 +1375,7 @@ static int cifs_commit_write(struct file *file, struct page *page,
|
|||
char *page_data;
|
||||
|
||||
xid = GetXid();
|
||||
cFYI(1, ("commit write for page %p up to position %lld for %d",
|
||||
cFYI(1, ("commit write for page %p up to position %lld for %d",
|
||||
page, position, to));
|
||||
spin_lock(&inode->i_lock);
|
||||
if (position > inode->i_size) {
|
||||
|
@ -1396,7 +1403,7 @@ static int cifs_commit_write(struct file *file, struct page *page,
|
|||
rc = 0;
|
||||
/* else if (rc < 0) should we set writebehind rc? */
|
||||
kunmap(page);
|
||||
} else {
|
||||
} else {
|
||||
set_page_dirty(page);
|
||||
}
|
||||
|
||||
|
@ -1412,9 +1419,9 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
|
|||
|
||||
xid = GetXid();
|
||||
|
||||
cFYI(1, ("Sync file - name: %s datasync: 0x%x",
|
||||
cFYI(1, ("Sync file - name: %s datasync: 0x%x",
|
||||
dentry->d_name.name, datasync));
|
||||
|
||||
|
||||
rc = filemap_fdatawrite(inode->i_mapping);
|
||||
if (rc == 0)
|
||||
CIFS_I(inode)->write_behind_rc = 0;
|
||||
|
@ -1438,7 +1445,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
|
|||
if (!inode)
|
||||
return; */
|
||||
|
||||
/* fill in rpages then
|
||||
/* fill in rpages then
|
||||
result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
|
||||
|
||||
/* cFYI(1, ("rpages is %d for sync page of Index %ld", rpages, index));
|
||||
|
@ -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)
|
||||
{
|
||||
struct inode * inode = file->f_path.dentry->d_inode;
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
int rc = 0;
|
||||
|
||||
/* Rather than do the steps manually:
|
||||
|
@ -1471,8 +1478,8 @@ int cifs_flush(struct file *file, fl_owner_t id)
|
|||
rc = filemap_fdatawrite(inode->i_mapping);
|
||||
if (!rc) /* reset wb rc if we were able to write out dirty pages */
|
||||
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;
|
||||
}
|
||||
|
@ -1508,13 +1515,13 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
|
|||
for (total_read = 0, current_offset = read_data;
|
||||
read_size > total_read;
|
||||
total_read += bytes_read, current_offset += bytes_read) {
|
||||
current_read_size = min_t(const int, read_size - total_read,
|
||||
current_read_size = min_t(const int, read_size - total_read,
|
||||
cifs_sb->rsize);
|
||||
rc = -EAGAIN;
|
||||
smb_read_data = NULL;
|
||||
while (rc == -EAGAIN) {
|
||||
int buf_type = CIFS_NO_BUFFER;
|
||||
if ((open_file->invalidHandle) &&
|
||||
if ((open_file->invalidHandle) &&
|
||||
(!open_file->closePend)) {
|
||||
rc = cifs_reopen_file(file, TRUE);
|
||||
if (rc != 0)
|
||||
|
@ -1535,9 +1542,9 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
|
|||
rc = -EFAULT;
|
||||
}
|
||||
|
||||
if(buf_type == CIFS_SMALL_BUFFER)
|
||||
if (buf_type == CIFS_SMALL_BUFFER)
|
||||
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);
|
||||
smb_read_data = NULL;
|
||||
}
|
||||
|
@ -1586,21 +1593,21 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
|
|||
if ((file->f_flags & O_ACCMODE) == O_WRONLY)
|
||||
cFYI(1, ("attempting read on write only file instance"));
|
||||
|
||||
for (total_read = 0, current_offset = read_data;
|
||||
for (total_read = 0, current_offset = read_data;
|
||||
read_size > total_read;
|
||||
total_read += bytes_read, current_offset += bytes_read) {
|
||||
current_read_size = min_t(const int, read_size - total_read,
|
||||
cifs_sb->rsize);
|
||||
/* For windows me and 9x we do not want to request more
|
||||
than it negotiated since it will refuse the read then */
|
||||
if((pTcon->ses) &&
|
||||
if ((pTcon->ses) &&
|
||||
!(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
|
||||
current_read_size = min_t(const int, current_read_size,
|
||||
pTcon->ses->server->maxBuf - 128);
|
||||
}
|
||||
rc = -EAGAIN;
|
||||
while (rc == -EAGAIN) {
|
||||
if ((open_file->invalidHandle) &&
|
||||
if ((open_file->invalidHandle) &&
|
||||
(!open_file->closePend)) {
|
||||
rc = cifs_reopen_file(file, TRUE);
|
||||
if (rc != 0)
|
||||
|
@ -1646,7 +1653,7 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
}
|
||||
|
||||
|
||||
static void cifs_copy_cache_pages(struct address_space *mapping,
|
||||
static void cifs_copy_cache_pages(struct address_space *mapping,
|
||||
struct list_head *pages, int bytes_read, char *data,
|
||||
struct pagevec *plru_pvec)
|
||||
{
|
||||
|
@ -1669,12 +1676,12 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
|
|||
continue;
|
||||
}
|
||||
|
||||
target = kmap_atomic(page,KM_USER0);
|
||||
target = kmap_atomic(page, KM_USER0);
|
||||
|
||||
if (PAGE_CACHE_SIZE > bytes_read) {
|
||||
memcpy(target, data, bytes_read);
|
||||
/* zero the tail end of this partial page */
|
||||
memset(target + bytes_read, 0,
|
||||
memset(target + bytes_read, 0,
|
||||
PAGE_CACHE_SIZE - bytes_read);
|
||||
bytes_read = 0;
|
||||
} else {
|
||||
|
@ -1703,7 +1710,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
int bytes_read = 0;
|
||||
unsigned int read_size,i;
|
||||
unsigned int read_size, i;
|
||||
char *smb_read_data = NULL;
|
||||
struct smb_com_read_rsp *pSMBr;
|
||||
struct pagevec lru_pvec;
|
||||
|
@ -1720,7 +1727,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||
pTcon = cifs_sb->tcon;
|
||||
|
||||
pagevec_init(&lru_pvec, 0);
|
||||
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
cFYI(1, ("rpages: num pages %d", num_pages));
|
||||
#endif
|
||||
for (i = 0; i < num_pages; ) {
|
||||
unsigned contig_pages;
|
||||
struct page *tmp_page;
|
||||
|
@ -1734,14 +1743,14 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||
|
||||
/* count adjacent pages that we will read into */
|
||||
contig_pages = 0;
|
||||
expected_index =
|
||||
expected_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) {
|
||||
contig_pages++;
|
||||
expected_index++;
|
||||
} else
|
||||
break;
|
||||
break;
|
||||
}
|
||||
if (contig_pages + i > num_pages)
|
||||
contig_pages = num_pages - i;
|
||||
|
@ -1753,10 +1762,13 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||
/* Read size needs to be in multiples of one page */
|
||||
read_size = min_t(const unsigned int, read_size,
|
||||
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;
|
||||
while (rc == -EAGAIN) {
|
||||
if ((open_file->invalidHandle) &&
|
||||
if ((open_file->invalidHandle) &&
|
||||
(!open_file->closePend)) {
|
||||
rc = cifs_reopen_file(file, TRUE);
|
||||
if (rc != 0)
|
||||
|
@ -1769,11 +1781,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||
&bytes_read, &smb_read_data,
|
||||
&buf_type);
|
||||
/* BB more RC checks ? */
|
||||
if (rc== -EAGAIN) {
|
||||
if (rc == -EAGAIN) {
|
||||
if (smb_read_data) {
|
||||
if(buf_type == CIFS_SMALL_BUFFER)
|
||||
if (buf_type == CIFS_SMALL_BUFFER)
|
||||
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);
|
||||
smb_read_data = NULL;
|
||||
}
|
||||
|
@ -1794,10 +1806,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||
if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
|
||||
i++; /* account for partial page */
|
||||
|
||||
/* server copy of file can have smaller size
|
||||
/* server copy of file can have smaller size
|
||||
than client */
|
||||
/* BB do we need to verify this common case ?
|
||||
this case is ok - if we are at server EOF
|
||||
/* BB do we need to verify this common case ?
|
||||
this case is ok - if we are at server EOF
|
||||
we will hit it on next read */
|
||||
|
||||
/* break; */
|
||||
|
@ -1806,14 +1818,14 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||
cFYI(1, ("No bytes read (%d) at offset %lld . "
|
||||
"Cleaning remaining pages from readahead list",
|
||||
bytes_read, offset));
|
||||
/* BB turn off caching and do new lookup on
|
||||
/* BB turn off caching and do new lookup on
|
||||
file size at server? */
|
||||
break;
|
||||
}
|
||||
if (smb_read_data) {
|
||||
if(buf_type == CIFS_SMALL_BUFFER)
|
||||
if (buf_type == CIFS_SMALL_BUFFER)
|
||||
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);
|
||||
smb_read_data = NULL;
|
||||
}
|
||||
|
@ -1824,12 +1836,12 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||
|
||||
/* need to free smb_read_data buf before exit */
|
||||
if (smb_read_data) {
|
||||
if(buf_type == CIFS_SMALL_BUFFER)
|
||||
if (buf_type == CIFS_SMALL_BUFFER)
|
||||
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);
|
||||
smb_read_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
FreeXid(xid);
|
||||
return rc;
|
||||
|
@ -1844,26 +1856,26 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
|
|||
page_cache_get(page);
|
||||
read_data = kmap(page);
|
||||
/* for reads over a certain size could initiate async read ahead */
|
||||
|
||||
|
||||
rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
|
||||
|
||||
|
||||
if (rc < 0)
|
||||
goto io_error;
|
||||
else
|
||||
cFYI(1, ("Bytes read %d",rc));
|
||||
|
||||
cFYI(1, ("Bytes read %d", rc));
|
||||
|
||||
file->f_path.dentry->d_inode->i_atime =
|
||||
current_fs_time(file->f_path.dentry->d_inode->i_sb);
|
||||
|
||||
|
||||
if (PAGE_CACHE_SIZE > rc)
|
||||
memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
|
||||
|
||||
flush_dcache_page(page);
|
||||
SetPageUptodate(page);
|
||||
rc = 0;
|
||||
|
||||
|
||||
io_error:
|
||||
kunmap(page);
|
||||
kunmap(page);
|
||||
page_cache_release(page);
|
||||
return rc;
|
||||
}
|
||||
|
@ -1881,7 +1893,7 @@ static int cifs_readpage(struct file *file, struct page *page)
|
|||
return -EBADF;
|
||||
}
|
||||
|
||||
cFYI(1, ("readpage %p at offset %d 0x%x\n",
|
||||
cFYI(1, ("readpage %p at offset %d 0x%x\n",
|
||||
page, (int)offset, (int)offset));
|
||||
|
||||
rc = cifs_readpage_worker(file, page, &offset);
|
||||
|
@ -1895,7 +1907,7 @@ static int cifs_readpage(struct file *file, struct page *page)
|
|||
/* We do not want to update the file size from server for inodes
|
||||
open for write - to avoid races with writepage extending
|
||||
the file - in the future we could consider allowing
|
||||
refreshing the inode only on increases in the file size
|
||||
refreshing the inode only on increases in the file size
|
||||
but this is tricky to do without racing with writebehind
|
||||
page caching in the current Linux kernel design */
|
||||
int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
|
||||
|
@ -1904,8 +1916,8 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
|
|||
|
||||
if (cifsInode)
|
||||
open_file = find_writable_file(cifsInode);
|
||||
|
||||
if(open_file) {
|
||||
|
||||
if (open_file) {
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
|
||||
/* there is not actually a write pending so let
|
||||
|
@ -1915,12 +1927,12 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
|
|||
|
||||
cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
|
||||
if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) {
|
||||
/* since no page cache to corrupt on directio
|
||||
/* since no page cache to corrupt on directio
|
||||
we can change size safely */
|
||||
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 0;
|
||||
|
@ -1935,7 +1947,7 @@ static int cifs_prepare_write(struct file *file, struct page *page,
|
|||
loff_t i_size;
|
||||
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))
|
||||
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.
|
||||
* zero it, and set the page uptodate
|
||||
*/
|
||||
void *kaddr = kmap_atomic(page, KM_USER0);
|
||||
|
||||
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);
|
||||
simple_prepare_write(file, page, from, to);
|
||||
SetPageUptodate(page);
|
||||
} else if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
|
||||
/* might as well read a page, it is fast enough */
|
||||
|
@ -1974,8 +1979,8 @@ static int cifs_prepare_write(struct file *file, struct page *page,
|
|||
this will be written out by commit_write so is fine */
|
||||
}
|
||||
|
||||
/* we do not need to pass errors back
|
||||
e.g. if we do not have read access to the file
|
||||
/* we do not need to pass errors back
|
||||
e.g. if we do not have read access to the file
|
||||
because cifs_commit_write will do the right thing. -- shaggy */
|
||||
|
||||
return 0;
|
||||
|
|
320
fs/cifs/inode.c
320
fs/cifs/inode.c
|
@ -57,14 +57,14 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
if (tmp_path == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* have to skip first of the double backslash of
|
||||
/* have to skip first of the double backslash of
|
||||
UNC name */
|
||||
strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
|
||||
strncat(tmp_path, search_path, MAX_PATHCONF);
|
||||
rc = connect_to_dfs_path(xid, pTcon->ses,
|
||||
/* treename + */ tmp_path,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
kfree(tmp_path);
|
||||
|
||||
|
@ -81,7 +81,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
/* get new inode */
|
||||
if (*pinode == NULL) {
|
||||
*pinode = new_inode(sb);
|
||||
if (*pinode == NULL)
|
||||
if (*pinode == NULL)
|
||||
return -ENOMEM;
|
||||
/* Is an i_ino of zero legal? */
|
||||
/* Are there sanity checks we can use to ensure that
|
||||
|
@ -92,7 +92,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
} /* note ino incremented to unique num in new_inode */
|
||||
if (sb->s_flags & MS_NOATIME)
|
||||
(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||
|
||||
|
||||
insert_inode_hash(*pinode);
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
cifsInfo->time = jiffies;
|
||||
cFYI(1, ("New time %ld", cifsInfo->time));
|
||||
/* this is ok to set on every inode revalidate */
|
||||
atomic_set(&cifsInfo->inUse,1);
|
||||
atomic_set(&cifsInfo->inUse, 1);
|
||||
|
||||
inode->i_atime =
|
||||
cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
|
||||
|
@ -114,8 +114,8 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
|
||||
inode->i_mode = le64_to_cpu(findData.Permissions);
|
||||
/* since we set the inode type below we need to mask off
|
||||
to avoid strange results if bits set above */
|
||||
inode->i_mode &= ~S_IFMT;
|
||||
to avoid strange results if bits set above */
|
||||
inode->i_mode &= ~S_IFMT;
|
||||
if (type == UNIX_FILE) {
|
||||
inode->i_mode |= S_IFREG;
|
||||
} else if (type == UNIX_SYMLINK) {
|
||||
|
@ -137,9 +137,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
} else {
|
||||
/* safest to call it a file if we do not know */
|
||||
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)
|
||||
inode->i_uid = cifs_sb->mnt_uid;
|
||||
else
|
||||
|
@ -149,7 +149,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
inode->i_gid = cifs_sb->mnt_gid;
|
||||
else
|
||||
inode->i_gid = le64_to_cpu(findData.Gid);
|
||||
|
||||
|
||||
inode->i_nlink = le64_to_cpu(findData.Nlinks);
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
|
@ -183,17 +183,17 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
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_NO_BRL)
|
||||
inode->i_fop =
|
||||
inode->i_fop =
|
||||
&cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
inode->i_fop = &cifs_file_direct_ops;
|
||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
inode->i_fop = &cifs_file_nobrl_ops;
|
||||
else /* not direct, send byte range locks */
|
||||
else /* not direct, send byte range locks */
|
||||
inode->i_fop = &cifs_file_ops;
|
||||
|
||||
/* check if server can support readpages */
|
||||
if (pTcon->ses->server->maxBuf <
|
||||
if (pTcon->ses->server->maxBuf <
|
||||
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
|
||||
inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
||||
else
|
||||
|
@ -215,7 +215,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
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,
|
||||
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;
|
||||
char buf[24];
|
||||
unsigned int bytes_read;
|
||||
char * pbuf;
|
||||
char *pbuf;
|
||||
|
||||
pbuf = buf;
|
||||
|
||||
|
@ -235,22 +235,22 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
|
|||
} else if (size < 8) {
|
||||
return -EINVAL; /* EOPNOTSUPP? */
|
||||
}
|
||||
|
||||
|
||||
rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
|
||||
CREATE_NOT_DIR, &netfid, &oplock, NULL,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc==0) {
|
||||
if (rc == 0) {
|
||||
int buf_type = CIFS_NO_BUFFER;
|
||||
/* Read header */
|
||||
rc = CIFSSMBRead(xid, pTcon,
|
||||
netfid,
|
||||
netfid,
|
||||
24 /* length */, 0 /* offset */,
|
||||
&bytes_read, &pbuf, &buf_type);
|
||||
if ((rc == 0) && (bytes_read >= 8)) {
|
||||
if (memcmp("IntxBLK", pbuf, 8) == 0) {
|
||||
cFYI(1,("Block device"));
|
||||
cFYI(1, ("Block device"));
|
||||
inode->i_mode |= S_IFBLK;
|
||||
if (bytes_read == 24) {
|
||||
/* 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);
|
||||
}
|
||||
} else if (memcmp("IntxCHR", pbuf, 8) == 0) {
|
||||
cFYI(1,("Char device"));
|
||||
cFYI(1, ("Char device"));
|
||||
inode->i_mode |= S_IFCHR;
|
||||
if (bytes_read == 24) {
|
||||
/* we have enough to decode dev num */
|
||||
|
@ -270,27 +270,26 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
|
|||
mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
|
||||
mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
|
||||
inode->i_rdev = MKDEV(mjr, mnr);
|
||||
}
|
||||
}
|
||||
} else if (memcmp("IntxLNK", pbuf, 7) == 0) {
|
||||
cFYI(1,("Symlink"));
|
||||
cFYI(1, ("Symlink"));
|
||||
inode->i_mode |= S_IFLNK;
|
||||
} else {
|
||||
inode->i_mode |= S_IFREG; /* file? */
|
||||
rc = -EOPNOTSUPP;
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
} else {
|
||||
inode->i_mode |= S_IFREG; /* then it is a file */
|
||||
rc = -EOPNOTSUPP; /* or some unknown SFU type */
|
||||
}
|
||||
rc = -EOPNOTSUPP; /* or some unknown SFU type */
|
||||
}
|
||||
CIFSSMBClose(xid, pTcon, netfid);
|
||||
}
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
#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,
|
||||
struct cifs_sb_info *cifs_sb, int xid)
|
||||
{
|
||||
|
@ -301,15 +300,15 @@ static int get_sfu_uid_mode(struct inode * inode,
|
|||
|
||||
rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
|
||||
ea_value, 4 /* size of buf */, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc < 0)
|
||||
return (int)rc;
|
||||
else if (rc > 3) {
|
||||
mode = le32_to_cpu(*((__le32 *)ea_value));
|
||||
inode->i_mode &= ~SFBITS_MASK;
|
||||
cFYI(1,("special bits 0%o org mode 0%o", mode, inode->i_mode));
|
||||
inode->i_mode &= ~SFBITS_MASK;
|
||||
cFYI(1, ("special bits 0%o org mode 0%o", mode, 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;
|
||||
} else {
|
||||
return 0;
|
||||
|
@ -317,8 +316,6 @@ static int get_sfu_uid_mode(struct inode * inode,
|
|||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
int cifs_get_inode_info(struct inode **pinode,
|
||||
|
@ -334,11 +331,11 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
int adjustTZ = FALSE;
|
||||
|
||||
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 (CIFS_I(*pinode)->clientCanCacheRead) {
|
||||
cFYI(1,("No need to revalidate cached inode sizes"));
|
||||
cFYI(1, ("No need to revalidate cached inode sizes"));
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
@ -359,12 +356,11 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
failed at least once - set flag in tcon or mount */
|
||||
if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
|
||||
rc = SMBQueryInformation(xid, pTcon, search_path,
|
||||
pfindData, cifs_sb->local_nls,
|
||||
pfindData, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
adjustTZ = TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
|
||||
if (rc) {
|
||||
|
@ -384,8 +380,8 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
strncat(tmp_path, search_path, MAX_PATHCONF);
|
||||
rc = connect_to_dfs_path(xid, pTcon->ses,
|
||||
/* treename + */ tmp_path,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
kfree(tmp_path);
|
||||
/* BB fix up inode etc. */
|
||||
|
@ -419,17 +415,17 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
there Windows server or network appliances for which
|
||||
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;
|
||||
__u64 inode_num;
|
||||
|
||||
rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
|
||||
search_path, &inode_num,
|
||||
rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
|
||||
search_path, &inode_num,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc1) {
|
||||
cFYI(1,("GetSrvInodeNum rc %d", rc1));
|
||||
cFYI(1, ("GetSrvInodeNum rc %d", rc1));
|
||||
/* BB EOPNOSUPP disable SERVER_INUM? */
|
||||
} else /* do we need cast or hash to ino? */
|
||||
(*pinode)->i_ino = inode_num;
|
||||
|
@ -463,7 +459,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
cFYI(0, ("Attributes came in as 0x%x", attr));
|
||||
if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
|
||||
inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
|
||||
inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
|
||||
inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
|
||||
}
|
||||
|
||||
/* set default mode. will override for dirs below */
|
||||
|
@ -471,8 +467,9 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
/* new inode, can safely set these fields */
|
||||
inode->i_mode = cifs_sb->mnt_file_mode;
|
||||
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 */
|
||||
inode->i_mode &= ~S_IFMT;
|
||||
to avoid strange results if type changes and both
|
||||
get orred in */
|
||||
inode->i_mode &= ~S_IFMT;
|
||||
/* if (attr & ATTR_REPARSE) */
|
||||
/* We no longer handle these as symlinks because we could not
|
||||
follow them due to the absolute path with drive letter */
|
||||
|
@ -490,13 +487,13 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
/* BB Finish for SFU style symlinks and devices */
|
||||
} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
|
||||
(cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
|
||||
if (decode_sfu_inode(inode,
|
||||
if (decode_sfu_inode(inode,
|
||||
le64_to_cpu(pfindData->EndOfFile),
|
||||
search_path,
|
||||
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 {
|
||||
inode->i_mode |= S_IFREG;
|
||||
/* treat the dos attribute of read-only as read-only
|
||||
|
@ -512,12 +509,12 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
/* BB add code here -
|
||||
validate if device or weird share or device type? */
|
||||
}
|
||||
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) {
|
||||
/* can not safely shrink the file size here if the
|
||||
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
|
||||
used for this calculation */
|
||||
|
@ -528,7 +525,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
|
||||
inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
|
||||
|
||||
/* BB fill in uid and gid here? with help from winbind?
|
||||
/* BB fill in uid and gid here? with help from winbind?
|
||||
or retrieve from NTFS stream extended attribute */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||
/* fill in uid, gid, mode from server ACL */
|
||||
|
@ -540,7 +537,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
inode->i_gid = cifs_sb->mnt_gid;
|
||||
/* set so we do not keep refreshing these fields with
|
||||
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)) {
|
||||
|
@ -557,7 +554,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
else /* not direct, send byte range locks */
|
||||
inode->i_fop = &cifs_file_ops;
|
||||
|
||||
if (pTcon->ses->server->maxBuf <
|
||||
if (pTcon->ses->server->maxBuf <
|
||||
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
|
||||
inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
||||
else
|
||||
|
@ -586,10 +583,11 @@ void cifs_read_inode(struct inode *inode)
|
|||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
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
|
||||
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 */
|
||||
_FreeXid(xid);
|
||||
}
|
||||
|
@ -623,9 +621,21 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
|||
FreeXid(xid);
|
||||
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,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
|
||||
psx_del_no_retry:
|
||||
if (!rc) {
|
||||
if (direntry->d_inode)
|
||||
drop_nlink(direntry->d_inode);
|
||||
|
@ -638,12 +648,12 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
|||
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
|
||||
CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
|
||||
&netfid, &oplock, NULL, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc==0) {
|
||||
if (rc == 0) {
|
||||
CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
CIFSSMBClose(xid, pTcon, netfid);
|
||||
if (direntry->d_inode)
|
||||
|
@ -659,7 +669,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
|||
rc = CIFSSMBSetTimes(xid, pTcon, full_path,
|
||||
pinfo_buf,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
else
|
||||
rc = -EOPNOTSUPP;
|
||||
|
@ -670,7 +680,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
|||
/* rc = CIFSSMBSetAttrLegacy(xid, pTcon,
|
||||
full_path,
|
||||
(__u16)ATTR_NORMAL,
|
||||
cifs_sb->local_nls);
|
||||
cifs_sb->local_nls);
|
||||
For some strange reason it seems that NT4 eats the
|
||||
old setattr call without actually setting the
|
||||
attributes so on to the third attempted workaround
|
||||
|
@ -683,9 +693,9 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
|||
FILE_WRITE_ATTRIBUTES, 0,
|
||||
&netfid, &oplock, NULL,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc==0) {
|
||||
if (rc == 0) {
|
||||
rc = CIFSSMBSetFileTimes(xid, pTcon,
|
||||
pinfo_buf,
|
||||
netfid);
|
||||
|
@ -694,10 +704,10 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
|||
}
|
||||
kfree(pinfo_buf);
|
||||
}
|
||||
if (rc==0) {
|
||||
rc = CIFSSMBDelFile(xid, pTcon, full_path,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
if (rc == 0) {
|
||||
rc = CIFSSMBDelFile(xid, pTcon, full_path,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (!rc) {
|
||||
if (direntry->d_inode)
|
||||
|
@ -711,10 +721,10 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
|||
CREATE_NOT_DIR |
|
||||
CREATE_DELETE_ON_CLOSE,
|
||||
&netfid, &oplock, NULL,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc==0) {
|
||||
if (rc == 0) {
|
||||
CIFSSMBRenameOpenFile(xid, pTcon,
|
||||
netfid, NULL,
|
||||
cifs_sb->local_nls,
|
||||
|
@ -773,8 +783,8 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
|
|||
|
||||
tmp_inode->i_mode = le64_to_cpu(pData->Permissions);
|
||||
/* since we set the inode type below we need to mask off type
|
||||
to avoid strange results if bits above were corrupt */
|
||||
tmp_inode->i_mode &= ~S_IFMT;
|
||||
to avoid strange results if bits above were corrupt */
|
||||
tmp_inode->i_mode &= ~S_IFMT;
|
||||
if (type == UNIX_FILE) {
|
||||
*pobject_type = DT_REG;
|
||||
tmp_inode->i_mode |= S_IFREG;
|
||||
|
@ -804,11 +814,11 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
|
|||
/* safest to just call it a file */
|
||||
*pobject_type = DT_REG;
|
||||
tmp_inode->i_mode |= S_IFREG;
|
||||
cFYI(1,("unknown inode type %d",type));
|
||||
cFYI(1, ("unknown inode type %d", type));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
cFYI(1,("object type: %d", type));
|
||||
cFYI(1, ("object type: %d", type));
|
||||
#endif
|
||||
tmp_inode->i_uid = le64_to_cpu(pData->Uid);
|
||||
tmp_inode->i_gid = le64_to_cpu(pData->Gid);
|
||||
|
@ -816,7 +826,7 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
|
|||
|
||||
spin_lock(&tmp_inode->i_lock);
|
||||
if (is_size_safe_to_change(cifsInfo, end_of_file)) {
|
||||
/* can not safely change the file size here if the
|
||||
/* can not safely change the file size here if the
|
||||
client is writing to it due to potential races */
|
||||
i_size_write(tmp_inode, end_of_file);
|
||||
|
||||
|
@ -830,27 +840,28 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
|
|||
cFYI(1, ("File inode"));
|
||||
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_NO_BRL)
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
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;
|
||||
else
|
||||
tmp_inode->i_fop = &cifs_file_ops;
|
||||
|
||||
if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
|
||||
(cifs_sb->tcon->ses->server->maxBuf <
|
||||
if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
|
||||
(cifs_sb->tcon->ses->server->maxBuf <
|
||||
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
|
||||
tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
||||
else
|
||||
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
||||
|
||||
if(isNewInode)
|
||||
return; /* No sense invalidating pages for new inode since we
|
||||
have not started caching readahead file data yet */
|
||||
if (isNewInode)
|
||||
return; /* No sense invalidating pages for new inode
|
||||
since we we have not started caching
|
||||
readahead file data yet */
|
||||
|
||||
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
|
||||
(local_size == tmp_inode->i_size)) {
|
||||
|
@ -869,10 +880,10 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
|
|||
tmp_inode->i_op = &cifs_symlink_inode_ops;
|
||||
/* tmp_inode->i_fop = *//* do not need to set to anything */
|
||||
} else {
|
||||
cFYI(1, ("Special inode"));
|
||||
cFYI(1, ("Special inode"));
|
||||
init_special_inode(tmp_inode, tmp_inode->i_mode,
|
||||
tmp_inode->i_rdev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||
|
@ -896,22 +907,22 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
|||
FreeXid(xid);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if((pTcon->ses->capabilities & CAP_UNIX) &&
|
||||
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
|
||||
if ((pTcon->ses->capabilities & CAP_UNIX) &&
|
||||
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
|
||||
u32 oplock = 0;
|
||||
FILE_UNIX_BASIC_INFO * pInfo =
|
||||
FILE_UNIX_BASIC_INFO * pInfo =
|
||||
kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
|
||||
if(pInfo == NULL) {
|
||||
if (pInfo == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto mkdir_out;
|
||||
}
|
||||
|
||||
|
||||
rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
|
||||
mode, NULL /* netfid */, pInfo, &oplock,
|
||||
full_path, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
full_path, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc) {
|
||||
cFYI(1, ("posix mkdir returned 0x%x", rc));
|
||||
|
@ -919,8 +930,9 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
|||
} else {
|
||||
int obj_type;
|
||||
if (pInfo->Type == -1) /* no return info - go query */
|
||||
goto mkdir_get_info;
|
||||
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need to set uid/gid */
|
||||
goto mkdir_get_info;
|
||||
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
|
||||
to set uid/gid */
|
||||
inc_nlink(inode);
|
||||
if (pTcon->nocase)
|
||||
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 =
|
||||
(unsigned long)pInfo->UniqueId;
|
||||
} /* 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_nlink = 2;
|
||||
|
||||
|
@ -949,18 +961,18 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
|||
posix_fill_in_inode(direntry->d_inode,
|
||||
pInfo, &obj_type, 1 /* NewInode */);
|
||||
#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));
|
||||
|
||||
if(newinode->i_nlink != 2)
|
||||
cFYI(1,("unexpected number of links %d",
|
||||
if (newinode->i_nlink != 2)
|
||||
cFYI(1, ("unexpected number of links %d",
|
||||
newinode->i_nlink));
|
||||
#endif
|
||||
}
|
||||
kfree(pInfo);
|
||||
goto mkdir_out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* BB add setting the equivalent of mode via CreateX w/ACLs */
|
||||
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
|
@ -968,14 +980,14 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
|||
cFYI(1, ("cifs_mkdir returned 0x%x", rc));
|
||||
d_drop(direntry);
|
||||
} else {
|
||||
mkdir_get_info:
|
||||
mkdir_get_info:
|
||||
inc_nlink(inode);
|
||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
||||
if (pTcon->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
||||
inode->i_sb,xid);
|
||||
inode->i_sb, xid);
|
||||
else
|
||||
rc = cifs_get_inode_info(&newinode, full_path, NULL,
|
||||
inode->i_sb,xid);
|
||||
inode->i_sb, xid);
|
||||
|
||||
if (pTcon->nocase)
|
||||
direntry->d_op = &cifs_ci_dentry_ops;
|
||||
|
@ -983,10 +995,10 @@ mkdir_get_info:
|
|||
direntry->d_op = &cifs_dentry_ops;
|
||||
d_instantiate(direntry, newinode);
|
||||
/* setting nlink not necessary except in cases where we
|
||||
* 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))
|
||||
direntry->d_inode->i_nlink = 2;
|
||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
|
||||
direntry->d_inode->i_nlink = 2;
|
||||
if (pTcon->unix_ext) {
|
||||
mode &= ~current->fs->umask;
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
||||
|
@ -1002,27 +1014,27 @@ mkdir_get_info:
|
|||
mode, (__u64)-1,
|
||||
(__u64)-1, 0 /* dev_t */,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
}
|
||||
} else {
|
||||
/* BB to be implemented via Windows secrty descriptors
|
||||
eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
|
||||
-1, -1, local_nls); */
|
||||
if(direntry->d_inode) {
|
||||
if (direntry->d_inode) {
|
||||
direntry->d_inode->i_mode = mode;
|
||||
direntry->d_inode->i_mode |= S_IFDIR;
|
||||
if(cifs_sb->mnt_cifs_flags &
|
||||
if (cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_SET_UID) {
|
||||
direntry->d_inode->i_uid =
|
||||
direntry->d_inode->i_uid =
|
||||
current->fsuid;
|
||||
direntry->d_inode->i_gid =
|
||||
direntry->d_inode->i_gid =
|
||||
current->fsgid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mkdir_out:
|
||||
mkdir_out:
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
return rc;
|
||||
|
@ -1056,7 +1068,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
|||
if (!rc) {
|
||||
drop_nlink(inode);
|
||||
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);
|
||||
spin_unlock(&direntry->d_inode->i_lock);
|
||||
}
|
||||
|
@ -1119,9 +1131,9 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
|
|||
kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
|
||||
if (info_buf_source != NULL) {
|
||||
info_buf_target = info_buf_source + 1;
|
||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
||||
if (pTcon->unix_ext)
|
||||
rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
|
||||
info_buf_source,
|
||||
info_buf_source,
|
||||
cifs_sb_source->local_nls,
|
||||
cifs_sb_source->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
|
@ -1171,12 +1183,12 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
|
|||
might not right be right access to request */
|
||||
rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
|
||||
CREATE_NOT_DIR, &netfid, &oplock, NULL,
|
||||
cifs_sb_source->local_nls,
|
||||
cifs_sb_source->mnt_cifs_flags &
|
||||
cifs_sb_source->local_nls,
|
||||
cifs_sb_source->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc==0) {
|
||||
if (rc == 0) {
|
||||
rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
|
||||
cifs_sb_source->local_nls,
|
||||
cifs_sb_source->local_nls,
|
||||
cifs_sb_source->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
CIFSSMBClose(xid, pTcon, netfid);
|
||||
|
@ -1247,9 +1259,9 @@ int cifs_revalidate(struct dentry *direntry)
|
|||
local_mtime = direntry->d_inode->i_mtime;
|
||||
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,
|
||||
direntry->d_sb,xid);
|
||||
direntry->d_sb, xid);
|
||||
if (rc) {
|
||||
cFYI(1, ("error on getting revalidate info %d", rc));
|
||||
/* if (rc != -ENOENT)
|
||||
|
@ -1258,7 +1270,7 @@ int cifs_revalidate(struct dentry *direntry)
|
|||
}
|
||||
} else {
|
||||
rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
|
||||
direntry->d_sb,xid);
|
||||
direntry->d_sb, xid);
|
||||
if (rc) {
|
||||
cFYI(1, ("error on getting revalidate info %d", rc));
|
||||
/* 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
|
||||
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)) {
|
||||
cFYI(1, ("cifs_revalidate - inode unchanged"));
|
||||
} else {
|
||||
|
@ -1298,7 +1310,7 @@ int cifs_revalidate(struct dentry *direntry)
|
|||
if (invalidate_inode) {
|
||||
/* shrink_dcache not necessary now that cifs dentry ops
|
||||
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); */
|
||||
if (S_ISREG(direntry->d_inode->i_mode)) {
|
||||
if (direntry->d_inode->i_mapping)
|
||||
|
@ -1313,7 +1325,7 @@ int cifs_revalidate(struct dentry *direntry)
|
|||
}
|
||||
}
|
||||
/* mutex_unlock(&direntry->d_inode->i_mutex); */
|
||||
|
||||
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
return rc;
|
||||
|
@ -1335,23 +1347,19 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
|
|||
pgoff_t index = from >> PAGE_CACHE_SHIFT;
|
||||
unsigned offset = from & (PAGE_CACHE_SIZE - 1);
|
||||
struct page *page;
|
||||
char *kaddr;
|
||||
int rc = 0;
|
||||
|
||||
page = grab_cache_page(mapping, index);
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
|
||||
kaddr = kmap_atomic(page, KM_USER0);
|
||||
memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
|
||||
flush_dcache_page(page);
|
||||
kunmap_atomic(kaddr, KM_USER0);
|
||||
zero_user_page(page, offset, PAGE_CACHE_SIZE - offset, KM_USER0);
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
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;
|
||||
unsigned long limit;
|
||||
|
@ -1424,13 +1432,13 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
|
||||
/* check if we have permission to change attrs */
|
||||
rc = inode_change_ok(direntry->d_inode, attrs);
|
||||
if(rc < 0) {
|
||||
if (rc < 0) {
|
||||
FreeXid(xid);
|
||||
return rc;
|
||||
} else
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
FreeXid(xid);
|
||||
|
@ -1459,16 +1467,16 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
|
||||
nfid, npid, FALSE);
|
||||
atomic_dec(&open_file->wrtPending);
|
||||
cFYI(1,("SetFSize for attrs rc = %d", rc));
|
||||
if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
||||
cFYI(1, ("SetFSize for attrs rc = %d", rc));
|
||||
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
||||
int bytes_written;
|
||||
rc = CIFSSMBWrite(xid, pTcon,
|
||||
nfid, 0, attrs->ia_size,
|
||||
&bytes_written, NULL, NULL,
|
||||
1 /* 45 seconds */);
|
||||
cFYI(1,("Wrt seteof rc %d", rc));
|
||||
cFYI(1, ("Wrt seteof rc %d", rc));
|
||||
}
|
||||
} else
|
||||
} else
|
||||
rc = -EINVAL;
|
||||
|
||||
if (rc != 0) {
|
||||
|
@ -1478,11 +1486,11 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
it by handle */
|
||||
rc = CIFSSMBSetEOF(xid, pTcon, full_path,
|
||||
attrs->ia_size, FALSE,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
|
||||
if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
||||
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
||||
__u16 netfid;
|
||||
int oplock = FALSE;
|
||||
|
||||
|
@ -1493,14 +1501,14 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
NULL, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc==0) {
|
||||
if (rc == 0) {
|
||||
int bytes_written;
|
||||
rc = CIFSSMBWrite(xid, pTcon,
|
||||
netfid, 0,
|
||||
attrs->ia_size,
|
||||
&bytes_written, NULL,
|
||||
NULL, 1 /* 45 sec */);
|
||||
cFYI(1,("wrt seteof rc %d",rc));
|
||||
cFYI(1, ("wrt seteof rc %d", rc));
|
||||
CIFSSMBClose(xid, pTcon, netfid);
|
||||
}
|
||||
|
||||
|
@ -1517,7 +1525,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
rc = cifs_vmtruncate(direntry->d_inode, attrs->ia_size);
|
||||
cifs_truncate_page(direntry->d_inode->i_mapping,
|
||||
direntry->d_inode->i_size);
|
||||
} else
|
||||
} else
|
||||
goto cifs_setattr_exit;
|
||||
}
|
||||
if (attrs->ia_valid & ATTR_UID) {
|
||||
|
@ -1535,11 +1543,11 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
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)))
|
||||
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
|
||||
0 /* dev_t */, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
else if (attrs->ia_valid & ATTR_MODE) {
|
||||
rc = 0;
|
||||
|
@ -1559,7 +1567,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs &
|
||||
(~ATTR_READONLY));
|
||||
/* Windows ignores set to zero */
|
||||
if(time_buf.Attributes == 0)
|
||||
if (time_buf.Attributes == 0)
|
||||
time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL);
|
||||
}
|
||||
/* BB to be implemented -
|
||||
|
@ -1585,7 +1593,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
stamps are changed explicitly (i.e. by utime()
|
||||
since we would then have a mix of client and
|
||||
server times */
|
||||
|
||||
|
||||
if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
|
||||
set_time = TRUE;
|
||||
/* Although Samba throws this field away
|
||||
|
@ -1624,7 +1632,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
NULL, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc==0) {
|
||||
if (rc == 0) {
|
||||
rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
|
||||
netfid);
|
||||
CIFSSMBClose(xid, pTcon, netfid);
|
||||
|
@ -1634,7 +1642,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
granularity */
|
||||
|
||||
/* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
|
||||
&time_buf, cifs_sb->local_nls); */
|
||||
&time_buf, cifs_sb->local_nls); */
|
||||
}
|
||||
}
|
||||
/* Even if error on time set, no sense failing the call if
|
||||
|
@ -1642,7 +1650,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
and this check ensures that we are not being called from
|
||||
sys_utimes in which case we ought to fail the call back to
|
||||
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)))
|
||||
rc = 0;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* 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)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
|
@ -30,7 +30,7 @@
|
|||
|
||||
#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)
|
||||
{
|
||||
int rc = -ENOTTY; /* strange error - but the precedent */
|
||||
|
|
116
fs/cifs/link.c
116
fs/cifs/link.c
|
@ -50,32 +50,33 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
|||
|
||||
fromName = build_path_from_dentry(old_file);
|
||||
toName = build_path_from_dentry(direntry);
|
||||
if((fromName == NULL) || (toName == NULL)) {
|
||||
if ((fromName == NULL) || (toName == NULL)) {
|
||||
rc = -ENOMEM;
|
||||
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,
|
||||
cifs_sb_target->local_nls,
|
||||
cifs_sb_target->local_nls,
|
||||
cifs_sb_target->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
else {
|
||||
rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
|
||||
cifs_sb_target->local_nls,
|
||||
cifs_sb_target->local_nls,
|
||||
cifs_sb_target->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if((rc == -EIO) || (rc == -EINVAL))
|
||||
rc = -EOPNOTSUPP;
|
||||
if ((rc == -EIO) || (rc == -EINVAL))
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
d_drop(direntry); /* force new lookup from server of target */
|
||||
|
||||
/* if source file is cached (oplocked) revalidate will not go to server
|
||||
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);
|
||||
if(rc == 0) {
|
||||
if (rc == 0) {
|
||||
old_file->d_inode->i_nlink++;
|
||||
/* BB should we make this contingent on superblock flag NOATIME? */
|
||||
/* old_file->d_inode->i_ctime = CURRENT_TIME;*/
|
||||
|
@ -84,14 +85,14 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
|||
to set the parent dir cifs inode time to zero
|
||||
to force revalidate (faster) for it too? */
|
||||
}
|
||||
/* if not oplocked will force revalidate to get info
|
||||
/* if not oplocked will force revalidate to get info
|
||||
on source file from srv */
|
||||
cifsInode->time = 0;
|
||||
|
||||
/* Will update parent dir timestamps from srv within a second.
|
||||
/* Will update parent dir timestamps from srv within a second.
|
||||
Would it really be worth it to set the parent dir (cifs
|
||||
inode) time field to zero to force revalidate on parent
|
||||
directory faster ie
|
||||
directory faster ie
|
||||
CIFS_I(inode)->time = 0; */
|
||||
}
|
||||
|
||||
|
@ -109,7 +110,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
|
|||
int rc = -EACCES;
|
||||
int xid;
|
||||
char *full_path = NULL;
|
||||
char * target_path = ERR_PTR(-ENOMEM);
|
||||
char *target_path = ERR_PTR(-ENOMEM);
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
|
||||
|
@ -129,13 +130,19 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
|
|||
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)
|
||||
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
|
||||
target_path,
|
||||
PATH_MAX-1,
|
||||
cifs_sb->local_nls);
|
||||
else {
|
||||
/* BB add read reparse point symlink code here */
|
||||
/* rc = CIFSSMBQueryReparseLinkInfo */
|
||||
/* BB Add code to Query ReparsePoint info */
|
||||
/* 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);
|
||||
|
||||
if(full_path == NULL) {
|
||||
if (full_path == NULL) {
|
||||
FreeXid(xid);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -185,19 +192,20 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
|
|||
cFYI(1, ("symname is %s", symname));
|
||||
|
||||
/* 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,
|
||||
cifs_sb->local_nls);
|
||||
/* 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 (pTcon->ses->capabilities & CAP_UNIX)
|
||||
if (pTcon->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
||||
inode->i_sb,xid);
|
||||
inode->i_sb, xid);
|
||||
else
|
||||
rc = cifs_get_inode_info(&newinode, full_path, NULL,
|
||||
inode->i_sb,xid);
|
||||
inode->i_sb, xid);
|
||||
|
||||
if (rc != 0) {
|
||||
cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d",
|
||||
|
@ -226,9 +234,9 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
|
|||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
char *full_path = NULL;
|
||||
char *tmp_path = NULL;
|
||||
char * tmpbuffer;
|
||||
unsigned char * referrals = NULL;
|
||||
char *tmp_path = NULL;
|
||||
char *tmpbuffer;
|
||||
unsigned char *referrals = NULL;
|
||||
int num_referrals = 0;
|
||||
int len;
|
||||
__u16 fid;
|
||||
|
@ -237,13 +245,13 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
|
|||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
pTcon = cifs_sb->tcon;
|
||||
|
||||
/* BB would it be safe against deadlock to grab this sem
|
||||
/* BB would it be safe against deadlock to grab this sem
|
||||
even though rename itself grabs the sem and calls lookup? */
|
||||
/* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
/* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/
|
||||
|
||||
if(full_path == NULL) {
|
||||
if (full_path == NULL) {
|
||||
FreeXid(xid);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -251,70 +259,80 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
|
|||
cFYI(1,
|
||||
("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
|
||||
full_path, inode, pBuffer, buflen));
|
||||
if(buflen > PATH_MAX)
|
||||
if (buflen > PATH_MAX)
|
||||
len = PATH_MAX;
|
||||
else
|
||||
len = buflen;
|
||||
tmpbuffer = kmalloc(len,GFP_KERNEL);
|
||||
if(tmpbuffer == NULL) {
|
||||
tmpbuffer = kmalloc(len, GFP_KERNEL);
|
||||
if (tmpbuffer == NULL) {
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
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)
|
||||
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
|
||||
tmpbuffer,
|
||||
len - 1,
|
||||
cifs_sb->local_nls);
|
||||
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 */
|
||||
|
||||
} else {
|
||||
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
|
||||
OPEN_REPARSE_POINT,&fid, &oplock, NULL,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
OPEN_REPARSE_POINT, &fid, &oplock, NULL,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if(!rc) {
|
||||
if (!rc) {
|
||||
rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
|
||||
tmpbuffer,
|
||||
len - 1,
|
||||
len - 1,
|
||||
fid,
|
||||
cifs_sb->local_nls);
|
||||
if(CIFSSMBClose(xid, pTcon, fid)) {
|
||||
cFYI(1,("Error closing junction point (open for ioctl)"));
|
||||
if (CIFSSMBClose(xid, pTcon, fid)) {
|
||||
cFYI(1, ("Error closing junction point "
|
||||
"(open for ioctl)"));
|
||||
}
|
||||
if(rc == -EIO) {
|
||||
if (rc == -EIO) {
|
||||
/* Query if DFS Junction */
|
||||
tmp_path =
|
||||
kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
|
||||
GFP_KERNEL);
|
||||
if (tmp_path) {
|
||||
strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
|
||||
strncat(tmp_path, full_path, MAX_PATHCONF);
|
||||
rc = get_dfs_path(xid, pTcon->ses, tmp_path,
|
||||
strncpy(tmp_path, pTcon->treeName,
|
||||
MAX_TREE_SIZE);
|
||||
strncat(tmp_path, full_path,
|
||||
MAX_PATHCONF);
|
||||
rc = get_dfs_path(xid, pTcon->ses,
|
||||
tmp_path,
|
||||
cifs_sb->local_nls,
|
||||
&num_referrals, &referrals,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
|
||||
if((num_referrals == 0) && (rc == 0))
|
||||
cFYI(1, ("Get DFS for %s rc = %d ",
|
||||
tmp_path, rc));
|
||||
if ((num_referrals == 0) && (rc == 0))
|
||||
rc = -EACCES;
|
||||
else {
|
||||
cFYI(1,("num referral: %d",num_referrals));
|
||||
if(referrals) {
|
||||
cFYI(1,("referral string: %s",referrals));
|
||||
strncpy(tmpbuffer, referrals, len-1);
|
||||
cFYI(1, ("num referral: %d",
|
||||
num_referrals));
|
||||
if (referrals) {
|
||||
cFYI(1,("referral string: %s", referrals));
|
||||
strncpy(tmpbuffer,
|
||||
referrals,
|
||||
len-1);
|
||||
}
|
||||
}
|
||||
kfree(referrals);
|
||||
kfree(tmp_path);
|
||||
}
|
||||
/* BB add code like else decode referrals then memcpy to
|
||||
tmpbuffer and free referrals string array BB */
|
||||
/* BB add code like else decode referrals
|
||||
then memcpy to tmpbuffer and free referrals
|
||||
string array BB */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
/*
|
||||
/*
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 1.9.
|
||||
a implementation of MD4 designed for use in the SMB authentication protocol
|
||||
Copyright (C) Andrew Tridgell 1997-1998.
|
||||
Modified by Steve French (sfrench@us.ibm.com) 2002-2003
|
||||
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
@ -170,7 +170,7 @@ mdfour(unsigned char *out, unsigned char *in, int n)
|
|||
|
||||
while (n > 64) {
|
||||
copy64(M, in);
|
||||
mdfour64(M,&A,&B, &C, &D);
|
||||
mdfour64(M, &A, &B, &C, &D);
|
||||
in += 64;
|
||||
n -= 64;
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
* will fill a supplied 16-byte array with the digest.
|
||||
*/
|
||||
|
||||
/* This code slightly modified to fit into Samba by
|
||||
abartlet@samba.org Jun 2001
|
||||
and to fit the cifs vfs by
|
||||
/* This code slightly modified to fit into Samba by
|
||||
abartlet@samba.org Jun 2001
|
||||
and to fit the cifs vfs by
|
||||
Steve French sfrench@us.ibm.com */
|
||||
|
||||
#include <linux/string.h>
|
||||
|
@ -106,7 +106,7 @@ MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
|
|||
}
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void
|
||||
|
|
239
fs/cifs/misc.c
239
fs/cifs/misc.c
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
|
@ -16,7 +16,7 @@
|
|||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
@ -32,12 +32,12 @@
|
|||
|
||||
extern mempool_t *cifs_sm_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,
|
||||
in a similar way to the mid which is useful to track each sent smb,
|
||||
and CurrentXid can also provide a running counter (although it
|
||||
will eventually wrap past zero) of the total vfs operations handled
|
||||
/* 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,
|
||||
and CurrentXid can also provide a running counter (although it
|
||||
will eventually wrap past zero) of the total vfs operations handled
|
||||
since the cifs fs was mounted */
|
||||
|
||||
unsigned int
|
||||
|
@ -47,10 +47,12 @@ _GetXid(void)
|
|||
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
GlobalTotalActiveXid++;
|
||||
|
||||
/* keep high water mark for number of simultaneous ops in filesystem */
|
||||
if (GlobalTotalActiveXid > GlobalMaxActiveXid)
|
||||
GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */
|
||||
if(GlobalTotalActiveXid > 65000)
|
||||
cFYI(1,("warning: more than 65000 requests active"));
|
||||
GlobalMaxActiveXid = GlobalTotalActiveXid;
|
||||
if (GlobalTotalActiveXid > 65000)
|
||||
cFYI(1, ("warning: more than 65000 requests active"));
|
||||
xid = GlobalCurrentXid++;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
return xid;
|
||||
|
@ -60,7 +62,7 @@ void
|
|||
_FreeXid(unsigned int xid)
|
||||
{
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
/* if(GlobalTotalActiveXid == 0)
|
||||
/* if (GlobalTotalActiveXid == 0)
|
||||
BUG(); */
|
||||
GlobalTotalActiveXid--;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
|
@ -144,12 +146,12 @@ cifs_buf_get(void)
|
|||
{
|
||||
struct smb_hdr *ret_buf = NULL;
|
||||
|
||||
/* We could use negotiated size instead of max_msgsize -
|
||||
but it may be more efficient to always alloc same size
|
||||
albeit slightly larger than necessary and maxbuffersize
|
||||
/* We could use negotiated size instead of max_msgsize -
|
||||
but it may be more efficient to always alloc same size
|
||||
albeit slightly larger than necessary and maxbuffersize
|
||||
defaults to this and can not be bigger */
|
||||
ret_buf =
|
||||
(struct smb_hdr *) mempool_alloc(cifs_req_poolp, GFP_KERNEL | GFP_NOFS);
|
||||
ret_buf = (struct smb_hdr *) mempool_alloc(cifs_req_poolp,
|
||||
GFP_KERNEL | GFP_NOFS);
|
||||
|
||||
/* clear the first few header bytes */
|
||||
/* 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"));*/
|
||||
return;
|
||||
}
|
||||
mempool_free(buf_to_free,cifs_req_poolp);
|
||||
mempool_free(buf_to_free, cifs_req_poolp);
|
||||
|
||||
atomic_dec(&bufAllocCount);
|
||||
return;
|
||||
|
@ -183,12 +185,12 @@ cifs_small_buf_get(void)
|
|||
{
|
||||
struct smb_hdr *ret_buf = NULL;
|
||||
|
||||
/* We could use negotiated size instead of max_msgsize -
|
||||
but it may be more efficient to always alloc same size
|
||||
albeit slightly larger than necessary and maxbuffersize
|
||||
/* We could use negotiated size instead of max_msgsize -
|
||||
but it may be more efficient to always alloc same size
|
||||
albeit slightly larger than necessary and maxbuffersize
|
||||
defaults to this and can not be bigger */
|
||||
ret_buf =
|
||||
(struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp, GFP_KERNEL | GFP_NOFS);
|
||||
ret_buf = (struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp,
|
||||
GFP_KERNEL | GFP_NOFS);
|
||||
if (ret_buf) {
|
||||
/* No need to clear memory here, cleared in header assemble */
|
||||
/* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
|
||||
|
@ -209,30 +211,30 @@ cifs_small_buf_release(void *buf_to_free)
|
|||
cFYI(1, ("Null buffer passed to cifs_small_buf_release"));
|
||||
return;
|
||||
}
|
||||
mempool_free(buf_to_free,cifs_sm_req_poolp);
|
||||
mempool_free(buf_to_free, cifs_sm_req_poolp);
|
||||
|
||||
atomic_dec(&smBufAllocCount);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
Find a free multiplex id (SMB mid). Otherwise there could be
|
||||
mid collisions which might cause problems, demultiplexing the
|
||||
wrong response to this request. Multiplex ids could collide if
|
||||
one of a series requests takes much longer than the others, or
|
||||
if a very large number of long lived requests (byte range
|
||||
locks or FindNotify requests) are pending. No more than
|
||||
64K-1 requests can be outstanding at one time. If no
|
||||
64K-1 requests can be outstanding at one time. If no
|
||||
mids are available, return zero. A future optimization
|
||||
could make the combination of mids and uid the key we use
|
||||
to demultiplex on (rather than mid alone).
|
||||
to demultiplex on (rather than mid alone).
|
||||
In addition to the above check, the cifs demultiplex
|
||||
code already used the command code as a secondary
|
||||
check of the frame and if signing is negotiated the
|
||||
response would be discarded if the mid were the same
|
||||
but the signature was wrong. Since the mid is not put in the
|
||||
pending queue until later (when it is about to be dispatched)
|
||||
we do have to limit the number of outstanding requests
|
||||
we do have to limit the number of outstanding requests
|
||||
to somewhat less than 64K-1 although it is hard to imagine
|
||||
so many threads being in the vfs at one time.
|
||||
*/
|
||||
|
@ -240,27 +242,27 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
|
|||
{
|
||||
__u16 mid = 0;
|
||||
__u16 last_mid;
|
||||
int collision;
|
||||
int collision;
|
||||
|
||||
if(server == NULL)
|
||||
if (server == NULL)
|
||||
return mid;
|
||||
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
last_mid = server->CurrentMid; /* we do not want to loop forever */
|
||||
server->CurrentMid++;
|
||||
/* This nested loop looks more expensive than it is.
|
||||
In practice the list of pending requests is short,
|
||||
In practice the list of pending requests is short,
|
||||
fewer than 50, and the mids are likely to be unique
|
||||
on the first pass through the loop unless some request
|
||||
takes longer than the 64 thousand requests before it
|
||||
(and it would also have to have been a request that
|
||||
did not time out) */
|
||||
while(server->CurrentMid != last_mid) {
|
||||
while (server->CurrentMid != last_mid) {
|
||||
struct list_head *tmp;
|
||||
struct mid_q_entry *mid_entry;
|
||||
|
||||
collision = 0;
|
||||
if(server->CurrentMid == 0)
|
||||
if (server->CurrentMid == 0)
|
||||
server->CurrentMid++;
|
||||
|
||||
list_for_each(tmp, &server->pending_mid_q) {
|
||||
|
@ -273,7 +275,7 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if(collision == 0) {
|
||||
if (collision == 0) {
|
||||
mid = server->CurrentMid;
|
||||
break;
|
||||
}
|
||||
|
@ -290,11 +292,11 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
|||
const struct cifsTconInfo *treeCon, int word_count
|
||||
/* length of fixed section (word count) in two byte units */)
|
||||
{
|
||||
struct list_head* temp_item;
|
||||
struct cifsSesInfo * ses;
|
||||
struct list_head *temp_item;
|
||||
struct cifsSesInfo *ses;
|
||||
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 =
|
||||
(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 */
|
||||
buffer->Uid = treeCon->ses->Suid;
|
||||
buffer->Mid = GetNextMid(treeCon->ses->server);
|
||||
if(multiuser_mount != 0) {
|
||||
if (multiuser_mount != 0) {
|
||||
/* For the multiuser case, there are few obvious technically */
|
||||
/* possible mechanisms to match the local linux user (uid) */
|
||||
/* to a valid remote smb user (smb_uid): */
|
||||
|
@ -348,21 +350,22 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
|||
/* flag were disabled. */
|
||||
|
||||
/* 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 */
|
||||
if(current->fsuid != treeCon->ses->linux_uid) {
|
||||
cFYI(1,("Multiuser mode and UID did not match tcon uid"));
|
||||
if (current->fsuid != treeCon->ses->linux_uid) {
|
||||
cFYI(1, ("Multiuser mode and UID "
|
||||
"did not match tcon uid"));
|
||||
read_lock(&GlobalSMBSeslock);
|
||||
list_for_each(temp_item, &GlobalSMBSessionList) {
|
||||
ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
|
||||
if(ses->linux_uid == current->fsuid) {
|
||||
if(ses->server == treeCon->ses->server) {
|
||||
cFYI(1,("found matching uid substitute right smb_uid"));
|
||||
if (ses->linux_uid == current->fsuid) {
|
||||
if (ses->server == treeCon->ses->server) {
|
||||
cFYI(1, ("found matching uid substitute right smb_uid"));
|
||||
buffer->Uid = ses->Suid;
|
||||
break;
|
||||
} else {
|
||||
/* BB eventually call cifs_setup_session here */
|
||||
cFYI(1,("local UID found but smb sess with this server does not exist"));
|
||||
/* BB eventually call cifs_setup_session here */
|
||||
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;
|
||||
if (treeCon->nocase)
|
||||
buffer->Flags |= SMBFLG_CASELESS;
|
||||
if((treeCon->ses) && (treeCon->ses->server))
|
||||
if(treeCon->ses->server->secMode &
|
||||
if ((treeCon->ses) && (treeCon->ses->server))
|
||||
if (treeCon->ses->server->secMode &
|
||||
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
||||
buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
||||
}
|
||||
|
@ -388,18 +391,18 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
|||
static int
|
||||
checkSMBhdr(struct smb_hdr *smb, __u16 mid)
|
||||
{
|
||||
/* Make sure that this really is an SMB, that it is a response,
|
||||
/* Make sure that this really is an SMB, that it is a response,
|
||||
and that the message ids match */
|
||||
if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
|
||||
(mid == smb->Mid)) {
|
||||
if(smb->Flags & SMBFLG_RESPONSE)
|
||||
return 0;
|
||||
else {
|
||||
if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
|
||||
(mid == smb->Mid)) {
|
||||
if (smb->Flags & SMBFLG_RESPONSE)
|
||||
return 0;
|
||||
else {
|
||||
/* 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;
|
||||
else
|
||||
cERROR(1, ("Rcvd Request not response"));
|
||||
cERROR(1, ("Received Request not response"));
|
||||
}
|
||||
} else { /* bad signature or mid */
|
||||
if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
|
||||
|
@ -426,9 +429,9 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
|
|||
smb->WordCount = 0;
|
||||
/* some error cases do not return wct and bcc */
|
||||
return 0;
|
||||
} else if ((length == sizeof(struct smb_hdr) + 1) &&
|
||||
} else if ((length == sizeof(struct smb_hdr) + 1) &&
|
||||
(smb->WordCount == 0)) {
|
||||
char * tmp = (char *)smb;
|
||||
char *tmp = (char *)smb;
|
||||
/* Need to work around a bug in two servers here */
|
||||
/* First, check if the part of bcc they sent was zero */
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
cERROR(1,("rcvd invalid byte count (bcc)"));
|
||||
cERROR(1, ("rcvd invalid byte count (bcc)"));
|
||||
} else {
|
||||
cERROR(1, ("Length less than smb header size"));
|
||||
}
|
||||
|
@ -458,32 +461,33 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
|
|||
return 1;
|
||||
clc_len = smbCalcSize_LE(smb);
|
||||
|
||||
if(4 + len != length) {
|
||||
cERROR(1, ("Length read does not match RFC1001 length %d",len));
|
||||
if (4 + len != length) {
|
||||
cERROR(1, ("Length read does not match RFC1001 length %d",
|
||||
len));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (4 + len != clc_len) {
|
||||
/* 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 */
|
||||
if(((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
|
||||
return 0; /* bcc wrapped */
|
||||
if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
|
||||
return 0; /* bcc wrapped */
|
||||
}
|
||||
cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d",
|
||||
clc_len, 4 + len, smb->Mid));
|
||||
/* Windows XP can return a few bytes too much, presumably
|
||||
an illegal pad, at the end of byte range lock responses
|
||||
an illegal pad, at the end of byte range lock responses
|
||||
so we allow for that three byte pad, as long as actual
|
||||
received length is as long or longer than calculated length */
|
||||
/* We have now had to extend this more, since there is a
|
||||
/* We have now had to extend this more, since there is a
|
||||
case in which it needs to be bigger still to handle a
|
||||
malformed response to transact2 findfirst from WinXP when
|
||||
access denied is returned and thus bcc and wct are zero
|
||||
but server says length is 0x21 bytes too long as if the server
|
||||
forget to reset the smb rfc1001 length when it reset the
|
||||
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;
|
||||
else {
|
||||
cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d",
|
||||
|
@ -495,61 +499,64 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
|
|||
}
|
||||
int
|
||||
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 *tmp1;
|
||||
struct cifsTconInfo *tcon;
|
||||
struct cifsFileInfo *netfile;
|
||||
|
||||
cFYI(1,("Checking for oplock break or dnotify response"));
|
||||
if((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
|
||||
cFYI(1, ("Checking for oplock break or dnotify response"));
|
||||
if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
|
||||
(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 file_notify_information * pnotify;
|
||||
struct file_notify_information *pnotify;
|
||||
__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);
|
||||
|
||||
pnotify = (struct file_notify_information *)
|
||||
((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 */
|
||||
/* cifs_dump_mem("Rcvd notify Data: ",buf,
|
||||
/* cifs_dump_mem("Rcvd notify Data: ",buf,
|
||||
sizeof(struct smb_hdr)+60); */
|
||||
return TRUE;
|
||||
}
|
||||
if(pSMBr->hdr.Status.CifsError) {
|
||||
cFYI(1,("notify err 0x%d",pSMBr->hdr.Status.CifsError));
|
||||
if (pSMBr->hdr.Status.CifsError) {
|
||||
cFYI(1, ("notify err 0x%d",
|
||||
pSMBr->hdr.Status.CifsError));
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
|
||||
}
|
||||
if (pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
|
||||
return FALSE;
|
||||
if(pSMB->hdr.Flags & SMBFLG_RESPONSE) {
|
||||
if (pSMB->hdr.Flags & SMBFLG_RESPONSE) {
|
||||
/* no sense logging error on invalid handle on oplock
|
||||
break - harmless race between close request and oplock
|
||||
break response is expected from time to time writing out
|
||||
large dirty files cached on the client */
|
||||
if ((NT_STATUS_INVALID_HANDLE) ==
|
||||
le32_to_cpu(pSMB->hdr.Status.CifsError)) {
|
||||
cFYI(1,("invalid handle on oplock break"));
|
||||
if ((NT_STATUS_INVALID_HANDLE) ==
|
||||
le32_to_cpu(pSMB->hdr.Status.CifsError)) {
|
||||
cFYI(1, ("invalid handle on oplock break"));
|
||||
return TRUE;
|
||||
} else if (ERRbadfid ==
|
||||
} else if (ERRbadfid ==
|
||||
le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE; /* on valid oplock brk we get "request" */
|
||||
}
|
||||
}
|
||||
if(pSMB->hdr.WordCount != 8)
|
||||
if (pSMB->hdr.WordCount != 8)
|
||||
return FALSE;
|
||||
|
||||
cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
|
||||
if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
|
||||
return FALSE;
|
||||
cFYI(1, ("oplock type 0x%d level 0x%d",
|
||||
pSMB->LockType, pSMB->OplockLevel));
|
||||
if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
|
||||
return FALSE;
|
||||
|
||||
/* look up tcon based on tid & uid */
|
||||
read_lock(&GlobalSMBSeslock);
|
||||
|
@ -557,36 +564,38 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
|||
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
||||
if ((tcon->tid == buf->Tid) && (srv == tcon->ses->server)) {
|
||||
cifs_stats_inc(&tcon->num_oplock_brks);
|
||||
list_for_each(tmp1,&tcon->openFileList){
|
||||
netfile = list_entry(tmp1,struct cifsFileInfo,
|
||||
list_for_each(tmp1, &tcon->openFileList) {
|
||||
netfile = list_entry(tmp1, struct cifsFileInfo,
|
||||
tlist);
|
||||
if(pSMB->Fid == netfile->netfid) {
|
||||
if (pSMB->Fid == netfile->netfid) {
|
||||
struct cifsInodeInfo *pCifsInode;
|
||||
read_unlock(&GlobalSMBSeslock);
|
||||
cFYI(1,("file id match, oplock break"));
|
||||
pCifsInode =
|
||||
cFYI(1,
|
||||
("file id match, oplock break"));
|
||||
pCifsInode =
|
||||
CIFS_I(netfile->pInode);
|
||||
pCifsInode->clientCanCacheAll = FALSE;
|
||||
if(pSMB->OplockLevel == 0)
|
||||
if (pSMB->OplockLevel == 0)
|
||||
pCifsInode->clientCanCacheRead
|
||||
= FALSE;
|
||||
pCifsInode->oplockPending = TRUE;
|
||||
AllocOplockQEntry(netfile->pInode,
|
||||
netfile->netfid,
|
||||
tcon);
|
||||
cFYI(1,("about to wake up oplock thd"));
|
||||
if(oplockThread)
|
||||
cFYI(1,
|
||||
("about to wake up oplock thread"));
|
||||
if (oplockThread)
|
||||
wake_up_process(oplockThread);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
read_unlock(&GlobalSMBSeslock);
|
||||
cFYI(1,("No matching file for oplock break"));
|
||||
cFYI(1, ("No matching file for oplock break"));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
names are little endian 16 bit Unicode on the wire */
|
||||
int
|
||||
cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
|
||||
const struct nls_table * cp)
|
||||
cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
|
||||
const struct nls_table *cp)
|
||||
{
|
||||
int i,j,len;
|
||||
int i, j, len;
|
||||
__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]);
|
||||
switch (src_char) {
|
||||
case 0:
|
||||
|
@ -678,10 +687,10 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
|
|||
case UNI_LESSTHAN:
|
||||
target[j] = '<';
|
||||
break;
|
||||
default:
|
||||
len = cp->uni2char(src_char, &target[j],
|
||||
default:
|
||||
len = cp->uni2char(src_char, &target[j],
|
||||
NLS_MAX_CHARSET_SIZE);
|
||||
if(len > 0) {
|
||||
if (len > 0) {
|
||||
j += len;
|
||||
continue;
|
||||
} else {
|
||||
|
@ -690,7 +699,7 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
|
|||
}
|
||||
j++;
|
||||
/* make sure we do not overrun callers allocated temp buffer */
|
||||
if(j >= (2 * NAME_MAX))
|
||||
if (j >= (2 * NAME_MAX))
|
||||
break;
|
||||
}
|
||||
cUCS_out:
|
||||
|
@ -703,18 +712,18 @@ cUCS_out:
|
|||
only legal in POSIX-like OS (if they are present in the string). Path
|
||||
names are little endian 16 bit Unicode on the wire */
|
||||
int
|
||||
cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
|
||||
const struct nls_table * cp, int mapChars)
|
||||
cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
|
||||
const struct nls_table *cp, int mapChars)
|
||||
{
|
||||
int i,j,charlen;
|
||||
int i, j, charlen;
|
||||
int len_remaining = maxlen;
|
||||
char src_char;
|
||||
__u16 temp;
|
||||
|
||||
if(!mapChars)
|
||||
if (!mapChars)
|
||||
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];
|
||||
switch (src_char) {
|
||||
case 0:
|
||||
|
@ -737,7 +746,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
|
|||
break;
|
||||
case '|':
|
||||
target[j] = cpu_to_le16(UNI_PIPE);
|
||||
break;
|
||||
break;
|
||||
/* BB We can not handle remapping slash until
|
||||
all the calls to build_path_from_dentry
|
||||
are modified, as they use slash as separator BB */
|
||||
|
@ -749,7 +758,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
|
|||
len_remaining, &temp);
|
||||
/* if no match, use question mark, which
|
||||
at least in some cases servers as wild card */
|
||||
if(charlen < 1) {
|
||||
if (charlen < 1) {
|
||||
target[j] = cpu_to_le16(0x003f);
|
||||
charlen = 1;
|
||||
} else
|
||||
|
@ -758,7 +767,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
|
|||
/* character may take more than one byte in the
|
||||
the source string, but will take exactly two
|
||||
bytes in the target string */
|
||||
i+= charlen;
|
||||
i += charlen;
|
||||
continue;
|
||||
}
|
||||
i++; /* move to next char in source string */
|
||||
|
|
|
@ -3,23 +3,22 @@
|
|||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
*
|
||||
* Error mapping routines from Samba libsmb/errormap.c
|
||||
* Copyright (C) Andrew Tridgell 2001
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
@ -30,9 +29,7 @@
|
|||
#include <linux/fs.h>
|
||||
#include <asm/div64.h>
|
||||
#include <asm/byteorder.h>
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
#include <linux/inet.h>
|
||||
#endif
|
||||
#include "cifsfs.h"
|
||||
#include "cifspdu.h"
|
||||
#include "cifsglob.h"
|
||||
|
@ -67,22 +64,22 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
|
|||
{ERRbadshare, -ETXTBSY},
|
||||
{ERRlock, -EACCES},
|
||||
{ERRunsup, -EINVAL},
|
||||
{ERRnosuchshare,-ENXIO},
|
||||
{ERRnosuchshare, -ENXIO},
|
||||
{ERRfilexists, -EEXIST},
|
||||
{ERRinvparm, -EINVAL},
|
||||
{ERRdiskfull, -ENOSPC},
|
||||
{ERRinvname, -ENOENT},
|
||||
{ERRinvlevel,-EOPNOTSUPP},
|
||||
{ERRinvlevel, -EOPNOTSUPP},
|
||||
{ERRdirnotempty, -ENOTEMPTY},
|
||||
{ERRnotlocked, -ENOLCK},
|
||||
{ERRcancelviolation, -ENOLCK},
|
||||
{ERRalreadyexists, -EEXIST},
|
||||
{ERRmoredata, -EOVERFLOW},
|
||||
{ERReasnotsupported,-EOPNOTSUPP},
|
||||
{ERReasnotsupported, -EOPNOTSUPP},
|
||||
{ErrQuota, -EDQUOT},
|
||||
{ErrNotALink, -ENOLINK},
|
||||
{ERRnetlogonNotStarted,-ENOPROTOOPT},
|
||||
{ErrTooManyLinks,-EMLINK},
|
||||
{ERRnetlogonNotStarted, -ENOPROTOOPT},
|
||||
{ErrTooManyLinks, -EMLINK},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
|
@ -133,85 +130,24 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
|
|||
/* returns 0 if invalid address */
|
||||
|
||||
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;
|
||||
|
||||
/* calculate length by finding first slash or NULL */
|
||||
/* BB Should we convert '/' slash to '\' here since it seems already done
|
||||
before this */
|
||||
if( address_family == AF_INET ){
|
||||
ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL);
|
||||
} else if( address_family == AF_INET6 ){
|
||||
/* BB Should we convert '/' slash to '\' here since it seems already
|
||||
* done before this */
|
||||
if ( address_family == AF_INET ) {
|
||||
ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL);
|
||||
} else if ( address_family == AF_INET6 ) {
|
||||
ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL);
|
||||
}
|
||||
#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
|
||||
if (ret > 0)
|
||||
ret = 1;
|
||||
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 */
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -246,7 +182,7 @@ static const struct {
|
|||
ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, {
|
||||
ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR},
|
||||
/* { This NT error code was 'sqashed'
|
||||
from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK
|
||||
from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK
|
||||
during the session setup } */
|
||||
{
|
||||
ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, {
|
||||
|
@ -261,7 +197,7 @@ static const struct {
|
|||
ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, {
|
||||
ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED},
|
||||
/* { This NT error code was 'sqashed'
|
||||
from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
|
||||
from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
|
||||
during the session setup } */
|
||||
{
|
||||
ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, {
|
||||
|
@ -331,7 +267,7 @@ static const struct {
|
|||
ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, {
|
||||
ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS},
|
||||
/* { This NT error code was 'sqashed'
|
||||
from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
|
||||
from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
|
||||
during the session setup } */
|
||||
{
|
||||
ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, {
|
||||
|
@ -341,7 +277,7 @@ static const struct {
|
|||
ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, {
|
||||
ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN},
|
||||
/* { This NT error code was 'sqashed'
|
||||
from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE
|
||||
from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE
|
||||
during the session setup } */
|
||||
{
|
||||
ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, {
|
||||
|
@ -393,8 +329,8 @@ static const struct {
|
|||
ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
|
||||
ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
|
||||
/* { This NT error code was 'sqashed'
|
||||
from NT_STATUS_INSUFFICIENT_RESOURCES to NT_STATUS_INSUFF_SERVER_RESOURCES
|
||||
during the session setup } */
|
||||
from NT_STATUS_INSUFFICIENT_RESOURCES to
|
||||
NT_STATUS_INSUFF_SERVER_RESOURCES during the session setup } */
|
||||
{
|
||||
ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
|
||||
ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
|
||||
|
@ -638,8 +574,8 @@ static const struct {
|
|||
ERRDOS, 19, NT_STATUS_TOO_LATE}, {
|
||||
ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
|
||||
/* { This NT error code was 'sqashed'
|
||||
from NT_STATUS_NO_TRUST_SAM_ACCOUNT to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
|
||||
during the session setup } */
|
||||
from NT_STATUS_NO_TRUST_SAM_ACCOUNT to
|
||||
NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE during the session setup } */
|
||||
{
|
||||
ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
|
||||
ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
|
||||
|
@ -658,7 +594,7 @@ static const struct {
|
|||
ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, {
|
||||
ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
|
||||
/* { This NT error code was 'sqashed'
|
||||
from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE
|
||||
from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE
|
||||
during the session setup } */
|
||||
{
|
||||
ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, {
|
||||
|
@ -789,7 +725,7 @@ cifs_print_status(__u32 status_code)
|
|||
if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
|
||||
(status_code & 0xFFFFFF)) {
|
||||
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++;
|
||||
}
|
||||
|
@ -821,7 +757,7 @@ int
|
|||
map_smb_to_linux_error(struct smb_hdr *smb)
|
||||
{
|
||||
unsigned int i;
|
||||
int rc = -EIO; /* if transport error smb error may not be set */
|
||||
int rc = -EIO; /* if transport error smb error may not be set */
|
||||
__u8 smberrclass;
|
||||
__u16 smberrcode;
|
||||
|
||||
|
@ -832,9 +768,10 @@ map_smb_to_linux_error(struct smb_hdr *smb)
|
|||
return 0;
|
||||
|
||||
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);
|
||||
if(cifsFYI & CIFS_RC)
|
||||
if (cifsFYI & CIFS_RC)
|
||||
cifs_print_status(err);
|
||||
ntstatus_to_dos(err, &smberrclass, &smberrcode);
|
||||
} else {
|
||||
|
@ -845,38 +782,42 @@ map_smb_to_linux_error(struct smb_hdr *smb)
|
|||
/* old style errors */
|
||||
|
||||
/* 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;
|
||||
i <
|
||||
sizeof (mapping_table_ERRDOS) /
|
||||
sizeof (struct smb_to_posix_error); i++) {
|
||||
if (mapping_table_ERRDOS[i].smb_err == 0)
|
||||
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;
|
||||
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;
|
||||
i <
|
||||
sizeof (mapping_table_ERRSRV) /
|
||||
sizeof (struct smb_to_posix_error); i++) {
|
||||
if (mapping_table_ERRSRV[i].smb_err == 0)
|
||||
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;
|
||||
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 */
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -910,7 +851,7 @@ smbCalcSize_LE(struct smb_hdr *ptr)
|
|||
struct timespec
|
||||
cifs_NTtimeToUnix(u64 ntutc)
|
||||
{
|
||||
struct timespec ts;
|
||||
struct timespec ts;
|
||||
/* BB what about the timezone? BB */
|
||||
|
||||
/* Subtract the NTFS time offset, then convert to 1s intervals. */
|
||||
|
@ -918,7 +859,7 @@ cifs_NTtimeToUnix(u64 ntutc)
|
|||
|
||||
t = ntutc - NTFS_TIME_OFFSET;
|
||||
ts.tv_nsec = do_div(t, 10000000) * 100;
|
||||
ts.tv_sec = t;
|
||||
ts.tv_sec = t;
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
@ -946,20 +887,20 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
|
|||
SMB_TIME * st = (SMB_TIME *)&time;
|
||||
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;
|
||||
min = st->Minutes;
|
||||
if((sec > 59) || (min > 59))
|
||||
cERROR(1,("illegal time min %d sec %d", min, sec));
|
||||
if ((sec > 59) || (min > 59))
|
||||
cERROR(1, ("illegal time min %d sec %d", min, sec));
|
||||
sec += (min * 60);
|
||||
sec += 60 * 60 * st->Hours;
|
||||
if(st->Hours > 24)
|
||||
cERROR(1,("illegal hours %d",st->Hours));
|
||||
if (st->Hours > 24)
|
||||
cERROR(1, ("illegal hours %d", st->Hours));
|
||||
days = sd->Day;
|
||||
month = sd->Month;
|
||||
if((days > 31) || (month > 12))
|
||||
cERROR(1,("illegal date, month %d day: %d", month, days));
|
||||
if ((days > 31) || (month > 12))
|
||||
cERROR(1, ("illegal date, month %d day: %d", month, days));
|
||||
month -= 1;
|
||||
days += total_days_of_prev_months[month];
|
||||
days += 3652; /* account for difference in days between 1980 and 1970 */
|
||||
|
@ -970,15 +911,15 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
|
|||
for years/100 except for years/400, but since the maximum number for DOS
|
||||
year is 2**7, the last year is 1980+127, which means we need 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) */
|
||||
if(year >= 120) /* the year 2100 */
|
||||
if (year >= 120) /* 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 */
|
||||
if(year != 120)
|
||||
if (year != 120)
|
||||
days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0);
|
||||
sec += 24 * 60 * 60 * days;
|
||||
sec += 24 * 60 * 60 * days;
|
||||
|
||||
ts.tv_sec = sec;
|
||||
|
||||
|
@ -986,4 +927,4 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
|
|||
|
||||
ts.tv_nsec = 0;
|
||||
return ts;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
/*
|
||||
/*
|
||||
* Unix SMB/Netbios implementation.
|
||||
* Version 1.9.
|
||||
* RPC Pipe client / server routines
|
||||
* Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 1.9.
|
||||
NT error code constants
|
||||
|
@ -6,17 +6,17 @@
|
|||
Copyright (C) John H Terpstra 1996-2000
|
||||
Copyright (C) Luke Kenneth Casson Leighton 1996-2000
|
||||
Copyright (C) Paul Ashton 1998-2000
|
||||
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
|
@ -16,7 +16,7 @@
|
|||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define NTLMSSP_SIGNATURE "NTLMSSP"
|
||||
|
@ -27,18 +27,18 @@
|
|||
#define UnknownMessage cpu_to_le32(8)
|
||||
|
||||
/* Negotiate Flags */
|
||||
#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode
|
||||
#define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM
|
||||
#define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm
|
||||
#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability
|
||||
#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality
|
||||
#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are in unicode */
|
||||
#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */
|
||||
#define NTLMSSP_REQUEST_TARGET 0x04 /* Server return its auth realm */
|
||||
#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signature capability */
|
||||
#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */
|
||||
#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
|
||||
#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
|
||||
#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication
|
||||
#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Sign/seal use LM session key */
|
||||
#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */
|
||||
#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
|
||||
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
|
||||
#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_LOCAL_CALL 0x4000 /* client/server on same machine */
|
||||
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign for all security levels */
|
||||
#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
|
||||
#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
|
||||
#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* fs/cifs/readdir.c
|
||||
*
|
||||
* Directory search handling
|
||||
*
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2004, 2007
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
|
@ -34,24 +34,23 @@
|
|||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
static void dump_cifs_file_struct(struct file *file, char *label)
|
||||
{
|
||||
struct cifsFileInfo * cf;
|
||||
struct cifsFileInfo *cf;
|
||||
|
||||
if (file) {
|
||||
cf = file->private_data;
|
||||
if (cf == NULL) {
|
||||
cFYI(1,("empty cifs private file data"));
|
||||
cFYI(1, ("empty cifs private file data"));
|
||||
return;
|
||||
}
|
||||
if (cf->invalidHandle) {
|
||||
cFYI(1,("invalid handle"));
|
||||
cFYI(1, ("invalid handle"));
|
||||
}
|
||||
if (cf->srch_inf.endOfSearch) {
|
||||
cFYI(1,("end of search"));
|
||||
cFYI(1, ("end of search"));
|
||||
}
|
||||
if (cf->srch_inf.emptyDir) {
|
||||
cFYI(1,("empty dir"));
|
||||
cFYI(1, ("empty dir"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#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);
|
||||
tmp_dentry = d_lookup(file->f_path.dentry, qstring);
|
||||
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;
|
||||
/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
|
||||
if (*ptmp_inode == NULL) {
|
||||
|
@ -87,7 +87,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
|
|||
} else {
|
||||
tmp_dentry = d_alloc(file->f_path.dentry, qstring);
|
||||
if (tmp_dentry == NULL) {
|
||||
cERROR(1,("Failed allocating dentry"));
|
||||
cERROR(1, ("Failed allocating dentry"));
|
||||
*ptmp_inode = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
|
|||
if (*ptmp_inode == NULL)
|
||||
return rc;
|
||||
if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
|
||||
(*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||
(*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||
rc = 2;
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
|
|||
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)) {
|
||||
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,
|
||||
char * buf, int *pobject_type, int isNewInode)
|
||||
char *buf, int *pobject_type, int isNewInode)
|
||||
{
|
||||
loff_t local_size;
|
||||
struct timespec local_mtime;
|
||||
|
@ -150,7 +150,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
|||
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
|
||||
} else { /* legacy, OS2 and DOS style */
|
||||
/* struct timespec ts;*/
|
||||
FIND_FILE_STANDARD_INFO * pfindData =
|
||||
FIND_FILE_STANDARD_INFO * pfindData =
|
||||
(FIND_FILE_STANDARD_INFO *)buf;
|
||||
|
||||
tmp_inode->i_mtime = cnvrtDosUnixTm(
|
||||
|
@ -175,7 +175,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
|||
|
||||
/* treat dos attribute of read-only as read-only mode bit e.g. 555? */
|
||||
/* 2767 perms - indicate mandatory locking */
|
||||
/* BB fill in uid and gid here? with help from winbind?
|
||||
/* BB fill in uid and gid here? with help from winbind?
|
||||
or retrieve from NTFS stream extended attribute */
|
||||
if (atomic_read(&cifsInfo->inUse) == 0) {
|
||||
tmp_inode->i_uid = cifs_sb->mnt_uid;
|
||||
|
@ -196,7 +196,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
|||
tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
|
||||
}
|
||||
tmp_inode->i_mode |= S_IFDIR;
|
||||
} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
|
||||
} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
|
||||
(attr & ATTR_SYSTEM)) {
|
||||
if (end_of_file == 0) {
|
||||
*pobject_type = DT_FIFO;
|
||||
|
@ -206,13 +206,13 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
|||
inode as needing revalidate and get the real type
|
||||
(blk vs chr vs. symlink) later ie in lookup */
|
||||
*pobject_type = DT_REG;
|
||||
tmp_inode->i_mode |= S_IFREG;
|
||||
cifsInfo->time = 0;
|
||||
tmp_inode->i_mode |= S_IFREG;
|
||||
cifsInfo->time = 0;
|
||||
}
|
||||
/* we no longer mark these because we could not follow them */
|
||||
/* } else if (attr & ATTR_REPARSE) {
|
||||
*pobject_type = DT_LNK;
|
||||
tmp_inode->i_mode |= S_IFLNK; */
|
||||
*pobject_type = DT_LNK;
|
||||
tmp_inode->i_mode |= S_IFLNK; */
|
||||
} else {
|
||||
*pobject_type = DT_REG;
|
||||
tmp_inode->i_mode |= S_IFREG;
|
||||
|
@ -220,7 +220,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
|||
tmp_inode->i_mode &= ~(S_IWUGO);
|
||||
else if ((tmp_inode->i_mode & S_IWUGO) == 0)
|
||||
/* the ATTR_READONLY flag may have been changed on */
|
||||
/* server -- set any w bits allowed by mnt_file_mode */
|
||||
/* server -- set any w bits allowed by mnt_file_mode */
|
||||
tmp_inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode);
|
||||
} /* could add code here - to validate if device or weird share type? */
|
||||
|
||||
|
@ -231,7 +231,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
|||
|
||||
spin_lock(&tmp_inode->i_lock);
|
||||
if (is_size_safe_to_change(cifsInfo, end_of_file)) {
|
||||
/* can not safely change the file size here if the
|
||||
/* can not safely change the file size here if the
|
||||
client is writing to it due to potential races */
|
||||
i_size_write(tmp_inode, end_of_file);
|
||||
|
||||
|
@ -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;
|
||||
else
|
||||
tmp_inode->i_fop = &cifs_file_direct_ops;
|
||||
|
||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
tmp_inode->i_fop = &cifs_file_nobrl_ops;
|
||||
else
|
||||
|
@ -322,8 +321,8 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
|
|||
|
||||
tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
|
||||
/* since we set the inode type below we need to mask off type
|
||||
to avoid strange results if bits above were corrupt */
|
||||
tmp_inode->i_mode &= ~S_IFMT;
|
||||
to avoid strange results if bits above were corrupt */
|
||||
tmp_inode->i_mode &= ~S_IFMT;
|
||||
if (type == UNIX_FILE) {
|
||||
*pobject_type = DT_REG;
|
||||
tmp_inode->i_mode |= S_IFREG;
|
||||
|
@ -353,7 +352,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
|
|||
/* safest to just call it a file */
|
||||
*pobject_type = DT_REG;
|
||||
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)
|
||||
|
@ -368,7 +367,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
|
|||
|
||||
spin_lock(&tmp_inode->i_lock);
|
||||
if (is_size_safe_to_change(cifsInfo, end_of_file)) {
|
||||
/* can not safely change the file size here if the
|
||||
/* can not safely change the file size here if the
|
||||
client is writing to it due to potential races */
|
||||
i_size_write(tmp_inode, end_of_file);
|
||||
|
||||
|
@ -393,15 +392,16 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
|
|||
tmp_inode->i_fop = &cifs_file_ops;
|
||||
|
||||
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))
|
||||
tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
|
||||
else
|
||||
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
||||
|
||||
if (isNewInode)
|
||||
return; /* No sense invalidating pages for new inode since we
|
||||
have not started caching readahead file data yet */
|
||||
return; /* No sense invalidating pages for new inode
|
||||
since we have not started caching readahead
|
||||
file data for it yet */
|
||||
|
||||
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
|
||||
(local_size == tmp_inode->i_size)) {
|
||||
|
@ -420,7 +420,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
|
|||
tmp_inode->i_op = &cifs_symlink_inode_ops;
|
||||
/* tmp_inode->i_fop = *//* do not need to set to anything */
|
||||
} else {
|
||||
cFYI(1, ("Special inode"));
|
||||
cFYI(1, ("Special inode"));
|
||||
init_special_inode(tmp_inode, tmp_inode->i_mode,
|
||||
tmp_inode->i_rdev);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
int rc = 0;
|
||||
char * full_path;
|
||||
struct cifsFileInfo * cifsFile;
|
||||
char *full_path;
|
||||
struct cifsFileInfo *cifsFile;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
|
||||
if (file->private_data == NULL) {
|
||||
file->private_data =
|
||||
kzalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
|
||||
file->private_data =
|
||||
kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
|
||||
}
|
||||
|
||||
if (file->private_data == NULL)
|
||||
|
@ -463,9 +463,11 @@ static int initiate_cifs_search(const int xid, struct file *file)
|
|||
|
||||
ffirst_retry:
|
||||
/* 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;
|
||||
} else if ((pTcon->ses->capabilities &
|
||||
} else if ((pTcon->ses->capabilities &
|
||||
(CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
|
||||
cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
|
||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||
|
@ -474,13 +476,13 @@ ffirst_retry:
|
|||
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,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
|
||||
if (rc == 0)
|
||||
cifsFile->invalidHandle = FALSE;
|
||||
if ((rc == -EOPNOTSUPP) &&
|
||||
if ((rc == -EOPNOTSUPP) &&
|
||||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
|
||||
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
|
||||
goto ffirst_retry;
|
||||
|
@ -495,17 +497,17 @@ static int cifs_unicode_bytelen(char *str)
|
|||
int len;
|
||||
__le16 * ustr = (__le16 *)str;
|
||||
|
||||
for(len=0;len <= PATH_MAX;len++) {
|
||||
for (len = 0; len <= PATH_MAX; len++) {
|
||||
if (ustr[len] == 0)
|
||||
return len << 1;
|
||||
}
|
||||
cFYI(1,("Unicode string longer than PATH_MAX found"));
|
||||
cFYI(1, ("Unicode string longer than PATH_MAX found"));
|
||||
return len << 1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (level == SMB_FIND_FILE_INFO_STANDARD) {
|
||||
|
@ -516,21 +518,21 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
|
|||
pfData->FileNameLength;
|
||||
} else
|
||||
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 */
|
||||
if (new_entry >= end_of_smb) {
|
||||
cERROR(1,
|
||||
("search entry %p began after end of SMB %p old entry %p",
|
||||
new_entry, end_of_smb, old_entry));
|
||||
new_entry, end_of_smb, old_entry));
|
||||
return NULL;
|
||||
} else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
|
||||
(new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb)) ||
|
||||
((level != SMB_FIND_FILE_INFO_STANDARD) &&
|
||||
(new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
|
||||
|| ((level != SMB_FIND_FILE_INFO_STANDARD) &&
|
||||
(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));
|
||||
return NULL;
|
||||
} else
|
||||
} else
|
||||
return new_entry;
|
||||
|
||||
}
|
||||
|
@ -541,8 +543,8 @@ 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)
|
||||
{
|
||||
int rc = 0;
|
||||
char * filename = NULL;
|
||||
int len = 0;
|
||||
char *filename = NULL;
|
||||
int len = 0;
|
||||
|
||||
if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
|
||||
FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
|
||||
|
@ -554,25 +556,25 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
|
|||
len = strnlen(filename, 5);
|
||||
}
|
||||
} else if (cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
||||
FILE_DIRECTORY_INFO * pFindData =
|
||||
FILE_DIRECTORY_INFO * pFindData =
|
||||
(FILE_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if (cfile->srch_inf.info_level ==
|
||||
} else if (cfile->srch_inf.info_level ==
|
||||
SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
|
||||
FILE_FULL_DIRECTORY_INFO * pFindData =
|
||||
FILE_FULL_DIRECTORY_INFO * pFindData =
|
||||
(FILE_FULL_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if (cfile->srch_inf.info_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;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if (cfile->srch_inf.info_level ==
|
||||
} else if (cfile->srch_inf.info_level ==
|
||||
SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
|
||||
FILE_BOTH_DIRECTORY_INFO * pFindData =
|
||||
FILE_BOTH_DIRECTORY_INFO * pFindData =
|
||||
(FILE_BOTH_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
|
@ -582,7 +584,8 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
|
|||
filename = &pFindData->FileName[0];
|
||||
len = pFindData->FileNameLength;
|
||||
} 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) {
|
||||
|
@ -595,15 +598,15 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
|
|||
} else if (len == 4) {
|
||||
/* check for .. */
|
||||
if ((ufilename[0] == UNICODE_DOT)
|
||||
&&(ufilename[1] == UNICODE_DOT))
|
||||
&& (ufilename[1] == UNICODE_DOT))
|
||||
rc = 2;
|
||||
}
|
||||
} else /* ASCII */ {
|
||||
if (len == 1) {
|
||||
if (filename[0] == '.')
|
||||
if (filename[0] == '.')
|
||||
rc = 1;
|
||||
} else if (len == 2) {
|
||||
if((filename[0] == '.') && (filename[1] == '.'))
|
||||
if ((filename[0] == '.') && (filename[1] == '.'))
|
||||
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
|
||||
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 cifsInodeInfo *cifsInfo = CIFS_I(inode);
|
||||
|
@ -633,22 +636,22 @@ static int is_dir_changed(struct file * file)
|
|||
/* We start counting in the buffer with entry 2 and increment for every
|
||||
entry (do not increment for . or .. entry) */
|
||||
static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||
struct file *file, char **ppCurrentEntry, int *num_to_ret)
|
||||
struct file *file, char **ppCurrentEntry, int *num_to_ret)
|
||||
{
|
||||
int rc = 0;
|
||||
int pos_in_buf = 0;
|
||||
loff_t first_entry_in_buffer;
|
||||
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 */
|
||||
|
||||
if ((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
|
||||
|
||||
if ((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
|
||||
(num_to_ret == NULL))
|
||||
return -ENOENT;
|
||||
|
||||
|
||||
*ppCurrentEntry = NULL;
|
||||
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;
|
||||
|
||||
/* if first entry in buf is zero then is first buffer
|
||||
|
@ -660,17 +663,17 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
|||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
dump_cifs_file_struct(file, "In fce ");
|
||||
#endif
|
||||
if (((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
|
||||
is_dir_changed(file)) ||
|
||||
if (((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
|
||||
is_dir_changed(file)) ||
|
||||
(index_to_find < first_entry_in_buffer)) {
|
||||
/* 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;
|
||||
CIFSFindClose(xid, pTcon, cifsFile->netfid);
|
||||
kfree(cifsFile->search_resume_name);
|
||||
cifsFile->search_resume_name = NULL;
|
||||
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)
|
||||
cifs_small_buf_release(cifsFile->srch_inf.
|
||||
ntwrk_buf_start);
|
||||
|
@ -678,17 +681,18 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
|||
cifs_buf_release(cifsFile->srch_inf.
|
||||
ntwrk_buf_start);
|
||||
}
|
||||
rc = initiate_cifs_search(xid,file);
|
||||
rc = initiate_cifs_search(xid, file);
|
||||
if (rc) {
|
||||
cFYI(1,("error %d reinitiating a search on rewind",rc));
|
||||
cFYI(1, ("error %d reinitiating a search on rewind",
|
||||
rc));
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
|
||||
(rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){
|
||||
cFYI(1,("calling findnext2"));
|
||||
rc = CIFSFindNext(xid,pTcon,cifsFile->netfid,
|
||||
while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
|
||||
(rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)) {
|
||||
cFYI(1, ("calling findnext2"));
|
||||
rc = CIFSFindNext(xid, pTcon, cifsFile->netfid,
|
||||
&cifsFile->srch_inf);
|
||||
if (rc)
|
||||
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 */
|
||||
/* scan and find it */
|
||||
int i;
|
||||
char * current_entry;
|
||||
char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
|
||||
char *current_entry;
|
||||
char *end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
|
||||
smbCalcSize((struct smb_hdr *)
|
||||
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
|
||||
- cifsFile->srch_inf.entries_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 */
|
||||
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);
|
||||
}
|
||||
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 */
|
||||
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",
|
||||
pos_in_buf,index_to_find,rc));
|
||||
pos_in_buf, index_to_find, rc));
|
||||
}
|
||||
rc = 0;
|
||||
*ppCurrentEntry = current_entry;
|
||||
} 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;
|
||||
}
|
||||
|
||||
if(pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
|
||||
cFYI(1,("can not return entries pos_in_buf beyond last entry"));
|
||||
if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
|
||||
cFYI(1, ("can not return entries pos_in_buf beyond last"));
|
||||
*num_to_ret = 0;
|
||||
} else
|
||||
*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 */
|
||||
static int cifs_get_name_from_search_buf(struct qstr *pqst,
|
||||
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;
|
||||
unsigned int len = 0;
|
||||
char * filename;
|
||||
struct nls_table * nlt = cifs_sb->local_nls;
|
||||
char *filename;
|
||||
struct nls_table *nlt = cifs_sb->local_nls;
|
||||
|
||||
*pinum = 0;
|
||||
|
||||
if(level == SMB_FIND_FILE_UNIX) {
|
||||
FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
|
||||
if (level == SMB_FIND_FILE_UNIX) {
|
||||
FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
|
||||
|
||||
filename = &pFindData->FileName[0];
|
||||
if(unicode) {
|
||||
if (unicode) {
|
||||
len = cifs_unicode_bytelen(filename);
|
||||
} else {
|
||||
/* BB should we make this strnlen of PATH_MAX? */
|
||||
len = strnlen(filename, PATH_MAX);
|
||||
}
|
||||
|
||||
/* BB fixme - hash low and high 32 bits if not 64 bit arch BB fixme */
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
|
||||
/* BB fixme - hash low and high 32 bits if not 64 bit arch BB */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
|
||||
*pinum = pFindData->UniqueId;
|
||||
} else if(level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
||||
FILE_DIRECTORY_INFO * pFindData =
|
||||
} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
||||
FILE_DIRECTORY_INFO *pFindData =
|
||||
(FILE_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if(level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
|
||||
FILE_FULL_DIRECTORY_INFO * pFindData =
|
||||
} else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
|
||||
FILE_FULL_DIRECTORY_INFO *pFindData =
|
||||
(FILE_FULL_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
} else if(level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
|
||||
SEARCH_ID_FULL_DIR_INFO * pFindData =
|
||||
} else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
|
||||
SEARCH_ID_FULL_DIR_INFO *pFindData =
|
||||
(SEARCH_ID_FULL_DIR_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
*pinum = pFindData->UniqueId;
|
||||
} else if(level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
|
||||
FILE_BOTH_DIRECTORY_INFO * pFindData =
|
||||
} else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
|
||||
FILE_BOTH_DIRECTORY_INFO *pFindData =
|
||||
(FILE_BOTH_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
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 *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
/* one byte length, no name conversion */
|
||||
len = (unsigned int)pFindData->FileNameLength;
|
||||
} else {
|
||||
cFYI(1,("Unknown findfirst level %d",level));
|
||||
cFYI(1, ("Unknown findfirst level %d", level));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(len > max_len) {
|
||||
cERROR(1,("bad search response length %d past smb end", len));
|
||||
if (len > max_len) {
|
||||
cERROR(1, ("bad search response length %d past smb end", len));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(unicode) {
|
||||
if (unicode) {
|
||||
/* BB fixme - test with long names */
|
||||
/* 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,
|
||||
(__le16 *)filename, len/2, nlt);
|
||||
else
|
||||
pqst->len = cifs_strfromUCS_le((char *)pqst->name,
|
||||
(__le16 *)filename,len/2,nlt);
|
||||
(__le16 *)filename, len/2, nlt);
|
||||
} else {
|
||||
pqst->name = filename;
|
||||
pqst->len = len;
|
||||
}
|
||||
pqst->hash = full_name_hash(pqst->name,pqst->len);
|
||||
/* cFYI(1,("filldir on %s",pqst->name)); */
|
||||
pqst->hash = full_name_hash(pqst->name, pqst->len);
|
||||
/* cFYI(1, ("filldir on %s",pqst->name)); */
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -821,49 +825,50 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
|
|||
{
|
||||
int rc = 0;
|
||||
struct qstr qstring;
|
||||
struct cifsFileInfo * pCifsF;
|
||||
struct cifsFileInfo *pCifsF;
|
||||
unsigned obj_type;
|
||||
ino_t inum;
|
||||
struct cifs_sb_info * cifs_sb;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct inode *tmp_inode;
|
||||
struct dentry *tmp_dentry;
|
||||
|
||||
/* get filename and len into qstring */
|
||||
/* get dentry */
|
||||
/* decide whether to create and populate ionde */
|
||||
if((direntry == NULL) || (file == NULL))
|
||||
if ((direntry == NULL) || (file == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
pCifsF = file->private_data;
|
||||
|
||||
if((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
|
||||
|
||||
if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
|
||||
return -ENOENT;
|
||||
|
||||
rc = cifs_entry_is_dot(pfindEntry,pCifsF);
|
||||
rc = cifs_entry_is_dot(pfindEntry, pCifsF);
|
||||
/* skip . and .. since we added them first */
|
||||
if(rc != 0)
|
||||
if (rc != 0)
|
||||
return 0;
|
||||
|
||||
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
||||
|
||||
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.unicode,cifs_sb,
|
||||
pCifsF->srch_inf.unicode, cifs_sb,
|
||||
max_len,
|
||||
&inum /* returned */);
|
||||
|
||||
if(rc)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = construct_dentry(&qstring,file,&tmp_inode, &tmp_dentry);
|
||||
if((tmp_inode == NULL) || (tmp_dentry == NULL))
|
||||
rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry);
|
||||
if ((tmp_inode == NULL) || (tmp_dentry == NULL))
|
||||
return -ENOMEM;
|
||||
|
||||
if(rc) {
|
||||
if (rc) {
|
||||
/* inode created, we need to hash it with right inode number */
|
||||
if(inum != 0) {
|
||||
/* BB fixme - hash the 2 32 quantities bits together if necessary BB */
|
||||
if (inum != 0) {
|
||||
/* BB fixme - hash the 2 32 quantities bits together if
|
||||
* necessary BB */
|
||||
tmp_inode->i_ino = inum;
|
||||
}
|
||||
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,
|
||||
so we can figure out whether to invalidate the inode cached
|
||||
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,
|
||||
(FILE_UNIX_INFO *)pfindEntry,
|
||||
&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 */,
|
||||
pfindEntry, &obj_type, rc);
|
||||
else
|
||||
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);
|
||||
if(rc == 2)
|
||||
if (rc == 2)
|
||||
d_rehash(tmp_dentry);
|
||||
}
|
||||
|
||||
|
||||
rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,
|
||||
tmp_inode->i_ino,obj_type);
|
||||
if(rc) {
|
||||
cFYI(1,("filldir rc = %d",rc));
|
||||
|
||||
|
||||
rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
|
||||
tmp_inode->i_ino, obj_type);
|
||||
if (rc) {
|
||||
cFYI(1, ("filldir rc = %d", rc));
|
||||
/* we can not return filldir errors to the caller
|
||||
since they are "normal" when the stat blocksize
|
||||
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;
|
||||
unsigned int len = 0;
|
||||
__u16 level;
|
||||
char * filename;
|
||||
char *filename;
|
||||
|
||||
if((cifsFile == NULL) || (current_entry == NULL))
|
||||
if ((cifsFile == NULL) || (current_entry == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
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;
|
||||
|
||||
filename = &pFindData->FileName[0];
|
||||
if(cifsFile->srch_inf.unicode) {
|
||||
if (cifsFile->srch_inf.unicode) {
|
||||
len = cifs_unicode_bytelen(filename);
|
||||
} else {
|
||||
/* BB should we make this strnlen of PATH_MAX? */
|
||||
len = strnlen(filename, PATH_MAX);
|
||||
}
|
||||
cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
|
||||
} else if(level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
||||
FILE_DIRECTORY_INFO * pFindData =
|
||||
} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
||||
FILE_DIRECTORY_INFO *pFindData =
|
||||
(FILE_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
||||
} else if(level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
|
||||
FILE_FULL_DIRECTORY_INFO * pFindData =
|
||||
} else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
|
||||
FILE_FULL_DIRECTORY_INFO *pFindData =
|
||||
(FILE_FULL_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
||||
} else if(level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
|
||||
SEARCH_ID_FULL_DIR_INFO * pFindData =
|
||||
} else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
|
||||
SEARCH_ID_FULL_DIR_INFO *pFindData =
|
||||
(SEARCH_ID_FULL_DIR_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
||||
} else if(level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
|
||||
FILE_BOTH_DIRECTORY_INFO * pFindData =
|
||||
} else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
|
||||
FILE_BOTH_DIRECTORY_INFO *pFindData =
|
||||
(FILE_BOTH_DIRECTORY_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
len = le32_to_cpu(pFindData->FileNameLength);
|
||||
cifsFile->srch_inf.resume_key = pFindData->FileIndex;
|
||||
} else if(level == SMB_FIND_FILE_INFO_STANDARD) {
|
||||
FIND_FILE_STANDARD_INFO * pFindData =
|
||||
} else if (level == SMB_FIND_FILE_INFO_STANDARD) {
|
||||
FIND_FILE_STANDARD_INFO *pFindData =
|
||||
(FIND_FILE_STANDARD_INFO *)current_entry;
|
||||
filename = &pFindData->FileName[0];
|
||||
/* one byte length, no name conversion */
|
||||
len = (unsigned int)pFindData->FileNameLength;
|
||||
cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
|
||||
} else {
|
||||
cFYI(1,("Unknown findfirst level %d",level));
|
||||
cFYI(1, ("Unknown findfirst level %d", level));
|
||||
return -EINVAL;
|
||||
}
|
||||
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 rc = 0;
|
||||
int xid,i;
|
||||
int xid, i;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
struct cifsFileInfo *cifsFile = NULL;
|
||||
char * current_entry;
|
||||
char *current_entry;
|
||||
int num_to_fill = 0;
|
||||
char * tmp_buf = NULL;
|
||||
char * end_of_smb;
|
||||
char *tmp_buf = NULL;
|
||||
char *end_of_smb;
|
||||
int max_len;
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
||||
pTcon = cifs_sb->tcon;
|
||||
if(pTcon == NULL)
|
||||
if (pTcon == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
switch ((int) file->f_pos) {
|
||||
|
@ -1005,27 +1010,27 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
|||
}
|
||||
file->f_pos++;
|
||||
default:
|
||||
/* 1) If search is active,
|
||||
is in current search buffer?
|
||||
/* 1) If search is active,
|
||||
is in current search buffer?
|
||||
if it before then restart search
|
||||
if after then keep searching till find it */
|
||||
|
||||
if(file->private_data == NULL) {
|
||||
rc = initiate_cifs_search(xid,file);
|
||||
cFYI(1,("initiate cifs search rc %d",rc));
|
||||
if(rc) {
|
||||
if (file->private_data == NULL) {
|
||||
rc = initiate_cifs_search(xid, file);
|
||||
cFYI(1, ("initiate cifs search rc %d", rc));
|
||||
if (rc) {
|
||||
FreeXid(xid);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if(file->private_data == NULL) {
|
||||
if (file->private_data == NULL) {
|
||||
rc = -EINVAL;
|
||||
FreeXid(xid);
|
||||
return rc;
|
||||
}
|
||||
cifsFile = file->private_data;
|
||||
if (cifsFile->srch_inf.endOfSearch) {
|
||||
if(cifsFile->srch_inf.emptyDir) {
|
||||
if (cifsFile->srch_inf.emptyDir) {
|
||||
cFYI(1, ("End of search, empty dir"));
|
||||
rc = 0;
|
||||
break;
|
||||
|
@ -1033,23 +1038,23 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
|||
} /* else {
|
||||
cifsFile->invalidHandle = TRUE;
|
||||
CIFSFindClose(xid, pTcon, cifsFile->netfid);
|
||||
}
|
||||
}
|
||||
kfree(cifsFile->search_resume_name);
|
||||
cifsFile->search_resume_name = NULL; */
|
||||
|
||||
rc = find_cifs_entry(xid,pTcon, file,
|
||||
¤t_entry,&num_to_fill);
|
||||
if(rc) {
|
||||
cFYI(1,("fce error %d",rc));
|
||||
rc = find_cifs_entry(xid, pTcon, file,
|
||||
¤t_entry, &num_to_fill);
|
||||
if (rc) {
|
||||
cFYI(1, ("fce error %d", rc));
|
||||
goto rddir2_exit;
|
||||
} else if (current_entry != NULL) {
|
||||
cFYI(1,("entry %lld found",file->f_pos));
|
||||
cFYI(1, ("entry %lld found", file->f_pos));
|
||||
} else {
|
||||
cFYI(1,("could not find entry"));
|
||||
cFYI(1, ("could not find entry"));
|
||||
goto rddir2_exit;
|
||||
}
|
||||
cFYI(1,("loop through %d times filling dir for net buf %p",
|
||||
num_to_fill,cifsFile->srch_inf.ntwrk_buf_start));
|
||||
cFYI(1, ("loop through %d times filling dir for net buf %p",
|
||||
num_to_fill, cifsFile->srch_inf.ntwrk_buf_start));
|
||||
max_len = smbCalcSize((struct smb_hdr *)
|
||||
cifsFile->srch_inf.ntwrk_buf_start);
|
||||
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,
|
||||
which actually does the conversion, has the same limit */
|
||||
tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL);
|
||||
for(i=0;(i<num_to_fill) && (rc == 0);i++) {
|
||||
if(current_entry == NULL) {
|
||||
for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
|
||||
if (current_entry == NULL) {
|
||||
/* evaluate whether this case is an error */
|
||||
cERROR(1,("past end of SMB num to fill %d i %d",
|
||||
num_to_fill, i));
|
||||
|
@ -1070,20 +1075,20 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
|||
we want to check for that here? */
|
||||
rc = cifs_filldir(current_entry, file,
|
||||
filldir, direntry, tmp_buf, max_len);
|
||||
if(rc == -EOVERFLOW) {
|
||||
if (rc == -EOVERFLOW) {
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
file->f_pos++;
|
||||
if(file->f_pos ==
|
||||
if (file->f_pos ==
|
||||
cifsFile->srch_inf.index_of_last_entry) {
|
||||
cFYI(1,("last entry in buf at pos %lld %s",
|
||||
file->f_pos,tmp_buf));
|
||||
cifs_save_resume_key(current_entry,cifsFile);
|
||||
cFYI(1, ("last entry in buf at pos %lld %s",
|
||||
file->f_pos, tmp_buf));
|
||||
cifs_save_resume_key(current_entry, cifsFile);
|
||||
break;
|
||||
} else
|
||||
current_entry =
|
||||
} else
|
||||
current_entry =
|
||||
nxt_dir_entry(current_entry, end_of_smb,
|
||||
cifsFile->srch_inf.info_level);
|
||||
}
|
||||
|
|
245
fs/cifs/sess.c
245
fs/cifs/sess.c
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* 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)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
|
@ -31,7 +31,7 @@
|
|||
#include <linux/utsname.h>
|
||||
|
||||
extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
|
||||
unsigned char *p24);
|
||||
unsigned char *p24);
|
||||
|
||||
static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
|
||||
{
|
||||
|
@ -45,13 +45,14 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
|
|||
|
||||
/* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
|
||||
|
||||
/* BB verify whether signing required on neg or just on auth frame
|
||||
/* BB verify whether signing required on neg or just on auth frame
|
||||
(and NTLM case) */
|
||||
|
||||
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
|
||||
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;
|
||||
|
||||
if (ses->capabilities & CAP_UNICODE) {
|
||||
|
@ -74,10 +75,10 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
|
|||
return capabilities;
|
||||
}
|
||||
|
||||
static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
||||
const struct nls_table * nls_cp)
|
||||
static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
|
||||
const struct nls_table *nls_cp)
|
||||
{
|
||||
char * bcc_ptr = *pbcc_area;
|
||||
char *bcc_ptr = *pbcc_area;
|
||||
int bytes_ret = 0;
|
||||
|
||||
/* 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++;
|
||||
} */
|
||||
/* copy user */
|
||||
if(ses->userName == NULL) {
|
||||
if (ses->userName == NULL) {
|
||||
/* null user mount */
|
||||
*bcc_ptr = 0;
|
||||
*(bcc_ptr+1) = 0;
|
||||
|
@ -100,14 +101,14 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
|||
bcc_ptr += 2 * bytes_ret;
|
||||
bcc_ptr += 2; /* account for null termination */
|
||||
/* copy domain */
|
||||
if(ses->domainName == NULL) {
|
||||
if (ses->domainName == NULL) {
|
||||
/* Sending null domain better than using a bogus domain name (as
|
||||
we did briefly in 2.6.18) since server will use its default */
|
||||
*bcc_ptr = 0;
|
||||
*(bcc_ptr+1) = 0;
|
||||
bytes_ret = 0;
|
||||
} else
|
||||
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
|
||||
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
|
||||
256, nls_cp);
|
||||
bcc_ptr += 2 * bytes_ret;
|
||||
bcc_ptr += 2; /* account for null terminator */
|
||||
|
@ -122,37 +123,37 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
|||
bcc_ptr += 2; /* trailing null */
|
||||
|
||||
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
|
||||
32, nls_cp);
|
||||
32, nls_cp);
|
||||
bcc_ptr += 2 * bytes_ret;
|
||||
bcc_ptr += 2; /* trailing null */
|
||||
|
||||
*pbcc_area = bcc_ptr;
|
||||
}
|
||||
|
||||
static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
||||
const struct nls_table * nls_cp)
|
||||
static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
|
||||
const struct nls_table *nls_cp)
|
||||
{
|
||||
char * bcc_ptr = *pbcc_area;
|
||||
char *bcc_ptr = *pbcc_area;
|
||||
|
||||
/* copy user */
|
||||
/* BB what about null user mounts - check that we do this BB */
|
||||
/* copy user */
|
||||
if(ses->userName == NULL) {
|
||||
/* BB what about null user mounts - check that we do this BB */
|
||||
} else { /* 300 should be long enough for any conceivable user name */
|
||||
strncpy(bcc_ptr, ses->userName, 300);
|
||||
}
|
||||
/* copy user */
|
||||
if (ses->userName == NULL) {
|
||||
/* BB what about null user mounts - check that we do this BB */
|
||||
} else { /* 300 should be long enough for any conceivable user name */
|
||||
strncpy(bcc_ptr, ses->userName, 300);
|
||||
}
|
||||
/* BB improve check for overflow */
|
||||
bcc_ptr += strnlen(ses->userName, 300);
|
||||
bcc_ptr += strnlen(ses->userName, 300);
|
||||
*bcc_ptr = 0;
|
||||
bcc_ptr++; /* account for null termination */
|
||||
bcc_ptr++; /* account for null termination */
|
||||
|
||||
/* copy domain */
|
||||
|
||||
if(ses->domainName != NULL) {
|
||||
strncpy(bcc_ptr, ses->domainName, 256);
|
||||
/* copy domain */
|
||||
|
||||
if (ses->domainName != NULL) {
|
||||
strncpy(bcc_ptr, 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
|
||||
so the server will default to its own domain */
|
||||
*bcc_ptr = 0;
|
||||
bcc_ptr++;
|
||||
|
@ -167,19 +168,20 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
|||
strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
|
||||
bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
|
||||
|
||||
*pbcc_area = bcc_ptr;
|
||||
*pbcc_area = bcc_ptr;
|
||||
}
|
||||
|
||||
static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
|
||||
const struct nls_table * nls_cp)
|
||||
static int decode_unicode_ssetup(char **pbcc_area, int bleft,
|
||||
struct cifsSesInfo *ses,
|
||||
const struct nls_table *nls_cp)
|
||||
{
|
||||
int rc = 0;
|
||||
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
|
||||
|
@ -189,7 +191,7 @@ static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInf
|
|||
their final Unicode string - in which case we
|
||||
now will not attempt to decode the byte of junk
|
||||
which follows it */
|
||||
|
||||
|
||||
words_left = bleft / 2;
|
||||
|
||||
/* save off server operating system */
|
||||
|
@ -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
|
||||
the end since (at least) WIN2K and Windows XP have a major bug in not null
|
||||
terminating last Unicode string in response */
|
||||
if(len >= words_left)
|
||||
if (len >= words_left)
|
||||
return rc;
|
||||
|
||||
if(ses->serverOS)
|
||||
if (ses->serverOS)
|
||||
kfree(ses->serverOS);
|
||||
/* UTF-8 string will not grow more than four times as big as UCS-16 */
|
||||
ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
|
||||
if(ses->serverOS != NULL) {
|
||||
if (ses->serverOS != NULL) {
|
||||
cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
|
||||
nls_cp);
|
||||
}
|
||||
|
@ -215,67 +217,68 @@ static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInf
|
|||
/* save off server network operating system */
|
||||
len = UniStrnlen((wchar_t *) data, words_left);
|
||||
|
||||
if(len >= words_left)
|
||||
if (len >= words_left)
|
||||
return rc;
|
||||
|
||||
if(ses->serverNOS)
|
||||
if (ses->serverNOS)
|
||||
kfree(ses->serverNOS);
|
||||
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,
|
||||
nls_cp);
|
||||
if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) {
|
||||
cFYI(1,("NT4 server"));
|
||||
if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) {
|
||||
cFYI(1, ("NT4 server"));
|
||||
ses->flags |= CIFS_SES_NT4;
|
||||
}
|
||||
}
|
||||
data += 2 * (len + 1);
|
||||
words_left -= len + 1;
|
||||
|
||||
/* save off server domain */
|
||||
len = UniStrnlen((wchar_t *) data, words_left);
|
||||
/* save off server domain */
|
||||
len = UniStrnlen((wchar_t *) data, words_left);
|
||||
|
||||
if(len > words_left)
|
||||
return rc;
|
||||
if (len > words_left)
|
||||
return rc;
|
||||
|
||||
if(ses->serverDomain)
|
||||
kfree(ses->serverDomain);
|
||||
ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
|
||||
if(ses->serverDomain != NULL) {
|
||||
cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
|
||||
nls_cp);
|
||||
ses->serverDomain[2*len] = 0;
|
||||
ses->serverDomain[(2*len) + 1] = 0;
|
||||
}
|
||||
data += 2 * (len + 1);
|
||||
words_left -= len + 1;
|
||||
|
||||
cFYI(1,("words left: %d",words_left));
|
||||
if (ses->serverDomain)
|
||||
kfree(ses->serverDomain);
|
||||
ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
|
||||
if (ses->serverDomain != NULL) {
|
||||
cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
|
||||
nls_cp);
|
||||
ses->serverDomain[2*len] = 0;
|
||||
ses->serverDomain[(2*len) + 1] = 0;
|
||||
}
|
||||
data += 2 * (len + 1);
|
||||
words_left -= len + 1;
|
||||
|
||||
cFYI(1, ("words left: %d", words_left));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
|
||||
const struct nls_table * nls_cp)
|
||||
static int decode_ascii_ssetup(char **pbcc_area, int bleft,
|
||||
struct cifsSesInfo *ses,
|
||||
const struct nls_table *nls_cp)
|
||||
{
|
||||
int rc = 0;
|
||||
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);
|
||||
if(len >= bleft)
|
||||
if (len >= bleft)
|
||||
return rc;
|
||||
|
||||
if(ses->serverOS)
|
||||
|
||||
if (ses->serverOS)
|
||||
kfree(ses->serverOS);
|
||||
|
||||
ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
|
||||
if(ses->serverOS)
|
||||
if (ses->serverOS)
|
||||
strncpy(ses->serverOS, bcc_ptr, len);
|
||||
if(strncmp(ses->serverOS, "OS/2",4) == 0) {
|
||||
cFYI(1,("OS/2 server"));
|
||||
if (strncmp(ses->serverOS, "OS/2", 4) == 0) {
|
||||
cFYI(1, ("OS/2 server"));
|
||||
ses->flags |= CIFS_SES_OS2;
|
||||
}
|
||||
|
||||
|
@ -283,34 +286,34 @@ static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo
|
|||
bleft -= len + 1;
|
||||
|
||||
len = strnlen(bcc_ptr, bleft);
|
||||
if(len >= bleft)
|
||||
if (len >= bleft)
|
||||
return rc;
|
||||
|
||||
if(ses->serverNOS)
|
||||
if (ses->serverNOS)
|
||||
kfree(ses->serverNOS);
|
||||
|
||||
ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
|
||||
if(ses->serverNOS)
|
||||
if (ses->serverNOS)
|
||||
strncpy(ses->serverNOS, bcc_ptr, len);
|
||||
|
||||
bcc_ptr += len + 1;
|
||||
bleft -= len + 1;
|
||||
|
||||
len = strnlen(bcc_ptr, bleft);
|
||||
if(len > bleft)
|
||||
return rc;
|
||||
len = strnlen(bcc_ptr, bleft);
|
||||
if (len > bleft)
|
||||
return rc;
|
||||
|
||||
/* No domain field in LANMAN case. Domain is
|
||||
returned by old servers in the SMB negprot response */
|
||||
/* BB For newer servers which do not support Unicode,
|
||||
but thus do return domain here we could add parsing
|
||||
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;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||
const struct nls_table *nls_cp)
|
||||
{
|
||||
|
@ -328,13 +331,13 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
__u16 action;
|
||||
int bytes_remaining;
|
||||
|
||||
if(ses == NULL)
|
||||
if (ses == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
type = ses->server->secType;
|
||||
|
||||
cFYI(1,("sess setup type %d",type));
|
||||
if(type == LANMAN) {
|
||||
cFYI(1, ("sess setup type %d", type));
|
||||
if (type == LANMAN) {
|
||||
#ifndef CONFIG_CIFS_WEAK_PW_HASH
|
||||
/* LANMAN and plaintext are less secure and off by default.
|
||||
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;
|
||||
#endif
|
||||
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 */
|
||||
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;
|
||||
|
||||
rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
|
||||
(void **)&smb_buf);
|
||||
if(rc)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pSMB = (SESSION_SETUP_ANDX *)smb_buf;
|
||||
|
@ -364,8 +367,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
second part which will include the strings
|
||||
and rest of bcc area, in order to avoid having
|
||||
to do a large buffer 17K allocation */
|
||||
iov[0].iov_base = (char *)pSMB;
|
||||
iov[0].iov_len = smb_buf->smb_buf_length + 4;
|
||||
iov[0].iov_base = (char *)pSMB;
|
||||
iov[0].iov_len = smb_buf->smb_buf_length + 4;
|
||||
|
||||
/* 2000 big enough to fit max user, domain, NOS name etc. */
|
||||
str_area = kmalloc(2000, GFP_KERNEL);
|
||||
|
@ -373,18 +376,18 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
|
||||
ses->flags &= ~CIFS_SES_LANMAN;
|
||||
|
||||
if(type == LANMAN) {
|
||||
if (type == LANMAN) {
|
||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||
char lnm_session_key[CIFS_SESS_KEY_SIZE];
|
||||
|
||||
/* no capabilities flags in old lanman negotiation */
|
||||
|
||||
pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
||||
pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
||||
/* BB calculate hash with password */
|
||||
/* and copy into bcc */
|
||||
|
||||
calc_lanman_hash(ses, lnm_session_key);
|
||||
ses->flags |= CIFS_SES_LANMAN;
|
||||
ses->flags |= CIFS_SES_LANMAN;
|
||||
/* #ifdef CONFIG_CIFS_DEBUG2
|
||||
cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
|
||||
CIFS_SESS_KEY_SIZE);
|
||||
|
@ -397,10 +400,10 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
changed to do higher than lanman dialect and
|
||||
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 */
|
||||
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||
#endif
|
||||
#endif
|
||||
} else if (type == NTLM) {
|
||||
char ntlm_session_key[CIFS_SESS_KEY_SIZE];
|
||||
|
||||
|
@ -409,38 +412,38 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
||||
pSMB->req_no_secext.CaseSensitivePasswordLength =
|
||||
cpu_to_le16(CIFS_SESS_KEY_SIZE);
|
||||
|
||||
|
||||
/* calculate session key */
|
||||
SMBNTencrypt(ses->password, ses->server->cryptKey,
|
||||
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? */
|
||||
cifs_calculate_mac_key(ses->server->mac_signing_key,
|
||||
cifs_calculate_mac_key(&ses->server->mac_signing_key,
|
||||
ntlm_session_key, ses->password);
|
||||
/* 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;
|
||||
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;
|
||||
if(ses->capabilities & CAP_UNICODE) {
|
||||
if (ses->capabilities & CAP_UNICODE) {
|
||||
/* unicode strings must be word aligned */
|
||||
if (iov[0].iov_len % 2) {
|
||||
*bcc_ptr = 0;
|
||||
bcc_ptr++;
|
||||
}
|
||||
bcc_ptr++;
|
||||
}
|
||||
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||
} else
|
||||
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||
} else if (type == NTLMv2) {
|
||||
char * v2_sess_key =
|
||||
char *v2_sess_key =
|
||||
kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
|
||||
|
||||
/* BB FIXME change all users of v2_sess_key to
|
||||
struct ntlmv2_resp */
|
||||
|
||||
if(v2_sess_key == NULL) {
|
||||
if (v2_sess_key == NULL) {
|
||||
cifs_small_buf_release(smb_buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -456,8 +459,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
|
||||
/* calculate session key */
|
||||
setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
|
||||
if(first_time) /* should this be moved into common code
|
||||
with similar ntlmv2 path? */
|
||||
if (first_time) /* should this be moved into common code
|
||||
with similar ntlmv2 path? */
|
||||
/* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_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);
|
||||
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);
|
||||
kfree(v2_sess_key);
|
||||
if(ses->capabilities & CAP_UNICODE) {
|
||||
if(iov[0].iov_len % 2) {
|
||||
if (ses->capabilities & CAP_UNICODE) {
|
||||
if (iov[0].iov_len % 2) {
|
||||
*bcc_ptr = 0;
|
||||
} bcc_ptr++;
|
||||
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||
|
@ -488,20 +492,20 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
BCC_LE(smb_buf) = cpu_to_le16(count);
|
||||
|
||||
iov[1].iov_base = str_area;
|
||||
iov[1].iov_len = count;
|
||||
iov[1].iov_len = count;
|
||||
rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
|
||||
/* SMB request buf freed in SendReceive2 */
|
||||
|
||||
cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
|
||||
if(rc)
|
||||
cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
|
||||
if (rc)
|
||||
goto ssetup_exit;
|
||||
|
||||
pSMB = (SESSION_SETUP_ANDX *)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;
|
||||
cERROR(1,("bad word count %d", smb_buf->WordCount));
|
||||
cERROR(1, ("bad word count %d", smb_buf->WordCount));
|
||||
goto ssetup_exit;
|
||||
}
|
||||
action = le16_to_cpu(pSMB->resp.Action);
|
||||
|
@ -514,31 +518,32 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||
bytes_remaining = BCC(smb_buf);
|
||||
bcc_ptr = pByteArea(smb_buf);
|
||||
|
||||
if(smb_buf->WordCount == 4) {
|
||||
if (smb_buf->WordCount == 4) {
|
||||
__u16 blob_len;
|
||||
blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
|
||||
bcc_ptr += blob_len;
|
||||
if(blob_len > bytes_remaining) {
|
||||
cERROR(1,("bad security blob length %d", blob_len));
|
||||
if (blob_len > bytes_remaining) {
|
||||
cERROR(1, ("bad security blob length %d", blob_len));
|
||||
rc = -EINVAL;
|
||||
goto ssetup_exit;
|
||||
}
|
||||
bytes_remaining -= blob_len;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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,
|
||||
ses, nls_cp);
|
||||
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:
|
||||
kfree(str_area);
|
||||
if(resp_buf_type == CIFS_SMALL_BUFFER) {
|
||||
cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
|
||||
if (resp_buf_type == CIFS_SMALL_BUFFER) {
|
||||
cFYI(1, ("ssetup freeing small buf %p", 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);
|
||||
|
||||
return rc;
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
/*
|
||||
/*
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 1.9.
|
||||
|
||||
a partial implementation of DES designed for use in the
|
||||
a partial implementation of DES designed for use in the
|
||||
SMB authentication protocol
|
||||
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
Modified by Steve French (sfrench@us.ibm.com) 2002,2004
|
||||
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* NOTES:
|
||||
/* NOTES:
|
||||
|
||||
This code makes no attempt to be fast! In fact, it is a very
|
||||
slow implementation
|
||||
slow implementation
|
||||
|
||||
This code is NOT a complete DES implementation. It implements only
|
||||
the minimum necessary for SMB authentication, as used by all SMB
|
||||
|
@ -153,7 +153,7 @@ static uchar sbox[8][4][16] = {
|
|||
};
|
||||
|
||||
static void
|
||||
permute(char *out, char *in, uchar * p, int n)
|
||||
permute(char *out, char *in, uchar *p, int n)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < n; i++)
|
||||
|
@ -202,18 +202,18 @@ dohash(char *out, char *in, char *key, int forw)
|
|||
char *rl;
|
||||
|
||||
/* Have to reduce stack usage */
|
||||
pk1 = kmalloc(56+56+64+64,GFP_KERNEL);
|
||||
if(pk1 == NULL)
|
||||
pk1 = kmalloc(56+56+64+64, GFP_KERNEL);
|
||||
if (pk1 == NULL)
|
||||
return;
|
||||
|
||||
ki = kmalloc(16*48, GFP_KERNEL);
|
||||
if(ki == NULL) {
|
||||
if (ki == NULL) {
|
||||
kfree(pk1);
|
||||
return;
|
||||
}
|
||||
|
||||
cd = pk1 + 56;
|
||||
pd1= cd + 56;
|
||||
pd1 = cd + 56;
|
||||
rl = pd1 + 64;
|
||||
|
||||
permute(pk1, key, perm1, 56);
|
||||
|
@ -247,7 +247,7 @@ dohash(char *out, char *in, char *key, int forw)
|
|||
char *r2; /* r2[32] */
|
||||
|
||||
er = kmalloc(48+48+32+32+32, GFP_KERNEL);
|
||||
if(er == NULL) {
|
||||
if (er == NULL) {
|
||||
kfree(pk1);
|
||||
kfree(ki);
|
||||
return;
|
||||
|
@ -327,8 +327,8 @@ smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
|
|||
char *keyb; /* keyb[64] */
|
||||
unsigned char key2[8];
|
||||
|
||||
outb = kmalloc(64 * 3,GFP_KERNEL);
|
||||
if(outb == NULL)
|
||||
outb = kmalloc(64 * 3, GFP_KERNEL);
|
||||
if (outb == NULL)
|
||||
return;
|
||||
|
||||
inb = outb + 64;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 1.9.
|
||||
SMB parameters and setup
|
||||
|
@ -7,17 +7,17 @@
|
|||
Modified by Jeremy Allison 1995.
|
||||
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
|
||||
Modified by Steve French (sfrench@us.ibm.com) 2002-2003
|
||||
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
@ -57,7 +57,7 @@ void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
|
|||
|
||||
/*
|
||||
This implements the X/Open SMB password encryption
|
||||
It takes a password, a 8 byte "crypt key" and puts 24 bytes of
|
||||
It takes a password, a 8 byte "crypt key" and puts 24 bytes of
|
||||
encrypted password into p24 */
|
||||
/* Note that password must be uppercased and null terminated */
|
||||
void
|
||||
|
@ -73,9 +73,9 @@ SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
|
|||
E_P16(p14, p21);
|
||||
|
||||
SMBOWFencrypt(p21, c8, p24);
|
||||
|
||||
memset(p14,0,15);
|
||||
memset(p21,0,21);
|
||||
|
||||
memset(p14, 0, 15);
|
||||
memset(p21, 0, 21);
|
||||
}
|
||||
|
||||
/* Routines for Windows NT MD4 Hash functions. */
|
||||
|
@ -90,14 +90,14 @@ _my_wcslen(__u16 * str)
|
|||
|
||||
/*
|
||||
* Convert a string into an NT UNICODE string.
|
||||
* Note that regardless of processor type
|
||||
* Note that regardless of processor type
|
||||
* this must be in intel (little-endian)
|
||||
* format.
|
||||
*/
|
||||
|
||||
static int
|
||||
_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;
|
||||
__u16 val;
|
||||
|
||||
|
@ -112,7 +112,7 @@ _my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
|
|||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Creates the MD4 Hash of the users password in NT UNICODE.
|
||||
*/
|
||||
|
||||
|
@ -123,7 +123,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16)
|
|||
__u16 wpwd[129];
|
||||
|
||||
/* Password cannot be longer than 128 characters */
|
||||
if(passwd) {
|
||||
if (passwd) {
|
||||
len = strlen((char *) passwd);
|
||||
if (len > 128) {
|
||||
len = 128;
|
||||
|
@ -138,7 +138,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16)
|
|||
len = _my_wcslen(wpwd) * sizeof (__u16);
|
||||
|
||||
mdfour(p16, (unsigned char *) wpwd, len);
|
||||
memset(wpwd,0,129 * 2);
|
||||
memset(wpwd, 0, 129 * 2);
|
||||
}
|
||||
|
||||
#if 0 /* currently unused */
|
||||
|
@ -178,17 +178,17 @@ ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
|
|||
const char *domain_n, unsigned char kr_buf[16],
|
||||
const struct nls_table *nls_codepage)
|
||||
{
|
||||
wchar_t * user_u;
|
||||
wchar_t * dom_u;
|
||||
wchar_t *user_u;
|
||||
wchar_t *dom_u;
|
||||
int user_l, domain_l;
|
||||
struct HMACMD5Context ctx;
|
||||
|
||||
/* might as well do one alloc to hold both (user_u and dom_u) */
|
||||
user_u = kmalloc(2048 * sizeof(wchar_t),GFP_KERNEL);
|
||||
if(user_u == NULL)
|
||||
user_u = kmalloc(2048 * sizeof(wchar_t), GFP_KERNEL);
|
||||
if (user_u == NULL)
|
||||
return;
|
||||
dom_u = user_u + 1024;
|
||||
|
||||
|
||||
/* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
|
||||
push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
|
||||
|
||||
|
@ -206,7 +206,7 @@ ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
|
|||
|
||||
kfree(user_u);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Does the des encryption from the NT or LM MD4 hash. */
|
||||
static void
|
||||
|
@ -256,15 +256,15 @@ SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
|
|||
#if 0
|
||||
static void
|
||||
SMBOWFencrypt_ntv2(const unsigned char kr[16],
|
||||
const struct data_blob * srv_chal,
|
||||
const struct data_blob * cli_chal, unsigned char resp_buf[16])
|
||||
const struct data_blob *srv_chal,
|
||||
const struct data_blob *cli_chal, unsigned char resp_buf[16])
|
||||
{
|
||||
struct HMACMD5Context ctx;
|
||||
struct HMACMD5Context ctx;
|
||||
|
||||
hmac_md5_init_limK_to_64(kr, 16, &ctx);
|
||||
hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
|
||||
hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
|
||||
hmac_md5_final(resp_buf, &ctx);
|
||||
hmac_md5_init_limK_to_64(kr, 16, &ctx);
|
||||
hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
|
||||
hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
|
||||
hmac_md5_final(resp_buf, &ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* Copyright (c) International Business Machines Corp., 2002,2004
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* See Error Codes section of the SNIA CIFS Specification
|
||||
* for more information
|
||||
* See Error Codes section of the SNIA CIFS Specification
|
||||
* for more information
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
|
@ -19,7 +19,7 @@
|
|||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define SUCCESS 0x00 /* The request was successful. */
|
||||
|
@ -110,7 +110,7 @@
|
|||
|
||||
/* Below errors are used internally (do not come over the wire) for passthrough
|
||||
from STATUS codes to POSIX only */
|
||||
#define ErrTooManyLinks 0xFFFE
|
||||
#define ErrTooManyLinks 0xFFFE
|
||||
|
||||
/* Following error codes may be generated with the ERRSRV error class.*/
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* 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)
|
||||
* Jeremy Allison (jra@samba.org) 2006.
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
|
@ -17,7 +17,7 @@
|
|||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
|
@ -32,7 +32,7 @@
|
|||
#include "cifsglob.h"
|
||||
#include "cifsproto.h"
|
||||
#include "cifs_debug.h"
|
||||
|
||||
|
||||
extern mempool_t *cifs_mid_poolp;
|
||||
extern struct kmem_cache *cifs_oplock_cachep;
|
||||
|
||||
|
@ -49,7 +49,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
|
|||
cERROR(1, ("Null TCP session in AllocMidQEntry"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,
|
||||
GFP_KERNEL | GFP_NOFS);
|
||||
if (temp == NULL)
|
||||
|
@ -86,7 +86,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
|
|||
list_del(&midEntry->qhead);
|
||||
atomic_dec(&midCount);
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
if(midEntry->largeBuf)
|
||||
if (midEntry->largeBuf)
|
||||
cifs_buf_release(midEntry->resp_buf);
|
||||
else
|
||||
cifs_small_buf_release(midEntry->resp_buf);
|
||||
|
@ -94,8 +94,8 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
|
|||
now = jiffies;
|
||||
/* commands taking longer than one second are indications that
|
||||
something is wrong, unless it is quite a slow link or server */
|
||||
if((now - midEntry->when_alloc) > HZ) {
|
||||
if((cifsFYI & CIFS_TIMER) &&
|
||||
if ((now - midEntry->when_alloc) > HZ) {
|
||||
if ((cifsFYI & CIFS_TIMER) &&
|
||||
(midEntry->command != SMB_COM_LOCKING_ANDX)) {
|
||||
printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
|
||||
midEntry->command, midEntry->mid);
|
||||
|
@ -110,10 +110,10 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
|
|||
}
|
||||
|
||||
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;
|
||||
if ((pinode== NULL) || (tcon == NULL)) {
|
||||
if ((pinode == NULL) || (tcon == NULL)) {
|
||||
cERROR(1, ("Null parms passed to AllocOplockQEntry"));
|
||||
return NULL;
|
||||
}
|
||||
|
@ -133,9 +133,9 @@ 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? */
|
||||
list_del(&oplockEntry->qhead);
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
|
@ -152,7 +152,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
|
|||
struct kvec iov;
|
||||
unsigned len = smb_buf_length + 4;
|
||||
|
||||
if(ssocket == NULL)
|
||||
if (ssocket == NULL)
|
||||
return -ENOTSOCK; /* BB eventually add reconnect code here */
|
||||
iov.iov_base = smb_buffer;
|
||||
iov.iov_len = len;
|
||||
|
@ -164,8 +164,8 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
|
|||
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
|
||||
|
||||
/* smb header is converted in header_assemble. bcc and rest of SMB word
|
||||
area, and byte area if necessary, is converted to littleendian in
|
||||
cifssmb.c and RFC1001 len is converted to bigendian in smb_send
|
||||
area, and byte area if necessary, is converted to littleendian in
|
||||
cifssmb.c and RFC1001 len is converted to bigendian in smb_send
|
||||
Flags2 is converted in SendReceive */
|
||||
|
||||
smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
|
||||
|
@ -177,9 +177,9 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
|
|||
if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
|
||||
i++;
|
||||
/* smaller timeout here than send2 since smaller size */
|
||||
/* Although it may not be required, this also is smaller
|
||||
oplock break time */
|
||||
if(i > 12) {
|
||||
/* Although it may not be required, this also is smaller
|
||||
oplock break time */
|
||||
if (i > 12) {
|
||||
cERROR(1,
|
||||
("sends on sock %p stuck for 7 seconds",
|
||||
ssocket));
|
||||
|
@ -189,7 +189,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
|
|||
msleep(1 << i);
|
||||
continue;
|
||||
}
|
||||
if (rc < 0)
|
||||
if (rc < 0)
|
||||
break;
|
||||
else
|
||||
i = 0; /* reset i after each successful send */
|
||||
|
@ -199,7 +199,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
|
|||
}
|
||||
|
||||
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 {
|
||||
rc = 0;
|
||||
}
|
||||
|
@ -223,8 +223,8 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
|
|||
unsigned int total_len;
|
||||
int first_vec = 0;
|
||||
unsigned int smb_buf_length = smb_buffer->smb_buf_length;
|
||||
|
||||
if(ssocket == NULL)
|
||||
|
||||
if (ssocket == NULL)
|
||||
return -ENOTSOCK; /* BB eventually add reconnect code here */
|
||||
|
||||
smb_msg.msg_name = sin;
|
||||
|
@ -234,8 +234,8 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
|
|||
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
|
||||
|
||||
/* smb header is converted in header_assemble. bcc and rest of SMB word
|
||||
area, and byte area if necessary, is converted to littleendian in
|
||||
cifssmb.c and RFC1001 len is converted to bigendian in smb_send
|
||||
area, and byte area if necessary, is converted to littleendian in
|
||||
cifssmb.c and RFC1001 len is converted to bigendian in smb_send
|
||||
Flags2 is converted in SendReceive */
|
||||
|
||||
|
||||
|
@ -252,7 +252,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
|
|||
n_vec - first_vec, total_len);
|
||||
if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
|
||||
i++;
|
||||
if(i >= 14) {
|
||||
if (i >= 14) {
|
||||
cERROR(1,
|
||||
("sends on sock %p stuck for 15 seconds",
|
||||
ssocket));
|
||||
|
@ -262,17 +262,17 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
|
|||
msleep(1 << i);
|
||||
continue;
|
||||
}
|
||||
if (rc < 0)
|
||||
if (rc < 0)
|
||||
break;
|
||||
|
||||
if (rc >= total_len) {
|
||||
WARN_ON(rc > total_len);
|
||||
break;
|
||||
}
|
||||
if(rc == 0) {
|
||||
if (rc == 0) {
|
||||
/* should never happen, letting socket clear before
|
||||
retrying is our only obvious option here */
|
||||
cERROR(1,("tcp sent no data"));
|
||||
cERROR(1, ("tcp sent no data"));
|
||||
msleep(500);
|
||||
continue;
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
|
|||
}
|
||||
|
||||
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
|
||||
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)
|
||||
{
|
||||
if(long_op == -1) {
|
||||
if (long_op == -1) {
|
||||
/* oplock breaks must not be held up */
|
||||
atomic_inc(&ses->server->inFlight);
|
||||
} else {
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
while(1) {
|
||||
if(atomic_read(&ses->server->inFlight) >=
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
while (1) {
|
||||
if (atomic_read(&ses->server->inFlight) >=
|
||||
cifs_max_pending){
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
|
@ -328,14 +328,14 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
|
|||
#endif
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
} else {
|
||||
if(ses->server->tcpStatus == CifsExiting) {
|
||||
if (ses->server->tcpStatus == CifsExiting) {
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* can not count locking commands against total since
|
||||
they are allowed to block on server */
|
||||
|
||||
/* can not count locking commands against total
|
||||
as they are allowed to block on server */
|
||||
|
||||
/* update # of requests on the wire to server */
|
||||
if (long_op < 3)
|
||||
atomic_inc(&ses->server->inFlight);
|
||||
|
@ -353,11 +353,11 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
|
|||
if (ses->server->tcpStatus == CifsExiting) {
|
||||
return -ENOENT;
|
||||
} 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;
|
||||
} else if (ses->status != CifsGood) {
|
||||
/* 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)) {
|
||||
return -EAGAIN;
|
||||
} /* else ok - we are setting up session */
|
||||
|
@ -369,7 +369,7 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int wait_for_response(struct cifsSesInfo *ses,
|
||||
static int wait_for_response(struct cifsSesInfo *ses,
|
||||
struct mid_q_entry *midQ,
|
||||
unsigned long timeout,
|
||||
unsigned long time_to_wait)
|
||||
|
@ -379,8 +379,8 @@ static int wait_for_response(struct cifsSesInfo *ses,
|
|||
for (;;) {
|
||||
curr_timeout = timeout + jiffies;
|
||||
wait_event(ses->server->response_q,
|
||||
(!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
|
||||
time_after(jiffies, curr_timeout) ||
|
||||
(!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
|
||||
time_after(jiffies, curr_timeout) ||
|
||||
((ses->server->tcpStatus != CifsGood) &&
|
||||
(ses->server->tcpStatus != CifsNew)));
|
||||
|
||||
|
@ -398,16 +398,16 @@ static int wait_for_response(struct cifsSesInfo *ses,
|
|||
spin_unlock(&GlobalMid_Lock);
|
||||
|
||||
/* Calculate time_to_wait past last receive time.
|
||||
Although we prefer not to time out if the
|
||||
Although we prefer not to time out if the
|
||||
server is still responding - we will time
|
||||
out if the server takes more than 15 (or 45
|
||||
out if the server takes more than 15 (or 45
|
||||
or 180) seconds to respond to this request
|
||||
and has not responded to any request from
|
||||
and has not responded to any request from
|
||||
other threads on the client within 10 seconds */
|
||||
lrt += time_to_wait;
|
||||
if (time_after(jiffies, lrt)) {
|
||||
/* No replies for time_to_wait. */
|
||||
cERROR(1,("server not responding"));
|
||||
cERROR(1, ("server not responding"));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
|
@ -417,8 +417,8 @@ static int wait_for_response(struct cifsSesInfo *ses,
|
|||
}
|
||||
|
||||
int
|
||||
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||
struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
|
||||
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||
struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
|
||||
const int long_op)
|
||||
{
|
||||
int rc = 0;
|
||||
|
@ -426,21 +426,21 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
unsigned long timeout;
|
||||
struct mid_q_entry *midQ;
|
||||
struct smb_hdr *in_buf = iov[0].iov_base;
|
||||
|
||||
|
||||
*pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
|
||||
|
||||
if ((ses == NULL) || (ses->server == NULL)) {
|
||||
cifs_small_buf_release(in_buf);
|
||||
cERROR(1,("Null session"));
|
||||
cERROR(1, ("Null session"));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if(ses->server->tcpStatus == CifsExiting) {
|
||||
if (ses->server->tcpStatus == CifsExiting) {
|
||||
cifs_small_buf_release(in_buf);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Ensure that we do not send more than 50 overlapping requests
|
||||
/* Ensure that we do not send more than 50 overlapping requests
|
||||
to the same server. We may make this configurable later or
|
||||
use ses->maxReq */
|
||||
|
||||
|
@ -450,23 +450,23 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* make sure that we sign in the same order that we send on this socket
|
||||
/* make sure that we sign in the same order that we send on this socket
|
||||
and avoid races inside tcp sendmsg code that could cause corruption
|
||||
of smb data */
|
||||
|
||||
down(&ses->server->tcpSem);
|
||||
down(&ses->server->tcpSem);
|
||||
|
||||
rc = allocate_mid(ses, in_buf, &midQ);
|
||||
if (rc) {
|
||||
up(&ses->server->tcpSem);
|
||||
cifs_small_buf_release(in_buf);
|
||||
/* Update # of requests on wire to server */
|
||||
atomic_dec(&ses->server->inFlight);
|
||||
atomic_dec(&ses->server->inFlight);
|
||||
wake_up(&ses->server->request_q);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
|
||||
rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
|
||||
|
||||
midQ->midState = MID_REQUEST_SUBMITTED;
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
|
@ -482,7 +482,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
up(&ses->server->tcpSem);
|
||||
cifs_small_buf_release(in_buf);
|
||||
|
||||
if(rc < 0)
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
if (long_op == -1)
|
||||
|
@ -490,18 +490,18 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
else if (long_op == 2) /* writes past end of file can take loong time */
|
||||
timeout = 180 * HZ;
|
||||
else if (long_op == 1)
|
||||
timeout = 45 * HZ; /* should be greater than
|
||||
timeout = 45 * HZ; /* should be greater than
|
||||
servers oplock break timeout (about 43 seconds) */
|
||||
else
|
||||
timeout = 15 * HZ;
|
||||
|
||||
/* wait for 15 seconds or until woken up due to response arriving or
|
||||
/* wait for 15 seconds or until woken up due to response arriving or
|
||||
due to last connection to this server being unmounted */
|
||||
if (signal_pending(current)) {
|
||||
/* if signal pending do not hold up user for full smb timeout
|
||||
but we still give response a chance to complete */
|
||||
timeout = 2 * HZ;
|
||||
}
|
||||
}
|
||||
|
||||
/* No user interrupts in wait - wreaks havoc with performance */
|
||||
wait_for_response(ses, midQ, timeout, 10 * HZ);
|
||||
|
@ -511,10 +511,10 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
spin_unlock(&GlobalMid_Lock);
|
||||
receive_len = midQ->resp_buf->smb_buf_length;
|
||||
} else {
|
||||
cERROR(1,("No response to cmd %d mid %d",
|
||||
cERROR(1, ("No response to cmd %d mid %d",
|
||||
midQ->command, midQ->mid));
|
||||
if(midQ->midState == MID_REQUEST_SUBMITTED) {
|
||||
if(ses->server->tcpStatus == CifsExiting)
|
||||
if (midQ->midState == MID_REQUEST_SUBMITTED) {
|
||||
if (ses->server->tcpStatus == CifsExiting)
|
||||
rc = -EHOSTDOWN;
|
||||
else {
|
||||
ses->server->tcpStatus = CifsNeedReconnect;
|
||||
|
@ -523,9 +523,9 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
}
|
||||
|
||||
if (rc != -EHOSTDOWN) {
|
||||
if(midQ->midState == MID_RETRY_NEEDED) {
|
||||
if (midQ->midState == MID_RETRY_NEEDED) {
|
||||
rc = -EAGAIN;
|
||||
cFYI(1,("marking request for retry"));
|
||||
cFYI(1, ("marking request for retry"));
|
||||
} else {
|
||||
rc = -EIO;
|
||||
}
|
||||
|
@ -533,21 +533,21 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
spin_unlock(&GlobalMid_Lock);
|
||||
DeleteMidQEntry(midQ);
|
||||
/* Update # of requests on wire to server */
|
||||
atomic_dec(&ses->server->inFlight);
|
||||
atomic_dec(&ses->server->inFlight);
|
||||
wake_up(&ses->server->request_q);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
|
||||
cERROR(1, ("Frame too large received. Length: %d Xid: %d",
|
||||
receive_len, xid));
|
||||
rc = -EIO;
|
||||
} else { /* rcvd frame is ok */
|
||||
if (midQ->resp_buf &&
|
||||
if (midQ->resp_buf &&
|
||||
(midQ->midState == MID_RESPONSE_RECEIVED)) {
|
||||
|
||||
iov[0].iov_base = (char *)midQ->resp_buf;
|
||||
if(midQ->largeBuf)
|
||||
if (midQ->largeBuf)
|
||||
*pRespBufType = CIFS_LARGE_BUFFER;
|
||||
else
|
||||
*pRespBufType = CIFS_SMALL_BUFFER;
|
||||
|
@ -555,14 +555,14 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
|
||||
dump_smb(midQ->resp_buf, 80);
|
||||
/* convert the length into a more usable form */
|
||||
if((receive_len > 24) &&
|
||||
if ((receive_len > 24) &&
|
||||
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
||||
SECMODE_SIGN_ENABLED))) {
|
||||
rc = cifs_verify_signature(midQ->resp_buf,
|
||||
ses->server->mac_signing_key,
|
||||
&ses->server->mac_signing_key,
|
||||
midQ->sequence_number+1);
|
||||
if(rc) {
|
||||
cERROR(1,("Unexpected SMB signature"));
|
||||
if (rc) {
|
||||
cERROR(1, ("Unexpected SMB signature"));
|
||||
/* BB FIXME add code to kill session */
|
||||
}
|
||||
}
|
||||
|
@ -576,19 +576,19 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
sizeof (struct smb_hdr) -
|
||||
4 /* do not count RFC1001 header */ +
|
||||
(2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
|
||||
BCC(midQ->resp_buf) =
|
||||
BCC(midQ->resp_buf) =
|
||||
le16_to_cpu(BCC_LE(midQ->resp_buf));
|
||||
midQ->resp_buf = NULL; /* mark it so will not be freed
|
||||
by DeleteMidQEntry */
|
||||
} else {
|
||||
rc = -EIO;
|
||||
cFYI(1,("Bad MID state?"));
|
||||
cFYI(1, ("Bad MID state?"));
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
DeleteMidQEntry(midQ);
|
||||
atomic_dec(&ses->server->inFlight);
|
||||
atomic_dec(&ses->server->inFlight);
|
||||
wake_up(&ses->server->request_q);
|
||||
|
||||
return rc;
|
||||
|
@ -605,18 +605,18 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
struct mid_q_entry *midQ;
|
||||
|
||||
if (ses == NULL) {
|
||||
cERROR(1,("Null smb session"));
|
||||
cERROR(1, ("Null smb session"));
|
||||
return -EIO;
|
||||
}
|
||||
if(ses->server == NULL) {
|
||||
cERROR(1,("Null tcp session"));
|
||||
if (ses->server == NULL) {
|
||||
cERROR(1, ("Null tcp session"));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if(ses->server->tcpStatus == CifsExiting)
|
||||
if (ses->server->tcpStatus == CifsExiting)
|
||||
return -ENOENT;
|
||||
|
||||
/* Ensure that we do not send more than 50 overlapping requests
|
||||
/* Ensure that we do not send more than 50 overlapping requests
|
||||
to the same server. We may make this configurable later or
|
||||
use ses->maxReq */
|
||||
|
||||
|
@ -624,17 +624,17 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* make sure that we sign in the same order that we send on this socket
|
||||
/* make sure that we sign in the same order that we send on this socket
|
||||
and avoid races inside tcp sendmsg code that could cause corruption
|
||||
of smb data */
|
||||
|
||||
down(&ses->server->tcpSem);
|
||||
down(&ses->server->tcpSem);
|
||||
|
||||
rc = allocate_mid(ses, in_buf, &midQ);
|
||||
if (rc) {
|
||||
up(&ses->server->tcpSem);
|
||||
/* Update # of requests on wire to server */
|
||||
atomic_dec(&ses->server->inFlight);
|
||||
atomic_dec(&ses->server->inFlight);
|
||||
wake_up(&ses->server->request_q);
|
||||
return rc;
|
||||
}
|
||||
|
@ -645,7 +645,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
DeleteMidQEntry(midQ);
|
||||
up(&ses->server->tcpSem);
|
||||
/* Update # of requests on wire to server */
|
||||
atomic_dec(&ses->server->inFlight);
|
||||
atomic_dec(&ses->server->inFlight);
|
||||
wake_up(&ses->server->request_q);
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -664,7 +664,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
#endif
|
||||
up(&ses->server->tcpSem);
|
||||
|
||||
if(rc < 0)
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
if (long_op == -1)
|
||||
|
@ -672,17 +672,17 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
else if (long_op == 2) /* writes past end of file can take loong time */
|
||||
timeout = 180 * HZ;
|
||||
else if (long_op == 1)
|
||||
timeout = 45 * HZ; /* should be greater than
|
||||
timeout = 45 * HZ; /* should be greater than
|
||||
servers oplock break timeout (about 43 seconds) */
|
||||
else
|
||||
timeout = 15 * HZ;
|
||||
/* wait for 15 seconds or until woken up due to response arriving or
|
||||
/* wait for 15 seconds or until woken up due to response arriving or
|
||||
due to last connection to this server being unmounted */
|
||||
if (signal_pending(current)) {
|
||||
/* if signal pending do not hold up user for full smb timeout
|
||||
but we still give response a chance to complete */
|
||||
timeout = 2 * HZ;
|
||||
}
|
||||
}
|
||||
|
||||
/* No user interrupts in wait - wreaks havoc with performance */
|
||||
wait_for_response(ses, midQ, timeout, 10 * HZ);
|
||||
|
@ -692,10 +692,10 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
spin_unlock(&GlobalMid_Lock);
|
||||
receive_len = midQ->resp_buf->smb_buf_length;
|
||||
} else {
|
||||
cERROR(1,("No response for cmd %d mid %d",
|
||||
cERROR(1, ("No response for cmd %d mid %d",
|
||||
midQ->command, midQ->mid));
|
||||
if(midQ->midState == MID_REQUEST_SUBMITTED) {
|
||||
if(ses->server->tcpStatus == CifsExiting)
|
||||
if (midQ->midState == MID_REQUEST_SUBMITTED) {
|
||||
if (ses->server->tcpStatus == CifsExiting)
|
||||
rc = -EHOSTDOWN;
|
||||
else {
|
||||
ses->server->tcpStatus = CifsNeedReconnect;
|
||||
|
@ -704,9 +704,9 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
}
|
||||
|
||||
if (rc != -EHOSTDOWN) {
|
||||
if(midQ->midState == MID_RETRY_NEEDED) {
|
||||
if (midQ->midState == MID_RETRY_NEEDED) {
|
||||
rc = -EAGAIN;
|
||||
cFYI(1,("marking request for retry"));
|
||||
cFYI(1, ("marking request for retry"));
|
||||
} else {
|
||||
rc = -EIO;
|
||||
}
|
||||
|
@ -714,11 +714,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
spin_unlock(&GlobalMid_Lock);
|
||||
DeleteMidQEntry(midQ);
|
||||
/* Update # of requests on wire to server */
|
||||
atomic_dec(&ses->server->inFlight);
|
||||
atomic_dec(&ses->server->inFlight);
|
||||
wake_up(&ses->server->request_q);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
|
||||
cERROR(1, ("Frame too large received. Length: %d Xid: %d",
|
||||
receive_len, xid));
|
||||
|
@ -734,14 +734,14 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
|
||||
dump_smb(out_buf, 92);
|
||||
/* convert the length into a more usable form */
|
||||
if((receive_len > 24) &&
|
||||
if ((receive_len > 24) &&
|
||||
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
||||
SECMODE_SIGN_ENABLED))) {
|
||||
rc = cifs_verify_signature(out_buf,
|
||||
ses->server->mac_signing_key,
|
||||
&ses->server->mac_signing_key,
|
||||
midQ->sequence_number+1);
|
||||
if(rc) {
|
||||
cERROR(1,("Unexpected SMB signature"));
|
||||
if (rc) {
|
||||
cERROR(1, ("Unexpected SMB signature"));
|
||||
/* BB FIXME add code to kill session */
|
||||
}
|
||||
}
|
||||
|
@ -759,13 +759,13 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
|
||||
} else {
|
||||
rc = -EIO;
|
||||
cERROR(1,("Bad MID state?"));
|
||||
cERROR(1, ("Bad MID state?"));
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
DeleteMidQEntry(midQ);
|
||||
atomic_dec(&ses->server->inFlight);
|
||||
atomic_dec(&ses->server->inFlight);
|
||||
wake_up(&ses->server->request_q);
|
||||
|
||||
return rc;
|
||||
|
@ -783,7 +783,7 @@ send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
|
|||
|
||||
header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
|
||||
in_buf->Mid = mid;
|
||||
down(&ses->server->tcpSem);
|
||||
down(&ses->server->tcpSem);
|
||||
rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
|
||||
if (rc) {
|
||||
up(&ses->server->tcpSem);
|
||||
|
@ -832,20 +832,20 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
|||
struct cifsSesInfo *ses;
|
||||
|
||||
if (tcon == NULL || tcon->ses == NULL) {
|
||||
cERROR(1,("Null smb session"));
|
||||
cERROR(1, ("Null smb session"));
|
||||
return -EIO;
|
||||
}
|
||||
ses = tcon->ses;
|
||||
|
||||
if(ses->server == NULL) {
|
||||
cERROR(1,("Null tcp session"));
|
||||
if (ses->server == NULL) {
|
||||
cERROR(1, ("Null tcp session"));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if(ses->server->tcpStatus == CifsExiting)
|
||||
if (ses->server->tcpStatus == CifsExiting)
|
||||
return -ENOENT;
|
||||
|
||||
/* Ensure that we do not send more than 50 overlapping requests
|
||||
/* Ensure that we do not send more than 50 overlapping requests
|
||||
to the same server. We may make this configurable later or
|
||||
use ses->maxReq */
|
||||
|
||||
|
@ -853,11 +853,11 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* make sure that we sign in the same order that we send on this socket
|
||||
/* make sure that we sign in the same order that we send on this socket
|
||||
and avoid races inside tcp sendmsg code that could cause corruption
|
||||
of smb data */
|
||||
|
||||
down(&ses->server->tcpSem);
|
||||
down(&ses->server->tcpSem);
|
||||
|
||||
rc = allocate_mid(ses, in_buf, &midQ);
|
||||
if (rc) {
|
||||
|
@ -887,14 +887,14 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
|||
#endif
|
||||
up(&ses->server->tcpSem);
|
||||
|
||||
if(rc < 0) {
|
||||
if (rc < 0) {
|
||||
DeleteMidQEntry(midQ);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Wait for a reply - allow signals to interrupt. */
|
||||
rc = wait_event_interruptible(ses->server->response_q,
|
||||
(!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
|
||||
(!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
|
||||
((ses->server->tcpStatus != CifsGood) &&
|
||||
(ses->server->tcpStatus != CifsNew)));
|
||||
|
||||
|
@ -928,7 +928,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
|||
}
|
||||
|
||||
/* 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. */
|
||||
rstart = 1;
|
||||
}
|
||||
|
@ -939,10 +939,10 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
|||
spin_unlock(&GlobalMid_Lock);
|
||||
receive_len = midQ->resp_buf->smb_buf_length;
|
||||
} else {
|
||||
cERROR(1,("No response for cmd %d mid %d",
|
||||
cERROR(1, ("No response for cmd %d mid %d",
|
||||
midQ->command, midQ->mid));
|
||||
if(midQ->midState == MID_REQUEST_SUBMITTED) {
|
||||
if(ses->server->tcpStatus == CifsExiting)
|
||||
if (midQ->midState == MID_REQUEST_SUBMITTED) {
|
||||
if (ses->server->tcpStatus == CifsExiting)
|
||||
rc = -EHOSTDOWN;
|
||||
else {
|
||||
ses->server->tcpStatus = CifsNeedReconnect;
|
||||
|
@ -951,9 +951,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
|||
}
|
||||
|
||||
if (rc != -EHOSTDOWN) {
|
||||
if(midQ->midState == MID_RETRY_NEEDED) {
|
||||
if (midQ->midState == MID_RETRY_NEEDED) {
|
||||
rc = -EAGAIN;
|
||||
cFYI(1,("marking request for retry"));
|
||||
cFYI(1, ("marking request for retry"));
|
||||
} else {
|
||||
rc = -EIO;
|
||||
}
|
||||
|
@ -962,7 +962,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
|||
DeleteMidQEntry(midQ);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
|
||||
cERROR(1, ("Frame too large received. Length: %d Xid: %d",
|
||||
receive_len, xid));
|
||||
|
@ -978,14 +978,14 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
|||
|
||||
dump_smb(out_buf, 92);
|
||||
/* convert the length into a more usable form */
|
||||
if((receive_len > 24) &&
|
||||
if ((receive_len > 24) &&
|
||||
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
||||
SECMODE_SIGN_ENABLED))) {
|
||||
rc = cifs_verify_signature(out_buf,
|
||||
ses->server->mac_signing_key,
|
||||
&ses->server->mac_signing_key,
|
||||
midQ->sequence_number+1);
|
||||
if(rc) {
|
||||
cERROR(1,("Unexpected SMB signature"));
|
||||
if (rc) {
|
||||
cERROR(1, ("Unexpected SMB signature"));
|
||||
/* 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));
|
||||
} else {
|
||||
rc = -EIO;
|
||||
cERROR(1,("Bad MID state?"));
|
||||
cERROR(1, ("Bad MID state?"));
|
||||
}
|
||||
}
|
||||
DeleteMidQEntry(midQ);
|
||||
|
|
229
fs/cifs/xattr.c
229
fs/cifs/xattr.c
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
|
@ -37,50 +37,52 @@
|
|||
#define XATTR_TRUSTED_PREFIX_LEN 8
|
||||
#define XATTR_SECURITY_PREFIX_LEN 9
|
||||
/* BB need to add server (Samba e.g) support for security and trusted prefix */
|
||||
|
||||
|
||||
|
||||
int cifs_removexattr(struct dentry * direntry, const char * ea_name)
|
||||
|
||||
int cifs_removexattr(struct dentry *direntry, const char *ea_name)
|
||||
{
|
||||
int rc = -EOPNOTSUPP;
|
||||
#ifdef CONFIG_CIFS_XATTR
|
||||
int xid;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
struct super_block * sb;
|
||||
char * full_path;
|
||||
|
||||
if(direntry == NULL)
|
||||
struct super_block *sb;
|
||||
char *full_path;
|
||||
|
||||
if (direntry == NULL)
|
||||
return -EIO;
|
||||
if(direntry->d_inode == NULL)
|
||||
if (direntry->d_inode == NULL)
|
||||
return -EIO;
|
||||
sb = direntry->d_inode->i_sb;
|
||||
if(sb == NULL)
|
||||
if (sb == NULL)
|
||||
return -EIO;
|
||||
xid = GetXid();
|
||||
|
||||
|
||||
cifs_sb = CIFS_SB(sb);
|
||||
pTcon = cifs_sb->tcon;
|
||||
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if(full_path == NULL) {
|
||||
if (full_path == NULL) {
|
||||
FreeXid(xid);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if(ea_name == NULL) {
|
||||
cFYI(1,("Null xattr names not supported"));
|
||||
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)
|
||||
&& (strncmp(ea_name,CIFS_XATTR_OS2_PREFIX,4))) {
|
||||
cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
|
||||
if (ea_name == NULL) {
|
||||
cFYI(1, ("Null xattr names not supported"));
|
||||
} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5)
|
||||
&& (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4))) {
|
||||
cFYI(1,
|
||||
("illegal xattr request %s (only user namespace supported)",
|
||||
ea_name));
|
||||
/* BB what if no namespace prefix? */
|
||||
/* Should we just pass them to server, except for
|
||||
system and perhaps security prefixes? */
|
||||
} 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;
|
||||
|
||||
ea_name+=5; /* skip past user. prefix */
|
||||
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL,
|
||||
ea_name += 5; /* skip past user. prefix */
|
||||
rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL,
|
||||
(__u16)0, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
}
|
||||
|
@ -91,23 +93,23 @@ remove_ea_exit:
|
|||
return rc;
|
||||
}
|
||||
|
||||
int cifs_setxattr(struct dentry * direntry, const char * ea_name,
|
||||
const void * ea_value, size_t value_size, int flags)
|
||||
int cifs_setxattr(struct dentry *direntry, const char *ea_name,
|
||||
const void *ea_value, size_t value_size, int flags)
|
||||
{
|
||||
int rc = -EOPNOTSUPP;
|
||||
#ifdef CONFIG_CIFS_XATTR
|
||||
int xid;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
struct super_block * sb;
|
||||
char * full_path;
|
||||
struct super_block *sb;
|
||||
char *full_path;
|
||||
|
||||
if(direntry == NULL)
|
||||
if (direntry == NULL)
|
||||
return -EIO;
|
||||
if(direntry->d_inode == NULL)
|
||||
if (direntry->d_inode == NULL)
|
||||
return -EIO;
|
||||
sb = direntry->d_inode->i_sb;
|
||||
if(sb == NULL)
|
||||
if (sb == NULL)
|
||||
return -EIO;
|
||||
xid = GetXid();
|
||||
|
||||
|
@ -115,7 +117,7 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
|
|||
pTcon = cifs_sb->tcon;
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if(full_path == NULL) {
|
||||
if (full_path == NULL) {
|
||||
FreeXid(xid);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -123,67 +125,69 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
|
|||
/* return alt name if available as pseudo attr */
|
||||
|
||||
/* 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 */
|
||||
if(value_size > MAX_EA_VALUE_SIZE) {
|
||||
cFYI(1,("size of EA value too large"));
|
||||
if (value_size > MAX_EA_VALUE_SIZE) {
|
||||
cFYI(1, ("size of EA value too large"));
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if(ea_name == NULL) {
|
||||
cFYI(1,("Null xattr names not supported"));
|
||||
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||
if (ea_name == NULL) {
|
||||
cFYI(1, ("Null xattr names not supported"));
|
||||
} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||
goto set_ea_exit;
|
||||
if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
|
||||
cFYI(1,("attempt to set cifs inode metadata"));
|
||||
if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) {
|
||||
cFYI(1, ("attempt to set cifs inode metadata"));
|
||||
}
|
||||
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,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||
} else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||
goto set_ea_exit;
|
||||
|
||||
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,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
} else {
|
||||
int temp;
|
||||
temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
|
||||
int temp;
|
||||
temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
|
||||
strlen(POSIX_ACL_XATTR_ACCESS));
|
||||
if (temp == 0) {
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
if(sb->s_flags & MS_POSIXACL)
|
||||
rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
|
||||
ea_value, (const int)value_size,
|
||||
ACL_TYPE_ACCESS,cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
if (sb->s_flags & MS_POSIXACL)
|
||||
rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
|
||||
ea_value, (const int)value_size,
|
||||
ACL_TYPE_ACCESS, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
cFYI(1,("set POSIX ACL rc %d",rc));
|
||||
cFYI(1, ("set POSIX ACL rc %d", rc));
|
||||
#else
|
||||
cFYI(1,("set POSIX ACL not supported"));
|
||||
cFYI(1, ("set POSIX ACL not supported"));
|
||||
#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
|
||||
if(sb->s_flags & MS_POSIXACL)
|
||||
rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
|
||||
ea_value, (const int)value_size,
|
||||
if (sb->s_flags & MS_POSIXACL)
|
||||
rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
|
||||
ea_value, (const int)value_size,
|
||||
ACL_TYPE_DEFAULT, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
cFYI(1,("set POSIX default ACL rc %d",rc));
|
||||
cFYI(1, ("set POSIX default ACL rc %d", rc));
|
||||
#else
|
||||
cFYI(1,("set default POSIX ACL not supported"));
|
||||
cFYI(1, ("set default POSIX ACL not supported"));
|
||||
#endif
|
||||
} 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? */
|
||||
/* Should we just pass them to server, except for
|
||||
/* Should we just pass them to server, except for
|
||||
system and perhaps security prefixes? */
|
||||
}
|
||||
}
|
||||
|
@ -195,23 +199,23 @@ set_ea_exit:
|
|||
return rc;
|
||||
}
|
||||
|
||||
ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
|
||||
void * ea_value, size_t buf_size)
|
||||
ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
|
||||
void *ea_value, size_t buf_size)
|
||||
{
|
||||
ssize_t rc = -EOPNOTSUPP;
|
||||
#ifdef CONFIG_CIFS_XATTR
|
||||
int xid;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
struct super_block * sb;
|
||||
char * full_path;
|
||||
struct super_block *sb;
|
||||
char *full_path;
|
||||
|
||||
if(direntry == NULL)
|
||||
if (direntry == NULL)
|
||||
return -EIO;
|
||||
if(direntry->d_inode == NULL)
|
||||
if (direntry->d_inode == NULL)
|
||||
return -EIO;
|
||||
sb = direntry->d_inode->i_sb;
|
||||
if(sb == NULL)
|
||||
if (sb == NULL)
|
||||
return -EIO;
|
||||
|
||||
xid = GetXid();
|
||||
|
@ -220,42 +224,42 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
|
|||
pTcon = cifs_sb->tcon;
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if(full_path == NULL) {
|
||||
if (full_path == NULL) {
|
||||
FreeXid(xid);
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* return dos attributes as pseudo xattr */
|
||||
/* return alt name if available as pseudo attr */
|
||||
if(ea_name == NULL) {
|
||||
cFYI(1,("Null xattr names not supported"));
|
||||
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||
if (ea_name == NULL) {
|
||||
cFYI(1, ("Null xattr names not supported"));
|
||||
} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||
goto get_ea_exit;
|
||||
|
||||
if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
|
||||
cFYI(1,("attempt to query cifs inode metadata"));
|
||||
if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) {
|
||||
cFYI(1, ("attempt to query cifs inode metadata"));
|
||||
/* revalidate/getattr then populate from inode */
|
||||
} /* BB add else when above is implemented */
|
||||
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,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||
} else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||
goto get_ea_exit;
|
||||
|
||||
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,
|
||||
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) {
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
if(sb->s_flags & MS_POSIXACL)
|
||||
if (sb->s_flags & MS_POSIXACL)
|
||||
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->mnt_cifs_flags &
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
/* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
|
||||
__u16 fid;
|
||||
|
@ -272,39 +276,40 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
|
|||
CIFSSMBClose(xid, pTcon, fid);
|
||||
}
|
||||
} */ /* BB enable after fixing up return data */
|
||||
|
||||
#else
|
||||
cFYI(1,("query POSIX ACL not supported yet"));
|
||||
#else
|
||||
cFYI(1, ("query POSIX ACL not supported yet"));
|
||||
#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) {
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
if(sb->s_flags & MS_POSIXACL)
|
||||
if (sb->s_flags & MS_POSIXACL)
|
||||
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->mnt_cifs_flags &
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
#else
|
||||
cFYI(1,("query POSIX default ACL not supported yet"));
|
||||
#else
|
||||
cFYI(1, ("query POSIX default ACL not supported yet"));
|
||||
#endif
|
||||
} else if(strncmp(ea_name,
|
||||
CIFS_XATTR_TRUSTED_PREFIX,XATTR_TRUSTED_PREFIX_LEN) == 0) {
|
||||
cFYI(1,("Trusted xattr namespace not supported yet"));
|
||||
} else if(strncmp(ea_name,
|
||||
CIFS_XATTR_SECURITY_PREFIX,XATTR_SECURITY_PREFIX_LEN) == 0) {
|
||||
cFYI(1,("Security xattr namespace not supported yet"));
|
||||
} else if (strncmp(ea_name,
|
||||
CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) {
|
||||
cFYI(1, ("Trusted xattr namespace not supported yet"));
|
||||
} else if (strncmp(ea_name,
|
||||
CIFS_XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) {
|
||||
cFYI(1, ("Security xattr namespace not supported yet"));
|
||||
} 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
|
||||
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 */
|
||||
|
||||
if(rc == -EINVAL)
|
||||
rc = -EOPNOTSUPP;
|
||||
if (rc == -EINVAL)
|
||||
rc = -EOPNOTSUPP;
|
||||
|
||||
get_ea_exit:
|
||||
kfree(full_path);
|
||||
|
@ -313,34 +318,34 @@ get_ea_exit:
|
|||
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;
|
||||
#ifdef CONFIG_CIFS_XATTR
|
||||
int xid;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
struct super_block * sb;
|
||||
char * full_path;
|
||||
struct super_block *sb;
|
||||
char *full_path;
|
||||
|
||||
if(direntry == NULL)
|
||||
if (direntry == NULL)
|
||||
return -EIO;
|
||||
if(direntry->d_inode == NULL)
|
||||
if (direntry->d_inode == NULL)
|
||||
return -EIO;
|
||||
sb = direntry->d_inode->i_sb;
|
||||
if(sb == NULL)
|
||||
if (sb == NULL)
|
||||
return -EIO;
|
||||
|
||||
cifs_sb = CIFS_SB(sb);
|
||||
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;
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if(full_path == NULL) {
|
||||
if (full_path == NULL) {
|
||||
FreeXid(xid);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -348,11 +353,11 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
|
|||
/* return alt name if available as pseudo attr */
|
||||
|
||||
/* 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 */
|
||||
rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size,
|
||||
rc = CIFSSMBQAllEAs(xid, pTcon, full_path, data, buf_size,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
|
||||
kfree(full_path);
|
||||
|
|
Загрузка…
Ссылка в новой задаче