Commit 789c56b7 authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 7209a1dc 1ff8392c
Version 1.50
------------
Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is
done with "serverino" mount option). Add support for POSIX Unlink
(helps with certain sharing violation cases when server such as
Samba supports newer POSIX CIFS Protocol Extensions).
Version 1.49 Version 1.49
------------ ------------
IPv6 support. Enable ipv6 addresses to be passed on mount (put the ipv6 IPv6 support. Enable ipv6 addresses to be passed on mount (put the ipv6
...@@ -8,7 +15,11 @@ when Unix Extensions were ignored). This allows users to override the ...@@ -8,7 +15,11 @@ when Unix Extensions were ignored). This allows users to override the
default uid and gid for files when they are certain that the uids or default uid and gid for files when they are certain that the uids or
gids on the server do not match those of the client. Make "sec=none" gids on the server do not match those of the client. Make "sec=none"
mount override username (so that null user connection is attempted) mount override username (so that null user connection is attempted)
to match what documentation said. to match what documentation said. Support for very large reads, over 127K,
available to some newer servers (such as Samba 3.0.26 and later but
note that it also requires setting CIFSMaxBufSize at module install
time to a larger value which may hurt performance in some cases).
Make sign option force signing (or fail if server does not support it).
Version 1.48 Version 1.48
------------ ------------
......
...@@ -301,10 +301,21 @@ A partial list of the supported mount options follows: ...@@ -301,10 +301,21 @@ A partial list of the supported mount options follows:
during the local client kernel build will be used. during the local client kernel build will be used.
If server does not support Unicode, this parameter is If server does not support Unicode, this parameter is
unused. unused.
rsize default read size (usually 16K) rsize default read size (usually 16K). The client currently
wsize default write size (usually 16K, 32K is often better over GigE) can not use rsize larger than CIFSMaxBufSize. CIFSMaxBufSize
maximum wsize currently allowed by CIFS is 57344 (14 4096 byte defaults to 16K and may be changed (from 8K to the maximum
pages) kmalloc size allowed by your kernel) at module install time
for cifs.ko. Setting CIFSMaxBufSize to a very large value
will cause cifs to use more memory and may reduce performance
in some cases. To use rsize greater than 127K (the original
cifs protocol maximum) also requires that the server support
a new Unix Capability flag (for very large read) which some
newer servers (e.g. Samba 3.0.26 or later) do. rsize can be
set from a minimum of 2048 to a maximum of 130048 (127K or
CIFSMaxBufSize, whichever is smaller)
wsize default write size (default 57344)
maximum wsize currently allowed by CIFS is 57344 (fourteen
4096 byte pages)
rw mount the network share read-write (note that the rw mount the network share read-write (note that the
server may still consider the share read-only) server may still consider the share read-only)
ro mount network share read-only ro mount network share read-only
...@@ -359,7 +370,7 @@ A partial list of the supported mount options follows: ...@@ -359,7 +370,7 @@ A partial list of the supported mount options follows:
Note that this does not affect the normal ACL check on the Note that this does not affect the normal ACL check on the
target machine done by the server software (of the server target machine done by the server software (of the server
ACL against the user name provided at mount time). ACL against the user name provided at mount time).
serverino Use servers inode numbers instead of generating automatically serverino Use server's inode numbers instead of generating automatically
incrementing inode numbers on the client. Although this will incrementing inode numbers on the client. Although this will
make it easier to spot hardlinked files (as they will have make it easier to spot hardlinked files (as they will have
the same inode numbers) and inode numbers may be persistent, the same inode numbers) and inode numbers may be persistent,
...@@ -367,12 +378,11 @@ A partial list of the supported mount options follows: ...@@ -367,12 +378,11 @@ A partial list of the supported mount options follows:
are unique if multiple server side mounts are exported under a are unique if multiple server side mounts are exported under a
single share (since inode numbers on the servers might not single share (since inode numbers on the servers might not
be unique if multiple filesystems are mounted under the same be unique if multiple filesystems are mounted under the same
shared higher level directory). Note that this requires that shared higher level directory). Note that some older
the server support the CIFS Unix Extensions as other servers (e.g. pre-Windows 2000) do not support returning UniqueIDs
do not return a unique IndexNumber on SMB FindFirst (most or the CIFS Unix Extensions equivalent and for those
servers return zero as the IndexNumber). Parameter has no this mount option will have no effect. Exporting cifs mounts
effect to Windows servers and others which do not support the under nfsd requires this mount option on the cifs mount.
CIFS Unix Extensions.
noserverino Client generates inode numbers (rather than using the actual one noserverino Client generates inode numbers (rather than using the actual one
from the server) by default. from the server) by default.
setuids If the CIFS Unix extensions are negotiated with the server setuids If the CIFS Unix extensions are negotiated with the server
...@@ -582,10 +592,10 @@ the start of smb requests and responses can be enabled via: ...@@ -582,10 +592,10 @@ the start of smb requests and responses can be enabled via:
echo 1 > /proc/fs/cifs/traceSMB echo 1 > /proc/fs/cifs/traceSMB
Two other experimental features are under development and to test Two other experimental features are under development. To test these
require enabling CONFIG_CIFS_EXPERIMENTAL requires enabling CONFIG_CIFS_EXPERIMENTAL
More efficient write operations ipv6 enablement
DNOTIFY fcntl: needed for support of directory change DNOTIFY fcntl: needed for support of directory change
notification and perhaps later for file leases) notification and perhaps later for file leases)
......
...@@ -18,9 +18,9 @@ better) ...@@ -18,9 +18,9 @@ better)
d) Kerberos/SPNEGO session setup support - (started) d) Kerberos/SPNEGO session setup support - (started)
e) More testing of NTLMv2 authentication (mostly implemented - double check e) Cleanup now unneeded SessSetup code in
that NTLMv2 signing works, also need to cleanup now unneeded SessSetup code in fs/cifs/connect.c and add back in NTLMSSP code if any servers
fs/cifs/connect.c) need it
f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
...@@ -106,6 +106,12 @@ but recognizes them ...@@ -106,6 +106,12 @@ but recognizes them
succeed but still return access denied (appears to be Windows succeed but still return access denied (appears to be Windows
server not cifs client problem) and has not been reproduced recently. server not cifs client problem) and has not been reproduced recently.
NTFS partitions do not have this problem. NTFS partitions do not have this problem.
4) Unix/POSIX capabilities are reset after reconnection, and affect
a few fields in the tree connection but we do do not know which
superblocks to apply these changes to. We should probably walk
the list of superblocks to set these. Also need to check the
flags on the second mount to the same share, and see if we
can do the same trick that NFS does to remount duplicate shares.
Misc testing to do Misc testing to do
================== ==================
......
/* /*
* The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in * 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 * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
* *
* Copyright (c) 2000 RP Internet (www.rpi.net.au). * Copyright (c) 2000 RP Internet (www.rpi.net.au).
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 }; 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 }; static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
/* /*
* ASN.1 context. * ASN.1 context.
*/ */
struct asn1_ctx { struct asn1_ctx {
...@@ -190,7 +190,7 @@ asn1_header_decode(struct asn1_ctx *ctx, ...@@ -190,7 +190,7 @@ asn1_header_decode(struct asn1_ctx *ctx,
unsigned char **eoc, unsigned char **eoc,
unsigned int *cls, unsigned int *con, unsigned int *tag) unsigned int *cls, unsigned int *con, unsigned int *tag)
{ {
unsigned int def = 0; unsigned int def = 0;
unsigned int len = 0; unsigned int len = 0;
if (!asn1_id_decode(ctx, cls, con, tag)) if (!asn1_id_decode(ctx, cls, con, tag))
...@@ -331,7 +331,7 @@ static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx, ...@@ -331,7 +331,7 @@ static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
*integer |= ch; *integer |= ch;
} }
return 1; return 1;
} }
static unsigned char static unsigned char
asn1_octets_decode(struct asn1_ctx *ctx, asn1_octets_decode(struct asn1_ctx *ctx,
...@@ -376,7 +376,7 @@ asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid) ...@@ -376,7 +376,7 @@ asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
return 1; return 1;
} }
static int static int
asn1_oid_decode(struct asn1_ctx *ctx, asn1_oid_decode(struct asn1_ctx *ctx,
unsigned char *eoc, unsigned long **oid, unsigned int *len) unsigned char *eoc, unsigned long **oid, unsigned int *len)
{ {
...@@ -459,7 +459,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -459,7 +459,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
unsigned int cls, con, tag, oidlen, rc; unsigned int cls, con, tag, oidlen, rc;
int use_ntlmssp = FALSE; int use_ntlmssp = FALSE;
*secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */ *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/
/* cifs_dump_mem(" Received SecBlob ", security_blob, length); */ /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
...@@ -498,7 +498,8 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -498,7 +498,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
return 0; return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON) } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|| (tag != ASN1_EOC)) { || (tag != ASN1_EOC)) {
cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0", cFYI(1,
("cls = %d con = %d tag = %d end = %p (%d) exit 0",
cls, con, tag, end, *end)); cls, con, tag, end, *end));
return 0; return 0;
} }
...@@ -508,7 +509,8 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -508,7 +509,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
return 0; return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON) } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) { || (tag != ASN1_SEQ)) {
cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1", cFYI(1,
("cls = %d con = %d tag = %d end = %p (%d) exit 1",
cls, con, tag, end, *end)); cls, con, tag, end, *end));
return 0; return 0;
} }
...@@ -540,32 +542,34 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -540,32 +542,34 @@ decode_negTokenInit(unsigned char *security_blob, int length,
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
if (!rc) { if (!rc) {
cFYI(1, cFYI(1,
("Error 1 decoding negTokenInit header exit 2")); ("Error decoding negTokenInit hdr exit2"));
return 0; return 0;
} }
if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
rc = asn1_oid_decode(&ctx, end, &oid, &oidlen); rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
if(rc) { if (rc) {
cFYI(1, cFYI(1,
("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx", ("OID len = %d oid = 0x%lx 0x%lx "
oidlen, *oid, *(oid + 1), *(oid + 2), "0x%lx 0x%lx",
*(oid + 3))); oidlen, *oid, *(oid + 1),
rc = compare_oid(oid, oidlen, NTLMSSP_OID, *(oid + 2), *(oid + 3)));
NTLMSSP_OID_LEN); rc = compare_oid(oid, oidlen,
NTLMSSP_OID, NTLMSSP_OID_LEN);
kfree(oid); kfree(oid);
if (rc) if (rc)
use_ntlmssp = TRUE; use_ntlmssp = TRUE;
} }
} else { } else {
cFYI(1,("This should be an oid what is going on? ")); cFYI(1, ("Should be an oid what is going on?"));
} }
} }
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, cFYI(1,
("Error decoding last part of negTokenInit exit 3")); ("Error decoding last part negTokenInit exit3"));
return 0; return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */ } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
/* tag = 3 indicating mechListMIC */
cFYI(1, cFYI(1,
("Exit 4 cls = %d con = %d tag = %d end = %p (%d)", ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end)); cls, con, tag, end, *end));
...@@ -573,7 +577,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -573,7 +577,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
} }
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, cFYI(1,
("Error decoding last part of negTokenInit exit 5")); ("Error decoding last part negTokenInit exit5"));
return 0; return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON) } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) { || (tag != ASN1_SEQ)) {
...@@ -584,7 +588,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -584,7 +588,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, cFYI(1,
("Error decoding last part of negTokenInit exit 7")); ("Error decoding last part negTokenInit exit 7"));
return 0; return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
cFYI(1, cFYI(1,
...@@ -594,20 +598,21 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -594,20 +598,21 @@ decode_negTokenInit(unsigned char *security_blob, int length,
} }
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, cFYI(1,
("Error decoding last part of negTokenInit exit 9")); ("Error decoding last part negTokenInit exit9"));
return 0; return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_PRI) } else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
|| (tag != ASN1_GENSTR)) { || (tag != ASN1_GENSTR)) {
cFYI(1, cFYI(1,
("Exit 10 cls = %d con = %d tag = %d end = %p (%d)", ("Exit10 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end)); cls, con, tag, end, *end));
return 0; return 0;
} }
cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */ cFYI(1, ("Need to call asn1_octets_decode() function for %s",
ctx.pointer)); /* is this UTF-8 or ASCII? */
} }
/* if (use_kerberos) /* if (use_kerberos)
*secType = Kerberos *secType = Kerberos
else */ else */
if (use_ntlmssp) { if (use_ntlmssp) {
*secType = NTLMSSP; *secType = NTLMSSP;
......
...@@ -58,7 +58,7 @@ cifs_dump_mem(char *label, void *data, int length) ...@@ -58,7 +58,7 @@ cifs_dump_mem(char *label, void *data, int length)
} }
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
void cifs_dump_detail(struct smb_hdr * smb) void cifs_dump_detail(struct smb_hdr *smb)
{ {
cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
smb->Command, smb->Status.CifsError, smb->Command, smb->Status.CifsError,
...@@ -67,10 +67,10 @@ void cifs_dump_detail(struct smb_hdr * smb) ...@@ -67,10 +67,10 @@ void cifs_dump_detail(struct smb_hdr * smb)
} }
void cifs_dump_mids(struct TCP_Server_Info * server) void cifs_dump_mids(struct TCP_Server_Info *server)
{ {
struct list_head *tmp; struct list_head *tmp;
struct mid_q_entry * mid_entry; struct mid_q_entry *mid_entry;
if (server == NULL) if (server == NULL)
return; return;
...@@ -114,12 +114,12 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -114,12 +114,12 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
{ {
struct list_head *tmp; struct list_head *tmp;
struct list_head *tmp1; struct list_head *tmp1;
struct mid_q_entry * mid_entry; struct mid_q_entry *mid_entry;
struct cifsSesInfo *ses; struct cifsSesInfo *ses;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
int i; int i;
int length = 0; int length = 0;
char * original_buf = buf; char *original_buf = buf;
*beginBuffer = buf + offset; *beginBuffer = buf + offset;
...@@ -145,7 +145,6 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -145,7 +145,6 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
(ses->serverNOS == NULL)) { (ses->serverNOS == NULL)) {
buf += sprintf(buf, "\nentry for %s not fully " buf += sprintf(buf, "\nentry for %s not fully "
"displayed\n\t", ses->serverName); "displayed\n\t", ses->serverName);
} else { } else {
length = length =
sprintf(buf, sprintf(buf,
...@@ -901,90 +900,14 @@ security_flags_write(struct file *file, const char __user *buffer, ...@@ -901,90 +900,14 @@ security_flags_write(struct file *file, const char __user *buffer,
} }
/* flags look ok - update the global security flags for cifs module */ /* flags look ok - update the global security flags for cifs module */
extended_security = flags; extended_security = flags;
if (extended_security & CIFSSEC_MUST_SIGN) {
/* requiring signing implies signing is allowed */
extended_security |= CIFSSEC_MAY_SIGN;
cFYI(1, ("packet signing now required"));
} else if ((extended_security & CIFSSEC_MAY_SIGN) == 0) {
cFYI(1, ("packet signing disabled"));
}
/* BB should we turn on MAY flags for other MUST options? */
return count; return count;
} }
/* static int
ntlmv2_enabled_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
len = sprintf(page, "%d\n", ntlmv2_support);
len -= off;
*start = page + off;
if (len > count)
len = count;
else
*eof = 1;
if (len < 0)
len = 0;
return len;
}
static int
ntlmv2_enabled_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char c;
int rc;
rc = get_user(c, buffer);
if (rc)
return rc;
if (c == '0' || c == 'n' || c == 'N')
ntlmv2_support = 0;
else if (c == '1' || c == 'y' || c == 'Y')
ntlmv2_support = 1;
else if (c == '2')
ntlmv2_support = 2;
return count;
}
static int
packet_signing_enabled_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
len = sprintf(page, "%d\n", sign_CIFS_PDUs);
len -= off;
*start = page + off;
if (len > count)
len = count;
else
*eof = 1;
if (len < 0)
len = 0;
return len;
}
static int
packet_signing_enabled_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char c;
int rc;
rc = get_user(c, buffer);
if (rc)
return rc;
if (c == '0' || c == 'n' || c == 'N')
sign_CIFS_PDUs = 0;
else if (c == '1' || c == 'y' || c == 'Y')
sign_CIFS_PDUs = 1;
else if (c == '2')
sign_CIFS_PDUs = 2;
return count;
} */
#endif #endif
...@@ -43,6 +43,6 @@ struct cifs_sb_info { ...@@ -43,6 +43,6 @@ struct cifs_sb_info {
mode_t mnt_dir_mode; mode_t mnt_dir_mode;
int mnt_cifs_flags; int mnt_cifs_flags;
int prepathlen; int prepathlen;
char * prepath; char *prepath;
}; };
#endif /* _CIFS_FS_SB_H */ #endif /* _CIFS_FS_SB_H */
...@@ -66,7 +66,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len, ...@@ -66,7 +66,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len,
{ {
int charlen; int charlen;
int i; int i;
wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */ wchar_t *wchar_to = (wchar_t *)to; /* needed to quiet sparse */
for (i = 0; len && *from; i++, from += charlen, len -= charlen) { for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
......
...@@ -5,20 +5,20 @@ ...@@ -5,20 +5,20 @@
* Convert a unicode character to upper or lower case using * Convert a unicode character to upper or lower case using
* compressed tables. * compressed tables.
* *
* Copyright (c) International Business Machines Corp., 2000,2005555555555555555555555555555555555555555555555555555555 * Copyright (c) International Business Machines Corp., 2000,2007
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* 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. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details. * the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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 * 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 *); ...@@ -70,7 +70,7 @@ int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
* Address of the first string * Address of the first string
*/ */
static inline wchar_t * static inline wchar_t *
UniStrcat(wchar_t * ucs1, const wchar_t * ucs2) UniStrcat(wchar_t *ucs1, const wchar_t *ucs2)
{ {
wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */ wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
...@@ -88,7 +88,7 @@ UniStrcat(wchar_t * ucs1, const wchar_t * ucs2) ...@@ -88,7 +88,7 @@ UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
* or NULL if the character is not in the string * or NULL if the character is not in the string
*/ */
static inline wchar_t * static inline wchar_t *
UniStrchr(const wchar_t * ucs, wchar_t uc) UniStrchr(const wchar_t *ucs, wchar_t uc)
{ {
while ((*ucs != uc) && *ucs) while ((*ucs != uc) && *ucs)
ucs++; ucs++;
...@@ -107,7 +107,7 @@ UniStrchr(const wchar_t * ucs, wchar_t uc) ...@@ -107,7 +107,7 @@ UniStrchr(const wchar_t * ucs, wchar_t uc)
* > 0: First string is greater than second * > 0: First string is greater than second
*/ */
static inline int static inline int
UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2) UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2)
{ {
while ((*ucs1 == *ucs2) && *ucs1) { while ((*ucs1 == *ucs2) && *ucs1) {
ucs1++; ucs1++;
...@@ -120,7 +120,7 @@ UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2) ...@@ -120,7 +120,7 @@ UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
* UniStrcpy: Copy a string * UniStrcpy: Copy a string
*/ */
static inline wchar_t * static inline wchar_t *
UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2) UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)
{ {
wchar_t *anchor = ucs1; /* save the start of result string */ wchar_t *anchor = ucs1; /* save the start of result string */
...@@ -132,7 +132,7 @@ UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2) ...@@ -132,7 +132,7 @@ UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2)
* UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes) * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
*/ */
static inline size_t static inline size_t
UniStrlen(const wchar_t * ucs1) UniStrlen(const wchar_t *ucs1)
{ {
int i = 0; int i = 0;
...@@ -142,10 +142,11 @@ UniStrlen(const wchar_t * ucs1) ...@@ -142,10 +142,11 @@ UniStrlen(const wchar_t * ucs1)
} }
/* /*
* UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a string (length limited) * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a
* string (length limited)
*/ */
static inline size_t static inline size_t
UniStrnlen(const wchar_t * ucs1, int maxlen) UniStrnlen(const wchar_t *ucs1, int maxlen)
{ {
int i = 0; int i = 0;
...@@ -161,7 +162,7 @@ UniStrnlen(const wchar_t * ucs1, int maxlen) ...@@ -161,7 +162,7 @@ UniStrnlen(const wchar_t * ucs1, int maxlen)
* UniStrncat: Concatenate length limited string * UniStrncat: Concatenate length limited string
*/ */
static inline wchar_t * static inline wchar_t *
UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n) UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
{ {
wchar_t *anchor = ucs1; /* save pointer to string 1 */ wchar_t *anchor = ucs1; /* save pointer to string 1 */
...@@ -179,7 +180,7 @@ UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n) ...@@ -179,7 +180,7 @@ UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
* UniStrncmp: Compare length limited string * UniStrncmp: Compare length limited string
*/ */
static inline int static inline int
UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n) UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
{ {
if (!n) if (!n)
return 0; /* Null strings are equal */ return 0; /* Null strings are equal */
...@@ -194,7 +195,7 @@ UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n) ...@@ -194,7 +195,7 @@ UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
* UniStrncmp_le: Compare length limited string - native to little-endian * UniStrncmp_le: Compare length limited string - native to little-endian
*/ */
static inline int static inline int
UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n) UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
{ {
if (!n) if (!n)
return 0; /* Null strings are equal */ return 0; /* Null strings are equal */
...@@ -209,7 +210,7 @@ UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n) ...@@ -209,7 +210,7 @@ UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
* UniStrncpy: Copy length limited string with pad * UniStrncpy: Copy length limited string with pad
*/ */
static inline wchar_t * static inline wchar_t *
UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n) UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
{ {
wchar_t *anchor = ucs1; wchar_t *anchor = ucs1;
...@@ -226,7 +227,7 @@ UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n) ...@@ -226,7 +227,7 @@ UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
* UniStrncpy_le: Copy length limited string with pad to little-endian * UniStrncpy_le: Copy length limited string with pad to little-endian
*/ */
static inline wchar_t * static inline wchar_t *
UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n) UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
{ {
wchar_t *anchor = ucs1; wchar_t *anchor = ucs1;
...@@ -247,7 +248,7 @@ UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n) ...@@ -247,7 +248,7 @@ UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
* NULL if no matching string is found * NULL if no matching string is found
*/ */
static inline wchar_t * static inline wchar_t *
UniStrstr(const wchar_t * ucs1, const wchar_t * ucs2) UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)
{ {
const wchar_t *anchor1 = ucs1; const wchar_t *anchor1 = ucs1;
const wchar_t *anchor2 = ucs2; const wchar_t *anchor2 = ucs2;
...@@ -297,7 +298,7 @@ UniToupper(register wchar_t uc) ...@@ -297,7 +298,7 @@ UniToupper(register wchar_t uc)
* UniStrupr: Upper case a unicode string * UniStrupr: Upper case a unicode string
*/ */
static inline wchar_t * static inline wchar_t *
UniStrupr(register wchar_t * upin) UniStrupr(register wchar_t *upin)
{ {
register wchar_t *up; register wchar_t *up;
...@@ -338,7 +339,7 @@ UniTolower(wchar_t uc) ...@@ -338,7 +339,7 @@ UniTolower(wchar_t uc)
* UniStrlwr: Lower case a unicode string * UniStrlwr: Lower case a unicode string
*/ */
static inline wchar_t * static inline wchar_t *
UniStrlwr(register wchar_t * upin) UniStrlwr(register wchar_t *upin)
{ {
register wchar_t *up; register wchar_t *up;
......
...@@ -3,16 +3,16 @@ ...@@ -3,16 +3,16 @@
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details. * the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
* uniupr.h - Unicode compressed case ranges * uniupr.h - Unicode compressed case ranges
...@@ -53,7 +53,7 @@ signed char CifsUniUpperTable[512] = { ...@@ -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 */ 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 */ -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 */ 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, -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 */ 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
}; };
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include "cifspdu.h" #include "cifspdu.h"
#include "cifsglob.h" #include "cifsglob.h"
#include "cifs_debug.h" #include "cifs_debug.h"
#include "md5.h" #include "md5.h"
#include "cifs_unicode.h" #include "cifs_unicode.h"
...@@ -29,54 +29,57 @@ ...@@ -29,54 +29,57 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/random.h> #include <linux/random.h>
/* Calculate and return the CIFS signature based on the mac key and the smb pdu */ /* Calculate and return the CIFS signature based on the mac key and SMB PDU */
/* the 16 byte signature must be allocated by the caller */ /* the 16 byte signature must be allocated by the caller */
/* Note we only use the 1st eight bytes */ /* Note we only use the 1st eight bytes */
/* Note that the smb header signature field on input contains the /* Note that the smb header signature field on input contains the
sequence number before this function is called */ sequence number before this function is called */
extern void mdfour(unsigned char *out, unsigned char *in, int n); extern void mdfour(unsigned char *out, unsigned char *in, int n);
extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
unsigned char *p24); unsigned char *p24);
static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
const char * key, char * signature) const struct mac_key *key, char *signature)
{ {
struct MD5Context context; struct MD5Context context;
if((cifs_pdu == NULL) || (signature == NULL)) if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL))
return -EINVAL; return -EINVAL;
MD5Init(&context); MD5Init(&context);
MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16); MD5Update(&context, (char *)&key->data, key->len);
MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); MD5Update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
MD5Final(signature,&context);
MD5Final(signature, &context);
return 0; return 0;
} }
int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server, int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
__u32 * pexpected_response_sequence_number) __u32 *pexpected_response_sequence_number)
{ {
int rc = 0; int rc = 0;
char smb_signature[20]; char smb_signature[20];
if((cifs_pdu == NULL) || (server == NULL)) if ((cifs_pdu == NULL) || (server == NULL))
return -EINVAL; return -EINVAL;
if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
return rc; return rc;
spin_lock(&GlobalMid_Lock); 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; cifs_pdu->Signature.Sequence.Reserved = 0;
*pexpected_response_sequence_number = server->sequence_number++; *pexpected_response_sequence_number = server->sequence_number++;
server->sequence_number++; server->sequence_number++;
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
rc = cifs_calculate_signature(cifs_pdu, server->mac_signing_key,smb_signature); rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key,
if(rc) smb_signature);
if (rc)
memset(cifs_pdu->Signature.SecuritySignature, 0, 8); memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
else else
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8); memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
...@@ -84,115 +87,119 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server, ...@@ -84,115 +87,119 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
return rc; return rc;
} }
static int cifs_calc_signature2(const struct kvec * iov, int n_vec, static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
const char * key, char * signature) const struct mac_key *key, char *signature)
{ {
struct MD5Context context; struct MD5Context context;
int i; int i;
if((iov == NULL) || (signature == NULL)) if ((iov == NULL) || (signature == NULL) || (key == NULL))
return -EINVAL; return -EINVAL;
MD5Init(&context); MD5Init(&context);
MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16); MD5Update(&context, (char *)&key->data, key->len);
for(i=0;i<n_vec;i++) { for (i = 0; i < n_vec; i++) {
if(iov[i].iov_base == NULL) { if (iov[i].iov_base == NULL) {
cERROR(1,("null iovec entry")); cERROR(1, ("null iovec entry"));
return -EIO; 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 */ 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 */ 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 */ if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
break; /* nothing to sign or corrupt header */ 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 } 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; 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) __u32 * pexpected_response_sequence_number)
{ {
int rc = 0; int rc = 0;
char smb_signature[20]; 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; return -EINVAL;
if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
return rc; return rc;
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
cifs_pdu->Signature.Sequence.SequenceNumber = cifs_pdu->Signature.Sequence.SequenceNumber =
cpu_to_le32(server->sequence_number); 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++; *pexpected_response_sequence_number = server->sequence_number++;
server->sequence_number++; server->sequence_number++;
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
rc = cifs_calc_signature2(iov, n_vec, server->mac_signing_key, rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key,
smb_signature); smb_signature);
if(rc) if (rc)
memset(cifs_pdu->Signature.SecuritySignature, 0, 8); memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
else else
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8); memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
return rc;
return rc;
} }
int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key, int cifs_verify_signature(struct smb_hdr *cifs_pdu,
__u32 expected_sequence_number) const struct mac_key *mac_key,
__u32 expected_sequence_number)
{ {
unsigned int rc; unsigned int rc;
char server_response_sig[8]; char server_response_sig[8];
char what_we_think_sig_should_be[20]; char what_we_think_sig_should_be[20];
if((cifs_pdu == NULL) || (mac_key == NULL)) if ((cifs_pdu == NULL) || (mac_key == NULL))
return -EINVAL; return -EINVAL;
if (cifs_pdu->Command == SMB_COM_NEGOTIATE) if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
return 0; return 0;
if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) { if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu; struct smb_com_lock_req *pSMB =
if(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE) (struct smb_com_lock_req *)cifs_pdu;
if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
return 0; return 0;
} }
/* BB what if signatures are supposed to be on for session but server does not /* BB what if signatures are supposed to be on for session but
send one? BB */ server does not send one? BB */
/* Do not need to verify session setups with signature "BSRSPYL " */ /* Do not need to verify session setups with signature "BSRSPYL " */
if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0) if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command)); cFYI(1, ("dummy signature received for smb command 0x%x",
cifs_pdu->Command));
/* save off the origiginal signature so we can modify the smb and check /* save off the origiginal signature so we can modify the smb and check
its signature against what the server sent */ its signature against what the server sent */
memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8); memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8);
cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(expected_sequence_number); cifs_pdu->Signature.Sequence.SequenceNumber =
cpu_to_le32(expected_sequence_number);
cifs_pdu->Signature.Sequence.Reserved = 0; cifs_pdu->Signature.Sequence.Reserved = 0;
rc = cifs_calculate_signature(cifs_pdu, mac_key, rc = cifs_calculate_signature(cifs_pdu, mac_key,
what_we_think_sig_should_be); what_we_think_sig_should_be);
if(rc) if (rc)
return rc; return rc;
/* cifs_dump_mem("what we think it should be: ",
/* cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */ what_we_think_sig_should_be, 16); */
if(memcmp(server_response_sig, what_we_think_sig_should_be, 8)) if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
return -EACCES; return -EACCES;
else else
return 0; return 0;
...@@ -200,89 +207,94 @@ int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key, ...@@ -200,89 +207,94 @@ int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
} }
/* We fill in key by putting in 40 byte array which was allocated by caller */ /* We fill in key by putting in 40 byte array which was allocated by caller */
int cifs_calculate_mac_key(char * key, const char * rn, const char * password) int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
const char *password)
{ {
char temp_key[16]; char temp_key[16];
if ((key == NULL) || (rn == NULL)) if ((key == NULL) || (rn == NULL))
return -EINVAL; return -EINVAL;
E_md4hash(password, temp_key); E_md4hash(password, temp_key);
mdfour(key,temp_key,16); mdfour(key->data.ntlm, temp_key, 16);
memcpy(key+16,rn, CIFS_SESS_KEY_SIZE); memcpy(key->data.ntlm+16, rn, CIFS_SESS_KEY_SIZE);
key->len = 40;
return 0; return 0;
} }
int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *ses,
const struct nls_table * nls_info) const struct nls_table *nls_info)
{ {
char temp_hash[16]; char temp_hash[16];
struct HMACMD5Context ctx; struct HMACMD5Context ctx;
char * ucase_buf; char *ucase_buf;
__le16 * unicode_buf; __le16 *unicode_buf;
unsigned int i,user_name_len,dom_name_len; unsigned int i, user_name_len, dom_name_len;
if(ses == NULL) if (ses == NULL)
return -EINVAL; return -EINVAL;
E_md4hash(ses->password, temp_hash); E_md4hash(ses->password, temp_hash);
hmac_md5_init_limK_to_64(temp_hash, 16, &ctx); hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
user_name_len = strlen(ses->userName); user_name_len = strlen(ses->userName);
if(user_name_len > MAX_USERNAME_SIZE) if (user_name_len > MAX_USERNAME_SIZE)
return -EINVAL; return -EINVAL;
if(ses->domainName == NULL) if (ses->domainName == NULL)
return -EINVAL; /* BB should we use CIFS_LINUX_DOM */ return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
dom_name_len = strlen(ses->domainName); dom_name_len = strlen(ses->domainName);
if(dom_name_len > MAX_USERNAME_SIZE) if (dom_name_len > MAX_USERNAME_SIZE)
return -EINVAL; return -EINVAL;
ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL); ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
if(ucase_buf == NULL) if (ucase_buf == NULL)
return -ENOMEM; return -ENOMEM;
unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL); unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
if(unicode_buf == NULL) { if (unicode_buf == NULL) {
kfree(ucase_buf); kfree(ucase_buf);
return -ENOMEM; return -ENOMEM;
} }
for(i=0;i<user_name_len;i++) for (i = 0; i < user_name_len; i++)
ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]]; ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
ucase_buf[i] = 0; ucase_buf[i] = 0;
user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info); user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf,
MAX_USERNAME_SIZE*2, nls_info);
unicode_buf[user_name_len] = 0; unicode_buf[user_name_len] = 0;
user_name_len++; user_name_len++;
for(i=0;i<dom_name_len;i++) for (i = 0; i < dom_name_len; i++)
ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]]; ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
ucase_buf[i] = 0; ucase_buf[i] = 0;
dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info); dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf,
MAX_USERNAME_SIZE*2, nls_info);
unicode_buf[user_name_len + dom_name_len] = 0; unicode_buf[user_name_len + dom_name_len] = 0;
hmac_md5_update((const unsigned char *) unicode_buf, hmac_md5_update((const unsigned char *) unicode_buf,
(user_name_len+dom_name_len)*2,&ctx); (user_name_len+dom_name_len)*2, &ctx);
hmac_md5_final(ses->server->mac_signing_key,&ctx); hmac_md5_final(ses->server->ntlmv2_hash, &ctx);
kfree(ucase_buf); kfree(ucase_buf);
kfree(unicode_buf); kfree(unicode_buf);
return 0; return 0;
} }
#ifdef CONFIG_CIFS_WEAK_PW_HASH #ifdef CONFIG_CIFS_WEAK_PW_HASH
void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key) void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key)
{ {
int i; int i;
char password_with_pad[CIFS_ENCPWD_SIZE]; char password_with_pad[CIFS_ENCPWD_SIZE];
if(ses->server == NULL) if (ses->server == NULL)
return; return;
memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
if(ses->password) if (ses->password)
strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE); strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0) if ((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
if(extended_security & CIFSSEC_MAY_PLNTXT) { if (extended_security & CIFSSEC_MAY_PLNTXT) {
memcpy(lnm_session_key, password_with_pad, CIFS_ENCPWD_SIZE); memcpy(lnm_session_key, password_with_pad,
CIFS_ENCPWD_SIZE);
return; return;
} }
...@@ -297,7 +309,7 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key) ...@@ -297,7 +309,7 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
utf8 and other multibyte codepages each need their own strupper utf8 and other multibyte codepages each need their own strupper
function since a byte at a time will ont work. */ function since a byte at a time will ont work. */
for(i = 0; i < CIFS_ENCPWD_SIZE; i++) { for (i = 0; i < CIFS_ENCPWD_SIZE; i++) {
password_with_pad[i] = toupper(password_with_pad[i]); password_with_pad[i] = toupper(password_with_pad[i]);
} }
...@@ -307,19 +319,19 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key) ...@@ -307,19 +319,19 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
} }
#endif /* CIFS_WEAK_PW_HASH */ #endif /* CIFS_WEAK_PW_HASH */
static int calc_ntlmv2_hash(struct cifsSesInfo *ses, static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
const struct nls_table * nls_cp) const struct nls_table *nls_cp)
{ {
int rc = 0; int rc = 0;
int len; int len;
char nt_hash[16]; char nt_hash[16];
struct HMACMD5Context * pctxt; struct HMACMD5Context *pctxt;
wchar_t * user; wchar_t *user;
wchar_t * domain; wchar_t *domain;
pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL); pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
if(pctxt == NULL) if (pctxt == NULL)
return -ENOMEM; return -ENOMEM;
/* calculate md4 hash of password */ /* calculate md4 hash of password */
...@@ -331,41 +343,45 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, ...@@ -331,41 +343,45 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
/* convert ses->userName to unicode and uppercase */ /* convert ses->userName to unicode and uppercase */
len = strlen(ses->userName); len = strlen(ses->userName);
user = kmalloc(2 + (len * 2), GFP_KERNEL); user = kmalloc(2 + (len * 2), GFP_KERNEL);
if(user == NULL) if (user == NULL)
goto calc_exit_2; goto calc_exit_2;
len = cifs_strtoUCS(user, ses->userName, len, nls_cp); len = cifs_strtoUCS(user, ses->userName, len, nls_cp);
UniStrupr(user); UniStrupr(user);
hmac_md5_update((char *)user, 2*len, pctxt); hmac_md5_update((char *)user, 2*len, pctxt);
/* convert ses->domainName to unicode and uppercase */ /* convert ses->domainName to unicode and uppercase */
if(ses->domainName) { if (ses->domainName) {
len = strlen(ses->domainName); len = strlen(ses->domainName);
domain = kmalloc(2 + (len * 2), GFP_KERNEL); domain = kmalloc(2 + (len * 2), GFP_KERNEL);
if(domain == NULL) if (domain == NULL)
goto calc_exit_1; goto calc_exit_1;
len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp); len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
UniStrupr(domain); /* the following line was removed since it didn't work well
with lower cased domain name that passed as an option.
Maybe converting the domain name earlier makes sense */
/* UniStrupr(domain); */
hmac_md5_update((char *)domain, 2*len, pctxt); hmac_md5_update((char *)domain, 2*len, pctxt);
kfree(domain); kfree(domain);
} }
calc_exit_1: calc_exit_1:
kfree(user); kfree(user);
calc_exit_2: calc_exit_2:
/* BB FIXME what about bytes 24 through 40 of the signing key? /* BB FIXME what about bytes 24 through 40 of the signing key?
compare with the NTLM example */ compare with the NTLM example */
hmac_md5_final(ses->server->mac_signing_key, pctxt); hmac_md5_final(ses->server->ntlmv2_hash, pctxt);
return rc; return rc;
} }
void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf, void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
const struct nls_table * nls_cp) const struct nls_table *nls_cp)
{ {
int rc; int rc;
struct ntlmv2_resp * buf = (struct ntlmv2_resp *)resp_buf; struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf;
struct HMACMD5Context context;
buf->blob_signature = cpu_to_le32(0x00000101); buf->blob_signature = cpu_to_le32(0x00000101);
buf->reserved = 0; buf->reserved = 0;
...@@ -379,21 +395,31 @@ void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf, ...@@ -379,21 +395,31 @@ void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
/* calculate buf->ntlmv2_hash */ /* calculate buf->ntlmv2_hash */
rc = calc_ntlmv2_hash(ses, nls_cp); rc = calc_ntlmv2_hash(ses, nls_cp);
if(rc) if (rc)
cERROR(1,("could not get v2 hash rc %d",rc)); cERROR(1, ("could not get v2 hash rc %d", rc));
CalcNTLMv2_response(ses, resp_buf); CalcNTLMv2_response(ses, resp_buf);
/* now calculate the MAC key for NTLMv2 */
hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
hmac_md5_update(resp_buf, 16, &context);
hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context);
memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf,
sizeof(struct ntlmv2_resp));
ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp);
} }
void CalcNTLMv2_response(const struct cifsSesInfo * ses, char * v2_session_response) void CalcNTLMv2_response(const struct cifsSesInfo *ses,
char *v2_session_response)
{ {
struct HMACMD5Context context; struct HMACMD5Context context;
/* rest of v2 struct already generated */ /* rest of v2 struct already generated */
memcpy(v2_session_response + 8, ses->server->cryptKey,8); memcpy(v2_session_response + 8, ses->server->cryptKey, 8);
hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context); hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
hmac_md5_update(v2_session_response+8, hmac_md5_update(v2_session_response+8,
sizeof(struct ntlmv2_resp) - 8, &context); sizeof(struct ntlmv2_resp) - 8, &context);
hmac_md5_final(v2_session_response,&context); hmac_md5_final(v2_session_response, &context);
/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */ /* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
} }
...@@ -64,23 +64,27 @@ unsigned int multiuser_mount = 0; ...@@ -64,23 +64,27 @@ unsigned int multiuser_mount = 0;
unsigned int extended_security = CIFSSEC_DEF; unsigned int extended_security = CIFSSEC_DEF;
/* unsigned int ntlmv2_support = 0; */ /* unsigned int ntlmv2_support = 0; */
unsigned int sign_CIFS_PDUs = 1; unsigned int sign_CIFS_PDUs = 1;
extern struct task_struct * oplockThread; /* remove sparse warning */ extern struct task_struct *oplockThread; /* remove sparse warning */
struct task_struct * oplockThread = NULL; struct task_struct *oplockThread = NULL;
/* extern struct task_struct * dnotifyThread; remove sparse warning */ /* extern struct task_struct * dnotifyThread; remove sparse warning */
static struct task_struct * dnotifyThread = NULL; static struct task_struct *dnotifyThread = NULL;
static const struct super_operations cifs_super_ops; static const struct super_operations cifs_super_ops;
unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
module_param(CIFSMaxBufSize, int, 0); module_param(CIFSMaxBufSize, int, 0);
MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048"); MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header). "
"Default: 16384 Range: 8192 to 130048");
unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL; unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
module_param(cifs_min_rcv, int, 0); module_param(cifs_min_rcv, int, 0);
MODULE_PARM_DESC(cifs_min_rcv,"Network buffers in pool. Default: 4 Range: 1 to 64"); MODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: "
"1 to 64");
unsigned int cifs_min_small = 30; unsigned int cifs_min_small = 30;
module_param(cifs_min_small, int, 0); module_param(cifs_min_small, int, 0);
MODULE_PARM_DESC(cifs_min_small,"Small network buffers in pool. Default: 30 Range: 2 to 256"); MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
"Range: 2 to 256");
unsigned int cifs_max_pending = CIFS_MAX_REQ; unsigned int cifs_max_pending = CIFS_MAX_REQ;
module_param(cifs_max_pending, int, 0); module_param(cifs_max_pending, int, 0);
MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256"); MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. "
"Default: 50 Range: 2 to 256");
extern mempool_t *cifs_sm_req_poolp; extern mempool_t *cifs_sm_req_poolp;
extern mempool_t *cifs_req_poolp; extern mempool_t *cifs_req_poolp;
...@@ -95,10 +99,10 @@ cifs_read_super(struct super_block *sb, void *data, ...@@ -95,10 +99,10 @@ cifs_read_super(struct super_block *sb, void *data,
struct inode *inode; struct inode *inode;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
int rc = 0; int rc = 0;
/* BB should we make this contingent on mount parm? */ /* BB should we make this contingent on mount parm? */
sb->s_flags |= MS_NODIRATIME | MS_NOATIME; sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);
cifs_sb = CIFS_SB(sb); cifs_sb = CIFS_SB(sb);
if (cifs_sb == NULL) if (cifs_sb == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -114,12 +118,9 @@ cifs_read_super(struct super_block *sb, void *data, ...@@ -114,12 +118,9 @@ cifs_read_super(struct super_block *sb, void *data,
sb->s_magic = CIFS_MAGIC_NUMBER; sb->s_magic = CIFS_MAGIC_NUMBER;
sb->s_op = &cifs_super_ops; sb->s_op = &cifs_super_ops;
#ifdef CONFIG_CIFS_EXPERIMENTAL
if (experimEnabled != 0)
sb->s_export_op = &cifs_export_ops;
#endif /* EXPERIMENTAL */
/* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512) /* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */ sb->s_blocksize =
cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
#ifdef CONFIG_CIFS_QUOTA #ifdef CONFIG_CIFS_QUOTA
sb->s_qcop = &cifs_quotactl_ops; sb->s_qcop = &cifs_quotactl_ops;
#endif #endif
...@@ -139,6 +140,13 @@ cifs_read_super(struct super_block *sb, void *data, ...@@ -139,6 +140,13 @@ cifs_read_super(struct super_block *sb, void *data,
goto out_no_root; goto out_no_root;
} }
#ifdef CONFIG_CIFS_EXPERIMENTAL
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
cFYI(1, ("export ops supported"));
sb->s_export_op = &cifs_export_ops;
}
#endif /* EXPERIMENTAL */
return 0; return 0;
out_no_root: out_no_root:
...@@ -149,7 +157,7 @@ cifs_read_super(struct super_block *sb, void *data, ...@@ -149,7 +157,7 @@ cifs_read_super(struct super_block *sb, void *data,
out_mount_failed: out_mount_failed:
if (cifs_sb) { if (cifs_sb) {
if (cifs_sb->local_nls) if (cifs_sb->local_nls)
unload_nls(cifs_sb->local_nls); unload_nls(cifs_sb->local_nls);
kfree(cifs_sb); kfree(cifs_sb);
} }
return rc; return rc;
...@@ -164,10 +172,10 @@ cifs_put_super(struct super_block *sb) ...@@ -164,10 +172,10 @@ cifs_put_super(struct super_block *sb)
cFYI(1, ("In cifs_put_super")); cFYI(1, ("In cifs_put_super"));
cifs_sb = CIFS_SB(sb); cifs_sb = CIFS_SB(sb);
if (cifs_sb == NULL) { if (cifs_sb == NULL) {
cFYI(1,("Empty cifs superblock info passed to unmount")); cFYI(1, ("Empty cifs superblock info passed to unmount"));
return; return;
} }
rc = cifs_umount(sb, cifs_sb); rc = cifs_umount(sb, cifs_sb);
if (rc) { if (rc) {
cERROR(1, ("cifs_umount failed with return code %d", rc)); cERROR(1, ("cifs_umount failed with return code %d", rc));
} }
...@@ -180,7 +188,7 @@ static int ...@@ -180,7 +188,7 @@ static int
cifs_statfs(struct dentry *dentry, struct kstatfs *buf) cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct super_block *sb = dentry->d_sb; struct super_block *sb = dentry->d_sb;
int xid; int xid;
int rc = -EOPNOTSUPP; int rc = -EOPNOTSUPP;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
...@@ -193,7 +201,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -193,7 +201,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
buf->f_type = CIFS_MAGIC_NUMBER; buf->f_type = CIFS_MAGIC_NUMBER;
/* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */ /* 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 presumably be total path, but note
that some servers (includinng Samba 3) that some servers (includinng Samba 3)
have a shorter maximum path */ have a shorter maximum path */
...@@ -217,8 +225,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -217,8 +225,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
bypassed it because we detected that this was an older LANMAN sess */ bypassed it because we detected that this was an older LANMAN sess */
if (rc) if (rc)
rc = SMBOldQFSInfo(xid, pTcon, buf); rc = SMBOldQFSInfo(xid, pTcon, buf);
/* /* int f_type;
int f_type;
__fsid_t f_fsid; __fsid_t f_fsid;
int f_namelen; */ int f_namelen; */
/* BB get from info in tcon struct at mount time call to QFSAttrInfo */ /* BB get from info in tcon struct at mount time call to QFSAttrInfo */
...@@ -227,7 +234,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -227,7 +234,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
longer available? */ longer available? */
} }
static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd) static int cifs_permission(struct inode *inode, int mask, struct nameidata *nd)
{ {
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
...@@ -235,10 +242,10 @@ static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd) ...@@ -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) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
return 0; return 0;
} else /* file mode might have been restricted at mount time } else /* file mode might have been restricted at mount time
on the client (above and beyond ACL on servers) for on the client (above and beyond ACL on servers) for
servers which do not support setting and viewing mode bits, 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); return generic_permission(inode, mask, NULL);
} }
...@@ -267,7 +274,7 @@ cifs_alloc_inode(struct super_block *sb) ...@@ -267,7 +274,7 @@ cifs_alloc_inode(struct super_block *sb)
cifs_inode->clientCanCacheRead = FALSE; cifs_inode->clientCanCacheRead = FALSE;
cifs_inode->clientCanCacheAll = FALSE; cifs_inode->clientCanCacheAll = FALSE;
cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
/* Can not set i_flags here - they get immediately overwritten /* Can not set i_flags here - they get immediately overwritten
to zero by the VFS */ to zero by the VFS */
/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/ /* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/
...@@ -309,26 +316,26 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) ...@@ -309,26 +316,26 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
seq_printf(s, ",posixpaths"); seq_printf(s, ",posixpaths");
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) || if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
!(cifs_sb->tcon->ses->capabilities & CAP_UNIX)) !(cifs_sb->tcon->unix_ext))
seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) || if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
!(cifs_sb->tcon->ses->capabilities & CAP_UNIX)) !(cifs_sb->tcon->unix_ext))
seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
seq_printf(s, ",rsize=%d",cifs_sb->rsize); seq_printf(s, ",rsize=%d", cifs_sb->rsize);
seq_printf(s, ",wsize=%d",cifs_sb->wsize); seq_printf(s, ",wsize=%d", cifs_sb->wsize);
} }
return 0; return 0;
} }
#ifdef CONFIG_CIFS_QUOTA #ifdef CONFIG_CIFS_QUOTA
int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid, int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid,
struct fs_disk_quota * pdquota) struct fs_disk_quota *pdquota)
{ {
int xid; int xid;
int rc = 0; int rc = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
if (cifs_sb) if (cifs_sb)
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
else else
...@@ -337,7 +344,7 @@ int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid, ...@@ -337,7 +344,7 @@ int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
xid = GetXid(); xid = GetXid();
if (pTcon) { if (pTcon) {
cFYI(1,("set type: 0x%x id: %d",quota_type,qid)); cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
} else { } else {
return -EIO; return -EIO;
} }
...@@ -346,8 +353,8 @@ int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid, ...@@ -346,8 +353,8 @@ int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
return rc; return rc;
} }
int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid, int cifs_xquota_get(struct super_block *sb, int quota_type, qid_t qid,
struct fs_disk_quota * pdquota) struct fs_disk_quota *pdquota)
{ {
int xid; int xid;
int rc = 0; int rc = 0;
...@@ -361,7 +368,7 @@ int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid, ...@@ -361,7 +368,7 @@ int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
xid = GetXid(); xid = GetXid();
if (pTcon) { if (pTcon) {
cFYI(1,("set type: 0x%x id: %d",quota_type,qid)); cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
} else { } else {
rc = -EIO; rc = -EIO;
} }
...@@ -370,9 +377,9 @@ int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid, ...@@ -370,9 +377,9 @@ int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
return rc; return rc;
} }
int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation) int cifs_xstate_set(struct super_block *sb, unsigned int flags, int operation)
{ {
int xid; int xid;
int rc = 0; int rc = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
...@@ -384,7 +391,7 @@ int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation) ...@@ -384,7 +391,7 @@ int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
xid = GetXid(); xid = GetXid();
if (pTcon) { if (pTcon) {
cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation)); cFYI(1, ("flags: 0x%x operation: 0x%x", flags, operation));
} else { } else {
rc = -EIO; rc = -EIO;
} }
...@@ -393,7 +400,7 @@ int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation) ...@@ -393,7 +400,7 @@ int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
return rc; return rc;
} }
int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats) int cifs_xstate_get(struct super_block *sb, struct fs_quota_stat *qstats)
{ {
int xid; int xid;
int rc = 0; int rc = 0;
...@@ -407,7 +414,7 @@ int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats) ...@@ -407,7 +414,7 @@ int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
} }
xid = GetXid(); xid = GetXid();
if (pTcon) { if (pTcon) {
cFYI(1,("pqstats %p",qstats)); cFYI(1, ("pqstats %p", qstats));
} else { } else {
rc = -EIO; rc = -EIO;
} }
...@@ -424,10 +431,10 @@ static struct quotactl_ops cifs_quotactl_ops = { ...@@ -424,10 +431,10 @@ static struct quotactl_ops cifs_quotactl_ops = {
}; };
#endif #endif
static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags) static void cifs_umount_begin(struct vfsmount *vfsmnt, int flags)
{ {
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo * tcon; struct cifsTconInfo *tcon;
if (!(flags & MNT_FORCE)) if (!(flags & MNT_FORCE))
return; return;
...@@ -445,9 +452,8 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags) ...@@ -445,9 +452,8 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */ /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
/* cancel_notify_requests(tcon); */ /* cancel_notify_requests(tcon); */
if (tcon->ses && tcon->ses->server) if (tcon->ses && tcon->ses->server) {
{ cFYI(1, ("wake up tasks now - umount begin not complete"));
cFYI(1,("wake up tasks now - umount begin not complete"));
wake_up_all(&tcon->ses->server->request_q); wake_up_all(&tcon->ses->server->request_q);
wake_up_all(&tcon->ses->server->response_q); wake_up_all(&tcon->ses->server->response_q);
msleep(1); /* yield */ msleep(1); /* yield */
...@@ -480,10 +486,11 @@ static const struct super_operations cifs_super_ops = { ...@@ -480,10 +486,11 @@ static const struct super_operations cifs_super_ops = {
.statfs = cifs_statfs, .statfs = cifs_statfs,
.alloc_inode = cifs_alloc_inode, .alloc_inode = cifs_alloc_inode,
.destroy_inode = cifs_destroy_inode, .destroy_inode = cifs_destroy_inode,
/* .drop_inode = generic_delete_inode, /* .drop_inode = generic_delete_inode,
.delete_inode = cifs_delete_inode, *//* Do not need the above two functions .delete_inode = cifs_delete_inode, */ /* Do not need above two
unless later we add lazy close of inodes or unless the kernel forgets to call functions unless later we add lazy close of inodes or unless the
us with the same number of releases (closes) as opens */ kernel forgets to call us with the same number of releases (closes)
as opens */
.show_options = cifs_show_options, .show_options = cifs_show_options,
.umount_begin = cifs_umount_begin, .umount_begin = cifs_umount_begin,
.remount_fs = cifs_remount, .remount_fs = cifs_remount,
...@@ -586,11 +593,11 @@ const struct inode_operations cifs_file_inode_ops = { ...@@ -586,11 +593,11 @@ const struct inode_operations cifs_file_inode_ops = {
.getxattr = cifs_getxattr, .getxattr = cifs_getxattr,
.listxattr = cifs_listxattr, .listxattr = cifs_listxattr,
.removexattr = cifs_removexattr, .removexattr = cifs_removexattr,
#endif #endif
}; };
const struct inode_operations cifs_symlink_inode_ops = { const struct inode_operations cifs_symlink_inode_ops = {
.readlink = generic_readlink, .readlink = generic_readlink,
.follow_link = cifs_follow_link, .follow_link = cifs_follow_link,
.put_link = cifs_put_link, .put_link = cifs_put_link,
.permission = cifs_permission, .permission = cifs_permission,
...@@ -602,7 +609,7 @@ const struct inode_operations cifs_symlink_inode_ops = { ...@@ -602,7 +609,7 @@ const struct inode_operations cifs_symlink_inode_ops = {
.getxattr = cifs_getxattr, .getxattr = cifs_getxattr,
.listxattr = cifs_listxattr, .listxattr = cifs_listxattr,
.removexattr = cifs_removexattr, .removexattr = cifs_removexattr,
#endif #endif
}; };
const struct file_operations cifs_file_ops = { const struct file_operations cifs_file_ops = {
...@@ -628,7 +635,7 @@ 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 = { 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 */ BB reevaluate whether they can be done with directio, no cache */
.read = cifs_user_read, .read = cifs_user_read,
.write = cifs_user_write, .write = cifs_user_write,
...@@ -668,7 +675,7 @@ const struct file_operations cifs_file_nobrl_ops = { ...@@ -668,7 +675,7 @@ const struct file_operations cifs_file_nobrl_ops = {
}; };
const struct file_operations cifs_file_direct_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 */ BB reevaluate whether they can be done with directio, no cache */
.read = cifs_user_read, .read = cifs_user_read,
.write = cifs_user_write, .write = cifs_user_write,
...@@ -693,11 +700,11 @@ const struct file_operations cifs_dir_ops = { ...@@ -693,11 +700,11 @@ const struct file_operations cifs_dir_ops = {
#ifdef CONFIG_CIFS_EXPERIMENTAL #ifdef CONFIG_CIFS_EXPERIMENTAL
.dir_notify = cifs_dir_notify, .dir_notify = cifs_dir_notify,
#endif /* CONFIG_CIFS_EXPERIMENTAL */ #endif /* CONFIG_CIFS_EXPERIMENTAL */
.ioctl = cifs_ioctl, .ioctl = cifs_ioctl,
}; };
static void static void
cifs_init_once(void *inode, struct kmem_cache * cachep, unsigned long flags) cifs_init_once(void *inode, struct kmem_cache *cachep, unsigned long flags)
{ {
struct cifsInodeInfo *cifsi = inode; struct cifsInodeInfo *cifsi = inode;
...@@ -749,7 +756,7 @@ cifs_init_request_bufs(void) ...@@ -749,7 +756,7 @@ cifs_init_request_bufs(void)
cifs_min_rcv = 1; cifs_min_rcv = 1;
else if (cifs_min_rcv > 64) { else if (cifs_min_rcv > 64) {
cifs_min_rcv = 64; cifs_min_rcv = 64;
cERROR(1,("cifs_min_rcv set to maximum (64)")); cERROR(1, ("cifs_min_rcv set to maximum (64)"));
} }
cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv, cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
...@@ -762,25 +769,25 @@ cifs_init_request_bufs(void) ...@@ -762,25 +769,25 @@ cifs_init_request_bufs(void)
/* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and /* 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 almost all handle based requests (but not write response, nor is it
sufficient for path based requests). A smaller size would have 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 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 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 */ alloc of large cifs buffers even when page debugging is on */
cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq", 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); NULL, NULL);
if (cifs_sm_req_cachep == NULL) { if (cifs_sm_req_cachep == NULL) {
mempool_destroy(cifs_req_poolp); mempool_destroy(cifs_req_poolp);
kmem_cache_destroy(cifs_req_cachep); kmem_cache_destroy(cifs_req_cachep);
return -ENOMEM; return -ENOMEM;
} }
if (cifs_min_small < 2) if (cifs_min_small < 2)
cifs_min_small = 2; cifs_min_small = 2;
else if (cifs_min_small > 256) { else if (cifs_min_small > 256) {
cifs_min_small = 256; cifs_min_small = 256;
cFYI(1,("cifs_min_small set to maximum (256)")); cFYI(1, ("cifs_min_small set to maximum (256)"));
} }
cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small, cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
...@@ -841,42 +848,43 @@ cifs_destroy_mids(void) ...@@ -841,42 +848,43 @@ cifs_destroy_mids(void)
kmem_cache_destroy(cifs_oplock_cachep); kmem_cache_destroy(cifs_oplock_cachep);
} }
static int cifs_oplock_thread(void * dummyarg) static int cifs_oplock_thread(void *dummyarg)
{ {
struct oplock_q_entry * oplock_item; struct oplock_q_entry *oplock_item;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct inode * inode; struct inode *inode;
__u16 netfid; __u16 netfid;
int rc; int rc;
set_freezable(); set_freezable();
do { do {
if (try_to_freeze()) if (try_to_freeze())
continue; continue;
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
if (list_empty(&GlobalOplock_Q)) { if (list_empty(&GlobalOplock_Q)) {
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(39*HZ); schedule_timeout(39*HZ);
} else { } else {
oplock_item = list_entry(GlobalOplock_Q.next, oplock_item = list_entry(GlobalOplock_Q.next,
struct oplock_q_entry, qhead); struct oplock_q_entry, qhead);
if (oplock_item) { if (oplock_item) {
cFYI(1,("found oplock item to write out")); cFYI(1, ("found oplock item to write out"));
pTcon = oplock_item->tcon; pTcon = oplock_item->tcon;
inode = oplock_item->pinode; inode = oplock_item->pinode;
netfid = oplock_item->netfid; netfid = oplock_item->netfid;
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
DeleteOplockQEntry(oplock_item); DeleteOplockQEntry(oplock_item);
/* can not grab inode sem here since it would /* 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 since vfs_unlink holds the i_mutex across
the call */ the call */
/* mutex_lock(&inode->i_mutex);*/ /* mutex_lock(&inode->i_mutex);*/
if (S_ISREG(inode->i_mode)) { if (S_ISREG(inode->i_mode)) {
rc = filemap_fdatawrite(inode->i_mapping); rc = filemap_fdatawrite(inode->i_mapping);
if (CIFS_I(inode)->clientCanCacheRead == 0) { if (CIFS_I(inode)->clientCanCacheRead
== 0) {
filemap_fdatawait(inode->i_mapping); filemap_fdatawait(inode->i_mapping);
invalidate_remote_inode(inode); invalidate_remote_inode(inode);
} }
...@@ -885,20 +893,22 @@ static int cifs_oplock_thread(void * dummyarg) ...@@ -885,20 +893,22 @@ static int cifs_oplock_thread(void * dummyarg)
/* mutex_unlock(&inode->i_mutex);*/ /* mutex_unlock(&inode->i_mutex);*/
if (rc) if (rc)
CIFS_I(inode)->write_behind_rc = rc; CIFS_I(inode)->write_behind_rc = rc;
cFYI(1,("Oplock flush inode %p rc %d",inode,rc)); cFYI(1, ("Oplock flush inode %p rc %d",
inode, rc));
/* releasing a stale oplock after recent reconnection
of smb session using a now incorrect file /* releasing stale oplock after recent reconnect
handle is not a data integrity issue but do of smb session using a now incorrect file
not bother sending an oplock release if session handle is not a data integrity issue but do
to server still is disconnected since oplock not bother sending an oplock release if session
to server still is disconnected since oplock
already released by the server in that case */ already released by the server in that case */
if (pTcon->tidStatus != CifsNeedReconnect) { if (pTcon->tidStatus != CifsNeedReconnect) {
rc = CIFSSMBLock(0, pTcon, netfid, rc = CIFSSMBLock(0, pTcon, netfid,
0 /* len */ , 0 /* offset */, 0, 0 /* len */ , 0 /* offset */, 0,
0, LOCKING_ANDX_OPLOCK_RELEASE, 0, LOCKING_ANDX_OPLOCK_RELEASE,
0 /* wait flag */); 0 /* wait flag */);
cFYI(1,("Oplock release rc = %d ",rc)); cFYI(1,
("Oplock release rc = %d ", rc));
} }
} else } else
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
...@@ -910,7 +920,7 @@ static int cifs_oplock_thread(void * dummyarg) ...@@ -910,7 +920,7 @@ static int cifs_oplock_thread(void * dummyarg)
return 0; return 0;
} }
static int cifs_dnotify_thread(void * dummyarg) static int cifs_dnotify_thread(void *dummyarg)
{ {
struct list_head *tmp; struct list_head *tmp;
struct cifsSesInfo *ses; struct cifsSesInfo *ses;
...@@ -925,9 +935,9 @@ static int cifs_dnotify_thread(void * dummyarg) ...@@ -925,9 +935,9 @@ static int cifs_dnotify_thread(void * dummyarg)
to be woken up and wakeq so the to be woken up and wakeq so the
thread can wake up and error out */ thread can wake up and error out */
list_for_each(tmp, &GlobalSMBSessionList) { list_for_each(tmp, &GlobalSMBSessionList) {
ses = list_entry(tmp, struct cifsSesInfo, ses = list_entry(tmp, struct cifsSesInfo,
cifsSessionList); cifsSessionList);
if (ses && ses->server && if (ses && ses->server &&
atomic_read(&ses->server->inFlight)) atomic_read(&ses->server->inFlight))
wake_up_all(&ses->server->response_q); wake_up_all(&ses->server->response_q);
} }
...@@ -951,13 +961,13 @@ init_cifs(void) ...@@ -951,13 +961,13 @@ init_cifs(void)
#ifdef CONFIG_CIFS_EXPERIMENTAL #ifdef CONFIG_CIFS_EXPERIMENTAL
INIT_LIST_HEAD(&GlobalDnotifyReqList); INIT_LIST_HEAD(&GlobalDnotifyReqList);
INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); INIT_LIST_HEAD(&GlobalDnotifyRsp_Q);
#endif #endif
/* /*
* Initialize Global counters * Initialize Global counters
*/ */
atomic_set(&sesInfoAllocCount, 0); atomic_set(&sesInfoAllocCount, 0);
atomic_set(&tconInfoAllocCount, 0); atomic_set(&tconInfoAllocCount, 0);
atomic_set(&tcpSesAllocCount,0); atomic_set(&tcpSesAllocCount, 0);
atomic_set(&tcpSesReconnectCount, 0); atomic_set(&tcpSesReconnectCount, 0);
atomic_set(&tconInfoReconnectCount, 0); atomic_set(&tconInfoReconnectCount, 0);
...@@ -978,10 +988,10 @@ init_cifs(void) ...@@ -978,10 +988,10 @@ init_cifs(void)
if (cifs_max_pending < 2) { if (cifs_max_pending < 2) {
cifs_max_pending = 2; cifs_max_pending = 2;
cFYI(1,("cifs_max_pending set to min of 2")); cFYI(1, ("cifs_max_pending set to min of 2"));
} else if (cifs_max_pending > 256) { } else if (cifs_max_pending > 256) {
cifs_max_pending = 256; cifs_max_pending = 256;
cFYI(1,("cifs_max_pending set to max of 256")); cFYI(1, ("cifs_max_pending set to max of 256"));
} }
rc = cifs_init_inodecache(); rc = cifs_init_inodecache();
...@@ -1003,14 +1013,14 @@ init_cifs(void) ...@@ -1003,14 +1013,14 @@ init_cifs(void)
oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd"); oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");
if (IS_ERR(oplockThread)) { if (IS_ERR(oplockThread)) {
rc = PTR_ERR(oplockThread); rc = PTR_ERR(oplockThread);
cERROR(1,("error %d create oplock thread", rc)); cERROR(1, ("error %d create oplock thread", rc));
goto out_unregister_filesystem; goto out_unregister_filesystem;
} }
dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd"); dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
if (IS_ERR(dnotifyThread)) { if (IS_ERR(dnotifyThread)) {
rc = PTR_ERR(dnotifyThread); rc = PTR_ERR(dnotifyThread);
cERROR(1,("error %d create dnotify thread", rc)); cERROR(1, ("error %d create dnotify thread", rc));
goto out_stop_oplock_thread; goto out_stop_oplock_thread;
} }
...@@ -1036,7 +1046,7 @@ init_cifs(void) ...@@ -1036,7 +1046,7 @@ init_cifs(void)
static void __exit static void __exit
exit_cifs(void) exit_cifs(void)
{ {
cFYI(0, ("In unregister ie exit_cifs")); cFYI(0, ("exit_cifs"));
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
cifs_proc_clean(); cifs_proc_clean();
#endif #endif
...@@ -1049,9 +1059,10 @@ exit_cifs(void) ...@@ -1049,9 +1059,10 @@ exit_cifs(void)
} }
MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */ MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
MODULE_DESCRIPTION MODULE_DESCRIPTION
("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows"); ("VFS to access servers complying with the SNIA CIFS Specification "
"e.g. Samba and Windows");
MODULE_VERSION(CIFS_VERSION); MODULE_VERSION(CIFS_VERSION);
module_init(init_cifs) module_init(init_cifs)
module_exit(exit_cifs) module_exit(exit_cifs)
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software * 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 #ifndef _CIFSFS_H
...@@ -43,9 +43,9 @@ extern void cifs_read_inode(struct inode *); ...@@ -43,9 +43,9 @@ extern void cifs_read_inode(struct inode *);
/* Functions related to inodes */ /* Functions related to inodes */
extern const struct inode_operations cifs_dir_inode_ops; extern const struct inode_operations cifs_dir_inode_ops;
extern int cifs_create(struct inode *, struct dentry *, int, extern int cifs_create(struct inode *, struct dentry *, int,
struct nameidata *); struct nameidata *);
extern struct dentry * cifs_lookup(struct inode *, struct dentry *, extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
struct nameidata *); struct nameidata *);
extern int cifs_unlink(struct inode *, struct dentry *); extern int cifs_unlink(struct inode *, struct dentry *);
extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *); extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
...@@ -63,16 +63,16 @@ extern const struct inode_operations cifs_symlink_inode_ops; ...@@ -63,16 +63,16 @@ extern const struct inode_operations cifs_symlink_inode_ops;
/* Functions related to files and directories */ /* Functions related to files and directories */
extern const struct file_operations cifs_file_ops; extern const struct file_operations cifs_file_ops;
extern const struct file_operations cifs_file_direct_ops; /* if directio mount */ extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
extern const struct file_operations cifs_file_nobrl_ops; extern const struct file_operations cifs_file_nobrl_ops;
extern const struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */ extern const struct file_operations cifs_file_direct_nobrl_ops; /* no brlocks */
extern int cifs_open(struct inode *inode, struct file *file); extern int cifs_open(struct inode *inode, struct file *file);
extern int cifs_close(struct inode *inode, struct file *file); extern int cifs_close(struct inode *inode, struct file *file);
extern int cifs_closedir(struct inode *inode, struct file *file); extern int cifs_closedir(struct inode *inode, struct file *file);
extern ssize_t cifs_user_read(struct file *file, char __user *read_data, extern ssize_t cifs_user_read(struct file *file, char __user *read_data,
size_t read_size, loff_t * poffset); size_t read_size, loff_t *poffset);
extern ssize_t cifs_user_write(struct file *file, const char __user *write_data, extern ssize_t cifs_user_write(struct file *file, const char __user *write_data,
size_t write_size, loff_t * poffset); size_t write_size, loff_t *poffset);
extern int cifs_lock(struct file *, int, struct file_lock *); extern int cifs_lock(struct file *, int, struct file_lock *);
extern int cifs_fsync(struct file *, struct dentry *, int); extern int cifs_fsync(struct file *, struct dentry *, int);
extern int cifs_flush(struct file *, fl_owner_t id); extern int cifs_flush(struct file *, fl_owner_t id);
...@@ -88,8 +88,9 @@ extern struct dentry_operations cifs_ci_dentry_ops; ...@@ -88,8 +88,9 @@ extern struct dentry_operations cifs_ci_dentry_ops;
/* Functions related to symlinks */ /* Functions related to symlinks */
extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd); extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *); extern void cifs_put_link(struct dentry *direntry,
extern int cifs_readlink(struct dentry *direntry, char __user *buffer, struct nameidata *nd, void *);
extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
int buflen); int buflen);
extern int cifs_symlink(struct inode *inode, struct dentry *direntry, extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
const char *symname); const char *symname);
...@@ -98,7 +99,7 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *, ...@@ -98,7 +99,7 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int); size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern int cifs_ioctl (struct inode * inode, struct file * filep, extern int cifs_ioctl (struct inode *inode, struct file *filep,
unsigned int command, unsigned long arg); unsigned int command, unsigned long arg);
#define CIFS_VERSION "1.49" #define CIFS_VERSION "1.50"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
/* /*
* fs/cifs/cifsglob.h * fs/cifs/cifsglob.h
* *
* Copyright (C) International Business Machines Corp., 2002,2006 * Copyright (C) International Business Machines Corp., 2002,2007
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* Jeremy Allison (jra@samba.org) * Jeremy Allison (jra@samba.org)
* *
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU Lesser General Public License for more details. * the GNU Lesser General Public License for more details.
* *
*/ */
#include <linux/in.h> #include <linux/in.h>
#include <linux/in6.h> #include <linux/in6.h>
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1 #define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
#define MAX_SERVER_SIZE 15 #define MAX_SERVER_SIZE 15
#define MAX_SHARE_SIZE 64 /* used to be 20 - this should still be enough */ #define MAX_SHARE_SIZE 64 /* used to be 20, this should still be enough */
#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null #define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
termination then *2 for unicode versions */ termination then *2 for unicode versions */
#define MAX_PASSWORD_SIZE 16 #define MAX_PASSWORD_SIZE 16
...@@ -38,13 +38,13 @@ ...@@ -38,13 +38,13 @@
/* /*
* MAX_REQ is the maximum number of requests that WE will send * MAX_REQ is the maximum number of requests that WE will send
* on one socket concurently. It also matches the most common * 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 * eventually want to use the negotiated value (in case
* future servers can handle more) when we are more confident that * future servers can handle more) when we are more confident that
* we will not have problems oveloading the socket with pending * we will not have problems oveloading the socket with pending
* write data. * write data.
*/ */
#define CIFS_MAX_REQ 50 #define CIFS_MAX_REQ 50
#define SERVER_NAME_LENGTH 15 #define SERVER_NAME_LENGTH 15
#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1) #define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
...@@ -104,6 +104,17 @@ enum protocolEnum { ...@@ -104,6 +104,17 @@ enum protocolEnum {
/* Netbios frames protocol not supported at this time */ /* Netbios frames protocol not supported at this time */
}; };
struct mac_key {
unsigned int len;
union {
char ntlm[CIFS_SESS_KEY_SIZE + 16];
struct {
char key[16];
struct ntlmv2_resp resp;
} ntlmv2;
} data;
};
/* /*
***************************************************************** *****************************************************************
* Except the CIFS PDUs themselves all the * Except the CIFS PDUs themselves all the
...@@ -120,13 +131,13 @@ struct TCP_Server_Info { ...@@ -120,13 +131,13 @@ struct TCP_Server_Info {
struct sockaddr_in sockAddr; struct sockaddr_in sockAddr;
struct sockaddr_in6 sockAddr6; struct sockaddr_in6 sockAddr6;
} addr; } 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*/ wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
struct list_head pending_mid_q; struct list_head pending_mid_q;
void *Server_NlsInfo; /* BB - placeholder for future NLS info */ void *Server_NlsInfo; /* BB - placeholder for future NLS info */
unsigned short server_codepage; /* codepage for the server */ unsigned short server_codepage; /* codepage for the server */
unsigned long ip_address; /* IP addr for the server if known */ unsigned long ip_address; /* IP addr for the server if known */
enum protocolEnum protocolType; enum protocolEnum protocolType;
char versionMajor; char versionMajor;
char versionMinor; char versionMinor;
unsigned svlocal:1; /* local server or remote */ unsigned svlocal:1; /* local server or remote */
...@@ -159,14 +170,15 @@ struct TCP_Server_Info { ...@@ -159,14 +170,15 @@ struct TCP_Server_Info {
/* 16th byte of RFC1001 workstation name is always null */ /* 16th byte of RFC1001 workstation name is always null */
char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
__u32 sequence_number; /* needed for CIFS PDU signature */ __u32 sequence_number; /* needed for CIFS PDU signature */
char mac_signing_key[CIFS_SESS_KEY_SIZE + 16]; struct mac_key mac_signing_key;
char ntlmv2_hash[16];
unsigned long lstrp; /* when we got last response from this server */ unsigned long lstrp; /* when we got last response from this server */
}; };
/* /*
* The following is our shortcut to user information. We surface the uid, * 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 * 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 cifsUidInfo {
struct list_head userList; struct list_head userList;
...@@ -197,11 +209,11 @@ struct cifsSesInfo { ...@@ -197,11 +209,11 @@ struct cifsSesInfo {
int Suid; /* remote smb uid */ int Suid; /* remote smb uid */
uid_t linux_uid; /* local Linux uid */ uid_t linux_uid; /* local Linux uid */
int capabilities; 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? */ TCP names - will ipv6 and sctp addresses fit? */
char userName[MAX_USERNAME_SIZE + 1]; char userName[MAX_USERNAME_SIZE + 1];
char * domainName; char *domainName;
char * password; char *password;
}; };
/* no more than one of the following three session flags may be set */ /* no more than one of the following three session flags may be set */
#define CIFS_SES_NT4 1 #define CIFS_SES_NT4 1
...@@ -213,7 +225,7 @@ struct cifsSesInfo { ...@@ -213,7 +225,7 @@ struct cifsSesInfo {
#define CIFS_SES_LANMAN 8 #define CIFS_SES_LANMAN 8
/* /*
* there is one of these for each connection to a resource on a particular * there is one of these for each connection to a resource on a particular
* session * session
*/ */
struct cifsTconInfo { struct cifsTconInfo {
struct list_head cifsConnectionList; struct list_head cifsConnectionList;
...@@ -269,7 +281,9 @@ struct cifsTconInfo { ...@@ -269,7 +281,9 @@ struct cifsTconInfo {
FILE_SYSTEM_UNIX_INFO fsUnixInfo; FILE_SYSTEM_UNIX_INFO fsUnixInfo;
unsigned retry:1; unsigned retry:1;
unsigned nocase:1; unsigned nocase:1;
/* BB add field for back pointer to sb struct? */ unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol
for this mount even if server would support */
/* BB add field for back pointer to sb struct(s)? */
}; };
/* /*
...@@ -291,9 +305,9 @@ struct cifs_search_info { ...@@ -291,9 +305,9 @@ struct cifs_search_info {
__u16 entries_in_buffer; __u16 entries_in_buffer;
__u16 info_level; __u16 info_level;
__u32 resume_key; __u32 resume_key;
char * ntwrk_buf_start; char *ntwrk_buf_start;
char * srch_entries_start; char *srch_entries_start;
char * presume_name; char *presume_name;
unsigned int resume_name_len; unsigned int resume_name_len;
unsigned endOfSearch:1; unsigned endOfSearch:1;
unsigned emptyDir:1; unsigned emptyDir:1;
...@@ -309,15 +323,15 @@ struct cifsFileInfo { ...@@ -309,15 +323,15 @@ struct cifsFileInfo {
__u16 netfid; /* file id from remote */ __u16 netfid; /* file id from remote */
/* BB add lock scope info here if needed */ ; /* BB add lock scope info here if needed */ ;
/* lock scope id (0 if none) */ /* lock scope id (0 if none) */
struct file * pfile; /* needed for writepage */ struct file *pfile; /* needed for writepage */
struct inode * pInode; /* needed for oplock break */ struct inode *pInode; /* needed for oplock break */
struct mutex lock_mutex; struct mutex lock_mutex;
struct list_head llist; /* list of byte range locks we have. */ struct list_head llist; /* list of byte range locks we have. */
unsigned closePend:1; /* file is marked to close */ unsigned closePend:1; /* file is marked to close */
unsigned invalidHandle:1; /* file closed via session abend */ unsigned invalidHandle:1; /* file closed via session abend */
atomic_t wrtPending; /* handle in use - defer close */ atomic_t wrtPending; /* handle in use - defer close */
struct semaphore fh_sem; /* prevents reopen race after dead ses*/ struct semaphore fh_sem; /* prevents reopen race after dead ses*/
char * search_resume_name; /* BB removeme BB */ char *search_resume_name; /* BB removeme BB */
struct cifs_search_info srch_inf; struct cifs_search_info srch_inf;
}; };
...@@ -327,7 +341,7 @@ struct cifsFileInfo { ...@@ -327,7 +341,7 @@ struct cifsFileInfo {
struct cifsInodeInfo { struct cifsInodeInfo {
struct list_head lockList; struct list_head lockList;
/* BB add in lists for dirty pages - i.e. write caching info for oplock */ /* BB add in lists for dirty pages i.e. write caching info for oplock */
struct list_head openFileList; struct list_head openFileList;
int write_behind_rc; int write_behind_rc;
__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
...@@ -381,9 +395,9 @@ static inline void cifs_stats_bytes_read(struct cifsTconInfo *tcon, ...@@ -381,9 +395,9 @@ static inline void cifs_stats_bytes_read(struct cifsTconInfo *tcon,
} }
#else #else
#define cifs_stats_inc(field) do {} while(0) #define cifs_stats_inc(field) do {} while (0)
#define cifs_stats_bytes_written(tcon, bytes) do {} while(0) #define cifs_stats_bytes_written(tcon, bytes) do {} while (0)
#define cifs_stats_bytes_read(tcon, bytes) do {} while(0) #define cifs_stats_bytes_read(tcon, bytes) do {} while (0)
#endif #endif
...@@ -410,8 +424,8 @@ struct mid_q_entry { ...@@ -410,8 +424,8 @@ struct mid_q_entry {
struct oplock_q_entry { struct oplock_q_entry {
struct list_head qhead; struct list_head qhead;
struct inode * pinode; struct inode *pinode;
struct cifsTconInfo * tcon; struct cifsTconInfo *tcon;
__u16 netfid; __u16 netfid;
}; };
...@@ -426,7 +440,7 @@ struct dir_notify_req { ...@@ -426,7 +440,7 @@ struct dir_notify_req {
__u16 netfid; __u16 netfid;
__u32 filter; /* CompletionFilter (for multishot) */ __u32 filter; /* CompletionFilter (for multishot) */
int multishot; int multishot;
struct file * pfile; struct file *pfile;
}; };
#define MID_FREE 0 #define MID_FREE 0
...@@ -464,7 +478,7 @@ require use of the stronger protocol */ ...@@ -464,7 +478,7 @@ require use of the stronger protocol */
#define CIFSSEC_MUST_LANMAN 0x10010 #define CIFSSEC_MUST_LANMAN 0x10010
#define CIFSSEC_MUST_PLNTXT 0x20020 #define CIFSSEC_MUST_PLNTXT 0x20020
#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */ #define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
#else #else
#define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */ #define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */
#endif /* WEAK_PW_HASH */ #endif /* WEAK_PW_HASH */
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ #define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
...@@ -502,7 +516,7 @@ require use of the stronger protocol */ ...@@ -502,7 +516,7 @@ require use of the stronger protocol */
* ---------- * ----------
* sesSem operations on smb session * sesSem operations on smb session
* tconSem operations on tree connection * 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 */ ...@@ -515,7 +529,7 @@ require use of the stronger protocol */
/* /*
* The list of servers that did not respond with NT LM 0.12. * The list of servers that did not respond with NT LM 0.12.
* This list helps improve performance and eliminate the messages indicating * 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 */ /* Feature not supported */
/* GLOBAL_EXTERN struct servers_not_supported *NotSuppList; */ /* GLOBAL_EXTERN struct servers_not_supported *NotSuppList; */
...@@ -568,12 +582,12 @@ GLOBAL_EXTERN atomic_t midCount; ...@@ -568,12 +582,12 @@ GLOBAL_EXTERN atomic_t midCount;
/* Misc globals */ /* Misc globals */
GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
to be established on existing mount if we 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 */ or equivalent for current user */
GLOBAL_EXTERN unsigned int oplockEnabled; GLOBAL_EXTERN unsigned int oplockEnabled;
GLOBAL_EXTERN unsigned int experimEnabled; GLOBAL_EXTERN unsigned int experimEnabled;
GLOBAL_EXTERN unsigned int lookupCacheEnabled; 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 */ with more secure ntlmssp2 challenge/resp */
GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
......
...@@ -144,7 +144,7 @@ ...@@ -144,7 +144,7 @@
#define SMBOPEN_OAPPEND 0x0001 #define SMBOPEN_OAPPEND 0x0001
/* /*
* SMB flag definitions * SMB flag definitions
*/ */
#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock smb */ #define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock smb */
#define SMBFLG_RCV_POSTED 0x02 /* obsolete */ #define SMBFLG_RCV_POSTED 0x02 /* obsolete */
...@@ -157,9 +157,9 @@ ...@@ -157,9 +157,9 @@
#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */ #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 */ path names in response */
#define SMBFLG2_KNOWS_EAS cpu_to_le16(2) #define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
#define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4) #define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
...@@ -260,7 +260,7 @@ ...@@ -260,7 +260,7 @@
#define ATTR_SPARSE 0x0200 #define ATTR_SPARSE 0x0200
#define ATTR_REPARSE 0x0400 #define ATTR_REPARSE 0x0400
#define ATTR_COMPRESSED 0x0800 #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 */ on offline storage */
#define ATTR_NOT_CONTENT_INDEXED 0x2000 #define ATTR_NOT_CONTENT_INDEXED 0x2000
#define ATTR_ENCRYPTED 0x4000 #define ATTR_ENCRYPTED 0x4000
...@@ -300,7 +300,7 @@ ...@@ -300,7 +300,7 @@
#define CREATE_DELETE_ON_CLOSE 0x00001000 #define CREATE_DELETE_ON_CLOSE 0x00001000
#define CREATE_OPEN_BY_ID 0x00002000 #define CREATE_OPEN_BY_ID 0x00002000
#define OPEN_REPARSE_POINT 0x00200000 #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 */ #define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */
/* ImpersonationLevel flags */ /* ImpersonationLevel flags */
...@@ -366,17 +366,19 @@ struct smb_hdr { ...@@ -366,17 +366,19 @@ struct smb_hdr {
#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 ) #define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
/* /*
* Computer Name Length * Computer Name Length (since Netbios name was length 16 with last byte 0x20)
* No longer as important, now that TCP names are more commonly used to
* resolve hosts.
*/ */
#define CNLEN 15 #define CNLEN 15
/* /*
* Share Name Length @S8A * Share Name Length (SNLEN)
* Note: This length is limited by the SMB used to get @S8A * Note: This length was limited by the SMB used to get
* the Share info. NetShareEnum only returns 13 @S8A * the Share info. NetShareEnum only returned 13
* chars, including the null termination. @S8A * chars, including the null termination.
* This was removed because it no longer is limiting.
*/ */
#define SNLEN 12 /*@S8A */
/* /*
* Comment Length * Comment Length
...@@ -394,8 +396,8 @@ struct smb_hdr { ...@@ -394,8 +396,8 @@ struct smb_hdr {
* *
* The Naming convention is the lower case version of the * The Naming convention is the lower case version of the
* smb command code name for the struct and this is typedef to 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 * uppercase version of the same name with the prefix SMB_ removed
* for brevity. Although typedefs are not commonly used for * for brevity. Although typedefs are not commonly used for
* structure definitions in the Linux kernel, their use in the * structure definitions in the Linux kernel, their use in the
* CIFS standards document, which this code is based on, may * CIFS standards document, which this code is based on, may
* make this one of the cases where typedefs for structures make * make this one of the cases where typedefs for structures make
...@@ -403,7 +405,7 @@ struct smb_hdr { ...@@ -403,7 +405,7 @@ struct smb_hdr {
* Typedefs can always be removed later if they are too distracting * Typedefs can always be removed later if they are too distracting
* and they are only used for the CIFSs PDUs themselves, not * and they are only used for the CIFSs PDUs themselves, not
* internal cifs vfs structures * internal cifs vfs structures
* *
*/ */
typedef struct negotiate_req { typedef struct negotiate_req {
...@@ -511,7 +513,7 @@ typedef union smb_com_session_setup_andx { ...@@ -511,7 +513,7 @@ typedef union smb_com_session_setup_andx {
unsigned char SecurityBlob[1]; /* followed by */ unsigned char SecurityBlob[1]; /* followed by */
/* STRING NativeOS */ /* STRING NativeOS */
/* STRING NativeLanMan */ /* STRING NativeLanMan */
} __attribute__((packed)) req; /* NTLM request format (with } __attribute__((packed)) req; /* NTLM request format (with
extended security */ extended security */
struct { /* request format */ struct { /* request format */
...@@ -549,7 +551,7 @@ typedef union smb_com_session_setup_andx { ...@@ -549,7 +551,7 @@ typedef union smb_com_session_setup_andx {
/* unsigned char * NativeOS; */ /* unsigned char * NativeOS; */
/* unsigned char * NativeLanMan; */ /* unsigned char * NativeLanMan; */
/* unsigned char * PrimaryDomain; */ /* unsigned char * PrimaryDomain; */
} __attribute__((packed)) resp; /* NTLM response } __attribute__((packed)) resp; /* NTLM response
(with or without extended sec) */ (with or without extended sec) */
struct { /* request format */ struct { /* request format */
...@@ -618,7 +620,7 @@ struct ntlmv2_resp { ...@@ -618,7 +620,7 @@ struct ntlmv2_resp {
#define CAP_NT_SMBS 0x00000010 #define CAP_NT_SMBS 0x00000010
#define CAP_STATUS32 0x00000040 #define CAP_STATUS32 0x00000040
#define CAP_LEVEL_II_OPLOCKS 0x00000080 #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?) */ (because NT_SMBs implies the same thing?) */
#define CAP_BULK_TRANSFER 0x20000000 #define CAP_BULK_TRANSFER 0x20000000
#define CAP_EXTENDED_SECURITY 0x80000000 #define CAP_EXTENDED_SECURITY 0x80000000
...@@ -676,7 +678,7 @@ typedef struct smb_com_logoff_andx_rsp { ...@@ -676,7 +678,7 @@ typedef struct smb_com_logoff_andx_rsp {
__u16 ByteCount; __u16 ByteCount;
} __attribute__((packed)) LOGOFF_ANDX_RSP; } __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 */ tree_connect PDU to effect disconnect */
/* tdis is probably simplest SMB PDU */ /* tdis is probably simplest SMB PDU */
struct { struct {
...@@ -712,6 +714,7 @@ typedef struct smb_com_findclose_req { ...@@ -712,6 +714,7 @@ typedef struct smb_com_findclose_req {
#define REQ_OPLOCK 0x00000002 #define REQ_OPLOCK 0x00000002
#define REQ_BATCHOPLOCK 0x00000004 #define REQ_BATCHOPLOCK 0x00000004
#define REQ_OPENDIRONLY 0x00000008 #define REQ_OPENDIRONLY 0x00000008
#define REQ_EXTENDED_INFO 0x00000010
typedef struct smb_com_open_req { /* also handles create */ typedef struct smb_com_open_req { /* also handles create */
struct smb_hdr hdr; /* wct = 24 */ struct smb_hdr hdr; /* wct = 24 */
...@@ -799,27 +802,28 @@ typedef struct smb_com_openx_rsp { ...@@ -799,27 +802,28 @@ typedef struct smb_com_openx_rsp {
__u32 FileId; __u32 FileId;
__u16 Reserved; __u16 Reserved;
__u16 ByteCount; __u16 ByteCount;
} __attribute__((packed)) OPENX_RSP; } __attribute__((packed)) OPENX_RSP;
/* For encoding of POSIX Open Request - see trans2 function 0x209 data struct */ /* For encoding of POSIX Open Request - see trans2 function 0x209 data struct */
/* Legacy write request for older servers */ /* Legacy write request for older servers */
typedef struct smb_com_writex_req { typedef struct smb_com_writex_req {
struct smb_hdr hdr; /* wct = 12 */ struct smb_hdr hdr; /* wct = 12 */
__u8 AndXCommand; __u8 AndXCommand;
__u8 AndXReserved; __u8 AndXReserved;
__le16 AndXOffset; __le16 AndXOffset;
__u16 Fid; __u16 Fid;
__le32 OffsetLow; __le32 OffsetLow;
__u32 Reserved; /* Timeout */ __u32 Reserved; /* Timeout */
__le16 WriteMode; /* 1 = write through */ __le16 WriteMode; /* 1 = write through */
__le16 Remaining; __le16 Remaining;
__le16 Reserved2; __le16 Reserved2;
__le16 DataLengthLow; __le16 DataLengthLow;
__le16 DataOffset; __le16 DataOffset;
__le16 ByteCount; __le16 ByteCount;
__u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */ __u8 Pad; /* BB check for whether padded to DWORD
char Data[0]; boundary and optimum performance here */
char Data[0];
} __attribute__((packed)) WRITEX_REQ; } __attribute__((packed)) WRITEX_REQ;
typedef struct smb_com_write_req { typedef struct smb_com_write_req {
...@@ -837,7 +841,8 @@ typedef struct smb_com_write_req { ...@@ -837,7 +841,8 @@ typedef struct smb_com_write_req {
__le16 DataOffset; __le16 DataOffset;
__le32 OffsetHigh; __le32 OffsetHigh;
__le16 ByteCount; __le16 ByteCount;
__u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */ __u8 Pad; /* BB check for whether padded to DWORD
boundary and optimum performance here */
char Data[0]; char Data[0];
} __attribute__((packed)) WRITE_REQ; } __attribute__((packed)) WRITE_REQ;
...@@ -855,17 +860,17 @@ typedef struct smb_com_write_rsp { ...@@ -855,17 +860,17 @@ typedef struct smb_com_write_rsp {
/* legacy read request for older servers */ /* legacy read request for older servers */
typedef struct smb_com_readx_req { typedef struct smb_com_readx_req {
struct smb_hdr hdr; /* wct = 10 */ struct smb_hdr hdr; /* wct = 10 */
__u8 AndXCommand; __u8 AndXCommand;
__u8 AndXReserved; __u8 AndXReserved;
__le16 AndXOffset; __le16 AndXOffset;
__u16 Fid; __u16 Fid;
__le32 OffsetLow; __le32 OffsetLow;
__le16 MaxCount; __le16 MaxCount;
__le16 MinCount; /* obsolete */ __le16 MinCount; /* obsolete */
__le32 Reserved; __le32 Reserved;
__le16 Remaining; __le16 Remaining;
__le16 ByteCount; __le16 ByteCount;
} __attribute__((packed)) READX_REQ; } __attribute__((packed)) READX_REQ;
typedef struct smb_com_read_req { typedef struct smb_com_read_req {
...@@ -896,7 +901,8 @@ typedef struct smb_com_read_rsp { ...@@ -896,7 +901,8 @@ typedef struct smb_com_read_rsp {
__le16 DataLengthHigh; __le16 DataLengthHigh;
__u64 Reserved2; __u64 Reserved2;
__u16 ByteCount; __u16 ByteCount;
__u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */ __u8 Pad; /* BB check for whether padded to DWORD
boundary and optimum performance here */
char Data[1]; char Data[1];
} __attribute__((packed)) READ_RSP; } __attribute__((packed)) READ_RSP;
...@@ -967,7 +973,7 @@ typedef struct smb_com_rename_req { ...@@ -967,7 +973,7 @@ typedef struct smb_com_rename_req {
#define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */ #define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */
#define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */ #define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */
#define COPY_VERIFY_WRITES 0x0010 #define COPY_VERIFY_WRITES 0x0010
#define COPY_TREE 0x0020 #define COPY_TREE 0x0020
typedef struct smb_com_copy_req { typedef struct smb_com_copy_req {
struct smb_hdr hdr; /* wct = 3 */ struct smb_hdr hdr; /* wct = 3 */
...@@ -975,7 +981,7 @@ typedef struct smb_com_copy_req { ...@@ -975,7 +981,7 @@ typedef struct smb_com_copy_req {
__le16 OpenFunction; __le16 OpenFunction;
__le16 Flags; __le16 Flags;
__le16 ByteCount; __le16 ByteCount;
__u8 BufferFormat; /* 4 = ASCII or Unicode */ __u8 BufferFormat; /* 4 = ASCII or Unicode */
unsigned char OldFileName[1]; unsigned char OldFileName[1];
/* followed by __u8 BufferFormat2 */ /* followed by __u8 BufferFormat2 */
/* followed by NewFileName string */ /* followed by NewFileName string */
...@@ -1083,28 +1089,28 @@ typedef struct smb_com_setattr_rsp { ...@@ -1083,28 +1089,28 @@ typedef struct smb_com_setattr_rsp {
/*******************************************************/ /*******************************************************/
/* NT Transact structure defintions follow */ /* NT Transact structure defintions follow */
/* Currently only ioctl, acl (get security descriptor) */ /* Currently only ioctl, acl (get security descriptor) */
/* and notify are implemented */ /* and notify are implemented */
/*******************************************************/ /*******************************************************/
typedef struct smb_com_ntransact_req { typedef struct smb_com_ntransact_req {
struct smb_hdr hdr; /* wct >= 19 */ struct smb_hdr hdr; /* wct >= 19 */
__u8 MaxSetupCount; __u8 MaxSetupCount;
__u16 Reserved; __u16 Reserved;
__le32 TotalParameterCount; __le32 TotalParameterCount;
__le32 TotalDataCount; __le32 TotalDataCount;
__le32 MaxParameterCount; __le32 MaxParameterCount;
__le32 MaxDataCount; __le32 MaxDataCount;
__le32 ParameterCount; __le32 ParameterCount;
__le32 ParameterOffset; __le32 ParameterOffset;
__le32 DataCount; __le32 DataCount;
__le32 DataOffset; __le32 DataOffset;
__u8 SetupCount; /* four setup words follow subcommand */ __u8 SetupCount; /* four setup words follow subcommand */
/* SNIA spec incorrectly included spurious pad here */ /* SNIA spec incorrectly included spurious pad here */
__le16 SubCommand; /* 2 = IOCTL/FSCTL */ __le16 SubCommand; /* 2 = IOCTL/FSCTL */
/* SetupCount words follow then */ /* SetupCount words follow then */
__le16 ByteCount; __le16 ByteCount;
__u8 Pad[3]; __u8 Pad[3];
__u8 Parms[0]; __u8 Parms[0];
} __attribute__((packed)) NTRANSACT_REQ; } __attribute__((packed)) NTRANSACT_REQ;
typedef struct smb_com_ntransact_rsp { typedef struct smb_com_ntransact_rsp {
...@@ -1120,7 +1126,7 @@ typedef struct smb_com_ntransact_rsp { ...@@ -1120,7 +1126,7 @@ typedef struct smb_com_ntransact_rsp {
__le32 DataDisplacement; __le32 DataDisplacement;
__u8 SetupCount; /* 0 */ __u8 SetupCount; /* 0 */
__u16 ByteCount; __u16 ByteCount;
/* __u8 Pad[3]; */ /* __u8 Pad[3]; */
/* parms and data follow */ /* parms and data follow */
} __attribute__((packed)) NTRANSACT_RSP; } __attribute__((packed)) NTRANSACT_RSP;
...@@ -1215,7 +1221,7 @@ typedef struct smb_com_transaction_change_notify_req { ...@@ -1215,7 +1221,7 @@ typedef struct smb_com_transaction_change_notify_req {
/* __u8 Data[1];*/ /* __u8 Data[1];*/
} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ; } __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 */ and validation routine */
typedef struct smb_com_transaction_change_notify_rsp { typedef struct smb_com_transaction_change_notify_rsp {
struct smb_hdr hdr; /* wct = 18 */ struct smb_hdr hdr; /* wct = 18 */
...@@ -1262,7 +1268,7 @@ struct file_notify_information { ...@@ -1262,7 +1268,7 @@ struct file_notify_information {
__le32 Action; __le32 Action;
__le32 FileNameLength; __le32 FileNameLength;
__u8 FileName[0]; __u8 FileName[0];
} __attribute__((packed)); } __attribute__((packed));
struct reparse_data { struct reparse_data {
__u32 ReparseTag; __u32 ReparseTag;
...@@ -1331,7 +1337,7 @@ struct trans2_resp { ...@@ -1331,7 +1337,7 @@ struct trans2_resp {
__u8 Reserved1; __u8 Reserved1;
/* SetupWords[SetupCount]; /* SetupWords[SetupCount];
__u16 ByteCount; __u16 ByteCount;
__u16 Reserved2;*/ __u16 Reserved2;*/
/* data area follows */ /* data area follows */
} __attribute__((packed)); } __attribute__((packed));
...@@ -1370,9 +1376,9 @@ struct smb_t2_rsp { ...@@ -1370,9 +1376,9 @@ struct smb_t2_rsp {
#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee #define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 #define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ #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_MODE_INFO 0x3f8
#define SMB_QUERY_FILE_ALGN_INFO 0x3f9 #define SMB_QUERY_FILE_ALGN_INFO 0x3f9
#define SMB_SET_FILE_BASIC_INFO 0x101 #define SMB_SET_FILE_BASIC_INFO 0x101
...@@ -1506,35 +1512,35 @@ struct smb_com_transaction2_sfi_req { ...@@ -1506,35 +1512,35 @@ struct smb_com_transaction2_sfi_req {
__u16 Pad1; __u16 Pad1;
__u16 Fid; __u16 Fid;
__le16 InformationLevel; __le16 InformationLevel;
__u16 Reserved4; __u16 Reserved4;
} __attribute__((packed)); } __attribute__((packed));
struct smb_com_transaction2_sfi_rsp { struct smb_com_transaction2_sfi_rsp {
struct smb_hdr hdr; /* wct = 10 + SetupCount */ struct smb_hdr hdr; /* wct = 10 + SetupCount */
struct trans2_resp t2; struct trans2_resp t2;
__u16 ByteCount; __u16 ByteCount;
__u16 Reserved2; /* parameter word reserved - __u16 Reserved2; /* parameter word reserved -
present for infolevels > 100 */ present for infolevels > 100 */
} __attribute__((packed)); } __attribute__((packed));
struct smb_t2_qfi_req { struct smb_t2_qfi_req {
struct smb_hdr hdr; struct smb_hdr hdr;
struct trans2_req t2; struct trans2_req t2;
__u8 Pad; __u8 Pad;
__u16 Fid; __u16 Fid;
__le16 InformationLevel; __le16 InformationLevel;
} __attribute__((packed)); } __attribute__((packed));
struct smb_t2_qfi_rsp { struct smb_t2_qfi_rsp {
struct smb_hdr hdr; /* wct = 10 + SetupCount */ struct smb_hdr hdr; /* wct = 10 + SetupCount */
struct trans2_resp t2; struct trans2_resp t2;
__u16 ByteCount; __u16 ByteCount;
__u16 Reserved2; /* parameter word reserved - __u16 Reserved2; /* parameter word reserved -
present for infolevels > 100 */ present for infolevels > 100 */
} __attribute__((packed)); } __attribute__((packed));
/* /*
* Flags on T2 FINDFIRST and FINDNEXT * Flags on T2 FINDFIRST and FINDNEXT
*/ */
#define CIFS_SEARCH_CLOSE_ALWAYS 0x0001 #define CIFS_SEARCH_CLOSE_ALWAYS 0x0001
#define CIFS_SEARCH_CLOSE_AT_END 0x0002 #define CIFS_SEARCH_CLOSE_AT_END 0x0002
...@@ -1743,7 +1749,9 @@ typedef struct smb_com_transaction2_get_dfs_refer_req { ...@@ -1743,7 +1749,9 @@ typedef struct smb_com_transaction2_get_dfs_refer_req {
__u8 Reserved3; __u8 Reserved3;
__le16 SubCommand; /* one setup word */ __le16 SubCommand; /* one setup word */
__le16 ByteCount; __le16 ByteCount;
__u8 Pad[3]; /* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */ __u8 Pad[3]; /* Win2K has sent 0x0F01 (max response length
perhaps?) followed by one byte pad - doesn't
seem to matter though */
__le16 MaxReferralLevel; __le16 MaxReferralLevel;
char RequestFileName[1]; char RequestFileName[1];
} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ; } __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ;
...@@ -1752,7 +1760,10 @@ typedef struct dfs_referral_level_3 { ...@@ -1752,7 +1760,10 @@ typedef struct dfs_referral_level_3 {
__le16 VersionNumber; __le16 VersionNumber;
__le16 ReferralSize; __le16 ReferralSize;
__le16 ServerType; /* 0x0001 = CIFS server */ __le16 ServerType; /* 0x0001 = CIFS server */
__le16 ReferralFlags; /* or proximity - not clear which since always set to zero - SNIA spec says 0x01 means strip off PathConsumed chars before submitting RequestFileName to remote node */ __le16 ReferralFlags; /* or proximity - not clear which since it is
always set to zero - SNIA spec says 0x01
means strip off PathConsumed chars before
submitting RequestFileName to remote node */
__le16 TimeToLive; __le16 TimeToLive;
__le16 Proximity; __le16 Proximity;
__le16 DfsPathOffset; __le16 DfsPathOffset;
...@@ -1778,11 +1789,13 @@ typedef struct smb_com_transaction_get_dfs_refer_rsp { ...@@ -1778,11 +1789,13 @@ typedef struct smb_com_transaction_get_dfs_refer_rsp {
#define DFSREF_STORAGE_SERVER 0x0002 #define DFSREF_STORAGE_SERVER 0x0002
/* IOCTL information */ /* IOCTL information */
/* List of ioctl function codes that look to be of interest to remote clients like this. */ /*
/* Need to do some experimentation to make sure they all work remotely. */ * List of ioctl function codes that look to be of interest to remote clients
/* Some of the following such as the encryption/compression ones would be */ * like this one. Need to do some experimentation to make sure they all work
/* invoked from tools via a specialized hook into the VFS rather than via the */ * remotely. Some of the following, such as the encryption/compression ones
/* standard vfs entry points */ * would be invoked from tools via a specialized hook into the VFS rather
* than via the standard vfs entry points
*/
#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000 #define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004 #define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008 #define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
...@@ -1811,7 +1824,7 @@ typedef struct smb_com_transaction_get_dfs_refer_rsp { ...@@ -1811,7 +1824,7 @@ typedef struct smb_com_transaction_get_dfs_refer_rsp {
/* /*
************************************************************************ ************************************************************************
* All structs for everything above the SMB PDUs themselves * 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 { ...@@ -1857,7 +1870,7 @@ typedef struct {
__le64 FreeAllocationUnits; __le64 FreeAllocationUnits;
__le32 SectorsPerAllocationUnit; __le32 SectorsPerAllocationUnit;
__le32 BytesPerSector; __le32 BytesPerSector;
} __attribute__((packed)) FILE_SYSTEM_INFO; /* size info, level 0x103 */ } __attribute__((packed)) FILE_SYSTEM_INFO; /* size info, level 0x103 */
typedef struct { typedef struct {
__le32 fsid; __le32 fsid;
...@@ -1871,7 +1884,7 @@ typedef struct { ...@@ -1871,7 +1884,7 @@ typedef struct {
__le16 MajorVersionNumber; __le16 MajorVersionNumber;
__le16 MinorVersionNumber; __le16 MinorVersionNumber;
__le64 Capability; __le64 Capability;
} __attribute__((packed)) FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */ } __attribute__((packed)) FILE_SYSTEM_UNIX_INFO; /* Unix extension level 0x200*/
/* Version numbers for CIFS UNIX major and minor. */ /* Version numbers for CIFS UNIX major and minor. */
#define CIFS_UNIX_MAJOR_VERSION 1 #define CIFS_UNIX_MAJOR_VERSION 1
...@@ -1885,16 +1898,20 @@ typedef struct { ...@@ -1885,16 +1898,20 @@ typedef struct {
#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */ #define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */
#define CIFS_UNIX_POSIX_PATH_OPS_CAP 0x00000020 /* Allow new POSIX path based #define CIFS_UNIX_POSIX_PATH_OPS_CAP 0x00000020 /* Allow new POSIX path based
calls including posix open calls including posix open
and posix unlink */ and posix unlink */
#define CIFS_UNIX_LARGE_READ_CAP 0x00000040 /* support reads >128K (up
to 0xFFFF00 */
#define CIFS_UNIX_LARGE_WRITE_CAP 0x00000080
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
/* Can not set pathnames cap yet until we send new posix create SMB since /* Can not set pathnames cap yet until we send new posix create SMB since
otherwise server can treat such handles opened with older ntcreatex otherwise server can treat such handles opened with older ntcreatex
(by a new client which knows how to send posix path ops) (by a new client which knows how to send posix path ops)
as non-posix handles (can affect write behavior with byte range locks. as non-posix handles (can affect write behavior with byte range locks.
We can add back in POSIX_PATH_OPS cap when Posix Create/Mkdir finished */ We can add back in POSIX_PATH_OPS cap when Posix Create/Mkdir finished */
/* #define CIFS_UNIX_CAP_MASK 0x0000003b */ /* #define CIFS_UNIX_CAP_MASK 0x000000fb */
#define CIFS_UNIX_CAP_MASK 0x0000001b #define CIFS_UNIX_CAP_MASK 0x000000db
#else #else
#define CIFS_UNIX_CAP_MASK 0x00000013 #define CIFS_UNIX_CAP_MASK 0x00000013
#endif /* CONFIG_CIFS_POSIX */ #endif /* CONFIG_CIFS_POSIX */
...@@ -1904,10 +1921,10 @@ typedef struct { ...@@ -1904,10 +1921,10 @@ typedef struct {
typedef struct { typedef struct {
/* For undefined recommended transfer size return -1 in that field */ /* For undefined recommended transfer size return -1 in that field */
__le32 OptimalTransferSize; /* bsize on some os, iosize on other os */ __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. /* The next three fields are in terms of the block size.
(above). If block size is unknown, 4096 would be a (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 Note that returning the blocks/blocksavail removes need
to make a second call (to QFSInfo level 0x103 to get this info. to make a second call (to QFSInfo level 0x103 to get this info.
UserBlockAvail is typically less than or equal to BlocksAvail, UserBlockAvail is typically less than or equal to BlocksAvail,
...@@ -2062,9 +2079,9 @@ struct file_alt_name_info { ...@@ -2062,9 +2079,9 @@ struct file_alt_name_info {
struct file_stream_info { struct file_stream_info {
__le32 number_of_streams; /* BB check sizes and verify location */ __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 size;
u64 allocation_size u64 allocation_size
stream info */ stream info */
}; /* level 0x109 */ }; /* level 0x109 */
...@@ -2083,7 +2100,7 @@ struct cifs_posix_ace { /* access control entry (ACE) */ ...@@ -2083,7 +2100,7 @@ struct cifs_posix_ace { /* access control entry (ACE) */
__u8 cifs_e_tag; __u8 cifs_e_tag;
__u8 cifs_e_perm; __u8 cifs_e_perm;
__le64 cifs_uid; /* or gid */ __le64 cifs_uid; /* or gid */
} __attribute__((packed)); } __attribute__((packed));
struct cifs_posix_acl { /* access conrol list (ACL) */ struct cifs_posix_acl { /* access conrol list (ACL) */
__le16 version; __le16 version;
...@@ -2138,6 +2155,12 @@ typedef struct { ...@@ -2138,6 +2155,12 @@ typedef struct {
/* struct following varies based on requested level */ /* struct following varies based on requested level */
} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */ } __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
#define SMB_POSIX_UNLINK_FILE_TARGET 0
#define SMB_POSIX_UNLINK_DIRECTORY_TARGET 1
struct unlink_psx_rq { /* level 0x20a SetPathInfo */
__le16 type;
} __attribute__((packed));
struct file_internal_info { struct file_internal_info {
__u64 UniqueId; /* inode number */ __u64 UniqueId; /* inode number */
...@@ -2154,7 +2177,7 @@ struct file_attrib_tag { ...@@ -2154,7 +2177,7 @@ struct file_attrib_tag {
/********************************************************/ /********************************************************/
/* FindFirst/FindNext transact2 data buffer formats */ /* FindFirst/FindNext transact2 data buffer formats */
/********************************************************/ /********************************************************/
typedef struct { typedef struct {
...@@ -2232,7 +2255,7 @@ typedef struct { ...@@ -2232,7 +2255,7 @@ typedef struct {
__le64 EndOfFile; __le64 EndOfFile;
__le64 AllocationSize; __le64 AllocationSize;
__le32 ExtFileAttributes; __le32 ExtFileAttributes;
__le32 FileNameLength; __le32 FileNameLength;
__le32 EaSize; /* length of the xattrs */ __le32 EaSize; /* length of the xattrs */
__u8 ShortNameLength; __u8 ShortNameLength;
__u8 Reserved; __u8 Reserved;
...@@ -2259,7 +2282,7 @@ typedef struct { ...@@ -2259,7 +2282,7 @@ typedef struct {
struct win_dev { struct win_dev {
unsigned char type[8]; /* IntxCHR or IntxBLK */ unsigned char type[8]; /* IntxCHR or IntxBLK */
__le64 major; __le64 major;
__le64 minor; __le64 minor;
} __attribute__((packed)); } __attribute__((packed));
struct gea { struct gea {
...@@ -2291,36 +2314,36 @@ struct fealist { ...@@ -2291,36 +2314,36 @@ struct fealist {
struct data_blob { struct data_blob {
__u8 *data; __u8 *data;
size_t length; size_t length;
void (*free) (struct data_blob * data_blob); void (*free) (struct data_blob *data_blob);
} __attribute__((packed)); } __attribute__((packed));
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
/* /*
For better POSIX semantics from Linux client, (even better For better POSIX semantics from Linux client, (even better
than the existing CIFS Unix Extensions) we need updated PDUs for: than the existing CIFS Unix Extensions) we need updated PDUs for:
1) PosixCreateX - to set and return the mode, inode#, device info and 1) PosixCreateX - to set and return the mode, inode#, device info and
perhaps add a CreateDevice - to create Pipes and other special .inodes perhaps add a CreateDevice - to create Pipes and other special .inodes
Also note POSIX open flags 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 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) forms short (matches readdir) and full (enough info to cache inodes)
4) Mkdir - set mode 4) Mkdir - set mode
And under consideration: And under consideration:
5) FindClose2 (return nanosecond timestamp ??) 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 corresponding attribute flag is set
7) sendfile - handle based copy 7) sendfile - handle based copy
8) Direct i/o 8) Direct i/o
9) Misc fcntls? 9) Misc fcntls?
what about fixing 64 bit alignment what about fixing 64 bit alignment
There are also various legacy SMB/CIFS requests used as is There are also various legacy SMB/CIFS requests used as is
From existing Lanman and NTLM dialects: From existing Lanman and NTLM dialects:
-------------------------------------- --------------------------------------
NEGOTIATE NEGOTIATE
...@@ -2341,48 +2364,48 @@ struct data_blob { ...@@ -2341,48 +2364,48 @@ struct data_blob {
(BB verify that never need to set allocation size) (BB verify that never need to set allocation size)
SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via
Unix ext?) Unix ext?)
COPY (note support for copy across directories) - FUTURE, OPTIONAL COPY (note support for copy across directories) - FUTURE, OPTIONAL
setting/getting OS/2 EAs - FUTURE (BB can this handle setting/getting OS/2 EAs - FUTURE (BB can this handle
setting Linux xattrs perfectly) - OPTIONAL setting Linux xattrs perfectly) - OPTIONAL
dnotify - FUTURE, OPTIONAL dnotify - FUTURE, OPTIONAL
quota - 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 NT_TRANSACT (IOCTL) QueryReparseInfo
are unneeded to servers compliant with the CIFS POSIX extensions are unneeded to servers compliant with the CIFS POSIX extensions
From CIFS Unix Extensions: From CIFS Unix Extensions:
------------------------- -------------------------
T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2) T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK) T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) BB check for missing
Actually need QUERY_FILE_UNIX_INFO since has inode num inode fields
BB what about a) blksize/blkbits/blocks Actually a need QUERY_FILE_UNIX_INFO
since has inode num
BB what about a) blksize/blkbits/blocks
b) i_version b) i_version
c) i_rdev c) i_rdev
d) notify mask? d) notify mask?
e) generation e) generation
f) size_seqcount f) size_seqcount
T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
*/ */
/* xsymlink is a symlink format (used by MacOS) that can be used /* xsymlink is a symlink format (used by MacOS) that can be used
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 mounted to operating systems that do not
support the cifs Unix extensions or EAs (for xattr support the cifs Unix extensions or EAs (for xattr
based symlinks). For such a file to be recognized 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, 2) signature must begin file data,
3) length field must be set to ASCII representation 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 */ 4) md5 must match that of the path data */
struct xsymlink { struct xsymlink {
...@@ -2393,10 +2416,10 @@ struct xsymlink { ...@@ -2393,10 +2416,10 @@ struct xsymlink {
char length[4]; char length[4];
char cr1; /* \n */ char cr1; /* \n */
/* md5 of valid subset of path ie path[0] through path[length-1] */ /* md5 of valid subset of path ie path[0] through path[length-1] */
__u8 md5[32]; __u8 md5[32];
char cr2; /* \n */ char cr2; /* \n */
/* if room left, then end with \n then 0x20s by convention but not required */ /* if room left, then end with \n then 0x20s by convention but not required */
char path[1024]; char path[1024];
} __attribute__((packed)); } __attribute__((packed));
typedef struct file_xattr_info { typedef struct file_xattr_info {
...@@ -2405,7 +2428,8 @@ typedef struct file_xattr_info { ...@@ -2405,7 +2428,8 @@ typedef struct file_xattr_info {
__u32 xattr_value_len; __u32 xattr_value_len;
char xattr_name[0]; char xattr_name[0];
/* followed by xattr_value[xattr_value_len], no pad */ /* followed by xattr_value[xattr_value_len], no pad */
} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute, info level 0x205 */ } __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute info
level 0x205 */
/* flags for chattr command */ /* flags for chattr command */
...@@ -2431,8 +2455,9 @@ typedef struct file_xattr_info { ...@@ -2431,8 +2455,9 @@ typedef struct file_xattr_info {
typedef struct file_chattr_info { typedef struct file_chattr_info {
__le64 mask; /* list of all possible attribute bits */ __le64 mask; /* list of all possible attribute bits */
__le64 mode; /* list of actual attribute bits on this inode */ __le64 mode; /* list of actual attribute bits on this inode */
} __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes (chattr, chflags) level 0x206 */ } __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes
(chattr, chflags) level 0x206 */
#endif #endif
#endif /* _CIFSPDU_H */ #endif /* _CIFSPDU_H */
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software * 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 #ifndef _CIFSPROTO_H
#define _CIFSPROTO_H #define _CIFSPROTO_H
...@@ -49,9 +49,9 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, ...@@ -49,9 +49,9 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
struct smb_hdr * /* out */ , struct smb_hdr * /* out */ ,
int * /* bytes returned */ , const int long_op); int * /* bytes returned */ , const int long_op);
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, 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); 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 cifsTconInfo *,
struct smb_hdr * /* input */ , struct smb_hdr * /* input */ ,
struct smb_hdr * /* out */ , struct smb_hdr * /* out */ ,
...@@ -64,19 +64,19 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr); ...@@ -64,19 +64,19 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr);
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
extern int decode_negTokenInit(unsigned char *security_blob, int length, extern int decode_negTokenInit(unsigned char *security_blob, int length,
enum securityEnum *secType); enum securityEnum *secType);
extern int cifs_inet_pton(int, char * source, void *dst); extern int cifs_inet_pton(int, char *source, void *dst);
extern int map_smb_to_linux_error(struct smb_hdr *smb); extern int map_smb_to_linux_error(struct smb_hdr *smb);
extern void header_assemble(struct smb_hdr *, char /* command */ , extern void header_assemble(struct smb_hdr *, char /* command */ ,
const struct cifsTconInfo *, int /* length of const struct cifsTconInfo *, int /* length of
fixed section (word count) in two byte units */); fixed section (word count) in two byte units */);
extern int small_smb_init_no_tc(const int smb_cmd, const int wct, extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
struct cifsSesInfo *ses, struct cifsSesInfo *ses,
void ** request_buf); void **request_buf);
extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
const int stage, const int stage,
const struct nls_table *nls_cp); const struct nls_table *nls_cp);
extern __u16 GetNextMid(struct TCP_Server_Info *server); extern __u16 GetNextMid(struct TCP_Server_Info *server);
extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16,
struct cifsTconInfo *); struct cifsTconInfo *);
extern void DeleteOplockQEntry(struct oplock_q_entry *); extern void DeleteOplockQEntry(struct oplock_q_entry *);
extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ ); extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
...@@ -85,12 +85,12 @@ extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); ...@@ -85,12 +85,12 @@ extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
extern int cifs_get_inode_info(struct inode **pinode, extern int cifs_get_inode_info(struct inode **pinode,
const unsigned char *search_path, const unsigned char *search_path,
FILE_ALL_INFO * pfile_info, FILE_ALL_INFO * pfile_info,
struct super_block *sb, int xid); struct super_block *sb, int xid);
extern int cifs_get_inode_info_unix(struct inode **pinode, extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path, const unsigned char *search_path,
struct super_block *sb,int xid); struct super_block *sb, int xid);
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
const char *); const char *);
...@@ -98,8 +98,8 @@ extern int cifs_umount(struct super_block *, struct cifs_sb_info *); ...@@ -98,8 +98,8 @@ extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
void cifs_proc_init(void); void cifs_proc_init(void);
void cifs_proc_clean(void); void cifs_proc_clean(void);
extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
struct nls_table * nls_info); struct nls_table *nls_info);
extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses); extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
...@@ -108,11 +108,11 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, ...@@ -108,11 +108,11 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
const char *searchName, const struct nls_table *nls_codepage, const char *searchName, const struct nls_table *nls_codepage,
__u16 *searchHandle, struct cifs_search_info * psrch_inf, __u16 *searchHandle, struct cifs_search_info *psrch_inf,
int map, const char dirsep); int map, const char dirsep);
extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
__u16 searchHandle, struct cifs_search_info * psrch_inf); __u16 searchHandle, struct cifs_search_info *psrch_inf);
extern int CIFSFindClose(const int, struct cifsTconInfo *tcon, extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
const __u16 search_handle); const __u16 search_handle);
...@@ -123,9 +123,9 @@ extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, ...@@ -123,9 +123,9 @@ extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
int legacy /* whether to use old info level */, int legacy /* whether to use old info level */,
const struct nls_table *nls_codepage, int remap); const struct nls_table *nls_codepage, int remap);
extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName, const unsigned char *searchName,
FILE_ALL_INFO * findData, FILE_ALL_INFO *findData,
const struct nls_table *nls_codepage, int remap); const struct nls_table *nls_codepage, int remap);
extern int CIFSSMBUnixQPathInfo(const int xid, extern int CIFSSMBUnixQPathInfo(const int xid,
struct cifsTconInfo *tcon, struct cifsTconInfo *tcon,
...@@ -143,13 +143,13 @@ extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, ...@@ -143,13 +143,13 @@ extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
const char *old_path, const char *old_path,
const struct nls_table *nls_codepage, int remap); const struct nls_table *nls_codepage, int remap);
extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
const char *old_path, const char *old_path,
const struct nls_table *nls_codepage, const struct nls_table *nls_codepage,
unsigned int *pnum_referrals, unsigned int *pnum_referrals,
unsigned char ** preferrals, unsigned char **preferrals,
int remap); int remap);
extern void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, extern void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
struct super_block * sb, struct smb_vol * vol); struct super_block *sb, struct smb_vol *vol);
extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
struct kstatfs *FSData); struct kstatfs *FSData);
extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, extern int SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon,
...@@ -181,11 +181,11 @@ extern int CIFSSMBSetEOF(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, const struct nls_table *nls_codepage,
int remap_special_chars); int remap_special_chars);
extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
__u64 size, __u16 fileHandle,__u32 opener_pid, __u64 size, __u16 fileHandle, __u32 opener_pid,
int AllocSizeFlag); int AllocSizeFlag);
extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon, extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
char *full_path, __u64 mode, __u64 uid, char *full_path, __u64 mode, __u64 uid,
__u64 gid, dev_t dev, __u64 gid, dev_t dev,
const struct nls_table *nls_codepage, const struct nls_table *nls_codepage,
int remap_special_chars); int remap_special_chars);
...@@ -196,7 +196,10 @@ extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, ...@@ -196,7 +196,10 @@ extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
const char *name, const struct nls_table *nls_codepage, const char *name, const struct nls_table *nls_codepage,
int remap_special_chars); int remap_special_chars);
extern int CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon,
const char *name, __u16 type,
const struct nls_table *nls_codepage,
int remap_special_chars);
extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
const char *name, const char *name,
const struct nls_table *nls_codepage, const struct nls_table *nls_codepage,
...@@ -205,8 +208,8 @@ extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, ...@@ -205,8 +208,8 @@ extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
const char *fromName, const char *toName, const char *fromName, const char *toName,
const struct nls_table *nls_codepage, const struct nls_table *nls_codepage,
int remap_special_chars); int remap_special_chars);
extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, extern int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
int netfid, char * target_name, int netfid, char *target_name,
const struct nls_table *nls_codepage, const struct nls_table *nls_codepage,
int remap_special_chars); int remap_special_chars);
extern int CIFSCreateHardLink(const int xid, extern int CIFSCreateHardLink(const int xid,
...@@ -217,7 +220,7 @@ extern int CIFSCreateHardLink(const int xid, ...@@ -217,7 +220,7 @@ extern int CIFSCreateHardLink(const int xid,
extern int CIFSUnixCreateHardLink(const int xid, extern int CIFSUnixCreateHardLink(const int xid,
struct cifsTconInfo *tcon, struct cifsTconInfo *tcon,
const char *fromName, const char *toName, const char *fromName, const char *toName,
const struct nls_table *nls_codepage, const struct nls_table *nls_codepage,
int remap_special_chars); int remap_special_chars);
extern int CIFSUnixCreateSymLink(const int xid, extern int CIFSUnixCreateSymLink(const int xid,
struct cifsTconInfo *tcon, struct cifsTconInfo *tcon,
...@@ -228,7 +231,7 @@ extern int CIFSSMBUnixQuerySymLink(const int xid, ...@@ -228,7 +231,7 @@ extern int CIFSSMBUnixQuerySymLink(const int xid,
const unsigned char *searchName, const unsigned char *searchName,
char *syminfo, const int buflen, char *syminfo, const int buflen,
const struct nls_table *nls_codepage); const struct nls_table *nls_codepage);
extern int CIFSSMBQueryReparseLinkInfo(const int xid, extern int CIFSSMBQueryReparseLinkInfo(const int xid,
struct cifsTconInfo *tcon, struct cifsTconInfo *tcon,
const unsigned char *searchName, const unsigned char *searchName,
char *symlinkinfo, const int buflen, __u16 fid, char *symlinkinfo, const int buflen, __u16 fid,
...@@ -244,35 +247,35 @@ extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, ...@@ -244,35 +247,35 @@ extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
const int access_flags, const int omode, const int access_flags, const int omode,
__u16 * netfid, int *pOplock, FILE_ALL_INFO *, __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
const struct nls_table *nls_codepage, int remap); 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, u32 posix_flags, __u64 mode, __u16 * netfid,
FILE_UNIX_BASIC_INFO *pRetData, FILE_UNIX_BASIC_INFO *pRetData,
__u32 *pOplock, const char *name, __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, extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
const int smb_file_id); const int smb_file_id);
extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
const int netfid, unsigned int count, const int netfid, unsigned int count,
const __u64 lseek, unsigned int *nbytes, char **buf, const __u64 lseek, unsigned int *nbytes, char **buf,
int * return_buf_type); int *return_buf_type);
extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
const int netfid, const unsigned int count, const int netfid, const unsigned int count,
const __u64 lseek, unsigned int *nbytes, const __u64 lseek, unsigned int *nbytes,
const char *buf, const char __user *ubuf, const char *buf, const char __user *ubuf,
const int long_op); const int long_op);
extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
const int netfid, const unsigned int count, 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); struct kvec *iov, const int nvec, const int long_op);
extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName, __u64 * inode_number, const unsigned char *searchName, __u64 * inode_number,
const struct nls_table *nls_codepage, const struct nls_table *nls_codepage,
int remap_special_chars); int remap_special_chars);
extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
const struct nls_table * codepage); const struct nls_table *codepage);
extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen, extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
const struct nls_table * cp, int mapChars); const struct nls_table *cp, int mapChars);
extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const __u16 netfid, const __u64 len, const __u16 netfid, const __u64 len,
...@@ -281,7 +284,7 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, ...@@ -281,7 +284,7 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const int waitFlag); const int waitFlag);
extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
const __u16 smb_file_id, const int get_flag, 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); const __u16 lock_type, const int waitFlag);
extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses); extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
...@@ -291,54 +294,56 @@ extern void sesInfoFree(struct cifsSesInfo *); ...@@ -291,54 +294,56 @@ extern void sesInfoFree(struct cifsSesInfo *);
extern struct cifsTconInfo *tconInfoAlloc(void); extern struct cifsTconInfo *tconInfoAlloc(void);
extern void tconInfoFree(struct cifsTconInfo *); extern void tconInfoFree(struct cifsTconInfo *);
extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *); extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
__u32 *); __u32 *);
extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, extern int cifs_verify_signature(struct smb_hdr *,
__u32 expected_sequence_number); const struct mac_key *mac_key,
extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); __u32 expected_sequence_number);
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, 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 *); const struct nls_table *);
extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * ); extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * );
extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
const struct nls_table *); const struct nls_table *);
#ifdef CONFIG_CIFS_WEAK_PW_HASH #ifdef CONFIG_CIFS_WEAK_PW_HASH
extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key); extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key);
#endif /* CIFS_WEAK_PW_HASH */ #endif /* CIFS_WEAK_PW_HASH */
extern int CIFSSMBCopy(int xid, extern int CIFSSMBCopy(int xid,
struct cifsTconInfo *source_tcon, struct cifsTconInfo *source_tcon,
const char *fromName, const char *fromName,
const __u16 target_tid, const __u16 target_tid,
const char *toName, const int flags, const char *toName, const int flags,
const struct nls_table *nls_codepage, const struct nls_table *nls_codepage,
int remap_special_chars); int remap_special_chars);
extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
const int notify_subdirs,const __u16 netfid, const int notify_subdirs, const __u16 netfid,
__u32 filter, struct file * file, int multishot, __u32 filter, struct file *file, int multishot,
const struct nls_table *nls_codepage); const struct nls_table *nls_codepage);
extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName, char * EAData, const unsigned char *searchName, char *EAData,
size_t bufsize, const struct nls_table *nls_codepage, size_t bufsize, const struct nls_table *nls_codepage,
int remap_special_chars); int remap_special_chars);
extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon, extern ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
const unsigned char * searchName,const unsigned char * ea_name, const unsigned char *searchName, const unsigned char *ea_name,
unsigned char * ea_value, size_t buf_size, unsigned char *ea_value, size_t buf_size,
const struct nls_table *nls_codepage, int remap_special_chars); const struct nls_table *nls_codepage, int remap_special_chars);
extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const char * ea_name, const char *fileName, const char *ea_name,
const void * ea_value, const __u16 ea_value_len, const void *ea_value, const __u16 ea_value_len,
const struct nls_table *nls_codepage, int remap_special_chars); const struct nls_table *nls_codepage, int remap_special_chars);
extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
__u16 fid, char *acl_inf, const int buflen, __u16 fid, char *acl_inf, const int buflen,
const int acl_type /* ACCESS vs. DEFAULT */); const int acl_type /* ACCESS vs. DEFAULT */);
extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName, const unsigned char *searchName,
char *acl_inf, const int buflen,const int acl_type, char *acl_inf, const int buflen, const int acl_type,
const struct nls_table *nls_codepage, int remap_special_chars); const struct nls_table *nls_codepage, int remap_special_chars);
extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
const unsigned char *fileName, const unsigned char *fileName,
const char *local_acl, const int buflen, const int acl_type, const char *local_acl, const int buflen, const int acl_type,
const struct nls_table *nls_codepage, int remap_special_chars); const struct nls_table *nls_codepage, int remap_special_chars);
extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, 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 */ #endif /* _CIFSPROTO_H */
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -135,10 +135,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -135,10 +135,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
char *full_path = NULL; char *full_path = NULL;
FILE_ALL_INFO * buf = NULL; FILE_ALL_INFO *buf = NULL;
struct inode *newinode = NULL; struct inode *newinode = NULL;
struct cifsFileInfo * pCifsFile = NULL; struct cifsFileInfo *pCifsFile = NULL;
struct cifsInodeInfo * pCifsInode; struct cifsInodeInfo *pCifsInode;
int disposition = FILE_OVERWRITE_IF; int disposition = FILE_OVERWRITE_IF;
int write_only = FALSE; int write_only = FALSE;
...@@ -207,8 +207,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -207,8 +207,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
} else { } else {
/* If Open reported that we actually created a file /* If Open reported that we actually created a file
then we now have to set the mode if possible */ then we now have to set the mode if possible */
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) && if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
(oplock & CIFS_CREATE_ACTION)) {
mode &= ~current->fs->umask; mode &= ~current->fs->umask;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
...@@ -235,8 +234,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -235,8 +234,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
/* Could set r/o dos attribute if mode & 0222 == 0 */ /* Could set r/o dos attribute if mode & 0222 == 0 */
} }
/* BB server might mask mode so we have to query for Unix case*/ /* server might mask mode so we have to query for it */
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->unix_ext)
rc = cifs_get_inode_info_unix(&newinode, full_path, rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb, xid); inode->i_sb, xid);
else { else {
...@@ -264,7 +263,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -264,7 +263,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
direntry->d_op = &cifs_dentry_ops; direntry->d_op = &cifs_dentry_ops;
d_instantiate(direntry, newinode); d_instantiate(direntry, newinode);
} }
if ((nd->flags & LOOKUP_OPEN) == FALSE) { if ((nd == NULL /* nfsd case - nfs srv does not set nd */) ||
((nd->flags & LOOKUP_OPEN) == FALSE)) {
/* mknod case - do not leave file open */ /* mknod case - do not leave file open */
CIFSSMBClose(xid, pTcon, fileHandle); CIFSSMBClose(xid, pTcon, fileHandle);
} else if (newinode) { } else if (newinode) {
...@@ -323,7 +323,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -323,7 +323,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
char *full_path = NULL; char *full_path = NULL;
struct inode * newinode = NULL; struct inode *newinode = NULL;
if (!old_valid_dev(device_number)) if (!old_valid_dev(device_number))
return -EINVAL; return -EINVAL;
...@@ -336,7 +336,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -336,7 +336,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) if (full_path == NULL)
rc = -ENOMEM; rc = -ENOMEM;
else if (pTcon->ses->capabilities & CAP_UNIX) { else if (pTcon->unix_ext) {
mode &= ~current->fs->umask; mode &= ~current->fs->umask;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
...@@ -490,7 +490,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -490,7 +490,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
cFYI(1, cFYI(1,
(" Full path: %s inode = 0x%p", full_path, direntry->d_inode)); (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->unix_ext)
rc = cifs_get_inode_info_unix(&newInode, full_path, rc = cifs_get_inode_info_unix(&newInode, full_path,
parent_dir_inode->i_sb, xid); parent_dir_inode->i_sb, xid);
else else
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* Common Internet FileSystem (CIFS) client * Common Internet FileSystem (CIFS) client
* *
* Operations related to support for exporting files via NFSD * Operations related to support for exporting files via NFSD
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -22,32 +22,45 @@ ...@@ -22,32 +22,45 @@
* along with this library; if not, write to the Free Software * 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
*/ */
/* /*
* See Documentation/filesystems/Exporting * See Documentation/filesystems/Exporting
* and examples in fs/exportfs * and examples in fs/exportfs
*
* Since cifs is a network file system, an "fsid" must be included for
* any nfs exports file entries which refer to cifs paths. In addition
* the cifs mount must be mounted with the "serverino" option (ie use stable
* server inode numbers instead of locally generated temporary ones).
* Although cifs inodes do not use generation numbers (have generation number
* of zero) - the inode number alone should be good enough for simple cases
* in which users want to export cifs shares with NFS. The decode and encode
* could be improved by using a new routine which expects 64 bit inode numbers
* instead of the default 32 bit routines in fs/exportfs
*
*/ */
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/exportfs.h> #include <linux/exportfs.h>
#include "cifsglob.h"
#include "cifs_debug.h"
#ifdef CONFIG_CIFS_EXPERIMENTAL #ifdef CONFIG_CIFS_EXPERIMENTAL
static struct dentry *cifs_get_parent(struct dentry *dentry) static struct dentry *cifs_get_parent(struct dentry *dentry)
{ {
/* BB need to add code here eventually to enable export via NFSD */ /* BB need to add code here eventually to enable export via NFSD */
return ERR_PTR(-EACCES); cFYI(1, ("get parent for %p", dentry));
return ERR_PTR(-EACCES);
} }
struct export_operations cifs_export_ops = { struct export_operations cifs_export_ops = {
.get_parent = cifs_get_parent, .get_parent = cifs_get_parent,
/* Following five export operations are unneeded so far and can default */ /* Following five export operations are unneeded so far and can default:
/* .get_dentry = .get_dentry =
.get_name = .get_name =
.find_exported_dentry = .find_exported_dentry =
.decode_fh = .decode_fh =
.encode_fs = */ .encode_fs = */
}; };
#endif /* EXPERIMENTAL */ #endif /* EXPERIMENTAL */
...@@ -66,7 +66,7 @@ static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags) ...@@ -66,7 +66,7 @@ static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags)
return cifs_ntfy_flags; return cifs_ntfy_flags;
} }
int cifs_dir_notify(struct file * file, unsigned long arg) int cifs_dir_notify(struct file *file, unsigned long arg)
{ {
int xid; int xid;
int rc = -EINVAL; int rc = -EINVAL;
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
* fs/cifs/file.c * fs/cifs/file.c
* *
* vfs operations that deal with files * vfs operations that deal with files
* *
* Copyright (C) International Business Machines Corp., 2002,2003 * Copyright (C) International Business Machines Corp., 2002,2007
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* Jeremy Allison (jra@samba.org) * Jeremy Allison (jra@samba.org)
* *
...@@ -45,7 +45,7 @@ static inline struct cifsFileInfo *cifs_init_private( ...@@ -45,7 +45,7 @@ static inline struct cifsFileInfo *cifs_init_private(
{ {
memset(private_data, 0, sizeof(struct cifsFileInfo)); memset(private_data, 0, sizeof(struct cifsFileInfo));
private_data->netfid = netfid; private_data->netfid = netfid;
private_data->pid = current->tgid; private_data->pid = current->tgid;
init_MUTEX(&private_data->fh_sem); init_MUTEX(&private_data->fh_sem);
mutex_init(&private_data->lock_mutex); mutex_init(&private_data->lock_mutex);
INIT_LIST_HEAD(&private_data->llist); INIT_LIST_HEAD(&private_data->llist);
...@@ -57,7 +57,7 @@ static inline struct cifsFileInfo *cifs_init_private( ...@@ -57,7 +57,7 @@ static inline struct cifsFileInfo *cifs_init_private(
does not tell us which handle the write is for so there can does not tell us which handle the write is for so there can
be a close (overlapping with write) of the filehandle that be a close (overlapping with write) of the filehandle that
cifs_writepages chose to use */ cifs_writepages chose to use */
atomic_set(&private_data->wrtPending,0); atomic_set(&private_data->wrtPending, 0);
return private_data; return private_data;
} }
...@@ -105,7 +105,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, ...@@ -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 in the list so we do not have to walk the
list to search for one in prepare_write */ list to search for one in prepare_write */
if ((file->f_flags & O_ACCMODE) == O_WRONLY) { if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
list_add_tail(&pCifsFile->flist, list_add_tail(&pCifsFile->flist,
&pCifsInode->openFileList); &pCifsInode->openFileList);
} else { } else {
list_add(&pCifsFile->flist, list_add(&pCifsFile->flist,
...@@ -138,7 +138,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, ...@@ -138,7 +138,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
} }
client_can_cache: client_can_cache:
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->unix_ext)
rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode, rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode,
full_path, inode->i_sb, xid); full_path, inode->i_sb, xid);
else else
...@@ -189,7 +189,7 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -189,7 +189,7 @@ int cifs_open(struct inode *inode, struct file *file)
/* needed for writepage */ /* needed for writepage */
pCifsFile->pfile = file; pCifsFile->pfile = file;
file->private_data = pCifsFile; file->private_data = pCifsFile;
break; break;
} }
...@@ -212,15 +212,15 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -212,15 +212,15 @@ int cifs_open(struct inode *inode, struct file *file)
return -ENOMEM; return -ENOMEM;
} }
cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", cFYI(1, ("inode = 0x%p file flags are 0x%x for %s",
inode, file->f_flags, full_path)); inode, file->f_flags, full_path));
desiredAccess = cifs_convert_flags(file->f_flags); desiredAccess = cifs_convert_flags(file->f_flags);
/********************************************************************* /*********************************************************************
* open flag mapping table: * open flag mapping table:
* *
* POSIX Flag CIFS Disposition * POSIX Flag CIFS Disposition
* ---------- ---------------- * ---------- ----------------
* O_CREAT FILE_OPEN_IF * O_CREAT FILE_OPEN_IF
* O_CREAT | O_EXCL FILE_CREATE * O_CREAT | O_EXCL FILE_CREATE
* O_CREAT | O_TRUNC FILE_OVERWRITE_IF * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
...@@ -228,12 +228,12 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -228,12 +228,12 @@ int cifs_open(struct inode *inode, struct file *file)
* none of the above FILE_OPEN * none of the above FILE_OPEN
* *
* Note that there is not a direct match between disposition * 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 * O_CREAT | O_TRUNC is similar but truncates the existing
* file rather than creating a new file as FILE_SUPERSEDE does * file rather than creating a new file as FILE_SUPERSEDE does
* (which uses the attributes / metadata passed in on open call) * (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 *? and the read write flags match reasonably. O_LARGEFILE
*? is irrelevant because largefile support is always used *? is irrelevant because largefile support is always used
*? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY, *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
...@@ -253,8 +253,8 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -253,8 +253,8 @@ int cifs_open(struct inode *inode, struct file *file)
and calling get_inode_info with returned buf (at least helps and calling get_inode_info with returned buf (at least helps
non-Unix server case) */ non-Unix server case) */
/* BB we can not do this if this is the second open of a file /* 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 and the first handle has writebehind data, we might be
able to simply do a filemap_fdatawrite/filemap_fdatawait first */ able to simply do a filemap_fdatawrite/filemap_fdatawait first */
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if (!buf) { if (!buf) {
...@@ -263,7 +263,7 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -263,7 +263,7 @@ int cifs_open(struct inode *inode, struct file *file)
} }
if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) 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, desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
& CIFS_MOUNT_MAP_SPECIAL_CHR); & CIFS_MOUNT_MAP_SPECIAL_CHR);
...@@ -300,15 +300,15 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -300,15 +300,15 @@ int cifs_open(struct inode *inode, struct file *file)
write_unlock(&GlobalSMBSeslock); 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 /* time to set mode which we can not set earlier due to
problems creating new read-only files */ problems creating new read-only files */
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) { if (pTcon->unix_ext) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path, CIFSSMBUnixSetPerms(xid, pTcon, full_path,
inode->i_mode, inode->i_mode,
(__u64)-1, (__u64)-1, 0 /* dev */, (__u64)-1, (__u64)-1, 0 /* dev */,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
} else { } else {
/* BB implement via Windows security descriptors eg /* BB implement via Windows security descriptors eg
...@@ -345,7 +345,7 @@ static int cifs_reopen_file(struct file *file, int can_flush) ...@@ -345,7 +345,7 @@ static int cifs_reopen_file(struct file *file, int can_flush)
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct cifsFileInfo *pCifsFile; struct cifsFileInfo *pCifsFile;
struct cifsInodeInfo *pCifsInode; struct cifsInodeInfo *pCifsInode;
struct inode * inode; struct inode *inode;
char *full_path = NULL; char *full_path = NULL;
int desiredAccess; int desiredAccess;
int disposition = FILE_OPEN; int disposition = FILE_OPEN;
...@@ -372,13 +372,13 @@ static int cifs_reopen_file(struct file *file, int can_flush) ...@@ -372,13 +372,13 @@ static int cifs_reopen_file(struct file *file, int can_flush)
} }
inode = file->f_path.dentry->d_inode; inode = file->f_path.dentry->d_inode;
if(inode == NULL) { if (inode == NULL) {
cERROR(1, ("inode not valid")); cERROR(1, ("inode not valid"));
dump_stack(); dump_stack();
rc = -EBADF; rc = -EBADF;
goto reopen_error_exit; goto reopen_error_exit;
} }
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
...@@ -396,7 +396,7 @@ static int cifs_reopen_file(struct file *file, int can_flush) ...@@ -396,7 +396,7 @@ static int cifs_reopen_file(struct file *file, int can_flush)
} }
cFYI(1, ("inode = 0x%p file flags 0x%x for %s", cFYI(1, ("inode = 0x%p file flags 0x%x for %s",
inode, file->f_flags,full_path)); inode, file->f_flags, full_path));
desiredAccess = cifs_convert_flags(file->f_flags); desiredAccess = cifs_convert_flags(file->f_flags);
if (oplockEnabled) if (oplockEnabled)
...@@ -405,14 +405,14 @@ static int cifs_reopen_file(struct file *file, int can_flush) ...@@ -405,14 +405,14 @@ static int cifs_reopen_file(struct file *file, int can_flush)
oplock = FALSE; oplock = FALSE;
/* Can not refresh inode by passing in file_info buf to be returned /* Can not refresh inode by passing in file_info buf to be returned
by SMBOpen and then calling get_inode_info with returned buf by SMBOpen and then calling get_inode_info with returned buf
since file might have write behind data that needs to be flushed 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 and server version of file size can be stale. If we knew for sure
that inode was not dirty locally we could do this */ that inode was not dirty locally we could do this */
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
CREATE_NOT_DIR, &netfid, &oplock, NULL, 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); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) { if (rc) {
up(&pCifsFile->fh_sem); up(&pCifsFile->fh_sem);
...@@ -430,7 +430,7 @@ static int cifs_reopen_file(struct file *file, int can_flush) ...@@ -430,7 +430,7 @@ static int cifs_reopen_file(struct file *file, int can_flush)
go to server to get inode info */ go to server to get inode info */
pCifsInode->clientCanCacheAll = FALSE; pCifsInode->clientCanCacheAll = FALSE;
pCifsInode->clientCanCacheRead = FALSE; pCifsInode->clientCanCacheRead = FALSE;
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->unix_ext)
rc = cifs_get_inode_info_unix(&inode, rc = cifs_get_inode_info_unix(&inode,
full_path, inode->i_sb, xid); full_path, inode->i_sb, xid);
else else
...@@ -486,23 +486,24 @@ int cifs_close(struct inode *inode, struct file *file) ...@@ -486,23 +486,24 @@ int cifs_close(struct inode *inode, struct file *file)
already closed */ already closed */
if (pTcon->tidStatus != CifsNeedReconnect) { if (pTcon->tidStatus != CifsNeedReconnect) {
int timeout = 2; int timeout = 2;
while((atomic_read(&pSMBFile->wrtPending) != 0) while ((atomic_read(&pSMBFile->wrtPending) != 0)
&& (timeout < 1000) ) { && (timeout < 1000) ) {
/* Give write a better chance to get to /* Give write a better chance to get to
server ahead of the close. We do not server ahead of the close. We do not
want to add a wait_q here as it would want to add a wait_q here as it would
increase the memory utilization as increase the memory utilization as
the struct would be in each open file, 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 */ clear the socket */
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
cFYI(1,("close delay, write pending")); cFYI(1, ("close delay, write pending"));
#endif /* DEBUG2 */ #endif /* DEBUG2 */
msleep(timeout); msleep(timeout);
timeout *= 4; timeout *= 4;
} }
if(atomic_read(&pSMBFile->wrtPending)) if (atomic_read(&pSMBFile->wrtPending))
cERROR(1,("close with pending writes")); cERROR(1,
("close with pending writes"));
rc = CIFSSMBClose(xid, pTcon, rc = CIFSSMBClose(xid, pTcon,
pSMBFile->netfid); pSMBFile->netfid);
} }
...@@ -534,7 +535,7 @@ int cifs_close(struct inode *inode, struct file *file) ...@@ -534,7 +535,7 @@ int cifs_close(struct inode *inode, struct file *file)
CIFS_I(inode)->clientCanCacheRead = FALSE; CIFS_I(inode)->clientCanCacheRead = FALSE;
CIFS_I(inode)->clientCanCacheAll = FALSE; CIFS_I(inode)->clientCanCacheAll = FALSE;
} }
if ((rc ==0) && CIFS_I(inode)->write_behind_rc) if ((rc == 0) && CIFS_I(inode)->write_behind_rc)
rc = CIFS_I(inode)->write_behind_rc; rc = CIFS_I(inode)->write_behind_rc;
FreeXid(xid); FreeXid(xid);
return rc; return rc;
...@@ -554,7 +555,8 @@ int cifs_closedir(struct inode *inode, struct file *file) ...@@ -554,7 +555,8 @@ int cifs_closedir(struct inode *inode, struct file *file)
if (pCFileStruct) { if (pCFileStruct) {
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); struct cifs_sb_info *cifs_sb =
CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
...@@ -572,7 +574,7 @@ int cifs_closedir(struct inode *inode, struct file *file) ...@@ -572,7 +574,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
if (ptmp) { if (ptmp) {
cFYI(1, ("closedir free smb buf in srch struct")); cFYI(1, ("closedir free smb buf in srch struct"));
pCFileStruct->srch_inf.ntwrk_buf_start = NULL; pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
if(pCFileStruct->srch_inf.smallBuf) if (pCFileStruct->srch_inf.smallBuf)
cifs_small_buf_release(ptmp); cifs_small_buf_release(ptmp);
else else
cifs_buf_release(ptmp); cifs_buf_release(ptmp);
...@@ -594,7 +596,8 @@ int cifs_closedir(struct inode *inode, struct file *file) ...@@ -594,7 +596,8 @@ int cifs_closedir(struct inode *inode, struct file *file)
static int store_file_lock(struct cifsFileInfo *fid, __u64 len, static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
__u64 offset, __u8 lockType) __u64 offset, __u8 lockType)
{ {
struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); struct cifsLockInfo *li =
kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
if (li == NULL) if (li == NULL)
return -ENOMEM; return -ENOMEM;
li->offset = offset; li->offset = offset;
...@@ -625,8 +628,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -625,8 +628,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
cFYI(1, ("Lock parm: 0x%x flockflags: " cFYI(1, ("Lock parm: 0x%x flockflags: "
"0x%x flocktype: 0x%x start: %lld end: %lld", "0x%x flocktype: 0x%x start: %lld end: %lld",
cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start, cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
pfLock->fl_end)); pfLock->fl_end));
if (pfLock->fl_flags & FL_POSIX) if (pfLock->fl_flags & FL_POSIX)
cFYI(1, ("Posix")); cFYI(1, ("Posix"));
...@@ -641,7 +644,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -641,7 +644,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
"not implemented yet")); "not implemented yet"));
if (pfLock->fl_flags & FL_LEASE) if (pfLock->fl_flags & FL_LEASE)
cFYI(1, ("Lease on file - not implemented yet")); 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))) (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
cFYI(1, ("Unknown lock flags 0x%x", pfLock->fl_flags)); 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) ...@@ -683,9 +686,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
account for negative length which we can not accept over the account for negative length which we can not accept over the
wire */ wire */
if (IS_GETLK(cmd)) { if (IS_GETLK(cmd)) {
if(posix_locking) { if (posix_locking) {
int posix_lock_type; int posix_lock_type;
if(lockType & LOCKING_ANDX_SHARED_LOCK) if (lockType & LOCKING_ANDX_SHARED_LOCK)
posix_lock_type = CIFS_RDLCK; posix_lock_type = CIFS_RDLCK;
else else
posix_lock_type = CIFS_WRLCK; posix_lock_type = CIFS_WRLCK;
...@@ -700,7 +703,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -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, rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
0, 1, lockType, 0 /* wait flag */ ); 0, 1, lockType, 0 /* wait flag */ );
if (rc == 0) { if (rc == 0) {
rc = CIFSSMBLock(xid, pTcon, netfid, length, rc = CIFSSMBLock(xid, pTcon, netfid, length,
pfLock->fl_start, 1 /* numUnlock */ , pfLock->fl_start, 1 /* numUnlock */ ,
0 /* numLock */ , lockType, 0 /* numLock */ , lockType,
0 /* wait flag */ ); 0 /* wait flag */ );
...@@ -729,22 +732,24 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -729,22 +732,24 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
if (posix_locking) { if (posix_locking) {
int posix_lock_type; int posix_lock_type;
if(lockType & LOCKING_ANDX_SHARED_LOCK) if (lockType & LOCKING_ANDX_SHARED_LOCK)
posix_lock_type = CIFS_RDLCK; posix_lock_type = CIFS_RDLCK;
else else
posix_lock_type = CIFS_WRLCK; posix_lock_type = CIFS_WRLCK;
if(numUnlock == 1) if (numUnlock == 1)
posix_lock_type = CIFS_UNLCK; posix_lock_type = CIFS_UNLCK;
rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
length, pfLock, length, pfLock,
posix_lock_type, wait_flag); posix_lock_type, wait_flag);
} else { } else {
struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data; struct cifsFileInfo *fid =
(struct cifsFileInfo *)file->private_data;
if (numLock) { if (numLock) {
rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, rc = CIFSSMBLock(xid, pTcon, netfid, length,
pfLock->fl_start,
0, numLock, lockType, wait_flag); 0, numLock, lockType, wait_flag);
if (rc == 0) { if (rc == 0) {
...@@ -763,7 +768,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -763,7 +768,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
list_for_each_entry_safe(li, tmp, &fid->llist, llist) { list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
if (pfLock->fl_start <= li->offset && if (pfLock->fl_start <= li->offset &&
length >= li->length) { length >= li->length) {
stored_rc = CIFSSMBLock(xid, pTcon, netfid, stored_rc = CIFSSMBLock(xid, pTcon,
netfid,
li->length, li->offset, li->length, li->offset,
1, 0, li->type, FALSE); 1, 0, li->type, FALSE);
if (stored_rc) if (stored_rc)
...@@ -805,7 +811,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, ...@@ -805,7 +811,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
if (file->private_data == NULL) if (file->private_data == NULL)
return -EBADF; return -EBADF;
open_file = (struct cifsFileInfo *) file->private_data; open_file = (struct cifsFileInfo *) file->private_data;
xid = GetXid(); xid = GetXid();
if (*poffset > file->f_path.dentry->d_inode->i_size) 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, ...@@ -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 and blocked, and the file has been freed on us while
we blocked so return what we managed to write */ we blocked so return what we managed to write */
return total_written; return total_written;
} }
if (open_file->closePend) { if (open_file->closePend) {
FreeXid(xid); FreeXid(xid);
if (total_written) if (total_written)
...@@ -867,8 +873,8 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, ...@@ -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 */ /* since the write may have blocked check these pointers again */
if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) { if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) {
struct inode *inode = 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 /* Do not update local mtime - server will set its actual value on write
* inode->i_ctime = inode->i_mtime = * inode->i_ctime = inode->i_mtime =
* current_fs_time(inode->i_sb);*/ * current_fs_time(inode->i_sb);*/
if (total_written > 0) { if (total_written > 0) {
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
...@@ -877,7 +883,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, ...@@ -877,7 +883,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
*poffset); *poffset);
spin_unlock(&inode->i_lock); 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); FreeXid(xid);
return total_written; return total_written;
...@@ -898,13 +904,13 @@ static ssize_t cifs_write(struct file *file, const char *write_data, ...@@ -898,13 +904,13 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
cFYI(1,("write %zd bytes to offset %lld of %s", write_size, cFYI(1, ("write %zd bytes to offset %lld of %s", write_size,
*poffset, file->f_path.dentry->d_name.name)); *poffset, file->f_path.dentry->d_name.name));
if (file->private_data == NULL) if (file->private_data == NULL)
return -EBADF; return -EBADF;
open_file = (struct cifsFileInfo *)file->private_data; open_file = (struct cifsFileInfo *)file->private_data;
xid = GetXid(); xid = GetXid();
if (*poffset > file->f_path.dentry->d_inode->i_size) 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, ...@@ -921,10 +927,10 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
FreeXid(xid); FreeXid(xid);
/* if we have gotten here we have written some data /* if we have gotten here we have written some data
and blocked, and the file has been freed on us 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 */ write */
return total_written; return total_written;
} }
if (open_file->closePend) { if (open_file->closePend) {
FreeXid(xid); FreeXid(xid);
if (total_written) if (total_written)
...@@ -935,14 +941,14 @@ static ssize_t cifs_write(struct file *file, const char *write_data, ...@@ -935,14 +941,14 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
if (open_file->invalidHandle) { if (open_file->invalidHandle) {
/* we could deadlock if we called /* we could deadlock if we called
filemap_fdatawait from here so tell filemap_fdatawait from here so tell
reopen_file not to flush data to reopen_file not to flush data to
server now */ server now */
rc = cifs_reopen_file(file, FALSE); rc = cifs_reopen_file(file, FALSE);
if (rc != 0) if (rc != 0)
break; break;
} }
if(experimEnabled || (pTcon->ses->server && if (experimEnabled || (pTcon->ses->server &&
((pTcon->ses->server->secMode & ((pTcon->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
== 0))) { == 0))) {
struct kvec iov[2]; struct kvec iov[2];
...@@ -976,7 +982,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data, ...@@ -976,7 +982,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
} }
} else } else
*poffset += bytes_written; *poffset += bytes_written;
long_op = FALSE; /* subsequent writes fast - long_op = FALSE; /* subsequent writes fast -
15 seconds is plenty */ 15 seconds is plenty */
} }
...@@ -1009,8 +1015,8 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) ...@@ -1009,8 +1015,8 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
the VFS or MM) should not happen but we had reports of on oops (due to the VFS or MM) should not happen but we had reports of on oops (due to
it being zero) during stress testcases so we need to check for it */ it being zero) during stress testcases so we need to check for it */
if(cifs_inode == NULL) { if (cifs_inode == NULL) {
cERROR(1,("Null inode passed to cifs_writeable_file")); cERROR(1, ("Null inode passed to cifs_writeable_file"));
dump_stack(); dump_stack();
return NULL; return NULL;
} }
...@@ -1024,13 +1030,14 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) ...@@ -1024,13 +1030,14 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
(open_file->pfile->f_flags & O_WRONLY))) { (open_file->pfile->f_flags & O_WRONLY))) {
atomic_inc(&open_file->wrtPending); atomic_inc(&open_file->wrtPending);
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
if((open_file->invalidHandle) && if ((open_file->invalidHandle) &&
(!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) { (!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
rc = cifs_reopen_file(open_file->pfile, FALSE); rc = cifs_reopen_file(open_file->pfile, FALSE);
/* if it fails, try another handle - might be */ /* if it fails, try another handle - might be */
/* dangerous to hold up writepages with retry */ /* dangerous to hold up writepages with retry */
if(rc) { if (rc) {
cFYI(1,("failed on reopen file in wp")); cFYI(1,
("failed on reopen file in wp"));
read_lock(&GlobalSMBSeslock); read_lock(&GlobalSMBSeslock);
/* can not use this handle, no write /* can not use this handle, no write
pending on this one after all */ pending on this one after all */
...@@ -1082,7 +1089,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) ...@@ -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 */ /* check to make sure that we are not extending the file */
if (mapping->host->i_size - offset < (loff_t)to) 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)); open_file = find_writable_file(CIFS_I(mapping->host));
if (open_file) { if (open_file) {
...@@ -1116,8 +1123,8 @@ static int cifs_writepages(struct address_space *mapping, ...@@ -1116,8 +1123,8 @@ static int cifs_writepages(struct address_space *mapping,
int done = 0; int done = 0;
pgoff_t end; pgoff_t end;
pgoff_t index; pgoff_t index;
int range_whole = 0; int range_whole = 0;
struct kvec * iov; struct kvec *iov;
int len; int len;
int n_iov = 0; int n_iov = 0;
pgoff_t next; pgoff_t next;
...@@ -1131,7 +1138,7 @@ static int cifs_writepages(struct address_space *mapping, ...@@ -1131,7 +1138,7 @@ static int cifs_writepages(struct address_space *mapping,
int xid; int xid;
cifs_sb = CIFS_SB(mapping->host->i_sb); cifs_sb = CIFS_SB(mapping->host->i_sb);
/* /*
* If wsize is smaller that the page cache size, default to writing * If wsize is smaller that the page cache size, default to writing
* one page at a time via cifs_writepage * one page at a time via cifs_writepage
...@@ -1139,14 +1146,14 @@ static int cifs_writepages(struct address_space *mapping, ...@@ -1139,14 +1146,14 @@ static int cifs_writepages(struct address_space *mapping,
if (cifs_sb->wsize < PAGE_CACHE_SIZE) if (cifs_sb->wsize < PAGE_CACHE_SIZE)
return generic_writepages(mapping, wbc); return generic_writepages(mapping, wbc);
if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server)) if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
if(cifs_sb->tcon->ses->server->secMode & if (cifs_sb->tcon->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
if(!experimEnabled) if (!experimEnabled)
return generic_writepages(mapping, wbc); return generic_writepages(mapping, wbc);
iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL); iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);
if(iov == NULL) if (iov == NULL)
return generic_writepages(mapping, wbc); return generic_writepages(mapping, wbc);
...@@ -1279,7 +1286,7 @@ static int cifs_writepages(struct address_space *mapping, ...@@ -1279,7 +1286,7 @@ static int cifs_writepages(struct address_space *mapping,
1); 1);
atomic_dec(&open_file->wrtPending); atomic_dec(&open_file->wrtPending);
if (rc || bytes_written < bytes_to_write) { if (rc || bytes_written < bytes_to_write) {
cERROR(1,("Write2 ret %d, written = %d", cERROR(1, ("Write2 ret %d, wrote %d",
rc, bytes_written)); rc, bytes_written));
/* BB what if continued retry is /* BB what if continued retry is
requested via mount flags? */ requested via mount flags? */
...@@ -1295,8 +1302,8 @@ static int cifs_writepages(struct address_space *mapping, ...@@ -1295,8 +1302,8 @@ static int cifs_writepages(struct address_space *mapping,
success rc but too little data written? */ success rc but too little data written? */
/* BB investigate retry logic on temporary /* BB investigate retry logic on temporary
server crash cases and how recovery works server crash cases and how recovery works
when page marked as error */ when page marked as error */
if(rc) if (rc)
SetPageError(page); SetPageError(page);
kunmap(page); kunmap(page);
unlock_page(page); unlock_page(page);
...@@ -1326,7 +1333,7 @@ static int cifs_writepages(struct address_space *mapping, ...@@ -1326,7 +1333,7 @@ static int cifs_writepages(struct address_space *mapping,
return rc; return rc;
} }
static int cifs_writepage(struct page* page, struct writeback_control *wbc) static int cifs_writepage(struct page *page, struct writeback_control *wbc)
{ {
int rc = -EFAULT; int rc = -EFAULT;
int xid; int xid;
...@@ -1334,7 +1341,7 @@ static int cifs_writepage(struct page* page, struct writeback_control *wbc) ...@@ -1334,7 +1341,7 @@ static int cifs_writepage(struct page* page, struct writeback_control *wbc)
xid = GetXid(); xid = GetXid();
/* BB add check for wbc flags */ /* BB add check for wbc flags */
page_cache_get(page); page_cache_get(page);
if (!PageUptodate(page)) { if (!PageUptodate(page)) {
cFYI(1, ("ppw - page not up to date")); cFYI(1, ("ppw - page not up to date"));
} }
...@@ -1348,7 +1355,7 @@ static int cifs_writepage(struct page* page, struct writeback_control *wbc) ...@@ -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 * Just unlocking the page will cause the radix tree tag-bits
* to fail to update with the state of the page correctly. * 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); rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
SetPageUptodate(page); /* BB add check for error and Clearuptodate? */ SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
unlock_page(page); unlock_page(page);
...@@ -1368,7 +1375,7 @@ static int cifs_commit_write(struct file *file, struct page *page, ...@@ -1368,7 +1375,7 @@ static int cifs_commit_write(struct file *file, struct page *page,
char *page_data; char *page_data;
xid = GetXid(); 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)); page, position, to));
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
if (position > inode->i_size) { if (position > inode->i_size) {
...@@ -1396,7 +1403,7 @@ static int cifs_commit_write(struct file *file, struct page *page, ...@@ -1396,7 +1403,7 @@ static int cifs_commit_write(struct file *file, struct page *page,
rc = 0; rc = 0;
/* else if (rc < 0) should we set writebehind rc? */ /* else if (rc < 0) should we set writebehind rc? */
kunmap(page); kunmap(page);
} else { } else {
set_page_dirty(page); set_page_dirty(page);
} }
...@@ -1412,9 +1419,9 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) ...@@ -1412,9 +1419,9 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
xid = GetXid(); 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)); dentry->d_name.name, datasync));
rc = filemap_fdatawrite(inode->i_mapping); rc = filemap_fdatawrite(inode->i_mapping);
if (rc == 0) if (rc == 0)
CIFS_I(inode)->write_behind_rc = 0; CIFS_I(inode)->write_behind_rc = 0;
...@@ -1438,7 +1445,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) ...@@ -1438,7 +1445,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
if (!inode) if (!inode)
return; */ return; */
/* fill in rpages then /* fill in rpages then
result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */ result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
/* cFYI(1, ("rpages is %d for sync page of Index %ld", rpages, index)); /* 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) ...@@ -1456,7 +1463,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
*/ */
int cifs_flush(struct file *file, fl_owner_t id) int cifs_flush(struct file *file, fl_owner_t id)
{ {
struct inode * inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
int rc = 0; int rc = 0;
/* Rather than do the steps manually: /* Rather than do the steps manually:
...@@ -1471,8 +1478,8 @@ int cifs_flush(struct file *file, fl_owner_t id) ...@@ -1471,8 +1478,8 @@ int cifs_flush(struct file *file, fl_owner_t id)
rc = filemap_fdatawrite(inode->i_mapping); rc = filemap_fdatawrite(inode->i_mapping);
if (!rc) /* reset wb rc if we were able to write out dirty pages */ if (!rc) /* reset wb rc if we were able to write out dirty pages */
CIFS_I(inode)->write_behind_rc = 0; CIFS_I(inode)->write_behind_rc = 0;
cFYI(1, ("Flush inode %p file %p rc %d",inode,file,rc)); cFYI(1, ("Flush inode %p file %p rc %d", inode, file, rc));
return rc; return rc;
} }
...@@ -1508,13 +1515,13 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, ...@@ -1508,13 +1515,13 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
for (total_read = 0, current_offset = read_data; for (total_read = 0, current_offset = read_data;
read_size > total_read; read_size > total_read;
total_read += bytes_read, current_offset += bytes_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); cifs_sb->rsize);
rc = -EAGAIN; rc = -EAGAIN;
smb_read_data = NULL; smb_read_data = NULL;
while (rc == -EAGAIN) { while (rc == -EAGAIN) {
int buf_type = CIFS_NO_BUFFER; int buf_type = CIFS_NO_BUFFER;
if ((open_file->invalidHandle) && if ((open_file->invalidHandle) &&
(!open_file->closePend)) { (!open_file->closePend)) {
rc = cifs_reopen_file(file, TRUE); rc = cifs_reopen_file(file, TRUE);
if (rc != 0) if (rc != 0)
...@@ -1535,9 +1542,9 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, ...@@ -1535,9 +1542,9 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
rc = -EFAULT; rc = -EFAULT;
} }
if(buf_type == CIFS_SMALL_BUFFER) if (buf_type == CIFS_SMALL_BUFFER)
cifs_small_buf_release(smb_read_data); cifs_small_buf_release(smb_read_data);
else if(buf_type == CIFS_LARGE_BUFFER) else if (buf_type == CIFS_LARGE_BUFFER)
cifs_buf_release(smb_read_data); cifs_buf_release(smb_read_data);
smb_read_data = NULL; smb_read_data = NULL;
} }
...@@ -1586,21 +1593,21 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, ...@@ -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) if ((file->f_flags & O_ACCMODE) == O_WRONLY)
cFYI(1, ("attempting read on write only file instance")); 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; read_size > total_read;
total_read += bytes_read, current_offset += bytes_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); cifs_sb->rsize);
/* For windows me and 9x we do not want to request more /* For windows me and 9x we do not want to request more
than it negotiated since it will refuse the read then */ than it negotiated since it will refuse the read then */
if((pTcon->ses) && if ((pTcon->ses) &&
!(pTcon->ses->capabilities & CAP_LARGE_FILES)) { !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
current_read_size = min_t(const int, current_read_size, current_read_size = min_t(const int, current_read_size,
pTcon->ses->server->maxBuf - 128); pTcon->ses->server->maxBuf - 128);
} }
rc = -EAGAIN; rc = -EAGAIN;
while (rc == -EAGAIN) { while (rc == -EAGAIN) {
if ((open_file->invalidHandle) && if ((open_file->invalidHandle) &&
(!open_file->closePend)) { (!open_file->closePend)) {
rc = cifs_reopen_file(file, TRUE); rc = cifs_reopen_file(file, TRUE);
if (rc != 0) if (rc != 0)
...@@ -1646,7 +1653,7 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -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 list_head *pages, int bytes_read, char *data,
struct pagevec *plru_pvec) struct pagevec *plru_pvec)
{ {
...@@ -1669,12 +1676,12 @@ static void cifs_copy_cache_pages(struct address_space *mapping, ...@@ -1669,12 +1676,12 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
continue; continue;
} }
target = kmap_atomic(page,KM_USER0); target = kmap_atomic(page, KM_USER0);
if (PAGE_CACHE_SIZE > bytes_read) { if (PAGE_CACHE_SIZE > bytes_read) {
memcpy(target, data, bytes_read); memcpy(target, data, bytes_read);
/* zero the tail end of this partial page */ /* zero the tail end of this partial page */
memset(target + bytes_read, 0, memset(target + bytes_read, 0,
PAGE_CACHE_SIZE - bytes_read); PAGE_CACHE_SIZE - bytes_read);
bytes_read = 0; bytes_read = 0;
} else { } else {
...@@ -1703,7 +1710,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -1703,7 +1710,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
int bytes_read = 0; int bytes_read = 0;
unsigned int read_size,i; unsigned int read_size, i;
char *smb_read_data = NULL; char *smb_read_data = NULL;
struct smb_com_read_rsp *pSMBr; struct smb_com_read_rsp *pSMBr;
struct pagevec lru_pvec; struct pagevec lru_pvec;
...@@ -1720,7 +1727,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -1720,7 +1727,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
pagevec_init(&lru_pvec, 0); pagevec_init(&lru_pvec, 0);
#ifdef CONFIG_CIFS_DEBUG2
cFYI(1, ("rpages: num pages %d", num_pages));
#endif
for (i = 0; i < num_pages; ) { for (i = 0; i < num_pages; ) {
unsigned contig_pages; unsigned contig_pages;
struct page *tmp_page; struct page *tmp_page;
...@@ -1734,14 +1743,14 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -1734,14 +1743,14 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
/* count adjacent pages that we will read into */ /* count adjacent pages that we will read into */
contig_pages = 0; contig_pages = 0;
expected_index = expected_index =
list_entry(page_list->prev, struct page, lru)->index; list_entry(page_list->prev, struct page, lru)->index;
list_for_each_entry_reverse(tmp_page,page_list,lru) { list_for_each_entry_reverse(tmp_page, page_list, lru) {
if (tmp_page->index == expected_index) { if (tmp_page->index == expected_index) {
contig_pages++; contig_pages++;
expected_index++; expected_index++;
} else } else
break; break;
} }
if (contig_pages + i > num_pages) if (contig_pages + i > num_pages)
contig_pages = num_pages - i; contig_pages = num_pages - i;
...@@ -1753,10 +1762,13 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -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 needs to be in multiples of one page */
read_size = min_t(const unsigned int, read_size, read_size = min_t(const unsigned int, read_size,
cifs_sb->rsize & PAGE_CACHE_MASK); cifs_sb->rsize & PAGE_CACHE_MASK);
#ifdef CONFIG_CIFS_DEBUG2
cFYI(1, ("rpages: read size 0x%x contiguous pages %d",
read_size, contig_pages));
#endif
rc = -EAGAIN; rc = -EAGAIN;
while (rc == -EAGAIN) { while (rc == -EAGAIN) {
if ((open_file->invalidHandle) && if ((open_file->invalidHandle) &&
(!open_file->closePend)) { (!open_file->closePend)) {
rc = cifs_reopen_file(file, TRUE); rc = cifs_reopen_file(file, TRUE);
if (rc != 0) if (rc != 0)
...@@ -1769,11 +1781,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -1769,11 +1781,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
&bytes_read, &smb_read_data, &bytes_read, &smb_read_data,
&buf_type); &buf_type);
/* BB more RC checks ? */ /* BB more RC checks ? */
if (rc== -EAGAIN) { if (rc == -EAGAIN) {
if (smb_read_data) { if (smb_read_data) {
if(buf_type == CIFS_SMALL_BUFFER) if (buf_type == CIFS_SMALL_BUFFER)
cifs_small_buf_release(smb_read_data); cifs_small_buf_release(smb_read_data);
else if(buf_type == CIFS_LARGE_BUFFER) else if (buf_type == CIFS_LARGE_BUFFER)
cifs_buf_release(smb_read_data); cifs_buf_release(smb_read_data);
smb_read_data = NULL; smb_read_data = NULL;
} }
...@@ -1794,10 +1806,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -1794,10 +1806,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) { if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
i++; /* account for partial page */ i++; /* account for partial page */
/* server copy of file can have smaller size /* server copy of file can have smaller size
than client */ than client */
/* BB do we need to verify this common case ? /* BB do we need to verify this common case ?
this case is ok - if we are at server EOF this case is ok - if we are at server EOF
we will hit it on next read */ we will hit it on next read */
/* break; */ /* break; */
...@@ -1806,14 +1818,14 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -1806,14 +1818,14 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
cFYI(1, ("No bytes read (%d) at offset %lld . " cFYI(1, ("No bytes read (%d) at offset %lld . "
"Cleaning remaining pages from readahead list", "Cleaning remaining pages from readahead list",
bytes_read, offset)); 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? */ file size at server? */
break; break;
} }
if (smb_read_data) { if (smb_read_data) {
if(buf_type == CIFS_SMALL_BUFFER) if (buf_type == CIFS_SMALL_BUFFER)
cifs_small_buf_release(smb_read_data); cifs_small_buf_release(smb_read_data);
else if(buf_type == CIFS_LARGE_BUFFER) else if (buf_type == CIFS_LARGE_BUFFER)
cifs_buf_release(smb_read_data); cifs_buf_release(smb_read_data);
smb_read_data = NULL; smb_read_data = NULL;
} }
...@@ -1824,12 +1836,12 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -1824,12 +1836,12 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
/* need to free smb_read_data buf before exit */ /* need to free smb_read_data buf before exit */
if (smb_read_data) { if (smb_read_data) {
if(buf_type == CIFS_SMALL_BUFFER) if (buf_type == CIFS_SMALL_BUFFER)
cifs_small_buf_release(smb_read_data); cifs_small_buf_release(smb_read_data);
else if(buf_type == CIFS_LARGE_BUFFER) else if (buf_type == CIFS_LARGE_BUFFER)
cifs_buf_release(smb_read_data); cifs_buf_release(smb_read_data);
smb_read_data = NULL; smb_read_data = NULL;
} }
FreeXid(xid); FreeXid(xid);
return rc; return rc;
...@@ -1844,26 +1856,26 @@ static int cifs_readpage_worker(struct file *file, struct page *page, ...@@ -1844,26 +1856,26 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
page_cache_get(page); page_cache_get(page);
read_data = kmap(page); read_data = kmap(page);
/* for reads over a certain size could initiate async read ahead */ /* for reads over a certain size could initiate async read ahead */
rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset); rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
if (rc < 0) if (rc < 0)
goto io_error; goto io_error;
else else
cFYI(1, ("Bytes read %d",rc)); cFYI(1, ("Bytes read %d", rc));
file->f_path.dentry->d_inode->i_atime = file->f_path.dentry->d_inode->i_atime =
current_fs_time(file->f_path.dentry->d_inode->i_sb); current_fs_time(file->f_path.dentry->d_inode->i_sb);
if (PAGE_CACHE_SIZE > rc) if (PAGE_CACHE_SIZE > rc)
memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc); memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
flush_dcache_page(page); flush_dcache_page(page);
SetPageUptodate(page); SetPageUptodate(page);
rc = 0; rc = 0;
io_error: io_error:
kunmap(page); kunmap(page);
page_cache_release(page); page_cache_release(page);
return rc; return rc;
} }
...@@ -1881,7 +1893,7 @@ static int cifs_readpage(struct file *file, struct page *page) ...@@ -1881,7 +1893,7 @@ static int cifs_readpage(struct file *file, struct page *page)
return -EBADF; 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)); page, (int)offset, (int)offset));
rc = cifs_readpage_worker(file, page, &offset); rc = cifs_readpage_worker(file, page, &offset);
...@@ -1895,7 +1907,7 @@ static int cifs_readpage(struct file *file, struct page *page) ...@@ -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 /* We do not want to update the file size from server for inodes
open for write - to avoid races with writepage extending open for write - to avoid races with writepage extending
the file - in the future we could consider allowing 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 but this is tricky to do without racing with writebehind
page caching in the current Linux kernel design */ page caching in the current Linux kernel design */
int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file) 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) ...@@ -1904,8 +1916,8 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
if (cifsInode) if (cifsInode)
open_file = find_writable_file(cifsInode); open_file = find_writable_file(cifsInode);
if(open_file) { if (open_file) {
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
/* there is not actually a write pending so let /* there is not actually a write pending so let
...@@ -1915,12 +1927,12 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file) ...@@ -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); cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) { 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 */ we can change size safely */
return 1; return 1;
} }
if(i_size_read(&cifsInode->vfs_inode) < end_of_file) if (i_size_read(&cifsInode->vfs_inode) < end_of_file)
return 1; return 1;
return 0; return 0;
...@@ -1935,7 +1947,7 @@ static int cifs_prepare_write(struct file *file, struct page *page, ...@@ -1935,7 +1947,7 @@ static int cifs_prepare_write(struct file *file, struct page *page,
loff_t i_size; loff_t i_size;
loff_t offset; loff_t offset;
cFYI(1, ("prepare write for page %p from %d to %d",page,from,to)); cFYI(1, ("prepare write for page %p from %d to %d", page, from, to));
if (PageUptodate(page)) if (PageUptodate(page))
return 0; return 0;
...@@ -1955,14 +1967,7 @@ static int cifs_prepare_write(struct file *file, struct page *page, ...@@ -1955,14 +1967,7 @@ static int cifs_prepare_write(struct file *file, struct page *page,
* We don't need to read data beyond the end of the file. * We don't need to read data beyond the end of the file.
* zero it, and set the page uptodate * zero it, and set the page uptodate
*/ */
void *kaddr = kmap_atomic(page, KM_USER0); simple_prepare_write(file, page, from, to);
if (from)
memset(kaddr, 0, from);
if (to < PAGE_CACHE_SIZE)
memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
SetPageUptodate(page); SetPageUptodate(page);
} else if ((file->f_flags & O_ACCMODE) != O_WRONLY) { } else if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
/* might as well read a page, it is fast enough */ /* might as well read a page, it is fast enough */
...@@ -1974,8 +1979,8 @@ static int cifs_prepare_write(struct file *file, struct page *page, ...@@ -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 */ this will be written out by commit_write so is fine */
} }
/* we do not need to pass errors back /* we do not need to pass errors back
e.g. if we do not have read access to the file e.g. if we do not have read access to the file
because cifs_commit_write will do the right thing. -- shaggy */ because cifs_commit_write will do the right thing. -- shaggy */
return 0; return 0;
......
...@@ -57,14 +57,14 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -57,14 +57,14 @@ int cifs_get_inode_info_unix(struct inode **pinode,
if (tmp_path == NULL) { if (tmp_path == NULL) {
return -ENOMEM; return -ENOMEM;
} }
/* have to skip first of the double backslash of /* have to skip first of the double backslash of
UNC name */ UNC name */
strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
strncat(tmp_path, search_path, MAX_PATHCONF); strncat(tmp_path, search_path, MAX_PATHCONF);
rc = connect_to_dfs_path(xid, pTcon->ses, rc = connect_to_dfs_path(xid, pTcon->ses,
/* treename + */ tmp_path, /* treename + */ tmp_path,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
kfree(tmp_path); kfree(tmp_path);
...@@ -81,7 +81,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -81,7 +81,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
/* get new inode */ /* get new inode */
if (*pinode == NULL) { if (*pinode == NULL) {
*pinode = new_inode(sb); *pinode = new_inode(sb);
if (*pinode == NULL) if (*pinode == NULL)
return -ENOMEM; return -ENOMEM;
/* Is an i_ino of zero legal? */ /* Is an i_ino of zero legal? */
/* Are there sanity checks we can use to ensure that /* Are there sanity checks we can use to ensure that
...@@ -92,7 +92,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -92,7 +92,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
} /* note ino incremented to unique num in new_inode */ } /* note ino incremented to unique num in new_inode */
if (sb->s_flags & MS_NOATIME) if (sb->s_flags & MS_NOATIME)
(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
insert_inode_hash(*pinode); insert_inode_hash(*pinode);
} }
...@@ -103,7 +103,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -103,7 +103,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
cifsInfo->time = jiffies; cifsInfo->time = jiffies;
cFYI(1, ("New time %ld", cifsInfo->time)); cFYI(1, ("New time %ld", cifsInfo->time));
/* this is ok to set on every inode revalidate */ /* this is ok to set on every inode revalidate */
atomic_set(&cifsInfo->inUse,1); atomic_set(&cifsInfo->inUse, 1);
inode->i_atime = inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime)); cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
...@@ -114,8 +114,8 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -114,8 +114,8 @@ int cifs_get_inode_info_unix(struct inode **pinode,
cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange)); cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
inode->i_mode = le64_to_cpu(findData.Permissions); inode->i_mode = le64_to_cpu(findData.Permissions);
/* since we set the inode type below we need to mask off /* since we set the inode type below we need to mask off
to avoid strange results if bits set above */ to avoid strange results if bits set above */
inode->i_mode &= ~S_IFMT; inode->i_mode &= ~S_IFMT;
if (type == UNIX_FILE) { if (type == UNIX_FILE) {
inode->i_mode |= S_IFREG; inode->i_mode |= S_IFREG;
} else if (type == UNIX_SYMLINK) { } else if (type == UNIX_SYMLINK) {
...@@ -137,9 +137,9 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -137,9 +137,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
} else { } else {
/* safest to call it a file if we do not know */ /* safest to call it a file if we do not know */
inode->i_mode |= S_IFREG; inode->i_mode |= S_IFREG;
cFYI(1,("unknown type %d",type)); cFYI(1, ("unknown type %d", type));
} }
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
inode->i_uid = cifs_sb->mnt_uid; inode->i_uid = cifs_sb->mnt_uid;
else else
...@@ -149,7 +149,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -149,7 +149,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
inode->i_gid = cifs_sb->mnt_gid; inode->i_gid = cifs_sb->mnt_gid;
else else
inode->i_gid = le64_to_cpu(findData.Gid); inode->i_gid = le64_to_cpu(findData.Gid);
inode->i_nlink = le64_to_cpu(findData.Nlinks); inode->i_nlink = le64_to_cpu(findData.Nlinks);
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
...@@ -183,17 +183,17 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -183,17 +183,17 @@ int cifs_get_inode_info_unix(struct inode **pinode,
inode->i_op = &cifs_file_inode_ops; inode->i_op = &cifs_file_inode_ops;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
inode->i_fop = inode->i_fop =
&cifs_file_direct_nobrl_ops; &cifs_file_direct_nobrl_ops;
else else
inode->i_fop = &cifs_file_direct_ops; 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)
inode->i_fop = &cifs_file_nobrl_ops; 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; inode->i_fop = &cifs_file_ops;
/* check if server can support readpages */ /* check if server can support readpages */
if (pTcon->ses->server->maxBuf < if (pTcon->ses->server->maxBuf <
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
inode->i_data.a_ops = &cifs_addr_ops_smallbuf; inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
else else
...@@ -215,7 +215,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -215,7 +215,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
return rc; return rc;
} }
static int decode_sfu_inode(struct inode * inode, __u64 size, static int decode_sfu_inode(struct inode *inode, __u64 size,
const unsigned char *path, const unsigned char *path,
struct cifs_sb_info *cifs_sb, int xid) struct cifs_sb_info *cifs_sb, int xid)
{ {
...@@ -225,7 +225,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size, ...@@ -225,7 +225,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
struct cifsTconInfo *pTcon = cifs_sb->tcon; struct cifsTconInfo *pTcon = cifs_sb->tcon;
char buf[24]; char buf[24];
unsigned int bytes_read; unsigned int bytes_read;
char * pbuf; char *pbuf;
pbuf = buf; pbuf = buf;
...@@ -235,22 +235,22 @@ static int decode_sfu_inode(struct inode * inode, __u64 size, ...@@ -235,22 +235,22 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
} else if (size < 8) { } else if (size < 8) {
return -EINVAL; /* EOPNOTSUPP? */ return -EINVAL; /* EOPNOTSUPP? */
} }
rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ, rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
CREATE_NOT_DIR, &netfid, &oplock, NULL, CREATE_NOT_DIR, &netfid, &oplock, NULL,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc==0) { if (rc == 0) {
int buf_type = CIFS_NO_BUFFER; int buf_type = CIFS_NO_BUFFER;
/* Read header */ /* Read header */
rc = CIFSSMBRead(xid, pTcon, rc = CIFSSMBRead(xid, pTcon,
netfid, netfid,
24 /* length */, 0 /* offset */, 24 /* length */, 0 /* offset */,
&bytes_read, &pbuf, &buf_type); &bytes_read, &pbuf, &buf_type);
if ((rc == 0) && (bytes_read >= 8)) { if ((rc == 0) && (bytes_read >= 8)) {
if (memcmp("IntxBLK", pbuf, 8) == 0) { if (memcmp("IntxBLK", pbuf, 8) == 0) {
cFYI(1,("Block device")); cFYI(1, ("Block device"));
inode->i_mode |= S_IFBLK; inode->i_mode |= S_IFBLK;
if (bytes_read == 24) { if (bytes_read == 24) {
/* we have enough to decode dev num */ /* we have enough to decode dev num */
...@@ -261,7 +261,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size, ...@@ -261,7 +261,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
inode->i_rdev = MKDEV(mjr, mnr); inode->i_rdev = MKDEV(mjr, mnr);
} }
} else if (memcmp("IntxCHR", pbuf, 8) == 0) { } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
cFYI(1,("Char device")); cFYI(1, ("Char device"));
inode->i_mode |= S_IFCHR; inode->i_mode |= S_IFCHR;
if (bytes_read == 24) { if (bytes_read == 24) {
/* we have enough to decode dev num */ /* we have enough to decode dev num */
...@@ -270,27 +270,26 @@ static int decode_sfu_inode(struct inode * inode, __u64 size, ...@@ -270,27 +270,26 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
inode->i_rdev = MKDEV(mjr, mnr); inode->i_rdev = MKDEV(mjr, mnr);
} }
} else if (memcmp("IntxLNK", pbuf, 7) == 0) { } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
cFYI(1,("Symlink")); cFYI(1, ("Symlink"));
inode->i_mode |= S_IFLNK; inode->i_mode |= S_IFLNK;
} else { } else {
inode->i_mode |= S_IFREG; /* file? */ inode->i_mode |= S_IFREG; /* file? */
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
} }
} else { } else {
inode->i_mode |= S_IFREG; /* then it is a file */ 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); CIFSSMBClose(xid, pTcon, netfid);
} }
return rc; return rc;
} }
#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
static int get_sfu_uid_mode(struct inode * inode, static int get_sfu_uid_mode(struct inode *inode,
const unsigned char *path, const unsigned char *path,
struct cifs_sb_info *cifs_sb, int xid) struct cifs_sb_info *cifs_sb, int xid)
{ {
...@@ -301,15 +300,15 @@ static int get_sfu_uid_mode(struct inode * inode, ...@@ -301,15 +300,15 @@ static int get_sfu_uid_mode(struct inode * inode,
rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
ea_value, 4 /* size of buf */, cifs_sb->local_nls, 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) if (rc < 0)
return (int)rc; return (int)rc;
else if (rc > 3) { else if (rc > 3) {
mode = le32_to_cpu(*((__le32 *)ea_value)); mode = le32_to_cpu(*((__le32 *)ea_value));
inode->i_mode &= ~SFBITS_MASK; inode->i_mode &= ~SFBITS_MASK;
cFYI(1,("special bits 0%o org mode 0%o", mode, inode->i_mode)); cFYI(1, ("special bits 0%o org mode 0%o", mode, inode->i_mode));
inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode; inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode;
cFYI(1,("special mode bits 0%o", mode)); cFYI(1, ("special mode bits 0%o", mode));
return 0; return 0;
} else { } else {
return 0; return 0;
...@@ -317,8 +316,6 @@ static int get_sfu_uid_mode(struct inode * inode, ...@@ -317,8 +316,6 @@ static int get_sfu_uid_mode(struct inode * inode,
#else #else
return -EOPNOTSUPP; return -EOPNOTSUPP;
#endif #endif
} }
int cifs_get_inode_info(struct inode **pinode, int cifs_get_inode_info(struct inode **pinode,
...@@ -334,11 +331,11 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -334,11 +331,11 @@ int cifs_get_inode_info(struct inode **pinode,
int adjustTZ = FALSE; int adjustTZ = FALSE;
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
cFYI(1,("Getting info on %s", search_path)); cFYI(1, ("Getting info on %s", search_path));
if ((pfindData == NULL) && (*pinode != NULL)) { if ((pfindData == NULL) && (*pinode != NULL)) {
if (CIFS_I(*pinode)->clientCanCacheRead) { if (CIFS_I(*pinode)->clientCanCacheRead) {
cFYI(1,("No need to revalidate cached inode sizes")); cFYI(1, ("No need to revalidate cached inode sizes"));
return rc; return rc;
} }
} }
...@@ -359,12 +356,11 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -359,12 +356,11 @@ int cifs_get_inode_info(struct inode **pinode,
failed at least once - set flag in tcon or mount */ failed at least once - set flag in tcon or mount */
if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
rc = SMBQueryInformation(xid, pTcon, search_path, rc = SMBQueryInformation(xid, pTcon, search_path,
pfindData, cifs_sb->local_nls, pfindData, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
adjustTZ = TRUE; adjustTZ = TRUE;
} }
} }
/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
if (rc) { if (rc) {
...@@ -384,8 +380,8 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -384,8 +380,8 @@ int cifs_get_inode_info(struct inode **pinode,
strncat(tmp_path, search_path, MAX_PATHCONF); strncat(tmp_path, search_path, MAX_PATHCONF);
rc = connect_to_dfs_path(xid, pTcon->ses, rc = connect_to_dfs_path(xid, pTcon->ses,
/* treename + */ tmp_path, /* treename + */ tmp_path,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
kfree(tmp_path); kfree(tmp_path);
/* BB fix up inode etc. */ /* BB fix up inode etc. */
...@@ -419,17 +415,17 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -419,17 +415,17 @@ int cifs_get_inode_info(struct inode **pinode,
there Windows server or network appliances for which there Windows server or network appliances for which
IndexNumber field is not guaranteed unique? */ IndexNumber field is not guaranteed unique? */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
int rc1 = 0; int rc1 = 0;
__u64 inode_num; __u64 inode_num;
rc1 = CIFSGetSrvInodeNumber(xid, pTcon, rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
search_path, &inode_num, search_path, &inode_num,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc1) { if (rc1) {
cFYI(1,("GetSrvInodeNum rc %d", rc1)); cFYI(1, ("GetSrvInodeNum rc %d", rc1));
/* BB EOPNOSUPP disable SERVER_INUM? */ /* BB EOPNOSUPP disable SERVER_INUM? */
} else /* do we need cast or hash to ino? */ } else /* do we need cast or hash to ino? */
(*pinode)->i_ino = inode_num; (*pinode)->i_ino = inode_num;
...@@ -463,7 +459,7 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -463,7 +459,7 @@ int cifs_get_inode_info(struct inode **pinode,
cFYI(0, ("Attributes came in as 0x%x", attr)); cFYI(0, ("Attributes came in as 0x%x", attr));
if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; 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 */ /* set default mode. will override for dirs below */
...@@ -471,8 +467,9 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -471,8 +467,9 @@ int cifs_get_inode_info(struct inode **pinode,
/* new inode, can safely set these fields */ /* new inode, can safely set these fields */
inode->i_mode = cifs_sb->mnt_file_mode; inode->i_mode = cifs_sb->mnt_file_mode;
else /* since we set the inode type below we need to mask off else /* since we set the inode type below we need to mask off
to avoid strange results if type changes and both get orred in */ to avoid strange results if type changes and both
inode->i_mode &= ~S_IFMT; get orred in */
inode->i_mode &= ~S_IFMT;
/* if (attr & ATTR_REPARSE) */ /* if (attr & ATTR_REPARSE) */
/* We no longer handle these as symlinks because we could not /* We no longer handle these as symlinks because we could not
follow them due to the absolute path with drive letter */ follow them due to the absolute path with drive letter */
...@@ -490,13 +487,13 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -490,13 +487,13 @@ int cifs_get_inode_info(struct inode **pinode,
/* BB Finish for SFU style symlinks and devices */ /* BB Finish for SFU style symlinks and devices */
} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
(cifsInfo->cifsAttrs & ATTR_SYSTEM)) { (cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
if (decode_sfu_inode(inode, if (decode_sfu_inode(inode,
le64_to_cpu(pfindData->EndOfFile), le64_to_cpu(pfindData->EndOfFile),
search_path, search_path,
cifs_sb, xid)) { cifs_sb, xid)) {
cFYI(1,("Unrecognized sfu inode type")); cFYI(1, ("Unrecognized sfu inode type"));
} }
cFYI(1,("sfu mode 0%o",inode->i_mode)); cFYI(1, ("sfu mode 0%o", inode->i_mode));
} else { } else {
inode->i_mode |= S_IFREG; inode->i_mode |= S_IFREG;
/* treat the dos attribute of read-only as read-only /* treat the dos attribute of read-only as read-only
...@@ -512,12 +509,12 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -512,12 +509,12 @@ int cifs_get_inode_info(struct inode **pinode,
/* BB add code here - /* BB add code here -
validate if device or weird share or device type? */ validate if device or weird share or device type? */
} }
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) { if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) {
/* can not safely shrink the file size here if the /* can not safely shrink the file size here if the
client is writing to it due to potential races */ client is writing to it due to potential races */
i_size_write(inode,le64_to_cpu(pfindData->EndOfFile)); i_size_write(inode, le64_to_cpu(pfindData->EndOfFile));
/* 512 bytes (2**9) is the fake blocksize that must be /* 512 bytes (2**9) is the fake blocksize that must be
used for this calculation */ used for this calculation */
...@@ -528,7 +525,7 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -528,7 +525,7 @@ int cifs_get_inode_info(struct inode **pinode,
inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); 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 */ or retrieve from NTFS stream extended attribute */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
/* fill in uid, gid, mode from server ACL */ /* fill in uid, gid, mode from server ACL */
...@@ -540,7 +537,7 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -540,7 +537,7 @@ int cifs_get_inode_info(struct inode **pinode,
inode->i_gid = cifs_sb->mnt_gid; inode->i_gid = cifs_sb->mnt_gid;
/* set so we do not keep refreshing these fields with /* set so we do not keep refreshing these fields with
bad data after user has changed them in memory */ bad data after user has changed them in memory */
atomic_set(&cifsInfo->inUse,1); atomic_set(&cifsInfo->inUse, 1);
} }
if (S_ISREG(inode->i_mode)) { if (S_ISREG(inode->i_mode)) {
...@@ -557,7 +554,7 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -557,7 +554,7 @@ int cifs_get_inode_info(struct inode **pinode,
else /* not direct, send byte range locks */ else /* not direct, send byte range locks */
inode->i_fop = &cifs_file_ops; inode->i_fop = &cifs_file_ops;
if (pTcon->ses->server->maxBuf < if (pTcon->ses->server->maxBuf <
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
inode->i_data.a_ops = &cifs_addr_ops_smallbuf; inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
else else
...@@ -586,10 +583,11 @@ void cifs_read_inode(struct inode *inode) ...@@ -586,10 +583,11 @@ void cifs_read_inode(struct inode *inode)
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
xid = GetXid(); xid = GetXid();
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid); if (cifs_sb->tcon->unix_ext)
cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
else else
cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid); cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
/* can not call macro FreeXid here since in a void func */ /* can not call macro FreeXid here since in a void func */
_FreeXid(xid); _FreeXid(xid);
} }
...@@ -623,9 +621,21 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -623,9 +621,21 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return -ENOMEM;
} }
rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
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); 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 (!rc) {
if (direntry->d_inode) if (direntry->d_inode)
drop_nlink(direntry->d_inode); drop_nlink(direntry->d_inode);
...@@ -638,12 +648,12 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -638,12 +648,12 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE, rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
&netfid, &oplock, NULL, cifs_sb->local_nls, &netfid, &oplock, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc==0) { if (rc == 0) {
CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL, CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
if (direntry->d_inode) if (direntry->d_inode)
...@@ -659,7 +669,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -659,7 +669,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
rc = CIFSSMBSetTimes(xid, pTcon, full_path, rc = CIFSSMBSetTimes(xid, pTcon, full_path,
pinfo_buf, pinfo_buf,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
else else
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
...@@ -670,7 +680,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -670,7 +680,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
/* rc = CIFSSMBSetAttrLegacy(xid, pTcon, /* rc = CIFSSMBSetAttrLegacy(xid, pTcon,
full_path, full_path,
(__u16)ATTR_NORMAL, (__u16)ATTR_NORMAL,
cifs_sb->local_nls); cifs_sb->local_nls);
For some strange reason it seems that NT4 eats the For some strange reason it seems that NT4 eats the
old setattr call without actually setting the old setattr call without actually setting the
attributes so on to the third attempted workaround attributes so on to the third attempted workaround
...@@ -683,9 +693,9 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -683,9 +693,9 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
FILE_WRITE_ATTRIBUTES, 0, FILE_WRITE_ATTRIBUTES, 0,
&netfid, &oplock, NULL, &netfid, &oplock, NULL,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc==0) { if (rc == 0) {
rc = CIFSSMBSetFileTimes(xid, pTcon, rc = CIFSSMBSetFileTimes(xid, pTcon,
pinfo_buf, pinfo_buf,
netfid); netfid);
...@@ -694,10 +704,10 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -694,10 +704,10 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
} }
kfree(pinfo_buf); kfree(pinfo_buf);
} }
if (rc==0) { if (rc == 0) {
rc = CIFSSMBDelFile(xid, pTcon, full_path, rc = CIFSSMBDelFile(xid, pTcon, full_path,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (!rc) { if (!rc) {
if (direntry->d_inode) if (direntry->d_inode)
...@@ -711,10 +721,10 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -711,10 +721,10 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
CREATE_NOT_DIR | CREATE_NOT_DIR |
CREATE_DELETE_ON_CLOSE, CREATE_DELETE_ON_CLOSE,
&netfid, &oplock, NULL, &netfid, &oplock, NULL,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc==0) { if (rc == 0) {
CIFSSMBRenameOpenFile(xid, pTcon, CIFSSMBRenameOpenFile(xid, pTcon,
netfid, NULL, netfid, NULL,
cifs_sb->local_nls, cifs_sb->local_nls,
...@@ -773,8 +783,8 @@ static void posix_fill_in_inode(struct inode *tmp_inode, ...@@ -773,8 +783,8 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
tmp_inode->i_mode = le64_to_cpu(pData->Permissions); tmp_inode->i_mode = le64_to_cpu(pData->Permissions);
/* since we set the inode type below we need to mask off type /* since we set the inode type below we need to mask off type
to avoid strange results if bits above were corrupt */ to avoid strange results if bits above were corrupt */
tmp_inode->i_mode &= ~S_IFMT; tmp_inode->i_mode &= ~S_IFMT;
if (type == UNIX_FILE) { if (type == UNIX_FILE) {
*pobject_type = DT_REG; *pobject_type = DT_REG;
tmp_inode->i_mode |= S_IFREG; tmp_inode->i_mode |= S_IFREG;
...@@ -804,11 +814,11 @@ static void posix_fill_in_inode(struct inode *tmp_inode, ...@@ -804,11 +814,11 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
/* safest to just call it a file */ /* safest to just call it a file */
*pobject_type = DT_REG; *pobject_type = DT_REG;
tmp_inode->i_mode |= S_IFREG; tmp_inode->i_mode |= S_IFREG;
cFYI(1,("unknown inode type %d",type)); cFYI(1, ("unknown inode type %d", type));
} }
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
cFYI(1,("object type: %d", type)); cFYI(1, ("object type: %d", type));
#endif #endif
tmp_inode->i_uid = le64_to_cpu(pData->Uid); tmp_inode->i_uid = le64_to_cpu(pData->Uid);
tmp_inode->i_gid = le64_to_cpu(pData->Gid); tmp_inode->i_gid = le64_to_cpu(pData->Gid);
...@@ -816,7 +826,7 @@ static void posix_fill_in_inode(struct inode *tmp_inode, ...@@ -816,7 +826,7 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
spin_lock(&tmp_inode->i_lock); spin_lock(&tmp_inode->i_lock);
if (is_size_safe_to_change(cifsInfo, end_of_file)) { 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 */ client is writing to it due to potential races */
i_size_write(tmp_inode, end_of_file); i_size_write(tmp_inode, end_of_file);
...@@ -830,27 +840,28 @@ static void posix_fill_in_inode(struct inode *tmp_inode, ...@@ -830,27 +840,28 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
cFYI(1, ("File inode")); cFYI(1, ("File inode"));
tmp_inode->i_op = &cifs_file_inode_ops; tmp_inode->i_op = &cifs_file_inode_ops;
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
else else
tmp_inode->i_fop = &cifs_file_direct_ops; tmp_inode->i_fop = &cifs_file_direct_ops;
} else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
tmp_inode->i_fop = &cifs_file_nobrl_ops; tmp_inode->i_fop = &cifs_file_nobrl_ops;
else else
tmp_inode->i_fop = &cifs_file_ops; tmp_inode->i_fop = &cifs_file_ops;
if((cifs_sb->tcon) && (cifs_sb->tcon->ses) && if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
(cifs_sb->tcon->ses->server->maxBuf < (cifs_sb->tcon->ses->server->maxBuf <
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
else else
tmp_inode->i_data.a_ops = &cifs_addr_ops; tmp_inode->i_data.a_ops = &cifs_addr_ops;
if(isNewInode) if (isNewInode)
return; /* No sense invalidating pages for new inode since we return; /* No sense invalidating pages for new inode
have not started caching readahead file data yet */ since we we have not started caching
readahead file data yet */
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
(local_size == tmp_inode->i_size)) { (local_size == tmp_inode->i_size)) {
...@@ -869,10 +880,10 @@ static void posix_fill_in_inode(struct inode *tmp_inode, ...@@ -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_op = &cifs_symlink_inode_ops;
/* tmp_inode->i_fop = *//* do not need to set to anything */ /* tmp_inode->i_fop = *//* do not need to set to anything */
} else { } else {
cFYI(1, ("Special inode")); cFYI(1, ("Special inode"));
init_special_inode(tmp_inode, tmp_inode->i_mode, init_special_inode(tmp_inode, tmp_inode->i_mode,
tmp_inode->i_rdev); tmp_inode->i_rdev);
} }
} }
int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) 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) ...@@ -896,22 +907,22 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return -ENOMEM;
} }
if((pTcon->ses->capabilities & CAP_UNIX) && if ((pTcon->ses->capabilities & CAP_UNIX) &&
(CIFS_UNIX_POSIX_PATH_OPS_CAP & (CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(pTcon->fsUnixInfo.Capability))) { le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
u32 oplock = 0; u32 oplock = 0;
FILE_UNIX_BASIC_INFO * pInfo = FILE_UNIX_BASIC_INFO * pInfo =
kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
if(pInfo == NULL) { if (pInfo == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
goto mkdir_out; goto mkdir_out;
} }
rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
mode, NULL /* netfid */, pInfo, &oplock, mode, NULL /* netfid */, pInfo, &oplock,
full_path, cifs_sb->local_nls, full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) { if (rc) {
cFYI(1, ("posix mkdir returned 0x%x", rc)); cFYI(1, ("posix mkdir returned 0x%x", rc));
...@@ -919,8 +930,9 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -919,8 +930,9 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
} else { } else {
int obj_type; int obj_type;
if (pInfo->Type == -1) /* no return info - go query */ if (pInfo->Type == -1) /* no return info - go query */
goto mkdir_get_info; goto mkdir_get_info;
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need to set uid/gid */ /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
to set uid/gid */
inc_nlink(inode); inc_nlink(inode);
if (pTcon->nocase) if (pTcon->nocase)
direntry->d_op = &cifs_ci_dentry_ops; direntry->d_op = &cifs_ci_dentry_ops;
...@@ -937,7 +949,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -937,7 +949,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
newinode->i_ino = newinode->i_ino =
(unsigned long)pInfo->UniqueId; (unsigned long)pInfo->UniqueId;
} /* note ino incremented to unique num in new_inode */ } /* note ino incremented to unique num in new_inode */
if(inode->i_sb->s_flags & MS_NOATIME) if (inode->i_sb->s_flags & MS_NOATIME)
newinode->i_flags |= S_NOATIME | S_NOCMTIME; newinode->i_flags |= S_NOATIME | S_NOCMTIME;
newinode->i_nlink = 2; newinode->i_nlink = 2;
...@@ -949,18 +961,18 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -949,18 +961,18 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
posix_fill_in_inode(direntry->d_inode, posix_fill_in_inode(direntry->d_inode,
pInfo, &obj_type, 1 /* NewInode */); pInfo, &obj_type, 1 /* NewInode */);
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
cFYI(1,("instantiated dentry %p %s to inode %p", cFYI(1, ("instantiated dentry %p %s to inode %p",
direntry, direntry->d_name.name, newinode)); direntry, direntry->d_name.name, newinode));
if(newinode->i_nlink != 2) if (newinode->i_nlink != 2)
cFYI(1,("unexpected number of links %d", cFYI(1, ("unexpected number of links %d",
newinode->i_nlink)); newinode->i_nlink));
#endif #endif
} }
kfree(pInfo); kfree(pInfo);
goto mkdir_out; goto mkdir_out;
} }
/* BB add setting the equivalent of mode via CreateX w/ACLs */ /* BB add setting the equivalent of mode via CreateX w/ACLs */
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
...@@ -968,14 +980,14 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -968,14 +980,14 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
cFYI(1, ("cifs_mkdir returned 0x%x", rc)); cFYI(1, ("cifs_mkdir returned 0x%x", rc));
d_drop(direntry); d_drop(direntry);
} else { } else {
mkdir_get_info: mkdir_get_info:
inc_nlink(inode); inc_nlink(inode);
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->unix_ext)
rc = cifs_get_inode_info_unix(&newinode, full_path, rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb,xid); inode->i_sb, xid);
else else
rc = cifs_get_inode_info(&newinode, full_path, NULL, rc = cifs_get_inode_info(&newinode, full_path, NULL,
inode->i_sb,xid); inode->i_sb, xid);
if (pTcon->nocase) if (pTcon->nocase)
direntry->d_op = &cifs_ci_dentry_ops; direntry->d_op = &cifs_ci_dentry_ops;
...@@ -983,10 +995,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -983,10 +995,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
direntry->d_op = &cifs_dentry_ops; direntry->d_op = &cifs_dentry_ops;
d_instantiate(direntry, newinode); d_instantiate(direntry, newinode);
/* setting nlink not necessary except in cases where we /* 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)) if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
direntry->d_inode->i_nlink = 2; direntry->d_inode->i_nlink = 2;
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) { if (pTcon->unix_ext) {
mode &= ~current->fs->umask; mode &= ~current->fs->umask;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path, CIFSSMBUnixSetPerms(xid, pTcon, full_path,
...@@ -1002,27 +1014,27 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -1002,27 +1014,27 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
mode, (__u64)-1, mode, (__u64)-1,
(__u64)-1, 0 /* dev_t */, (__u64)-1, 0 /* dev_t */,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
} }
} else { } else {
/* BB to be implemented via Windows secrty descriptors /* BB to be implemented via Windows secrty descriptors
eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
-1, -1, local_nls); */ -1, -1, local_nls); */
if(direntry->d_inode) { if (direntry->d_inode) {
direntry->d_inode->i_mode = mode; direntry->d_inode->i_mode = mode;
direntry->d_inode->i_mode |= S_IFDIR; direntry->d_inode->i_mode |= S_IFDIR;
if(cifs_sb->mnt_cifs_flags & if (cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_SET_UID) { CIFS_MOUNT_SET_UID) {
direntry->d_inode->i_uid = direntry->d_inode->i_uid =
current->fsuid; current->fsuid;
direntry->d_inode->i_gid = direntry->d_inode->i_gid =
current->fsgid; current->fsgid;
} }
} }
} }
} }
mkdir_out: mkdir_out:
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
return rc; return rc;
...@@ -1056,7 +1068,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) ...@@ -1056,7 +1068,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
if (!rc) { if (!rc) {
drop_nlink(inode); drop_nlink(inode);
spin_lock(&direntry->d_inode->i_lock); spin_lock(&direntry->d_inode->i_lock);
i_size_write(direntry->d_inode,0); i_size_write(direntry->d_inode, 0);
clear_nlink(direntry->d_inode); clear_nlink(direntry->d_inode);
spin_unlock(&direntry->d_inode->i_lock); spin_unlock(&direntry->d_inode->i_lock);
} }
...@@ -1119,9 +1131,9 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry, ...@@ -1119,9 +1131,9 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
if (info_buf_source != NULL) { if (info_buf_source != NULL) {
info_buf_target = info_buf_source + 1; info_buf_target = info_buf_source + 1;
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->unix_ext)
rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName, rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
info_buf_source, info_buf_source,
cifs_sb_source->local_nls, cifs_sb_source->local_nls,
cifs_sb_source->mnt_cifs_flags & cifs_sb_source->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
...@@ -1171,12 +1183,12 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry, ...@@ -1171,12 +1183,12 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
might not right be right access to request */ might not right be right access to request */
rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ, rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
CREATE_NOT_DIR, &netfid, &oplock, NULL, CREATE_NOT_DIR, &netfid, &oplock, NULL,
cifs_sb_source->local_nls, cifs_sb_source->local_nls,
cifs_sb_source->mnt_cifs_flags & cifs_sb_source->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc==0) { if (rc == 0) {
rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName, rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
cifs_sb_source->local_nls, cifs_sb_source->local_nls,
cifs_sb_source->mnt_cifs_flags & cifs_sb_source->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
...@@ -1247,9 +1259,9 @@ int cifs_revalidate(struct dentry *direntry) ...@@ -1247,9 +1259,9 @@ int cifs_revalidate(struct dentry *direntry)
local_mtime = direntry->d_inode->i_mtime; local_mtime = direntry->d_inode->i_mtime;
local_size = direntry->d_inode->i_size; local_size = direntry->d_inode->i_size;
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) { if (cifs_sb->tcon->unix_ext) {
rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path, rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
direntry->d_sb,xid); direntry->d_sb, xid);
if (rc) { if (rc) {
cFYI(1, ("error on getting revalidate info %d", rc)); cFYI(1, ("error on getting revalidate info %d", rc));
/* if (rc != -ENOENT) /* if (rc != -ENOENT)
...@@ -1258,7 +1270,7 @@ int cifs_revalidate(struct dentry *direntry) ...@@ -1258,7 +1270,7 @@ int cifs_revalidate(struct dentry *direntry)
} }
} else { } else {
rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL, rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
direntry->d_sb,xid); direntry->d_sb, xid);
if (rc) { if (rc) {
cFYI(1, ("error on getting revalidate info %d", rc)); cFYI(1, ("error on getting revalidate info %d", rc));
/* if (rc != -ENOENT) /* if (rc != -ENOENT)
...@@ -1271,7 +1283,7 @@ int cifs_revalidate(struct dentry *direntry) ...@@ -1271,7 +1283,7 @@ int cifs_revalidate(struct dentry *direntry)
/* if not oplocked, we invalidate inode pages if mtime or file size /* if not oplocked, we invalidate inode pages if mtime or file size
had changed on server */ had changed on server */
if (timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) && if (timespec_equal(&local_mtime, &direntry->d_inode->i_mtime) &&
(local_size == direntry->d_inode->i_size)) { (local_size == direntry->d_inode->i_size)) {
cFYI(1, ("cifs_revalidate - inode unchanged")); cFYI(1, ("cifs_revalidate - inode unchanged"));
} else { } else {
...@@ -1298,7 +1310,7 @@ int cifs_revalidate(struct dentry *direntry) ...@@ -1298,7 +1310,7 @@ int cifs_revalidate(struct dentry *direntry)
if (invalidate_inode) { if (invalidate_inode) {
/* shrink_dcache not necessary now that cifs dentry ops /* shrink_dcache not necessary now that cifs dentry ops
are exported for negative dentries */ are exported for negative dentries */
/* if(S_ISDIR(direntry->d_inode->i_mode)) /* if (S_ISDIR(direntry->d_inode->i_mode))
shrink_dcache_parent(direntry); */ shrink_dcache_parent(direntry); */
if (S_ISREG(direntry->d_inode->i_mode)) { if (S_ISREG(direntry->d_inode->i_mode)) {
if (direntry->d_inode->i_mapping) if (direntry->d_inode->i_mapping)
...@@ -1313,7 +1325,7 @@ int cifs_revalidate(struct dentry *direntry) ...@@ -1313,7 +1325,7 @@ int cifs_revalidate(struct dentry *direntry)
} }
} }
/* mutex_unlock(&direntry->d_inode->i_mutex); */ /* mutex_unlock(&direntry->d_inode->i_mutex); */
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
return rc; return rc;
...@@ -1335,23 +1347,19 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from) ...@@ -1335,23 +1347,19 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
pgoff_t index = from >> PAGE_CACHE_SHIFT; pgoff_t index = from >> PAGE_CACHE_SHIFT;
unsigned offset = from & (PAGE_CACHE_SIZE - 1); unsigned offset = from & (PAGE_CACHE_SIZE - 1);
struct page *page; struct page *page;
char *kaddr;
int rc = 0; int rc = 0;
page = grab_cache_page(mapping, index); page = grab_cache_page(mapping, index);
if (!page) if (!page)
return -ENOMEM; return -ENOMEM;
kaddr = kmap_atomic(page, KM_USER0); zero_user_page(page, offset, PAGE_CACHE_SIZE - offset, KM_USER0);
memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
unlock_page(page); unlock_page(page);
page_cache_release(page); page_cache_release(page);
return rc; return rc;
} }
static int cifs_vmtruncate(struct inode * inode, loff_t offset) static int cifs_vmtruncate(struct inode *inode, loff_t offset)
{ {
struct address_space *mapping = inode->i_mapping; struct address_space *mapping = inode->i_mapping;
unsigned long limit; unsigned long limit;
...@@ -1424,13 +1432,13 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1424,13 +1432,13 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
/* check if we have permission to change attrs */ /* check if we have permission to change attrs */
rc = inode_change_ok(direntry->d_inode, attrs); rc = inode_change_ok(direntry->d_inode, attrs);
if(rc < 0) { if (rc < 0) {
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} else } else
rc = 0; rc = 0;
} }
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
FreeXid(xid); FreeXid(xid);
...@@ -1459,16 +1467,16 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1459,16 +1467,16 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
nfid, npid, FALSE); nfid, npid, FALSE);
atomic_dec(&open_file->wrtPending); atomic_dec(&open_file->wrtPending);
cFYI(1,("SetFSize for attrs rc = %d", rc)); cFYI(1, ("SetFSize for attrs rc = %d", rc));
if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
int bytes_written; int bytes_written;
rc = CIFSSMBWrite(xid, pTcon, rc = CIFSSMBWrite(xid, pTcon,
nfid, 0, attrs->ia_size, nfid, 0, attrs->ia_size,
&bytes_written, NULL, NULL, &bytes_written, NULL, NULL,
1 /* 45 seconds */); 1 /* 45 seconds */);
cFYI(1,("Wrt seteof rc %d", rc)); cFYI(1, ("Wrt seteof rc %d", rc));
} }
} else } else
rc = -EINVAL; rc = -EINVAL;
if (rc != 0) { if (rc != 0) {
...@@ -1478,11 +1486,11 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1478,11 +1486,11 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
it by handle */ it by handle */
rc = CIFSSMBSetEOF(xid, pTcon, full_path, rc = CIFSSMBSetEOF(xid, pTcon, full_path,
attrs->ia_size, FALSE, attrs->ia_size, FALSE,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc)); cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
__u16 netfid; __u16 netfid;
int oplock = FALSE; int oplock = FALSE;
...@@ -1493,14 +1501,14 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1493,14 +1501,14 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
NULL, cifs_sb->local_nls, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc==0) { if (rc == 0) {
int bytes_written; int bytes_written;
rc = CIFSSMBWrite(xid, pTcon, rc = CIFSSMBWrite(xid, pTcon,
netfid, 0, netfid, 0,
attrs->ia_size, attrs->ia_size,
&bytes_written, NULL, &bytes_written, NULL,
NULL, 1 /* 45 sec */); NULL, 1 /* 45 sec */);
cFYI(1,("wrt seteof rc %d",rc)); cFYI(1, ("wrt seteof rc %d", rc));
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
} }
...@@ -1517,7 +1525,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1517,7 +1525,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
rc = cifs_vmtruncate(direntry->d_inode, attrs->ia_size); rc = cifs_vmtruncate(direntry->d_inode, attrs->ia_size);
cifs_truncate_page(direntry->d_inode->i_mapping, cifs_truncate_page(direntry->d_inode->i_mapping,
direntry->d_inode->i_size); direntry->d_inode->i_size);
} else } else
goto cifs_setattr_exit; goto cifs_setattr_exit;
} }
if (attrs->ia_valid & ATTR_UID) { if (attrs->ia_valid & ATTR_UID) {
...@@ -1535,11 +1543,11 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1535,11 +1543,11 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
mode = attrs->ia_mode; mode = attrs->ia_mode;
} }
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) if ((pTcon->unix_ext)
&& (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID))) && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid, rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
0 /* dev_t */, cifs_sb->local_nls, 0 /* dev_t */, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
else if (attrs->ia_valid & ATTR_MODE) { else if (attrs->ia_valid & ATTR_MODE) {
rc = 0; rc = 0;
...@@ -1559,7 +1567,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1559,7 +1567,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs & time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs &
(~ATTR_READONLY)); (~ATTR_READONLY));
/* Windows ignores set to zero */ /* Windows ignores set to zero */
if(time_buf.Attributes == 0) if (time_buf.Attributes == 0)
time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL);
} }
/* BB to be implemented - /* BB to be implemented -
...@@ -1585,7 +1593,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1585,7 +1593,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
stamps are changed explicitly (i.e. by utime() stamps are changed explicitly (i.e. by utime()
since we would then have a mix of client and since we would then have a mix of client and
server times */ server times */
if (set_time && (attrs->ia_valid & ATTR_CTIME)) { if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
set_time = TRUE; set_time = TRUE;
/* Although Samba throws this field away /* Although Samba throws this field away
...@@ -1624,7 +1632,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1624,7 +1632,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
NULL, cifs_sb->local_nls, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc==0) { if (rc == 0) {
rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf, rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
netfid); netfid);
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
...@@ -1634,7 +1642,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1634,7 +1642,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
granularity */ granularity */
/* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path, /* 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 /* 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) ...@@ -1642,7 +1650,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
and this check ensures that we are not being called from and this check ensures that we are not being called from
sys_utimes in which case we ought to fail the call back to sys_utimes in which case we ought to fail the call back to
the user when the server rejects the call */ the user when the server rejects the call */
if((rc) && (attrs->ia_valid & if ((rc) && (attrs->ia_valid &
(ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE))) (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
rc = 0; rc = 0;
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* vfs operations that deal with io control * vfs operations that deal with io control
* *
* Copyright (C) International Business Machines Corp., 2005 * Copyright (C) International Business Machines Corp., 2005,2007
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2) #define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
int cifs_ioctl (struct inode * inode, struct file * filep, int cifs_ioctl (struct inode *inode, struct file *filep,
unsigned int command, unsigned long arg) unsigned int command, unsigned long arg)
{ {
int rc = -ENOTTY; /* strange error - but the precedent */ int rc = -ENOTTY; /* strange error - but the precedent */
......
...@@ -50,32 +50,33 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, ...@@ -50,32 +50,33 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
fromName = build_path_from_dentry(old_file); fromName = build_path_from_dentry(old_file);
toName = build_path_from_dentry(direntry); toName = build_path_from_dentry(direntry);
if((fromName == NULL) || (toName == NULL)) { if ((fromName == NULL) || (toName == NULL)) {
rc = -ENOMEM; rc = -ENOMEM;
goto cifs_hl_exit; goto cifs_hl_exit;
} }
if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX) /* if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)*/
if (pTcon->unix_ext)
rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
cifs_sb_target->local_nls, cifs_sb_target->local_nls,
cifs_sb_target->mnt_cifs_flags & cifs_sb_target->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
else { else {
rc = CIFSCreateHardLink(xid, pTcon, fromName, toName, rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
cifs_sb_target->local_nls, cifs_sb_target->local_nls,
cifs_sb_target->mnt_cifs_flags & cifs_sb_target->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if((rc == -EIO) || (rc == -EINVAL)) if ((rc == -EIO) || (rc == -EINVAL))
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
} }
d_drop(direntry); /* force new lookup from server of target */ d_drop(direntry); /* force new lookup from server of target */
/* if source file is cached (oplocked) revalidate will not go to server /* if source file is cached (oplocked) revalidate will not go to server
until the file is closed or oplock broken so update nlinks locally */ until the file is closed or oplock broken so update nlinks locally */
if(old_file->d_inode) { if (old_file->d_inode) {
cifsInode = CIFS_I(old_file->d_inode); cifsInode = CIFS_I(old_file->d_inode);
if(rc == 0) { if (rc == 0) {
old_file->d_inode->i_nlink++; old_file->d_inode->i_nlink++;
/* BB should we make this contingent on superblock flag NOATIME? */ /* BB should we make this contingent on superblock flag NOATIME? */
/* old_file->d_inode->i_ctime = CURRENT_TIME;*/ /* old_file->d_inode->i_ctime = CURRENT_TIME;*/
...@@ -84,14 +85,14 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, ...@@ -84,14 +85,14 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
to set the parent dir cifs inode time to zero to set the parent dir cifs inode time to zero
to force revalidate (faster) for it too? */ 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 */ on source file from srv */
cifsInode->time = 0; 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 Would it really be worth it to set the parent dir (cifs
inode) time field to zero to force revalidate on parent inode) time field to zero to force revalidate on parent
directory faster ie directory faster ie
CIFS_I(inode)->time = 0; */ CIFS_I(inode)->time = 0; */
} }
...@@ -109,7 +110,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) ...@@ -109,7 +110,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
int rc = -EACCES; int rc = -EACCES;
int xid; int xid;
char *full_path = NULL; char *full_path = NULL;
char * target_path = ERR_PTR(-ENOMEM); char *target_path = ERR_PTR(-ENOMEM);
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
...@@ -129,13 +130,19 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) ...@@ -129,13 +130,19 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
goto out; goto out;
} }
/* BB add read reparse point symlink code and Unix extensions symlink code here BB */ /* We could change this to:
if (pTcon->unix_ext)
but there does not seem any point in refusing to
get symlink info if we can, even if unix extensions
turned off for this mount */
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->ses->capabilities & CAP_UNIX)
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path, rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
target_path, target_path,
PATH_MAX-1, PATH_MAX-1,
cifs_sb->local_nls); cifs_sb->local_nls);
else { else {
/* BB add read reparse point symlink code here */
/* rc = CIFSSMBQueryReparseLinkInfo */ /* rc = CIFSSMBQueryReparseLinkInfo */
/* BB Add code to Query ReparsePoint info */ /* BB Add code to Query ReparsePoint info */
/* BB Add MAC style xsymlink check here if enabled */ /* BB Add MAC style xsymlink check here if enabled */
...@@ -176,7 +183,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) ...@@ -176,7 +183,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) { if (full_path == NULL) {
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return -ENOMEM;
} }
...@@ -185,19 +192,20 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) ...@@ -185,19 +192,20 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
cFYI(1, ("symname is %s", symname)); cFYI(1, ("symname is %s", symname));
/* BB what if DFS and this volume is on different share? BB */ /* BB what if DFS and this volume is on different share? BB */
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) if (pTcon->unix_ext)
rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
cifs_sb->local_nls); cifs_sb->local_nls);
/* else /* else
rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */ rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,
cifs_sb_target->local_nls); */
if (rc == 0) { if (rc == 0) {
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->unix_ext)
rc = cifs_get_inode_info_unix(&newinode, full_path, rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb,xid); inode->i_sb, xid);
else else
rc = cifs_get_inode_info(&newinode, full_path, NULL, rc = cifs_get_inode_info(&newinode, full_path, NULL,
inode->i_sb,xid); inode->i_sb, xid);
if (rc != 0) { if (rc != 0) {
cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d", cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d",
...@@ -226,9 +234,9 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) ...@@ -226,9 +234,9 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
char *full_path = NULL; char *full_path = NULL;
char *tmp_path = NULL; char *tmp_path = NULL;
char * tmpbuffer; char *tmpbuffer;
unsigned char * referrals = NULL; unsigned char *referrals = NULL;
int num_referrals = 0; int num_referrals = 0;
int len; int len;
__u16 fid; __u16 fid;
...@@ -237,13 +245,13 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) ...@@ -237,13 +245,13 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon; 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? */ even though rename itself grabs the sem and calls lookup? */
/* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/ /* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
/* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/ /* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/
if(full_path == NULL) { if (full_path == NULL) {
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return -ENOMEM;
} }
...@@ -251,70 +259,80 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) ...@@ -251,70 +259,80 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
cFYI(1, cFYI(1,
("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d", ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
full_path, inode, pBuffer, buflen)); full_path, inode, pBuffer, buflen));
if(buflen > PATH_MAX) if (buflen > PATH_MAX)
len = PATH_MAX; len = PATH_MAX;
else else
len = buflen; len = buflen;
tmpbuffer = kmalloc(len,GFP_KERNEL); tmpbuffer = kmalloc(len, GFP_KERNEL);
if(tmpbuffer == NULL) { if (tmpbuffer == NULL) {
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return -ENOMEM;
} }
/* BB add read reparse point symlink code and Unix extensions symlink code here BB */ /* BB add read reparse point symlink code and
Unix extensions symlink code here BB */
/* We could disable this based on pTcon->unix_ext flag instead ... but why? */
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path, rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
tmpbuffer, tmpbuffer,
len - 1, len - 1,
cifs_sb->local_nls); cifs_sb->local_nls);
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
cERROR(1,("SFU style symlinks not implemented yet")); cERROR(1, ("SFU style symlinks not implemented yet"));
/* add open and read as in fs/cifs/inode.c */ /* add open and read as in fs/cifs/inode.c */
} else { } else {
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
OPEN_REPARSE_POINT,&fid, &oplock, NULL, OPEN_REPARSE_POINT, &fid, &oplock, NULL,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if(!rc) { if (!rc) {
rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path, rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
tmpbuffer, tmpbuffer,
len - 1, len - 1,
fid, fid,
cifs_sb->local_nls); cifs_sb->local_nls);
if(CIFSSMBClose(xid, pTcon, fid)) { if (CIFSSMBClose(xid, pTcon, fid)) {
cFYI(1,("Error closing junction point (open for ioctl)")); cFYI(1, ("Error closing junction point "
"(open for ioctl)"));
} }
if(rc == -EIO) { if (rc == -EIO) {
/* Query if DFS Junction */ /* Query if DFS Junction */
tmp_path = tmp_path =
kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1, kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
GFP_KERNEL); GFP_KERNEL);
if (tmp_path) { if (tmp_path) {
strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); strncpy(tmp_path, pTcon->treeName,
strncat(tmp_path, full_path, MAX_PATHCONF); MAX_TREE_SIZE);
rc = get_dfs_path(xid, pTcon->ses, tmp_path, strncat(tmp_path, full_path,
MAX_PATHCONF);
rc = get_dfs_path(xid, pTcon->ses,
tmp_path,
cifs_sb->local_nls, cifs_sb->local_nls,
&num_referrals, &referrals, &num_referrals, &referrals,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc)); cFYI(1, ("Get DFS for %s rc = %d ",
if((num_referrals == 0) && (rc == 0)) tmp_path, rc));
if ((num_referrals == 0) && (rc == 0))
rc = -EACCES; rc = -EACCES;
else { else {
cFYI(1,("num referral: %d",num_referrals)); cFYI(1, ("num referral: %d",
if(referrals) { num_referrals));
cFYI(1,("referral string: %s",referrals)); if (referrals) {
strncpy(tmpbuffer, referrals, len-1); cFYI(1,("referral string: %s", referrals));
strncpy(tmpbuffer,
referrals,
len-1);
} }
} }
kfree(referrals); kfree(referrals);
kfree(tmp_path); kfree(tmp_path);
} }
/* BB add code like else decode referrals then memcpy to /* BB add code like else decode referrals
tmpbuffer and free referrals string array BB */ then memcpy to tmpbuffer and free referrals
string array BB */
} }
} }
} }
......
/* /*
Unix SMB/Netbios implementation. Unix SMB/Netbios implementation.
Version 1.9. Version 1.9.
a implementation of MD4 designed for use in the SMB authentication protocol a implementation of MD4 designed for use in the SMB authentication protocol
Copyright (C) Andrew Tridgell 1997-1998. Copyright (C) Andrew Tridgell 1997-1998.
Modified by Steve French (sfrench@us.ibm.com) 2002-2003 Modified by Steve French (sfrench@us.ibm.com) 2002-2003
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License 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., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
...@@ -170,7 +170,7 @@ mdfour(unsigned char *out, unsigned char *in, int n) ...@@ -170,7 +170,7 @@ mdfour(unsigned char *out, unsigned char *in, int n)
while (n > 64) { while (n > 64) {
copy64(M, in); copy64(M, in);
mdfour64(M,&A,&B, &C, &D); mdfour64(M, &A, &B, &C, &D);
in += 64; in += 64;
n -= 64; n -= 64;
} }
......
...@@ -15,9 +15,9 @@ ...@@ -15,9 +15,9 @@
* will fill a supplied 16-byte array with the digest. * will fill a supplied 16-byte array with the digest.
*/ */
/* This code slightly modified to fit into Samba by /* This code slightly modified to fit into Samba by
abartlet@samba.org Jun 2001 abartlet@samba.org Jun 2001
and to fit the cifs vfs by and to fit the cifs vfs by
Steve French sfrench@us.ibm.com */ Steve French sfrench@us.ibm.com */
#include <linux/string.h> #include <linux/string.h>
...@@ -106,7 +106,7 @@ MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) ...@@ -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) * 1 0* (64-bit count of bits processed, MSB-first)
*/ */
void void
......
/* /*
* fs/cifs/misc.c * fs/cifs/misc.c
* *
* Copyright (C) International Business Machines Corp., 2002,2005 * Copyright (C) International Business Machines Corp., 2002,2007
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software * 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> #include <linux/slab.h>
...@@ -32,12 +32,12 @@ ...@@ -32,12 +32,12 @@
extern mempool_t *cifs_sm_req_poolp; extern mempool_t *cifs_sm_req_poolp;
extern mempool_t *cifs_req_poolp; extern mempool_t *cifs_req_poolp;
extern struct task_struct * oplockThread; extern struct task_struct *oplockThread;
/* The xid serves as a useful identifier for each incoming vfs request, /* The xid serves as a useful identifier for each incoming vfs request,
in a similar way to the mid which is useful to track each sent smb, in a similar way to the mid which is useful to track each sent smb,
and CurrentXid can also provide a running counter (although it and CurrentXid can also provide a running counter (although it
will eventually wrap past zero) of the total vfs operations handled will eventually wrap past zero) of the total vfs operations handled
since the cifs fs was mounted */ since the cifs fs was mounted */
unsigned int unsigned int
...@@ -47,10 +47,12 @@ _GetXid(void) ...@@ -47,10 +47,12 @@ _GetXid(void)
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
GlobalTotalActiveXid++; GlobalTotalActiveXid++;
/* keep high water mark for number of simultaneous ops in filesystem */
if (GlobalTotalActiveXid > GlobalMaxActiveXid) if (GlobalTotalActiveXid > GlobalMaxActiveXid)
GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */ GlobalMaxActiveXid = GlobalTotalActiveXid;
if(GlobalTotalActiveXid > 65000) if (GlobalTotalActiveXid > 65000)
cFYI(1,("warning: more than 65000 requests active")); cFYI(1, ("warning: more than 65000 requests active"));
xid = GlobalCurrentXid++; xid = GlobalCurrentXid++;
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
return xid; return xid;
...@@ -60,7 +62,7 @@ void ...@@ -60,7 +62,7 @@ void
_FreeXid(unsigned int xid) _FreeXid(unsigned int xid)
{ {
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
/* if(GlobalTotalActiveXid == 0) /* if (GlobalTotalActiveXid == 0)
BUG(); */ BUG(); */
GlobalTotalActiveXid--; GlobalTotalActiveXid--;
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
...@@ -144,12 +146,12 @@ cifs_buf_get(void) ...@@ -144,12 +146,12 @@ cifs_buf_get(void)
{ {
struct smb_hdr *ret_buf = NULL; struct smb_hdr *ret_buf = NULL;
/* We could use negotiated size instead of max_msgsize - /* We could use negotiated size instead of max_msgsize -
but it may be more efficient to always alloc same size but it may be more efficient to always alloc same size
albeit slightly larger than necessary and maxbuffersize albeit slightly larger than necessary and maxbuffersize
defaults to this and can not be bigger */ defaults to this and can not be bigger */
ret_buf = ret_buf = (struct smb_hdr *) mempool_alloc(cifs_req_poolp,
(struct smb_hdr *) mempool_alloc(cifs_req_poolp, GFP_KERNEL | GFP_NOFS); GFP_KERNEL | GFP_NOFS);
/* clear the first few header bytes */ /* clear the first few header bytes */
/* for most paths, more is cleared in header_assemble */ /* for most paths, more is cleared in header_assemble */
...@@ -172,7 +174,7 @@ cifs_buf_release(void *buf_to_free) ...@@ -172,7 +174,7 @@ cifs_buf_release(void *buf_to_free)
/* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/ /* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
return; return;
} }
mempool_free(buf_to_free,cifs_req_poolp); mempool_free(buf_to_free, cifs_req_poolp);
atomic_dec(&bufAllocCount); atomic_dec(&bufAllocCount);
return; return;
...@@ -183,12 +185,12 @@ cifs_small_buf_get(void) ...@@ -183,12 +185,12 @@ cifs_small_buf_get(void)
{ {
struct smb_hdr *ret_buf = NULL; struct smb_hdr *ret_buf = NULL;
/* We could use negotiated size instead of max_msgsize - /* We could use negotiated size instead of max_msgsize -
but it may be more efficient to always alloc same size but it may be more efficient to always alloc same size
albeit slightly larger than necessary and maxbuffersize albeit slightly larger than necessary and maxbuffersize
defaults to this and can not be bigger */ defaults to this and can not be bigger */
ret_buf = ret_buf = (struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp,
(struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp, GFP_KERNEL | GFP_NOFS); GFP_KERNEL | GFP_NOFS);
if (ret_buf) { if (ret_buf) {
/* No need to clear memory here, cleared in header assemble */ /* No need to clear memory here, cleared in header assemble */
/* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/ /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
...@@ -209,30 +211,30 @@ cifs_small_buf_release(void *buf_to_free) ...@@ -209,30 +211,30 @@ cifs_small_buf_release(void *buf_to_free)
cFYI(1, ("Null buffer passed to cifs_small_buf_release")); cFYI(1, ("Null buffer passed to cifs_small_buf_release"));
return; return;
} }
mempool_free(buf_to_free,cifs_sm_req_poolp); mempool_free(buf_to_free, cifs_sm_req_poolp);
atomic_dec(&smBufAllocCount); atomic_dec(&smBufAllocCount);
return; return;
} }
/* /*
Find a free multiplex id (SMB mid). Otherwise there could be Find a free multiplex id (SMB mid). Otherwise there could be
mid collisions which might cause problems, demultiplexing the mid collisions which might cause problems, demultiplexing the
wrong response to this request. Multiplex ids could collide if wrong response to this request. Multiplex ids could collide if
one of a series requests takes much longer than the others, or one of a series requests takes much longer than the others, or
if a very large number of long lived requests (byte range if a very large number of long lived requests (byte range
locks or FindNotify requests) are pending. No more than 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 mids are available, return zero. A future optimization
could make the combination of mids and uid the key we use 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 In addition to the above check, the cifs demultiplex
code already used the command code as a secondary code already used the command code as a secondary
check of the frame and if signing is negotiated the check of the frame and if signing is negotiated the
response would be discarded if the mid were the same response would be discarded if the mid were the same
but the signature was wrong. Since the mid is not put in the but the signature was wrong. Since the mid is not put in the
pending queue until later (when it is about to be dispatched) 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 to somewhat less than 64K-1 although it is hard to imagine
so many threads being in the vfs at one time. so many threads being in the vfs at one time.
*/ */
...@@ -240,27 +242,27 @@ __u16 GetNextMid(struct TCP_Server_Info *server) ...@@ -240,27 +242,27 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
{ {
__u16 mid = 0; __u16 mid = 0;
__u16 last_mid; __u16 last_mid;
int collision; int collision;
if(server == NULL) if (server == NULL)
return mid; return mid;
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
last_mid = server->CurrentMid; /* we do not want to loop forever */ last_mid = server->CurrentMid; /* we do not want to loop forever */
server->CurrentMid++; server->CurrentMid++;
/* This nested loop looks more expensive than it is. /* 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 fewer than 50, and the mids are likely to be unique
on the first pass through the loop unless some request on the first pass through the loop unless some request
takes longer than the 64 thousand requests before it takes longer than the 64 thousand requests before it
(and it would also have to have been a request that (and it would also have to have been a request that
did not time out) */ did not time out) */
while(server->CurrentMid != last_mid) { while (server->CurrentMid != last_mid) {
struct list_head *tmp; struct list_head *tmp;
struct mid_q_entry *mid_entry; struct mid_q_entry *mid_entry;
collision = 0; collision = 0;
if(server->CurrentMid == 0) if (server->CurrentMid == 0)
server->CurrentMid++; server->CurrentMid++;
list_for_each(tmp, &server->pending_mid_q) { list_for_each(tmp, &server->pending_mid_q) {
...@@ -273,7 +275,7 @@ __u16 GetNextMid(struct TCP_Server_Info *server) ...@@ -273,7 +275,7 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
break; break;
} }
} }
if(collision == 0) { if (collision == 0) {
mid = server->CurrentMid; mid = server->CurrentMid;
break; break;
} }
...@@ -290,11 +292,11 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , ...@@ -290,11 +292,11 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
const struct cifsTconInfo *treeCon, int word_count const struct cifsTconInfo *treeCon, int word_count
/* length of fixed section (word count) in two byte units */) /* length of fixed section (word count) in two byte units */)
{ {
struct list_head* temp_item; struct list_head *temp_item;
struct cifsSesInfo * ses; struct cifsSesInfo *ses;
char *temp = (char *) buffer; char *temp = (char *) buffer;
memset(temp,0,256); /* bigger than MAX_CIFS_HDR_SIZE */ memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */
buffer->smb_buf_length = buffer->smb_buf_length =
(2 * word_count) + sizeof (struct smb_hdr) - (2 * word_count) + sizeof (struct smb_hdr) -
...@@ -325,7 +327,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , ...@@ -325,7 +327,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
/* Uid is not converted */ /* Uid is not converted */
buffer->Uid = treeCon->ses->Suid; buffer->Uid = treeCon->ses->Suid;
buffer->Mid = GetNextMid(treeCon->ses->server); buffer->Mid = GetNextMid(treeCon->ses->server);
if(multiuser_mount != 0) { if (multiuser_mount != 0) {
/* For the multiuser case, there are few obvious technically */ /* For the multiuser case, there are few obvious technically */
/* possible mechanisms to match the local linux user (uid) */ /* possible mechanisms to match the local linux user (uid) */
/* to a valid remote smb user (smb_uid): */ /* to a valid remote smb user (smb_uid): */
...@@ -348,21 +350,22 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , ...@@ -348,21 +350,22 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
/* flag were disabled. */ /* flag were disabled. */
/* BB Add support for establishing new tCon and SMB Session */ /* BB Add support for establishing new tCon and SMB Session */
/* with userid/password pairs found on the smb session */ /* with userid/password pairs found on the smb session */
/* for other target tcp/ip addresses BB */ /* for other target tcp/ip addresses BB */
if(current->fsuid != treeCon->ses->linux_uid) { if (current->fsuid != treeCon->ses->linux_uid) {
cFYI(1,("Multiuser mode and UID did not match tcon uid")); cFYI(1, ("Multiuser mode and UID "
"did not match tcon uid"));
read_lock(&GlobalSMBSeslock); read_lock(&GlobalSMBSeslock);
list_for_each(temp_item, &GlobalSMBSessionList) { list_for_each(temp_item, &GlobalSMBSessionList) {
ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList); ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
if(ses->linux_uid == current->fsuid) { if (ses->linux_uid == current->fsuid) {
if(ses->server == treeCon->ses->server) { if (ses->server == treeCon->ses->server) {
cFYI(1,("found matching uid substitute right smb_uid")); cFYI(1, ("found matching uid substitute right smb_uid"));
buffer->Uid = ses->Suid; buffer->Uid = ses->Suid;
break; break;
} else { } else {
/* BB eventually call cifs_setup_session here */ /* BB eventually call cifs_setup_session here */
cFYI(1,("local UID found but smb sess with this server does not exist")); cFYI(1, ("local UID found but no smb sess with this server exists"));
} }
} }
} }
...@@ -374,8 +377,8 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , ...@@ -374,8 +377,8 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
buffer->Flags2 |= SMBFLG2_DFS; buffer->Flags2 |= SMBFLG2_DFS;
if (treeCon->nocase) if (treeCon->nocase)
buffer->Flags |= SMBFLG_CASELESS; buffer->Flags |= SMBFLG_CASELESS;
if((treeCon->ses) && (treeCon->ses->server)) if ((treeCon->ses) && (treeCon->ses->server))
if(treeCon->ses->server->secMode & if (treeCon->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
} }
...@@ -388,18 +391,18 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , ...@@ -388,18 +391,18 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
static int static int
checkSMBhdr(struct smb_hdr *smb, __u16 mid) 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 */ and that the message ids match */
if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) && if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
(mid == smb->Mid)) { (mid == smb->Mid)) {
if(smb->Flags & SMBFLG_RESPONSE) if (smb->Flags & SMBFLG_RESPONSE)
return 0; return 0;
else { else {
/* only one valid case where server sends us request */ /* only one valid case where server sends us request */
if(smb->Command == SMB_COM_LOCKING_ANDX) if (smb->Command == SMB_COM_LOCKING_ANDX)
return 0; return 0;
else else
cERROR(1, ("Rcvd Request not response")); cERROR(1, ("Received Request not response"));
} }
} else { /* bad signature or mid */ } else { /* bad signature or mid */
if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
...@@ -426,9 +429,9 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) ...@@ -426,9 +429,9 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
smb->WordCount = 0; smb->WordCount = 0;
/* some error cases do not return wct and bcc */ /* some error cases do not return wct and bcc */
return 0; return 0;
} else if ((length == sizeof(struct smb_hdr) + 1) && } else if ((length == sizeof(struct smb_hdr) + 1) &&
(smb->WordCount == 0)) { (smb->WordCount == 0)) {
char * tmp = (char *)smb; char *tmp = (char *)smb;
/* Need to work around a bug in two servers here */ /* Need to work around a bug in two servers here */
/* First, check if the part of bcc they sent was zero */ /* First, check if the part of bcc they sent was zero */
if (tmp[sizeof(struct smb_hdr)] == 0) { if (tmp[sizeof(struct smb_hdr)] == 0) {
...@@ -442,7 +445,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) ...@@ -442,7 +445,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
tmp[sizeof(struct smb_hdr)+1] = 0; tmp[sizeof(struct smb_hdr)+1] = 0;
return 0; return 0;
} }
cERROR(1,("rcvd invalid byte count (bcc)")); cERROR(1, ("rcvd invalid byte count (bcc)"));
} else { } else {
cERROR(1, ("Length less than smb header size")); cERROR(1, ("Length less than smb header size"));
} }
...@@ -458,32 +461,33 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) ...@@ -458,32 +461,33 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
return 1; return 1;
clc_len = smbCalcSize_LE(smb); clc_len = smbCalcSize_LE(smb);
if(4 + len != length) { if (4 + len != length) {
cERROR(1, ("Length read does not match RFC1001 length %d",len)); cERROR(1, ("Length read does not match RFC1001 length %d",
len));
return 1; return 1;
} }
if (4 + len != clc_len) { if (4 + len != clc_len) {
/* check if bcc wrapped around for large read responses */ /* check if bcc wrapped around for large read responses */
if((len > 64 * 1024) && (len > clc_len)) { if ((len > 64 * 1024) && (len > clc_len)) {
/* check if lengths match mod 64K */ /* check if lengths match mod 64K */
if(((4 + len) & 0xFFFF) == (clc_len & 0xFFFF)) if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
return 0; /* bcc wrapped */ return 0; /* bcc wrapped */
} }
cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d", cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d",
clc_len, 4 + len, smb->Mid)); clc_len, 4 + len, smb->Mid));
/* Windows XP can return a few bytes too much, presumably /* 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 so we allow for that three byte pad, as long as actual
received length is as long or longer than calculated length */ 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 case in which it needs to be bigger still to handle a
malformed response to transact2 findfirst from WinXP when malformed response to transact2 findfirst from WinXP when
access denied is returned and thus bcc and wct are zero access denied is returned and thus bcc and wct are zero
but server says length is 0x21 bytes too long as if the server but server says length is 0x21 bytes too long as if the server
forget to reset the smb rfc1001 length when it reset the forget to reset the smb rfc1001 length when it reset the
wct and bcc to minimum size and drop the t2 parms and data */ wct and bcc to minimum size and drop the t2 parms and data */
if((4+len > clc_len) && (len <= clc_len + 512)) if ((4+len > clc_len) && (len <= clc_len + 512))
return 0; return 0;
else { else {
cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d", cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d",
...@@ -495,61 +499,64 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) ...@@ -495,61 +499,64 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
} }
int int
is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
{ {
struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf; struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
struct list_head *tmp; struct list_head *tmp;
struct list_head *tmp1; struct list_head *tmp1;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
struct cifsFileInfo *netfile; struct cifsFileInfo *netfile;
cFYI(1,("Checking for oplock break or dnotify response")); cFYI(1, ("Checking for oplock break or dnotify response"));
if((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) && if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
(pSMB->hdr.Flags & SMBFLG_RESPONSE)) { (pSMB->hdr.Flags & SMBFLG_RESPONSE)) {
struct smb_com_transaction_change_notify_rsp * pSMBr = struct smb_com_transaction_change_notify_rsp *pSMBr =
(struct smb_com_transaction_change_notify_rsp *)buf; (struct smb_com_transaction_change_notify_rsp *)buf;
struct file_notify_information * pnotify; struct file_notify_information *pnotify;
__u32 data_offset = 0; __u32 data_offset = 0;
if(pSMBr->ByteCount > sizeof(struct file_notify_information)) { if (pSMBr->ByteCount > sizeof(struct file_notify_information)) {
data_offset = le32_to_cpu(pSMBr->DataOffset); data_offset = le32_to_cpu(pSMBr->DataOffset);
pnotify = (struct file_notify_information *) pnotify = (struct file_notify_information *)
((char *)&pSMBr->hdr.Protocol + data_offset); ((char *)&pSMBr->hdr.Protocol + data_offset);
cFYI(1,("dnotify on %s Action: 0x%x",pnotify->FileName, cFYI(1, ("dnotify on %s Action: 0x%x",
pnotify->FileName,
pnotify->Action)); /* BB removeme BB */ pnotify->Action)); /* BB removeme BB */
/* cifs_dump_mem("Rcvd notify Data: ",buf, /* cifs_dump_mem("Rcvd notify Data: ",buf,
sizeof(struct smb_hdr)+60); */ sizeof(struct smb_hdr)+60); */
return TRUE; return TRUE;
} }
if(pSMBr->hdr.Status.CifsError) { if (pSMBr->hdr.Status.CifsError) {
cFYI(1,("notify err 0x%d",pSMBr->hdr.Status.CifsError)); cFYI(1, ("notify err 0x%d",
pSMBr->hdr.Status.CifsError));
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX) if (pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
return FALSE; return FALSE;
if(pSMB->hdr.Flags & SMBFLG_RESPONSE) { if (pSMB->hdr.Flags & SMBFLG_RESPONSE) {
/* no sense logging error on invalid handle on oplock /* no sense logging error on invalid handle on oplock
break - harmless race between close request and oplock break - harmless race between close request and oplock
break response is expected from time to time writing out break response is expected from time to time writing out
large dirty files cached on the client */ large dirty files cached on the client */
if ((NT_STATUS_INVALID_HANDLE) == if ((NT_STATUS_INVALID_HANDLE) ==
le32_to_cpu(pSMB->hdr.Status.CifsError)) { le32_to_cpu(pSMB->hdr.Status.CifsError)) {
cFYI(1,("invalid handle on oplock break")); cFYI(1, ("invalid handle on oplock break"));
return TRUE; return TRUE;
} else if (ERRbadfid == } else if (ERRbadfid ==
le16_to_cpu(pSMB->hdr.Status.DosError.Error)) { le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
return TRUE; return TRUE;
} else { } else {
return FALSE; /* on valid oplock brk we get "request" */ return FALSE; /* on valid oplock brk we get "request" */
} }
} }
if(pSMB->hdr.WordCount != 8) if (pSMB->hdr.WordCount != 8)
return FALSE; return FALSE;
cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel)); cFYI(1, ("oplock type 0x%d level 0x%d",
if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)) pSMB->LockType, pSMB->OplockLevel));
return FALSE; if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
return FALSE;
/* look up tcon based on tid & uid */ /* look up tcon based on tid & uid */
read_lock(&GlobalSMBSeslock); read_lock(&GlobalSMBSeslock);
...@@ -557,36 +564,38 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) ...@@ -557,36 +564,38 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
if ((tcon->tid == buf->Tid) && (srv == tcon->ses->server)) { if ((tcon->tid == buf->Tid) && (srv == tcon->ses->server)) {
cifs_stats_inc(&tcon->num_oplock_brks); cifs_stats_inc(&tcon->num_oplock_brks);
list_for_each(tmp1,&tcon->openFileList){ list_for_each(tmp1, &tcon->openFileList) {
netfile = list_entry(tmp1,struct cifsFileInfo, netfile = list_entry(tmp1, struct cifsFileInfo,
tlist); tlist);
if(pSMB->Fid == netfile->netfid) { if (pSMB->Fid == netfile->netfid) {
struct cifsInodeInfo *pCifsInode; struct cifsInodeInfo *pCifsInode;
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
cFYI(1,("file id match, oplock break")); cFYI(1,
pCifsInode = ("file id match, oplock break"));
pCifsInode =
CIFS_I(netfile->pInode); CIFS_I(netfile->pInode);
pCifsInode->clientCanCacheAll = FALSE; pCifsInode->clientCanCacheAll = FALSE;
if(pSMB->OplockLevel == 0) if (pSMB->OplockLevel == 0)
pCifsInode->clientCanCacheRead pCifsInode->clientCanCacheRead
= FALSE; = FALSE;
pCifsInode->oplockPending = TRUE; pCifsInode->oplockPending = TRUE;
AllocOplockQEntry(netfile->pInode, AllocOplockQEntry(netfile->pInode,
netfile->netfid, netfile->netfid,
tcon); tcon);
cFYI(1,("about to wake up oplock thd")); cFYI(1,
if(oplockThread) ("about to wake up oplock thread"));
if (oplockThread)
wake_up_process(oplockThread); wake_up_process(oplockThread);
return TRUE; return TRUE;
} }
} }
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
cFYI(1,("No matching file for oplock break")); cFYI(1, ("No matching file for oplock break"));
return TRUE; return TRUE;
} }
} }
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
cFYI(1,("Can not process oplock break for non-existent connection")); cFYI(1, ("Can not process oplock break for non-existent connection"));
return TRUE; return TRUE;
} }
...@@ -643,13 +652,13 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) ...@@ -643,13 +652,13 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
only legal in POSIX-like OS (if they are present in the string). Path only legal in POSIX-like OS (if they are present in the string). Path
names are little endian 16 bit Unicode on the wire */ names are little endian 16 bit Unicode on the wire */
int int
cifs_convertUCSpath(char *target, const __le16 * source, int maxlen, cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
const struct nls_table * cp) const struct nls_table *cp)
{ {
int i,j,len; int i, j, len;
__u16 src_char; __u16 src_char;
for(i = 0, j = 0; i < maxlen; i++) { for (i = 0, j = 0; i < maxlen; i++) {
src_char = le16_to_cpu(source[i]); src_char = le16_to_cpu(source[i]);
switch (src_char) { switch (src_char) {
case 0: case 0:
...@@ -678,10 +687,10 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen, ...@@ -678,10 +687,10 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
case UNI_LESSTHAN: case UNI_LESSTHAN:
target[j] = '<'; target[j] = '<';
break; break;
default: default:
len = cp->uni2char(src_char, &target[j], len = cp->uni2char(src_char, &target[j],
NLS_MAX_CHARSET_SIZE); NLS_MAX_CHARSET_SIZE);
if(len > 0) { if (len > 0) {
j += len; j += len;
continue; continue;
} else { } else {
...@@ -690,7 +699,7 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen, ...@@ -690,7 +699,7 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
} }
j++; j++;
/* make sure we do not overrun callers allocated temp buffer */ /* make sure we do not overrun callers allocated temp buffer */
if(j >= (2 * NAME_MAX)) if (j >= (2 * NAME_MAX))
break; break;
} }
cUCS_out: cUCS_out:
...@@ -703,18 +712,18 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen, ...@@ -703,18 +712,18 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
only legal in POSIX-like OS (if they are present in the string). Path only legal in POSIX-like OS (if they are present in the string). Path
names are little endian 16 bit Unicode on the wire */ names are little endian 16 bit Unicode on the wire */
int int
cifsConvertToUCS(__le16 * target, const char *source, int maxlen, cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
const struct nls_table * cp, int mapChars) const struct nls_table *cp, int mapChars)
{ {
int i,j,charlen; int i, j, charlen;
int len_remaining = maxlen; int len_remaining = maxlen;
char src_char; char src_char;
__u16 temp; __u16 temp;
if(!mapChars) if (!mapChars)
return cifs_strtoUCS(target, source, PATH_MAX, cp); return cifs_strtoUCS(target, source, PATH_MAX, cp);
for(i = 0, j = 0; i < maxlen; j++) { for (i = 0, j = 0; i < maxlen; j++) {
src_char = source[i]; src_char = source[i];
switch (src_char) { switch (src_char) {
case 0: case 0:
...@@ -737,7 +746,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen, ...@@ -737,7 +746,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
break; break;
case '|': case '|':
target[j] = cpu_to_le16(UNI_PIPE); target[j] = cpu_to_le16(UNI_PIPE);
break; break;
/* BB We can not handle remapping slash until /* BB We can not handle remapping slash until
all the calls to build_path_from_dentry all the calls to build_path_from_dentry
are modified, as they use slash as separator BB */ are modified, as they use slash as separator BB */
...@@ -749,7 +758,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen, ...@@ -749,7 +758,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
len_remaining, &temp); len_remaining, &temp);
/* if no match, use question mark, which /* if no match, use question mark, which
at least in some cases servers as wild card */ at least in some cases servers as wild card */
if(charlen < 1) { if (charlen < 1) {
target[j] = cpu_to_le16(0x003f); target[j] = cpu_to_le16(0x003f);
charlen = 1; charlen = 1;
} else } else
...@@ -758,7 +767,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen, ...@@ -758,7 +767,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
/* character may take more than one byte in the /* character may take more than one byte in the
the source string, but will take exactly two the source string, but will take exactly two
bytes in the target string */ bytes in the target string */
i+= charlen; i += charlen;
continue; continue;
} }
i++; /* move to next char in source string */ i++; /* move to next char in source string */
......
...@@ -3,23 +3,22 @@ ...@@ -3,23 +3,22 @@
* *
* Copyright (c) International Business Machines Corp., 2002 * Copyright (c) International Business Machines Corp., 2002
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* Error mapping routines from Samba libsmb/errormap.c * Error mapping routines from Samba libsmb/errormap.c
* Copyright (C) Andrew Tridgell 2001 * Copyright (C) Andrew Tridgell 2001
* *
*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details. * the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
...@@ -30,9 +29,7 @@ ...@@ -30,9 +29,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <asm/div64.h> #include <asm/div64.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#ifdef CONFIG_CIFS_EXPERIMENTAL
#include <linux/inet.h> #include <linux/inet.h>
#endif
#include "cifsfs.h" #include "cifsfs.h"
#include "cifspdu.h" #include "cifspdu.h"
#include "cifsglob.h" #include "cifsglob.h"
...@@ -67,22 +64,22 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = { ...@@ -67,22 +64,22 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
{ERRbadshare, -ETXTBSY}, {ERRbadshare, -ETXTBSY},
{ERRlock, -EACCES}, {ERRlock, -EACCES},
{ERRunsup, -EINVAL}, {ERRunsup, -EINVAL},
{ERRnosuchshare,-ENXIO}, {ERRnosuchshare, -ENXIO},
{ERRfilexists, -EEXIST}, {ERRfilexists, -EEXIST},
{ERRinvparm, -EINVAL}, {ERRinvparm, -EINVAL},
{ERRdiskfull, -ENOSPC}, {ERRdiskfull, -ENOSPC},
{ERRinvname, -ENOENT}, {ERRinvname, -ENOENT},
{ERRinvlevel,-EOPNOTSUPP}, {ERRinvlevel, -EOPNOTSUPP},
{ERRdirnotempty, -ENOTEMPTY}, {ERRdirnotempty, -ENOTEMPTY},
{ERRnotlocked, -ENOLCK}, {ERRnotlocked, -ENOLCK},
{ERRcancelviolation, -ENOLCK}, {ERRcancelviolation, -ENOLCK},
{ERRalreadyexists, -EEXIST}, {ERRalreadyexists, -EEXIST},
{ERRmoredata, -EOVERFLOW}, {ERRmoredata, -EOVERFLOW},
{ERReasnotsupported,-EOPNOTSUPP}, {ERReasnotsupported, -EOPNOTSUPP},
{ErrQuota, -EDQUOT}, {ErrQuota, -EDQUOT},
{ErrNotALink, -ENOLINK}, {ErrNotALink, -ENOLINK},
{ERRnetlogonNotStarted,-ENOPROTOOPT}, {ERRnetlogonNotStarted, -ENOPROTOOPT},
{ErrTooManyLinks,-EMLINK}, {ErrTooManyLinks, -EMLINK},
{0, 0} {0, 0}
}; };
...@@ -133,85 +130,24 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = { ...@@ -133,85 +130,24 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
/* returns 0 if invalid address */ /* returns 0 if invalid address */
int int
cifs_inet_pton(int address_family, char *cp,void *dst) cifs_inet_pton(int address_family, char *cp, void *dst)
{ {
#ifdef CONFIG_CIFS_EXPERIMENTAL
int ret = 0; int ret = 0;
/* calculate length by finding first slash or NULL */ /* calculate length by finding first slash or NULL */
/* BB Should we convert '/' slash to '\' here since it seems already done /* BB Should we convert '/' slash to '\' here since it seems already
before this */ * done before this */
if( address_family == AF_INET ){ if ( address_family == AF_INET ) {
ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL); ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL);
} else if( address_family == AF_INET6 ){ } else if ( address_family == AF_INET6 ) {
ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL);
} }
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
cFYI(1,("address conversion returned %d for %s", ret, cp)); cFYI(1, ("address conversion returned %d for %s", ret, cp));
#endif #endif
if (ret > 0) if (ret > 0)
ret = 1; ret = 1;
return ret; return ret;
#else
int value;
int digit;
int i;
char temp;
char bytes[4];
char *end = bytes;
static const int addr_class_max[4] =
{ 0xffffffff, 0xffffff, 0xffff, 0xff };
if(address_family != AF_INET)
return -EAFNOSUPPORT;
for (i = 0; i < 4; i++) {
bytes[i] = 0;
}
temp = *cp;
while (TRUE) {
if (!isdigit(temp))
return 0;
value = 0;
digit = 0;
for (;;) {
if (isascii(temp) && isdigit(temp)) {
value = (value * 10) + temp - '0';
temp = *++cp;
digit = 1;
} else
break;
}
if (temp == '.') {
if ((end > bytes + 2) || (value > 255))
return 0;
*end++ = value;
temp = *++cp;
} else if (temp == ':') {
cFYI(1,("IPv6 addresses not supported for CIFS mounts yet"));
return -1;
} else
break;
}
/* check for last characters */
if (temp != '\0' && (!isascii(temp) || !isspace(temp)))
if (temp != '\\') {
if (temp != '/')
return 0;
else
(*cp = '\\'); /* switch the slash the expected way */
}
if (value > addr_class_max[end - bytes])
return 0;
*((__be32 *)dst) = *((__be32 *) bytes) | htonl(value);
return 1; /* success */
#endif /* EXPERIMENTAL */
} }
/***************************************************************************** /*****************************************************************************
...@@ -246,7 +182,7 @@ static const struct { ...@@ -246,7 +182,7 @@ static const struct {
ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, { ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, {
ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR}, ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR},
/* { This NT error code was 'sqashed' /* { 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 } */ during the session setup } */
{ {
ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, { ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, {
...@@ -261,7 +197,7 @@ static const struct { ...@@ -261,7 +197,7 @@ static const struct {
ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, { ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, {
ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED}, ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED},
/* { This NT error code was 'sqashed' /* { 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 } */ during the session setup } */
{ {
ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, { ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, {
...@@ -331,7 +267,7 @@ static const struct { ...@@ -331,7 +267,7 @@ static const struct {
ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, { ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, {
ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS}, ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS},
/* { This NT error code was 'sqashed' /* { 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 } */ during the session setup } */
{ {
ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, {
...@@ -341,7 +277,7 @@ static const struct { ...@@ -341,7 +277,7 @@ static const struct {
ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, { ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, {
ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN}, ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN},
/* { This NT error code was 'sqashed' /* { 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 } */ during the session setup } */
{ {
ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, { ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, {
...@@ -393,8 +329,8 @@ static const struct { ...@@ -393,8 +329,8 @@ static const struct {
ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, { ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED}, ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
/* { This NT error code was 'sqashed' /* { This NT error code was 'sqashed'
from NT_STATUS_INSUFFICIENT_RESOURCES to NT_STATUS_INSUFF_SERVER_RESOURCES from NT_STATUS_INSUFFICIENT_RESOURCES to
during the session setup } */ NT_STATUS_INSUFF_SERVER_RESOURCES during the session setup } */
{ {
ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, { ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, { ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
...@@ -638,8 +574,8 @@ static const struct { ...@@ -638,8 +574,8 @@ static const struct {
ERRDOS, 19, NT_STATUS_TOO_LATE}, { ERRDOS, 19, NT_STATUS_TOO_LATE}, {
ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET}, ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
/* { This NT error code was 'sqashed' /* { This NT error code was 'sqashed'
from NT_STATUS_NO_TRUST_SAM_ACCOUNT to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE from NT_STATUS_NO_TRUST_SAM_ACCOUNT to
during the session setup } */ NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE during the session setup } */
{ {
ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, { ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, { ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
...@@ -658,7 +594,7 @@ static const struct { ...@@ -658,7 +594,7 @@ static const struct {
ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, { ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, {
ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT}, ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
/* { This NT error code was 'sqashed' /* { 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 } */ during the session setup } */
{ {
ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, { ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, {
...@@ -789,7 +725,7 @@ cifs_print_status(__u32 status_code) ...@@ -789,7 +725,7 @@ cifs_print_status(__u32 status_code)
if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) == if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
(status_code & 0xFFFFFF)) { (status_code & 0xFFFFFF)) {
printk(KERN_NOTICE "Status code returned 0x%08x %s\n", printk(KERN_NOTICE "Status code returned 0x%08x %s\n",
status_code,nt_errs[idx].nt_errstr); status_code, nt_errs[idx].nt_errstr);
} }
idx++; idx++;
} }
...@@ -821,7 +757,7 @@ int ...@@ -821,7 +757,7 @@ int
map_smb_to_linux_error(struct smb_hdr *smb) map_smb_to_linux_error(struct smb_hdr *smb)
{ {
unsigned int i; 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; __u8 smberrclass;
__u16 smberrcode; __u16 smberrcode;
...@@ -832,9 +768,10 @@ map_smb_to_linux_error(struct smb_hdr *smb) ...@@ -832,9 +768,10 @@ map_smb_to_linux_error(struct smb_hdr *smb)
return 0; return 0;
if (smb->Flags2 & SMBFLG2_ERR_STATUS) { if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
/* translate the newer STATUS codes to old style errors and then to POSIX errors */ /* translate the newer STATUS codes to old style SMB errors
* and then to POSIX errors */
__u32 err = le32_to_cpu(smb->Status.CifsError); __u32 err = le32_to_cpu(smb->Status.CifsError);
if(cifsFYI & CIFS_RC) if (cifsFYI & CIFS_RC)
cifs_print_status(err); cifs_print_status(err);
ntstatus_to_dos(err, &smberrclass, &smberrcode); ntstatus_to_dos(err, &smberrclass, &smberrcode);
} else { } else {
...@@ -845,38 +782,42 @@ map_smb_to_linux_error(struct smb_hdr *smb) ...@@ -845,38 +782,42 @@ map_smb_to_linux_error(struct smb_hdr *smb)
/* old style errors */ /* old style errors */
/* DOS class smb error codes - map DOS */ /* DOS class smb error codes - map DOS */
if (smberrclass == ERRDOS) { /* one byte field no need to byte reverse */ if (smberrclass == ERRDOS) { /* 1 byte field no need to byte reverse */
for (i = 0; for (i = 0;
i < i <
sizeof (mapping_table_ERRDOS) / sizeof (mapping_table_ERRDOS) /
sizeof (struct smb_to_posix_error); i++) { sizeof (struct smb_to_posix_error); i++) {
if (mapping_table_ERRDOS[i].smb_err == 0) if (mapping_table_ERRDOS[i].smb_err == 0)
break; break;
else if (mapping_table_ERRDOS[i].smb_err == smberrcode) { else if (mapping_table_ERRDOS[i].smb_err ==
smberrcode) {
rc = mapping_table_ERRDOS[i].posix_code; rc = mapping_table_ERRDOS[i].posix_code;
break; break;
} }
/* else try the next error mapping one to see if it will match */ /* else try next error mapping one to see if match */
} }
} else if (smberrclass == ERRSRV) { /* server class of error codes */ } else if (smberrclass == ERRSRV) { /* server class of error codes */
for (i = 0; for (i = 0;
i < i <
sizeof (mapping_table_ERRSRV) / sizeof (mapping_table_ERRSRV) /
sizeof (struct smb_to_posix_error); i++) { sizeof (struct smb_to_posix_error); i++) {
if (mapping_table_ERRSRV[i].smb_err == 0) if (mapping_table_ERRSRV[i].smb_err == 0)
break; break;
else if (mapping_table_ERRSRV[i].smb_err == smberrcode) { else if (mapping_table_ERRSRV[i].smb_err ==
smberrcode) {
rc = mapping_table_ERRSRV[i].posix_code; rc = mapping_table_ERRSRV[i].posix_code;
break; break;
} }
/* else try the next error mapping one to see if it will match */ /* else try next error mapping to see if match */
} }
} }
/* else ERRHRD class errors or junk - return EIO */ /* else ERRHRD class errors or junk - return EIO */
cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc)); cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!",
smberrcode, rc));
/* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */ /* generic corrective action e.g. reconnect SMB session on
* ERRbaduid could be added */
return rc; return rc;
} }
...@@ -910,7 +851,7 @@ smbCalcSize_LE(struct smb_hdr *ptr) ...@@ -910,7 +851,7 @@ smbCalcSize_LE(struct smb_hdr *ptr)
struct timespec struct timespec
cifs_NTtimeToUnix(u64 ntutc) cifs_NTtimeToUnix(u64 ntutc)
{ {
struct timespec ts; struct timespec ts;
/* BB what about the timezone? BB */ /* BB what about the timezone? BB */
/* Subtract the NTFS time offset, then convert to 1s intervals. */ /* Subtract the NTFS time offset, then convert to 1s intervals. */
...@@ -918,7 +859,7 @@ cifs_NTtimeToUnix(u64 ntutc) ...@@ -918,7 +859,7 @@ cifs_NTtimeToUnix(u64 ntutc)
t = ntutc - NTFS_TIME_OFFSET; t = ntutc - NTFS_TIME_OFFSET;
ts.tv_nsec = do_div(t, 10000000) * 100; ts.tv_nsec = do_div(t, 10000000) * 100;
ts.tv_sec = t; ts.tv_sec = t;
return ts; return ts;
} }
...@@ -946,20 +887,20 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time) ...@@ -946,20 +887,20 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
SMB_TIME * st = (SMB_TIME *)&time; SMB_TIME * st = (SMB_TIME *)&time;
SMB_DATE * sd = (SMB_DATE *)&date; SMB_DATE * sd = (SMB_DATE *)&date;
cFYI(1,("date %d time %d",date, time)); cFYI(1, ("date %d time %d", date, time));
sec = 2 * st->TwoSeconds; sec = 2 * st->TwoSeconds;
min = st->Minutes; min = st->Minutes;
if((sec > 59) || (min > 59)) if ((sec > 59) || (min > 59))
cERROR(1,("illegal time min %d sec %d", min, sec)); cERROR(1, ("illegal time min %d sec %d", min, sec));
sec += (min * 60); sec += (min * 60);
sec += 60 * 60 * st->Hours; sec += 60 * 60 * st->Hours;
if(st->Hours > 24) if (st->Hours > 24)
cERROR(1,("illegal hours %d",st->Hours)); cERROR(1, ("illegal hours %d", st->Hours));
days = sd->Day; days = sd->Day;
month = sd->Month; month = sd->Month;
if((days > 31) || (month > 12)) if ((days > 31) || (month > 12))
cERROR(1,("illegal date, month %d day: %d", month, days)); cERROR(1, ("illegal date, month %d day: %d", month, days));
month -= 1; month -= 1;
days += total_days_of_prev_months[month]; days += total_days_of_prev_months[month];
days += 3652; /* account for difference in days between 1980 and 1970 */ days += 3652; /* account for difference in days between 1980 and 1970 */
...@@ -970,15 +911,15 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time) ...@@ -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 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 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 consider 2 special case years, ie the years 2000 and 2100, and only
adjust for the lack of leap year for the year 2100, as 2000 was a adjust for the lack of leap year for the year 2100, as 2000 was a
leap year (divisable by 400) */ leap year (divisable by 400) */
if(year >= 120) /* the year 2100 */ if (year >= 120) /* the year 2100 */
days = days - 1; /* do not count leap year for the year 2100 */ days = days - 1; /* do not count leap year for the year 2100 */
/* adjust for leap year where we are still before leap day */ /* adjust for leap year where we are still before leap day */
if(year != 120) if (year != 120)
days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0); days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0);
sec += 24 * 60 * 60 * days; sec += 24 * 60 * 60 * days;
ts.tv_sec = sec; ts.tv_sec = sec;
...@@ -986,4 +927,4 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time) ...@@ -986,4 +927,4 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
ts.tv_nsec = 0; ts.tv_nsec = 0;
return ts; return ts;
} }
/* /*
* Unix SMB/Netbios implementation. * Unix SMB/Netbios implementation.
* Version 1.9. * Version 1.9.
* RPC Pipe client / server routines * RPC Pipe client / server routines
* Copyright (C) Luke Kenneth Casson Leighton 1997-2001. * Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
......
/* /*
Unix SMB/Netbios implementation. Unix SMB/Netbios implementation.
Version 1.9. Version 1.9.
NT error code constants NT error code constants
...@@ -6,17 +6,17 @@ ...@@ -6,17 +6,17 @@
Copyright (C) John H Terpstra 1996-2000 Copyright (C) John H Terpstra 1996-2000
Copyright (C) Luke Kenneth Casson Leighton 1996-2000 Copyright (C) Luke Kenneth Casson Leighton 1996-2000
Copyright (C) Paul Ashton 1998-2000 Copyright (C) Paul Ashton 1998-2000
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License 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., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
......
/* /*
* fs/cifs/ntlmssp.h * fs/cifs/ntlmssp.h
* *
* Copyright (c) International Business Machines Corp., 2002,2006 * Copyright (c) International Business Machines Corp., 2002,2007
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software * 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" #define NTLMSSP_SIGNATURE "NTLMSSP"
...@@ -27,18 +27,18 @@ ...@@ -27,18 +27,18 @@
#define UnknownMessage cpu_to_le32(8) #define UnknownMessage cpu_to_le32(8)
/* Negotiate Flags */ /* Negotiate Flags */
#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode #define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are in unicode */
#define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM #define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */
#define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm #define NTLMSSP_REQUEST_TARGET 0x04 /* Server return its auth realm */
#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability #define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signature capability */
#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality #define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */
#define NTLMSSP_NEGOTIATE_DGRAM 0x0040 #define NTLMSSP_NEGOTIATE_DGRAM 0x0040
#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal #define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Sign/seal use LM session key */
#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication #define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */
#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 #define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000 #define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 // client/server on same machine #define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server on same machine */
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 // Sign for all security levels #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign for all security levels */
#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000 #define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
#define NTLMSSP_TARGET_TYPE_SERVER 0x20000 #define NTLMSSP_TARGET_TYPE_SERVER 0x20000
#define NTLMSSP_TARGET_TYPE_SHARE 0x40000 #define NTLMSSP_TARGET_TYPE_SHARE 0x40000
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* fs/cifs/readdir.c * fs/cifs/readdir.c
* *
* Directory search handling * Directory search handling
* *
* Copyright (C) International Business Machines Corp., 2004, 2007 * Copyright (C) International Business Machines Corp., 2004, 2007
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
...@@ -34,24 +34,23 @@ ...@@ -34,24 +34,23 @@
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
static void dump_cifs_file_struct(struct file *file, char *label) static void dump_cifs_file_struct(struct file *file, char *label)
{ {
struct cifsFileInfo * cf; struct cifsFileInfo *cf;
if (file) { if (file) {
cf = file->private_data; cf = file->private_data;
if (cf == NULL) { if (cf == NULL) {
cFYI(1,("empty cifs private file data")); cFYI(1, ("empty cifs private file data"));
return; return;
} }
if (cf->invalidHandle) { if (cf->invalidHandle) {
cFYI(1,("invalid handle")); cFYI(1, ("invalid handle"));
} }
if (cf->srch_inf.endOfSearch) { if (cf->srch_inf.endOfSearch) {
cFYI(1,("end of search")); cFYI(1, ("end of search"));
} }
if (cf->srch_inf.emptyDir) { if (cf->srch_inf.emptyDir) {
cFYI(1,("empty dir")); cFYI(1, ("empty dir"));
} }
} }
} }
#endif /* DEBUG2 */ #endif /* DEBUG2 */
...@@ -73,7 +72,8 @@ static int construct_dentry(struct qstr *qstring, struct file *file, ...@@ -73,7 +72,8 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
qstring->hash = full_name_hash(qstring->name, qstring->len); qstring->hash = full_name_hash(qstring->name, qstring->len);
tmp_dentry = d_lookup(file->f_path.dentry, qstring); tmp_dentry = d_lookup(file->f_path.dentry, qstring);
if (tmp_dentry) { if (tmp_dentry) {
cFYI(0, ("existing dentry with inode 0x%p", tmp_dentry->d_inode)); cFYI(0, ("existing dentry with inode 0x%p",
tmp_dentry->d_inode));
*ptmp_inode = tmp_dentry->d_inode; *ptmp_inode = tmp_dentry->d_inode;
/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/ /* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
if (*ptmp_inode == NULL) { if (*ptmp_inode == NULL) {
...@@ -87,7 +87,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file, ...@@ -87,7 +87,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
} else { } else {
tmp_dentry = d_alloc(file->f_path.dentry, qstring); tmp_dentry = d_alloc(file->f_path.dentry, qstring);
if (tmp_dentry == NULL) { if (tmp_dentry == NULL) {
cERROR(1,("Failed allocating dentry")); cERROR(1, ("Failed allocating dentry"));
*ptmp_inode = NULL; *ptmp_inode = NULL;
return rc; return rc;
} }
...@@ -100,7 +100,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file, ...@@ -100,7 +100,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
if (*ptmp_inode == NULL) if (*ptmp_inode == NULL)
return rc; return rc;
if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME) 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; rc = 2;
} }
...@@ -109,7 +109,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file, ...@@ -109,7 +109,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
return rc; return rc;
} }
static void AdjustForTZ(struct cifsTconInfo * tcon, struct inode * inode) static void AdjustForTZ(struct cifsTconInfo *tcon, struct inode *inode)
{ {
if ((tcon) && (tcon->ses) && (tcon->ses->server)) { if ((tcon) && (tcon->ses) && (tcon->ses->server)) {
inode->i_ctime.tv_sec += tcon->ses->server->timeAdj; inode->i_ctime.tv_sec += tcon->ses->server->timeAdj;
...@@ -121,7 +121,7 @@ static void AdjustForTZ(struct cifsTconInfo * tcon, struct inode * inode) ...@@ -121,7 +121,7 @@ static void AdjustForTZ(struct cifsTconInfo * tcon, struct inode * inode)
static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
char * buf, int *pobject_type, int isNewInode) char *buf, int *pobject_type, int isNewInode)
{ {
loff_t local_size; loff_t local_size;
struct timespec local_mtime; struct timespec local_mtime;
...@@ -150,7 +150,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, ...@@ -150,7 +150,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
} else { /* legacy, OS2 and DOS style */ } else { /* legacy, OS2 and DOS style */
/* struct timespec ts;*/ /* struct timespec ts;*/
FIND_FILE_STANDARD_INFO * pfindData = FIND_FILE_STANDARD_INFO * pfindData =
(FIND_FILE_STANDARD_INFO *)buf; (FIND_FILE_STANDARD_INFO *)buf;
tmp_inode->i_mtime = cnvrtDosUnixTm( tmp_inode->i_mtime = cnvrtDosUnixTm(
...@@ -175,7 +175,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, ...@@ -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? */ /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
/* 2767 perms - indicate mandatory locking */ /* 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 */ or retrieve from NTFS stream extended attribute */
if (atomic_read(&cifsInfo->inUse) == 0) { if (atomic_read(&cifsInfo->inUse) == 0) {
tmp_inode->i_uid = cifs_sb->mnt_uid; 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, ...@@ -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 = cifs_sb->mnt_dir_mode;
} }
tmp_inode->i_mode |= S_IFDIR; 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)) { (attr & ATTR_SYSTEM)) {
if (end_of_file == 0) { if (end_of_file == 0) {
*pobject_type = DT_FIFO; *pobject_type = DT_FIFO;
...@@ -206,13 +206,13 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, ...@@ -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 inode as needing revalidate and get the real type
(blk vs chr vs. symlink) later ie in lookup */ (blk vs chr vs. symlink) later ie in lookup */
*pobject_type = DT_REG; *pobject_type = DT_REG;
tmp_inode->i_mode |= S_IFREG; tmp_inode->i_mode |= S_IFREG;
cifsInfo->time = 0; cifsInfo->time = 0;
} }
/* we no longer mark these because we could not follow them */ /* we no longer mark these because we could not follow them */
/* } else if (attr & ATTR_REPARSE) { /* } else if (attr & ATTR_REPARSE) {
*pobject_type = DT_LNK; *pobject_type = DT_LNK;
tmp_inode->i_mode |= S_IFLNK; */ tmp_inode->i_mode |= S_IFLNK; */
} else { } else {
*pobject_type = DT_REG; *pobject_type = DT_REG;
tmp_inode->i_mode |= S_IFREG; tmp_inode->i_mode |= S_IFREG;
...@@ -220,7 +220,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, ...@@ -220,7 +220,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
tmp_inode->i_mode &= ~(S_IWUGO); tmp_inode->i_mode &= ~(S_IWUGO);
else if ((tmp_inode->i_mode & S_IWUGO) == 0) else if ((tmp_inode->i_mode & S_IWUGO) == 0)
/* the ATTR_READONLY flag may have been changed on */ /* 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); tmp_inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode);
} /* could add code here - to validate if device or weird share type? */ } /* 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, ...@@ -231,7 +231,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
spin_lock(&tmp_inode->i_lock); spin_lock(&tmp_inode->i_lock);
if (is_size_safe_to_change(cifsInfo, end_of_file)) { 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 */ client is writing to it due to potential races */
i_size_write(tmp_inode, end_of_file); 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, ...@@ -254,7 +254,6 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
else else
tmp_inode->i_fop = &cifs_file_direct_ops; tmp_inode->i_fop = &cifs_file_direct_ops;
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
tmp_inode->i_fop = &cifs_file_nobrl_ops; tmp_inode->i_fop = &cifs_file_nobrl_ops;
else else
...@@ -322,8 +321,8 @@ static void unix_fill_in_inode(struct inode *tmp_inode, ...@@ -322,8 +321,8 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions); tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
/* since we set the inode type below we need to mask off type /* since we set the inode type below we need to mask off type
to avoid strange results if bits above were corrupt */ to avoid strange results if bits above were corrupt */
tmp_inode->i_mode &= ~S_IFMT; tmp_inode->i_mode &= ~S_IFMT;
if (type == UNIX_FILE) { if (type == UNIX_FILE) {
*pobject_type = DT_REG; *pobject_type = DT_REG;
tmp_inode->i_mode |= S_IFREG; tmp_inode->i_mode |= S_IFREG;
...@@ -353,7 +352,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode, ...@@ -353,7 +352,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
/* safest to just call it a file */ /* safest to just call it a file */
*pobject_type = DT_REG; *pobject_type = DT_REG;
tmp_inode->i_mode |= S_IFREG; tmp_inode->i_mode |= S_IFREG;
cFYI(1,("unknown inode type %d",type)); cFYI(1, ("unknown inode type %d", type));
} }
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
...@@ -368,7 +367,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode, ...@@ -368,7 +367,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
spin_lock(&tmp_inode->i_lock); spin_lock(&tmp_inode->i_lock);
if (is_size_safe_to_change(cifsInfo, end_of_file)) { 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 */ client is writing to it due to potential races */
i_size_write(tmp_inode, end_of_file); i_size_write(tmp_inode, end_of_file);
...@@ -393,15 +392,16 @@ static void unix_fill_in_inode(struct inode *tmp_inode, ...@@ -393,15 +392,16 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
tmp_inode->i_fop = &cifs_file_ops; tmp_inode->i_fop = &cifs_file_ops;
if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
(cifs_sb->tcon->ses->server->maxBuf < (cifs_sb->tcon->ses->server->maxBuf <
PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
else else
tmp_inode->i_data.a_ops = &cifs_addr_ops; tmp_inode->i_data.a_ops = &cifs_addr_ops;
if (isNewInode) if (isNewInode)
return; /* No sense invalidating pages for new inode since we return; /* No sense invalidating pages for new inode
have not started caching readahead file data yet */ since we have not started caching readahead
file data for it yet */
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
(local_size == tmp_inode->i_size)) { (local_size == tmp_inode->i_size)) {
...@@ -420,7 +420,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode, ...@@ -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_op = &cifs_symlink_inode_ops;
/* tmp_inode->i_fop = *//* do not need to set to anything */ /* tmp_inode->i_fop = *//* do not need to set to anything */
} else { } else {
cFYI(1, ("Special inode")); cFYI(1, ("Special inode"));
init_special_inode(tmp_inode, tmp_inode->i_mode, init_special_inode(tmp_inode, tmp_inode->i_mode,
tmp_inode->i_rdev); tmp_inode->i_rdev);
} }
...@@ -429,14 +429,14 @@ static void unix_fill_in_inode(struct inode *tmp_inode, ...@@ -429,14 +429,14 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
static int initiate_cifs_search(const int xid, struct file *file) static int initiate_cifs_search(const int xid, struct file *file)
{ {
int rc = 0; int rc = 0;
char * full_path; char *full_path;
struct cifsFileInfo * cifsFile; struct cifsFileInfo *cifsFile;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
if (file->private_data == NULL) { if (file->private_data == NULL) {
file->private_data = file->private_data =
kzalloc(sizeof(struct cifsFileInfo),GFP_KERNEL); kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
} }
if (file->private_data == NULL) if (file->private_data == NULL)
...@@ -463,9 +463,11 @@ static int initiate_cifs_search(const int xid, struct file *file) ...@@ -463,9 +463,11 @@ static int initiate_cifs_search(const int xid, struct file *file)
ffirst_retry: ffirst_retry:
/* test for Unix extensions */ /* test for Unix extensions */
if (pTcon->ses->capabilities & CAP_UNIX) { /* but now check for them on the share/mount not on the SMB session */
/* if (pTcon->ses->capabilities & CAP_UNIX) { */
if (pTcon->unix_ext) {
cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
} else if ((pTcon->ses->capabilities & } else if ((pTcon->ses->capabilities &
(CAP_NT_SMBS | CAP_NT_FIND)) == 0) { (CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD; cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
...@@ -474,13 +476,13 @@ static int initiate_cifs_search(const int xid, struct file *file) ...@@ -474,13 +476,13 @@ static int initiate_cifs_search(const int xid, struct file *file)
cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
} }
rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls,
&cifsFile->netfid, &cifsFile->srch_inf, &cifsFile->netfid, &cifsFile->srch_inf,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
if (rc == 0) if (rc == 0)
cifsFile->invalidHandle = FALSE; 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)) {
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
goto ffirst_retry; goto ffirst_retry;
...@@ -495,17 +497,17 @@ static int cifs_unicode_bytelen(char *str) ...@@ -495,17 +497,17 @@ static int cifs_unicode_bytelen(char *str)
int len; int len;
__le16 * ustr = (__le16 *)str; __le16 * ustr = (__le16 *)str;
for(len=0;len <= PATH_MAX;len++) { for (len = 0; len <= PATH_MAX; len++) {
if (ustr[len] == 0) if (ustr[len] == 0)
return len << 1; return len << 1;
} }
cFYI(1,("Unicode string longer than PATH_MAX found")); cFYI(1, ("Unicode string longer than PATH_MAX found"));
return len << 1; return len << 1;
} }
static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level) static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
{ {
char * new_entry; char *new_entry;
FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry; FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
if (level == SMB_FIND_FILE_INFO_STANDARD) { if (level == SMB_FIND_FILE_INFO_STANDARD) {
...@@ -516,21 +518,21 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level) ...@@ -516,21 +518,21 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
pfData->FileNameLength; pfData->FileNameLength;
} else } else
new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset); new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
cFYI(1,("new entry %p old entry %p",new_entry,old_entry)); cFYI(1, ("new entry %p old entry %p", new_entry, old_entry));
/* validate that new_entry is not past end of SMB */ /* validate that new_entry is not past end of SMB */
if (new_entry >= end_of_smb) { if (new_entry >= end_of_smb) {
cERROR(1, cERROR(1,
("search entry %p began after end of SMB %p old entry %p", ("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; return NULL;
} else if (((level == SMB_FIND_FILE_INFO_STANDARD) && } else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
(new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb)) || (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
((level != SMB_FIND_FILE_INFO_STANDARD) && || ((level != SMB_FIND_FILE_INFO_STANDARD) &&
(new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) { (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
cERROR(1,("search entry %p extends after end of SMB %p", cERROR(1, ("search entry %p extends after end of SMB %p",
new_entry, end_of_smb)); new_entry, end_of_smb));
return NULL; return NULL;
} else } else
return new_entry; return new_entry;
} }
...@@ -541,8 +543,8 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level) ...@@ -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) static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
{ {
int rc = 0; int rc = 0;
char * filename = NULL; char *filename = NULL;
int len = 0; int len = 0;
if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) { if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry; 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) ...@@ -554,25 +556,25 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
len = strnlen(filename, 5); len = strnlen(filename, 5);
} }
} else if (cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) { } 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; (FILE_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength); len = le32_to_cpu(pFindData->FileNameLength);
} else if (cfile->srch_inf.info_level == } else if (cfile->srch_inf.info_level ==
SMB_FIND_FILE_FULL_DIRECTORY_INFO) { SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
FILE_FULL_DIRECTORY_INFO * pFindData = FILE_FULL_DIRECTORY_INFO * pFindData =
(FILE_FULL_DIRECTORY_INFO *)current_entry; (FILE_FULL_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength); len = le32_to_cpu(pFindData->FileNameLength);
} else if (cfile->srch_inf.info_level == } else if (cfile->srch_inf.info_level ==
SMB_FIND_FILE_ID_FULL_DIR_INFO) { SMB_FIND_FILE_ID_FULL_DIR_INFO) {
SEARCH_ID_FULL_DIR_INFO * pFindData = SEARCH_ID_FULL_DIR_INFO * pFindData =
(SEARCH_ID_FULL_DIR_INFO *)current_entry; (SEARCH_ID_FULL_DIR_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength); len = le32_to_cpu(pFindData->FileNameLength);
} else if (cfile->srch_inf.info_level == } else if (cfile->srch_inf.info_level ==
SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
FILE_BOTH_DIRECTORY_INFO * pFindData = FILE_BOTH_DIRECTORY_INFO * pFindData =
(FILE_BOTH_DIRECTORY_INFO *)current_entry; (FILE_BOTH_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength); len = le32_to_cpu(pFindData->FileNameLength);
...@@ -582,7 +584,8 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile) ...@@ -582,7 +584,8 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
len = pFindData->FileNameLength; len = pFindData->FileNameLength;
} else { } else {
cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level)); cFYI(1, ("Unknown findfirst level %d",
cfile->srch_inf.info_level));
} }
if (filename) { if (filename) {
...@@ -595,15 +598,15 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile) ...@@ -595,15 +598,15 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
} else if (len == 4) { } else if (len == 4) {
/* check for .. */ /* check for .. */
if ((ufilename[0] == UNICODE_DOT) if ((ufilename[0] == UNICODE_DOT)
&&(ufilename[1] == UNICODE_DOT)) && (ufilename[1] == UNICODE_DOT))
rc = 2; rc = 2;
} }
} else /* ASCII */ { } else /* ASCII */ {
if (len == 1) { if (len == 1) {
if (filename[0] == '.') if (filename[0] == '.')
rc = 1; rc = 1;
} else if (len == 2) { } else if (len == 2) {
if((filename[0] == '.') && (filename[1] == '.')) if ((filename[0] == '.') && (filename[1] == '.'))
rc = 2; rc = 2;
} }
} }
...@@ -614,7 +617,7 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile) ...@@ -614,7 +617,7 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
/* Check if directory that we are searching has changed so we can decide /* Check if directory that we are searching has changed so we can decide
whether we can use the cached search results from the previous search */ whether we can use the cached search results from the previous search */
static int is_dir_changed(struct file * file) static int is_dir_changed(struct file *file)
{ {
struct inode *inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
struct cifsInodeInfo *cifsInfo = CIFS_I(inode); struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
...@@ -633,22 +636,22 @@ static int is_dir_changed(struct file * file) ...@@ -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 /* We start counting in the buffer with entry 2 and increment for every
entry (do not increment for . or .. entry) */ entry (do not increment for . or .. entry) */
static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, 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 rc = 0;
int pos_in_buf = 0; int pos_in_buf = 0;
loff_t first_entry_in_buffer; loff_t first_entry_in_buffer;
loff_t index_to_find = file->f_pos; loff_t index_to_find = file->f_pos;
struct cifsFileInfo * cifsFile = file->private_data; struct cifsFileInfo *cifsFile = file->private_data;
/* check if index in the buffer */ /* check if index in the buffer */
if ((cifsFile == NULL) || (ppCurrentEntry == NULL) || if ((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
(num_to_ret == NULL)) (num_to_ret == NULL))
return -ENOENT; return -ENOENT;
*ppCurrentEntry = NULL; *ppCurrentEntry = NULL;
first_entry_in_buffer = first_entry_in_buffer =
cifsFile->srch_inf.index_of_last_entry - cifsFile->srch_inf.index_of_last_entry -
cifsFile->srch_inf.entries_in_buffer; cifsFile->srch_inf.entries_in_buffer;
/* if first entry in buf is zero then is first 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, ...@@ -660,17 +663,17 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
dump_cifs_file_struct(file, "In fce "); dump_cifs_file_struct(file, "In fce ");
#endif #endif
if (((index_to_find < cifsFile->srch_inf.index_of_last_entry) && if (((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
is_dir_changed(file)) || is_dir_changed(file)) ||
(index_to_find < first_entry_in_buffer)) { (index_to_find < first_entry_in_buffer)) {
/* close and restart search */ /* close and restart search */
cFYI(1,("search backing up - close and restart search")); cFYI(1, ("search backing up - close and restart search"));
cifsFile->invalidHandle = TRUE; cifsFile->invalidHandle = TRUE;
CIFSFindClose(xid, pTcon, cifsFile->netfid); CIFSFindClose(xid, pTcon, cifsFile->netfid);
kfree(cifsFile->search_resume_name); kfree(cifsFile->search_resume_name);
cifsFile->search_resume_name = NULL; cifsFile->search_resume_name = NULL;
if (cifsFile->srch_inf.ntwrk_buf_start) { if (cifsFile->srch_inf.ntwrk_buf_start) {
cFYI(1,("freeing SMB ff cache buf on search rewind")); cFYI(1, ("freeing SMB ff cache buf on search rewind"));
if (cifsFile->srch_inf.smallBuf) if (cifsFile->srch_inf.smallBuf)
cifs_small_buf_release(cifsFile->srch_inf. cifs_small_buf_release(cifsFile->srch_inf.
ntwrk_buf_start); ntwrk_buf_start);
...@@ -678,17 +681,18 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, ...@@ -678,17 +681,18 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
cifs_buf_release(cifsFile->srch_inf. cifs_buf_release(cifsFile->srch_inf.
ntwrk_buf_start); ntwrk_buf_start);
} }
rc = initiate_cifs_search(xid,file); rc = initiate_cifs_search(xid, file);
if (rc) { if (rc) {
cFYI(1,("error %d reinitiating a search on rewind",rc)); cFYI(1, ("error %d reinitiating a search on rewind",
rc));
return rc; return rc;
} }
} }
while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
(rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){ (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)) {
cFYI(1,("calling findnext2")); cFYI(1, ("calling findnext2"));
rc = CIFSFindNext(xid,pTcon,cifsFile->netfid, rc = CIFSFindNext(xid, pTcon, cifsFile->netfid,
&cifsFile->srch_inf); &cifsFile->srch_inf);
if (rc) if (rc)
return -ENOENT; return -ENOENT;
...@@ -697,8 +701,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, ...@@ -697,8 +701,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
/* we found the buffer that contains the entry */ /* we found the buffer that contains the entry */
/* scan and find it */ /* scan and find it */
int i; int i;
char * current_entry; char *current_entry;
char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + char *end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
smbCalcSize((struct smb_hdr *) smbCalcSize((struct smb_hdr *)
cifsFile->srch_inf.ntwrk_buf_start); cifsFile->srch_inf.ntwrk_buf_start);
...@@ -706,28 +710,28 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, ...@@ -706,28 +710,28 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
- cifsFile->srch_inf.entries_in_buffer; - cifsFile->srch_inf.entries_in_buffer;
pos_in_buf = index_to_find - first_entry_in_buffer; pos_in_buf = index_to_find - first_entry_in_buffer;
cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); cFYI(1, ("found entry - pos_in_buf %d", pos_in_buf));
for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) { for (i=0; (i < (pos_in_buf)) && (current_entry != NULL); i++) {
/* go entry by entry figuring out which is first */ /* go entry by entry figuring out which is first */
current_entry = nxt_dir_entry(current_entry,end_of_smb, current_entry = nxt_dir_entry(current_entry, end_of_smb,
cifsFile->srch_inf.info_level); cifsFile->srch_inf.info_level);
} }
if((current_entry == NULL) && (i < pos_in_buf)) { if ((current_entry == NULL) && (i < pos_in_buf)) {
/* BB fixme - check if we should flag this error */ /* BB fixme - check if we should flag this error */
cERROR(1,("reached end of buf searching for pos in buf" cERROR(1, ("reached end of buf searching for pos in buf"
" %d index to find %lld rc %d", " %d index to find %lld rc %d",
pos_in_buf,index_to_find,rc)); pos_in_buf, index_to_find, rc));
} }
rc = 0; rc = 0;
*ppCurrentEntry = current_entry; *ppCurrentEntry = current_entry;
} else { } else {
cFYI(1,("index not in buffer - could not findnext into it")); cFYI(1, ("index not in buffer - could not findnext into it"));
return 0; return 0;
} }
if(pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) { if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
cFYI(1,("can not return entries pos_in_buf beyond last entry")); cFYI(1, ("can not return entries pos_in_buf beyond last"));
*num_to_ret = 0; *num_to_ret = 0;
} else } else
*num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf; *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
...@@ -738,81 +742,81 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, ...@@ -738,81 +742,81 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
/* inode num, inode type and filename returned */ /* inode num, inode type and filename returned */
static int cifs_get_name_from_search_buf(struct qstr *pqst, static int cifs_get_name_from_search_buf(struct qstr *pqst,
char *current_entry, __u16 level, unsigned int unicode, char *current_entry, __u16 level, unsigned int unicode,
struct cifs_sb_info * cifs_sb, int max_len, ino_t *pinum) struct cifs_sb_info *cifs_sb, int max_len, ino_t *pinum)
{ {
int rc = 0; int rc = 0;
unsigned int len = 0; unsigned int len = 0;
char * filename; char *filename;
struct nls_table * nlt = cifs_sb->local_nls; struct nls_table *nlt = cifs_sb->local_nls;
*pinum = 0; *pinum = 0;
if(level == SMB_FIND_FILE_UNIX) { if (level == SMB_FIND_FILE_UNIX) {
FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry; FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
if(unicode) { if (unicode) {
len = cifs_unicode_bytelen(filename); len = cifs_unicode_bytelen(filename);
} else { } else {
/* BB should we make this strnlen of PATH_MAX? */ /* BB should we make this strnlen of PATH_MAX? */
len = strnlen(filename, PATH_MAX); len = strnlen(filename, PATH_MAX);
} }
/* BB fixme - hash low and high 32 bits if not 64 bit arch BB fixme */ /* BB fixme - hash low and high 32 bits if not 64 bit arch BB */
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
*pinum = pFindData->UniqueId; *pinum = pFindData->UniqueId;
} else if(level == SMB_FIND_FILE_DIRECTORY_INFO) { } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
FILE_DIRECTORY_INFO * pFindData = FILE_DIRECTORY_INFO *pFindData =
(FILE_DIRECTORY_INFO *)current_entry; (FILE_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength); len = le32_to_cpu(pFindData->FileNameLength);
} else if(level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) { } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
FILE_FULL_DIRECTORY_INFO * pFindData = FILE_FULL_DIRECTORY_INFO *pFindData =
(FILE_FULL_DIRECTORY_INFO *)current_entry; (FILE_FULL_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength); len = le32_to_cpu(pFindData->FileNameLength);
} else if(level == SMB_FIND_FILE_ID_FULL_DIR_INFO) { } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
SEARCH_ID_FULL_DIR_INFO * pFindData = SEARCH_ID_FULL_DIR_INFO *pFindData =
(SEARCH_ID_FULL_DIR_INFO *)current_entry; (SEARCH_ID_FULL_DIR_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength); len = le32_to_cpu(pFindData->FileNameLength);
*pinum = pFindData->UniqueId; *pinum = pFindData->UniqueId;
} else if(level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
FILE_BOTH_DIRECTORY_INFO * pFindData = FILE_BOTH_DIRECTORY_INFO *pFindData =
(FILE_BOTH_DIRECTORY_INFO *)current_entry; (FILE_BOTH_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength); len = le32_to_cpu(pFindData->FileNameLength);
} else if(level == SMB_FIND_FILE_INFO_STANDARD) { } else if (level == SMB_FIND_FILE_INFO_STANDARD) {
FIND_FILE_STANDARD_INFO * pFindData = FIND_FILE_STANDARD_INFO * pFindData =
(FIND_FILE_STANDARD_INFO *)current_entry; (FIND_FILE_STANDARD_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
/* one byte length, no name conversion */ /* one byte length, no name conversion */
len = (unsigned int)pFindData->FileNameLength; len = (unsigned int)pFindData->FileNameLength;
} else { } else {
cFYI(1,("Unknown findfirst level %d",level)); cFYI(1, ("Unknown findfirst level %d", level));
return -EINVAL; return -EINVAL;
} }
if(len > max_len) { if (len > max_len) {
cERROR(1,("bad search response length %d past smb end", len)); cERROR(1, ("bad search response length %d past smb end", len));
return -EINVAL; return -EINVAL;
} }
if(unicode) { if (unicode) {
/* BB fixme - test with long names */ /* BB fixme - test with long names */
/* Note converted filename can be longer than in unicode */ /* Note converted filename can be longer than in unicode */
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
pqst->len = cifs_convertUCSpath((char *)pqst->name, pqst->len = cifs_convertUCSpath((char *)pqst->name,
(__le16 *)filename, len/2, nlt); (__le16 *)filename, len/2, nlt);
else else
pqst->len = cifs_strfromUCS_le((char *)pqst->name, pqst->len = cifs_strfromUCS_le((char *)pqst->name,
(__le16 *)filename,len/2,nlt); (__le16 *)filename, len/2, nlt);
} else { } else {
pqst->name = filename; pqst->name = filename;
pqst->len = len; pqst->len = len;
} }
pqst->hash = full_name_hash(pqst->name,pqst->len); pqst->hash = full_name_hash(pqst->name, pqst->len);
/* cFYI(1,("filldir on %s",pqst->name)); */ /* cFYI(1, ("filldir on %s",pqst->name)); */
return rc; return rc;
} }
...@@ -821,49 +825,50 @@ static int cifs_filldir(char *pfindEntry, struct file *file, ...@@ -821,49 +825,50 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
{ {
int rc = 0; int rc = 0;
struct qstr qstring; struct qstr qstring;
struct cifsFileInfo * pCifsF; struct cifsFileInfo *pCifsF;
unsigned obj_type; unsigned obj_type;
ino_t inum; ino_t inum;
struct cifs_sb_info * cifs_sb; struct cifs_sb_info *cifs_sb;
struct inode *tmp_inode; struct inode *tmp_inode;
struct dentry *tmp_dentry; struct dentry *tmp_dentry;
/* get filename and len into qstring */ /* get filename and len into qstring */
/* get dentry */ /* get dentry */
/* decide whether to create and populate ionde */ /* decide whether to create and populate ionde */
if((direntry == NULL) || (file == NULL)) if ((direntry == NULL) || (file == NULL))
return -EINVAL; return -EINVAL;
pCifsF = file->private_data; pCifsF = file->private_data;
if((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL)) if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
return -ENOENT; return -ENOENT;
rc = cifs_entry_is_dot(pfindEntry,pCifsF); rc = cifs_entry_is_dot(pfindEntry, pCifsF);
/* skip . and .. since we added them first */ /* skip . and .. since we added them first */
if(rc != 0) if (rc != 0)
return 0; return 0;
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
qstring.name = scratch_buf; qstring.name = scratch_buf;
rc = cifs_get_name_from_search_buf(&qstring,pfindEntry, rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
pCifsF->srch_inf.info_level, pCifsF->srch_inf.info_level,
pCifsF->srch_inf.unicode,cifs_sb, pCifsF->srch_inf.unicode, cifs_sb,
max_len, max_len,
&inum /* returned */); &inum /* returned */);
if(rc) if (rc)
return rc; return rc;
rc = construct_dentry(&qstring,file,&tmp_inode, &tmp_dentry); rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry);
if((tmp_inode == NULL) || (tmp_dentry == NULL)) if ((tmp_inode == NULL) || (tmp_dentry == NULL))
return -ENOMEM; return -ENOMEM;
if(rc) { if (rc) {
/* inode created, we need to hash it with right inode number */ /* inode created, we need to hash it with right inode number */
if(inum != 0) { if (inum != 0) {
/* BB fixme - hash the 2 32 quantities bits together if necessary BB */ /* BB fixme - hash the 2 32 quantities bits together if
* necessary BB */
tmp_inode->i_ino = inum; tmp_inode->i_ino = inum;
} }
insert_inode_hash(tmp_inode); insert_inode_hash(tmp_inode);
...@@ -872,27 +877,27 @@ static int cifs_filldir(char *pfindEntry, struct file *file, ...@@ -872,27 +877,27 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
/* we pass in rc below, indicating whether it is a new inode, /* we pass in rc below, indicating whether it is a new inode,
so we can figure out whether to invalidate the inode cached so we can figure out whether to invalidate the inode cached
data if the file has changed */ data if the file has changed */
if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
unix_fill_in_inode(tmp_inode, unix_fill_in_inode(tmp_inode,
(FILE_UNIX_INFO *)pfindEntry, (FILE_UNIX_INFO *)pfindEntry,
&obj_type, rc); &obj_type, rc);
else if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */, fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */,
pfindEntry, &obj_type, rc); pfindEntry, &obj_type, rc);
else else
fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc); fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc);
if(rc) /* new inode - needs to be tied to dentry */ { if (rc) /* new inode - needs to be tied to dentry */ {
d_instantiate(tmp_dentry, tmp_inode); d_instantiate(tmp_dentry, tmp_inode);
if(rc == 2) if (rc == 2)
d_rehash(tmp_dentry); d_rehash(tmp_dentry);
} }
rc = filldir(direntry,qstring.name,qstring.len,file->f_pos, rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
tmp_inode->i_ino,obj_type); tmp_inode->i_ino, obj_type);
if(rc) { if (rc) {
cFYI(1,("filldir rc = %d",rc)); cFYI(1, ("filldir rc = %d", rc));
/* we can not return filldir errors to the caller /* we can not return filldir errors to the caller
since they are "normal" when the stat blocksize since they are "normal" when the stat blocksize
is too small - we return remapped error instead */ is too small - we return remapped error instead */
...@@ -909,57 +914,57 @@ static int cifs_save_resume_key(const char *current_entry, ...@@ -909,57 +914,57 @@ static int cifs_save_resume_key(const char *current_entry,
int rc = 0; int rc = 0;
unsigned int len = 0; unsigned int len = 0;
__u16 level; __u16 level;
char * filename; char *filename;
if((cifsFile == NULL) || (current_entry == NULL)) if ((cifsFile == NULL) || (current_entry == NULL))
return -EINVAL; return -EINVAL;
level = cifsFile->srch_inf.info_level; level = cifsFile->srch_inf.info_level;
if(level == SMB_FIND_FILE_UNIX) { if (level == SMB_FIND_FILE_UNIX) {
FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry; FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
if(cifsFile->srch_inf.unicode) { if (cifsFile->srch_inf.unicode) {
len = cifs_unicode_bytelen(filename); len = cifs_unicode_bytelen(filename);
} else { } else {
/* BB should we make this strnlen of PATH_MAX? */ /* BB should we make this strnlen of PATH_MAX? */
len = strnlen(filename, PATH_MAX); len = strnlen(filename, PATH_MAX);
} }
cifsFile->srch_inf.resume_key = pFindData->ResumeKey; cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
} else if(level == SMB_FIND_FILE_DIRECTORY_INFO) { } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
FILE_DIRECTORY_INFO * pFindData = FILE_DIRECTORY_INFO *pFindData =
(FILE_DIRECTORY_INFO *)current_entry; (FILE_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength); len = le32_to_cpu(pFindData->FileNameLength);
cifsFile->srch_inf.resume_key = pFindData->FileIndex; cifsFile->srch_inf.resume_key = pFindData->FileIndex;
} else if(level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) { } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
FILE_FULL_DIRECTORY_INFO * pFindData = FILE_FULL_DIRECTORY_INFO *pFindData =
(FILE_FULL_DIRECTORY_INFO *)current_entry; (FILE_FULL_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength); len = le32_to_cpu(pFindData->FileNameLength);
cifsFile->srch_inf.resume_key = pFindData->FileIndex; cifsFile->srch_inf.resume_key = pFindData->FileIndex;
} else if(level == SMB_FIND_FILE_ID_FULL_DIR_INFO) { } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
SEARCH_ID_FULL_DIR_INFO * pFindData = SEARCH_ID_FULL_DIR_INFO *pFindData =
(SEARCH_ID_FULL_DIR_INFO *)current_entry; (SEARCH_ID_FULL_DIR_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength); len = le32_to_cpu(pFindData->FileNameLength);
cifsFile->srch_inf.resume_key = pFindData->FileIndex; cifsFile->srch_inf.resume_key = pFindData->FileIndex;
} else if(level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
FILE_BOTH_DIRECTORY_INFO * pFindData = FILE_BOTH_DIRECTORY_INFO *pFindData =
(FILE_BOTH_DIRECTORY_INFO *)current_entry; (FILE_BOTH_DIRECTORY_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength); len = le32_to_cpu(pFindData->FileNameLength);
cifsFile->srch_inf.resume_key = pFindData->FileIndex; cifsFile->srch_inf.resume_key = pFindData->FileIndex;
} else if(level == SMB_FIND_FILE_INFO_STANDARD) { } else if (level == SMB_FIND_FILE_INFO_STANDARD) {
FIND_FILE_STANDARD_INFO * pFindData = FIND_FILE_STANDARD_INFO *pFindData =
(FIND_FILE_STANDARD_INFO *)current_entry; (FIND_FILE_STANDARD_INFO *)current_entry;
filename = &pFindData->FileName[0]; filename = &pFindData->FileName[0];
/* one byte length, no name conversion */ /* one byte length, no name conversion */
len = (unsigned int)pFindData->FileNameLength; len = (unsigned int)pFindData->FileNameLength;
cifsFile->srch_inf.resume_key = pFindData->ResumeKey; cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
} else { } else {
cFYI(1,("Unknown findfirst level %d",level)); cFYI(1, ("Unknown findfirst level %d", level));
return -EINVAL; return -EINVAL;
} }
cifsFile->srch_inf.resume_name_len = len; cifsFile->srch_inf.resume_name_len = len;
...@@ -970,21 +975,21 @@ static int cifs_save_resume_key(const char *current_entry, ...@@ -970,21 +975,21 @@ static int cifs_save_resume_key(const char *current_entry,
int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
{ {
int rc = 0; int rc = 0;
int xid,i; int xid, i;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct cifsFileInfo *cifsFile = NULL; struct cifsFileInfo *cifsFile = NULL;
char * current_entry; char *current_entry;
int num_to_fill = 0; int num_to_fill = 0;
char * tmp_buf = NULL; char *tmp_buf = NULL;
char * end_of_smb; char *end_of_smb;
int max_len; int max_len;
xid = GetXid(); xid = GetXid();
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
if(pTcon == NULL) if (pTcon == NULL)
return -EINVAL; return -EINVAL;
switch ((int) file->f_pos) { switch ((int) file->f_pos) {
...@@ -1005,27 +1010,27 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) ...@@ -1005,27 +1010,27 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
} }
file->f_pos++; file->f_pos++;
default: default:
/* 1) If search is active, /* 1) If search is active,
is in current search buffer? is in current search buffer?
if it before then restart search if it before then restart search
if after then keep searching till find it */ if after then keep searching till find it */
if(file->private_data == NULL) { if (file->private_data == NULL) {
rc = initiate_cifs_search(xid,file); rc = initiate_cifs_search(xid, file);
cFYI(1,("initiate cifs search rc %d",rc)); cFYI(1, ("initiate cifs search rc %d", rc));
if(rc) { if (rc) {
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
} }
if(file->private_data == NULL) { if (file->private_data == NULL) {
rc = -EINVAL; rc = -EINVAL;
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
cifsFile = file->private_data; cifsFile = file->private_data;
if (cifsFile->srch_inf.endOfSearch) { if (cifsFile->srch_inf.endOfSearch) {
if(cifsFile->srch_inf.emptyDir) { if (cifsFile->srch_inf.emptyDir) {
cFYI(1, ("End of search, empty dir")); cFYI(1, ("End of search, empty dir"));
rc = 0; rc = 0;
break; break;
...@@ -1033,23 +1038,23 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) ...@@ -1033,23 +1038,23 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
} /* else { } /* else {
cifsFile->invalidHandle = TRUE; cifsFile->invalidHandle = TRUE;
CIFSFindClose(xid, pTcon, cifsFile->netfid); CIFSFindClose(xid, pTcon, cifsFile->netfid);
} }
kfree(cifsFile->search_resume_name); kfree(cifsFile->search_resume_name);
cifsFile->search_resume_name = NULL; */ cifsFile->search_resume_name = NULL; */
rc = find_cifs_entry(xid,pTcon, file, rc = find_cifs_entry(xid, pTcon, file,
&current_entry,&num_to_fill); &current_entry, &num_to_fill);
if(rc) { if (rc) {
cFYI(1,("fce error %d",rc)); cFYI(1, ("fce error %d", rc));
goto rddir2_exit; goto rddir2_exit;
} else if (current_entry != NULL) { } else if (current_entry != NULL) {
cFYI(1,("entry %lld found",file->f_pos)); cFYI(1, ("entry %lld found", file->f_pos));
} else { } else {
cFYI(1,("could not find entry")); cFYI(1, ("could not find entry"));
goto rddir2_exit; goto rddir2_exit;
} }
cFYI(1,("loop through %d times filling dir for net buf %p", cFYI(1, ("loop through %d times filling dir for net buf %p",
num_to_fill,cifsFile->srch_inf.ntwrk_buf_start)); num_to_fill, cifsFile->srch_inf.ntwrk_buf_start));
max_len = smbCalcSize((struct smb_hdr *) max_len = smbCalcSize((struct smb_hdr *)
cifsFile->srch_inf.ntwrk_buf_start); cifsFile->srch_inf.ntwrk_buf_start);
end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
...@@ -1059,8 +1064,8 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) ...@@ -1059,8 +1064,8 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
such multibyte target UTF-8 characters. cifs_unicode.c, such multibyte target UTF-8 characters. cifs_unicode.c,
which actually does the conversion, has the same limit */ which actually does the conversion, has the same limit */
tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL); tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL);
for(i=0;(i<num_to_fill) && (rc == 0);i++) { for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
if(current_entry == NULL) { if (current_entry == NULL) {
/* evaluate whether this case is an error */ /* evaluate whether this case is an error */
cERROR(1,("past end of SMB num to fill %d i %d", cERROR(1,("past end of SMB num to fill %d i %d",
num_to_fill, i)); num_to_fill, i));
...@@ -1070,20 +1075,20 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) ...@@ -1070,20 +1075,20 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
we want to check for that here? */ we want to check for that here? */
rc = cifs_filldir(current_entry, file, rc = cifs_filldir(current_entry, file,
filldir, direntry, tmp_buf, max_len); filldir, direntry, tmp_buf, max_len);
if(rc == -EOVERFLOW) { if (rc == -EOVERFLOW) {
rc = 0; rc = 0;
break; break;
} }
file->f_pos++; file->f_pos++;
if(file->f_pos == if (file->f_pos ==
cifsFile->srch_inf.index_of_last_entry) { cifsFile->srch_inf.index_of_last_entry) {
cFYI(1,("last entry in buf at pos %lld %s", cFYI(1, ("last entry in buf at pos %lld %s",
file->f_pos,tmp_buf)); file->f_pos, tmp_buf));
cifs_save_resume_key(current_entry,cifsFile); cifs_save_resume_key(current_entry, cifsFile);
break; break;
} else } else
current_entry = current_entry =
nxt_dir_entry(current_entry, end_of_smb, nxt_dir_entry(current_entry, end_of_smb,
cifsFile->srch_inf.info_level); cifsFile->srch_inf.info_level);
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* SMB/CIFS session setup handling routines * SMB/CIFS session setup handling routines
* *
* Copyright (c) International Business Machines Corp., 2006 * Copyright (c) International Business Machines Corp., 2006, 2007
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <linux/utsname.h> #include <linux/utsname.h>
extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, 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) 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) ...@@ -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 */ /* 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) */ (and NTLM case) */
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) if (ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
if (ses->capabilities & CAP_UNICODE) { if (ses->capabilities & CAP_UNICODE) {
...@@ -74,10 +75,10 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) ...@@ -74,10 +75,10 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
return capabilities; return capabilities;
} }
static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
const struct nls_table * nls_cp) const struct nls_table *nls_cp)
{ {
char * bcc_ptr = *pbcc_area; char *bcc_ptr = *pbcc_area;
int bytes_ret = 0; int bytes_ret = 0;
/* BB FIXME add check that strings total less /* BB FIXME add check that strings total less
...@@ -89,7 +90,7 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, ...@@ -89,7 +90,7 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
bcc_ptr++; bcc_ptr++;
} */ } */
/* copy user */ /* copy user */
if(ses->userName == NULL) { if (ses->userName == NULL) {
/* null user mount */ /* null user mount */
*bcc_ptr = 0; *bcc_ptr = 0;
*(bcc_ptr+1) = 0; *(bcc_ptr+1) = 0;
...@@ -100,14 +101,14 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, ...@@ -100,14 +101,14 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
bcc_ptr += 2 * bytes_ret; bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null termination */ bcc_ptr += 2; /* account for null termination */
/* copy domain */ /* copy domain */
if(ses->domainName == NULL) { if (ses->domainName == NULL) {
/* Sending null domain better than using a bogus domain name (as /* Sending null domain better than using a bogus domain name (as
we did briefly in 2.6.18) since server will use its default */ we did briefly in 2.6.18) since server will use its default */
*bcc_ptr = 0; *bcc_ptr = 0;
*(bcc_ptr+1) = 0; *(bcc_ptr+1) = 0;
bytes_ret = 0; bytes_ret = 0;
} else } else
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName, bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
256, nls_cp); 256, nls_cp);
bcc_ptr += 2 * bytes_ret; bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null terminator */ bcc_ptr += 2; /* account for null terminator */
...@@ -122,37 +123,37 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, ...@@ -122,37 +123,37 @@ static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
bcc_ptr += 2; /* trailing null */ bcc_ptr += 2; /* trailing null */
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
32, nls_cp); 32, nls_cp);
bcc_ptr += 2 * bytes_ret; bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */ bcc_ptr += 2; /* trailing null */
*pbcc_area = bcc_ptr; *pbcc_area = bcc_ptr;
} }
static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
const struct nls_table * nls_cp) const struct nls_table *nls_cp)
{ {
char * bcc_ptr = *pbcc_area; char *bcc_ptr = *pbcc_area;
/* copy user */ /* copy user */
/* BB what about null user mounts - check that we do this BB */ /* BB what about null user mounts - check that we do this BB */
/* copy user */ /* copy user */
if(ses->userName == NULL) { if (ses->userName == NULL) {
/* BB what about null user mounts - check that we do this BB */ /* BB what about null user mounts - check that we do this BB */
} else { /* 300 should be long enough for any conceivable user name */ } else { /* 300 should be long enough for any conceivable user name */
strncpy(bcc_ptr, ses->userName, 300); strncpy(bcc_ptr, ses->userName, 300);
} }
/* BB improve check for overflow */ /* BB improve check for overflow */
bcc_ptr += strnlen(ses->userName, 300); bcc_ptr += strnlen(ses->userName, 300);
*bcc_ptr = 0; *bcc_ptr = 0;
bcc_ptr++; /* account for null termination */ bcc_ptr++; /* account for null termination */
/* copy domain */ /* copy domain */
if(ses->domainName != NULL) { if (ses->domainName != NULL) {
strncpy(bcc_ptr, ses->domainName, 256); strncpy(bcc_ptr, ses->domainName, 256);
bcc_ptr += strnlen(ses->domainName, 256); bcc_ptr += strnlen(ses->domainName, 256);
} /* else we will send a null domain name } /* else we will send a null domain name
so the server will default to its own domain */ so the server will default to its own domain */
*bcc_ptr = 0; *bcc_ptr = 0;
bcc_ptr++; bcc_ptr++;
...@@ -167,19 +168,20 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, ...@@ -167,19 +168,20 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; 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, static int decode_unicode_ssetup(char **pbcc_area, int bleft,
const struct nls_table * nls_cp) struct cifsSesInfo *ses,
const struct nls_table *nls_cp)
{ {
int rc = 0; int rc = 0;
int words_left, len; int words_left, len;
char * data = *pbcc_area; char *data = *pbcc_area;
cFYI(1,("bleft %d",bleft)); cFYI(1, ("bleft %d", bleft));
/* SMB header is unaligned, so cifs servers word align start of /* SMB header is unaligned, so cifs servers word align start of
...@@ -189,7 +191,7 @@ static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInf ...@@ -189,7 +191,7 @@ static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInf
their final Unicode string - in which case we their final Unicode string - in which case we
now will not attempt to decode the byte of junk now will not attempt to decode the byte of junk
which follows it */ which follows it */
words_left = bleft / 2; words_left = bleft / 2;
/* save off server operating system */ /* save off server operating system */
...@@ -198,14 +200,14 @@ static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInf ...@@ -198,14 +200,14 @@ static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInf
/* We look for obvious messed up bcc or strings in response so we do not go off /* We look for obvious messed up bcc or strings in response so we do not go off
the end since (at least) WIN2K and Windows XP have a major bug in not null the end since (at least) WIN2K and Windows XP have a major bug in not null
terminating last Unicode string in response */ terminating last Unicode string in response */
if(len >= words_left) if (len >= words_left)
return rc; return rc;
if(ses->serverOS) if (ses->serverOS)
kfree(ses->serverOS); kfree(ses->serverOS);
/* UTF-8 string will not grow more than four times as big as UCS-16 */ /* UTF-8 string will not grow more than four times as big as UCS-16 */
ses->serverOS = kzalloc(4 * len, GFP_KERNEL); ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
if(ses->serverOS != NULL) { if (ses->serverOS != NULL) {
cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
nls_cp); nls_cp);
} }
...@@ -215,67 +217,68 @@ static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInf ...@@ -215,67 +217,68 @@ static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInf
/* save off server network operating system */ /* save off server network operating system */
len = UniStrnlen((wchar_t *) data, words_left); len = UniStrnlen((wchar_t *) data, words_left);
if(len >= words_left) if (len >= words_left)
return rc; return rc;
if(ses->serverNOS) if (ses->serverNOS)
kfree(ses->serverNOS); kfree(ses->serverNOS);
ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */ ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
if(ses->serverNOS != NULL) { if (ses->serverNOS != NULL) {
cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
nls_cp); nls_cp);
if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) { if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) {
cFYI(1,("NT4 server")); cFYI(1, ("NT4 server"));
ses->flags |= CIFS_SES_NT4; ses->flags |= CIFS_SES_NT4;
} }
} }
data += 2 * (len + 1); data += 2 * (len + 1);
words_left -= len + 1; words_left -= len + 1;
/* save off server domain */ /* save off server domain */
len = UniStrnlen((wchar_t *) data, words_left); len = UniStrnlen((wchar_t *) data, words_left);
if(len > words_left) if (len > words_left)
return rc; return rc;
if(ses->serverDomain) if (ses->serverDomain)
kfree(ses->serverDomain); kfree(ses->serverDomain);
ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */ ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
if(ses->serverDomain != NULL) { if (ses->serverDomain != NULL) {
cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
nls_cp); nls_cp);
ses->serverDomain[2*len] = 0; ses->serverDomain[2*len] = 0;
ses->serverDomain[(2*len) + 1] = 0; ses->serverDomain[(2*len) + 1] = 0;
} }
data += 2 * (len + 1); data += 2 * (len + 1);
words_left -= len + 1; words_left -= len + 1;
cFYI(1,("words left: %d",words_left)); cFYI(1, ("words left: %d", words_left));
return rc; return rc;
} }
static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses, static int decode_ascii_ssetup(char **pbcc_area, int bleft,
const struct nls_table * nls_cp) struct cifsSesInfo *ses,
const struct nls_table *nls_cp)
{ {
int rc = 0; int rc = 0;
int len; int len;
char * bcc_ptr = *pbcc_area; char *bcc_ptr = *pbcc_area;
cFYI(1, ("decode sessetup ascii. bleft %d", bleft));
cFYI(1,("decode sessetup ascii. bleft %d", bleft));
len = strnlen(bcc_ptr, bleft); len = strnlen(bcc_ptr, bleft);
if(len >= bleft) if (len >= bleft)
return rc; return rc;
if(ses->serverOS) if (ses->serverOS)
kfree(ses->serverOS); kfree(ses->serverOS);
ses->serverOS = kzalloc(len + 1, GFP_KERNEL); ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
if(ses->serverOS) if (ses->serverOS)
strncpy(ses->serverOS, bcc_ptr, len); strncpy(ses->serverOS, bcc_ptr, len);
if(strncmp(ses->serverOS, "OS/2",4) == 0) { if (strncmp(ses->serverOS, "OS/2", 4) == 0) {
cFYI(1,("OS/2 server")); cFYI(1, ("OS/2 server"));
ses->flags |= CIFS_SES_OS2; ses->flags |= CIFS_SES_OS2;
} }
...@@ -283,34 +286,34 @@ static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo ...@@ -283,34 +286,34 @@ static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo
bleft -= len + 1; bleft -= len + 1;
len = strnlen(bcc_ptr, bleft); len = strnlen(bcc_ptr, bleft);
if(len >= bleft) if (len >= bleft)
return rc; return rc;
if(ses->serverNOS) if (ses->serverNOS)
kfree(ses->serverNOS); kfree(ses->serverNOS);
ses->serverNOS = kzalloc(len + 1, GFP_KERNEL); ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
if(ses->serverNOS) if (ses->serverNOS)
strncpy(ses->serverNOS, bcc_ptr, len); strncpy(ses->serverNOS, bcc_ptr, len);
bcc_ptr += len + 1; bcc_ptr += len + 1;
bleft -= len + 1; bleft -= len + 1;
len = strnlen(bcc_ptr, bleft); len = strnlen(bcc_ptr, bleft);
if(len > bleft) if (len > bleft)
return rc; return rc;
/* No domain field in LANMAN case. Domain is /* No domain field in LANMAN case. Domain is
returned by old servers in the SMB negprot response */ returned by old servers in the SMB negprot response */
/* BB For newer servers which do not support Unicode, /* BB For newer servers which do not support Unicode,
but thus do return domain here we could add parsing but thus do return domain here we could add parsing
for it later, but it is not very important */ for it later, but it is not very important */
cFYI(1,("ascii: bytes left %d",bleft)); cFYI(1, ("ascii: bytes left %d", bleft));
return rc; return rc;
} }
int int
CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
const struct nls_table *nls_cp) const struct nls_table *nls_cp)
{ {
...@@ -328,13 +331,13 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -328,13 +331,13 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
__u16 action; __u16 action;
int bytes_remaining; int bytes_remaining;
if(ses == NULL) if (ses == NULL)
return -EINVAL; return -EINVAL;
type = ses->server->secType; type = ses->server->secType;
cFYI(1,("sess setup type %d",type)); cFYI(1, ("sess setup type %d", type));
if(type == LANMAN) { if (type == LANMAN) {
#ifndef CONFIG_CIFS_WEAK_PW_HASH #ifndef CONFIG_CIFS_WEAK_PW_HASH
/* LANMAN and plaintext are less secure and off by default. /* LANMAN and plaintext are less secure and off by default.
So we make this explicitly be turned on in kconfig (in the So we make this explicitly be turned on in kconfig (in the
...@@ -344,15 +347,15 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -344,15 +347,15 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
return -EOPNOTSUPP; return -EOPNOTSUPP;
#endif #endif
wct = 10; /* lanman 2 style sessionsetup */ wct = 10; /* lanman 2 style sessionsetup */
} else if((type == NTLM) || (type == NTLMv2)) { } else if ((type == NTLM) || (type == NTLMv2)) {
/* For NTLMv2 failures eventually may need to retry NTLM */ /* For NTLMv2 failures eventually may need to retry NTLM */
wct = 13; /* old style NTLM sessionsetup */ wct = 13; /* old style NTLM sessionsetup */
} else /* same size for negotiate or auth, NTLMSSP or extended security */ } else /* same size: negotiate or auth, NTLMSSP or extended security */
wct = 12; wct = 12;
rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses, rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
(void **)&smb_buf); (void **)&smb_buf);
if(rc) if (rc)
return rc; return rc;
pSMB = (SESSION_SETUP_ANDX *)smb_buf; pSMB = (SESSION_SETUP_ANDX *)smb_buf;
...@@ -364,8 +367,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -364,8 +367,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
second part which will include the strings second part which will include the strings
and rest of bcc area, in order to avoid having and rest of bcc area, in order to avoid having
to do a large buffer 17K allocation */ to do a large buffer 17K allocation */
iov[0].iov_base = (char *)pSMB; iov[0].iov_base = (char *)pSMB;
iov[0].iov_len = smb_buf->smb_buf_length + 4; iov[0].iov_len = smb_buf->smb_buf_length + 4;
/* 2000 big enough to fit max user, domain, NOS name etc. */ /* 2000 big enough to fit max user, domain, NOS name etc. */
str_area = kmalloc(2000, GFP_KERNEL); str_area = kmalloc(2000, GFP_KERNEL);
...@@ -373,18 +376,18 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -373,18 +376,18 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
ses->flags &= ~CIFS_SES_LANMAN; ses->flags &= ~CIFS_SES_LANMAN;
if(type == LANMAN) { if (type == LANMAN) {
#ifdef CONFIG_CIFS_WEAK_PW_HASH #ifdef CONFIG_CIFS_WEAK_PW_HASH
char lnm_session_key[CIFS_SESS_KEY_SIZE]; char lnm_session_key[CIFS_SESS_KEY_SIZE];
/* no capabilities flags in old lanman negotiation */ /* 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 */ /* BB calculate hash with password */
/* and copy into bcc */ /* and copy into bcc */
calc_lanman_hash(ses, lnm_session_key); calc_lanman_hash(ses, lnm_session_key);
ses->flags |= CIFS_SES_LANMAN; ses->flags |= CIFS_SES_LANMAN;
/* #ifdef CONFIG_CIFS_DEBUG2 /* #ifdef CONFIG_CIFS_DEBUG2
cifs_dump_mem("cryptkey: ",ses->server->cryptKey, cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
CIFS_SESS_KEY_SIZE); CIFS_SESS_KEY_SIZE);
...@@ -397,10 +400,10 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -397,10 +400,10 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
changed to do higher than lanman dialect and changed to do higher than lanman dialect and
we reconnected would we ever calc signing_key? */ we reconnected would we ever calc signing_key? */
cFYI(1,("Negotiating LANMAN setting up strings")); cFYI(1, ("Negotiating LANMAN setting up strings"));
/* Unicode not allowed for LANMAN dialects */ /* Unicode not allowed for LANMAN dialects */
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
#endif #endif
} else if (type == NTLM) { } else if (type == NTLM) {
char ntlm_session_key[CIFS_SESS_KEY_SIZE]; char ntlm_session_key[CIFS_SESS_KEY_SIZE];
...@@ -409,38 +412,38 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -409,38 +412,38 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
cpu_to_le16(CIFS_SESS_KEY_SIZE); cpu_to_le16(CIFS_SESS_KEY_SIZE);
pSMB->req_no_secext.CaseSensitivePasswordLength = pSMB->req_no_secext.CaseSensitivePasswordLength =
cpu_to_le16(CIFS_SESS_KEY_SIZE); cpu_to_le16(CIFS_SESS_KEY_SIZE);
/* calculate session key */ /* calculate session key */
SMBNTencrypt(ses->password, ses->server->cryptKey, SMBNTencrypt(ses->password, ses->server->cryptKey,
ntlm_session_key); ntlm_session_key);
if(first_time) /* should this be moved into common code if (first_time) /* should this be moved into common code
with similar ntlmv2 path? */ with similar ntlmv2 path? */
cifs_calculate_mac_key(ses->server->mac_signing_key, cifs_calculate_mac_key(&ses->server->mac_signing_key,
ntlm_session_key, ses->password); ntlm_session_key, ses->password);
/* copy session key */ /* copy session key */
memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE); memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
bcc_ptr += CIFS_SESS_KEY_SIZE; bcc_ptr += CIFS_SESS_KEY_SIZE;
memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE); memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
bcc_ptr += CIFS_SESS_KEY_SIZE; bcc_ptr += CIFS_SESS_KEY_SIZE;
if(ses->capabilities & CAP_UNICODE) { if (ses->capabilities & CAP_UNICODE) {
/* unicode strings must be word aligned */ /* unicode strings must be word aligned */
if (iov[0].iov_len % 2) { if (iov[0].iov_len % 2) {
*bcc_ptr = 0; *bcc_ptr = 0;
bcc_ptr++; bcc_ptr++;
} }
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
} else } else
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
} else if (type == NTLMv2) { } else if (type == NTLMv2) {
char * v2_sess_key = char *v2_sess_key =
kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL); kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
/* BB FIXME change all users of v2_sess_key to /* BB FIXME change all users of v2_sess_key to
struct ntlmv2_resp */ struct ntlmv2_resp */
if(v2_sess_key == NULL) { if (v2_sess_key == NULL) {
cifs_small_buf_release(smb_buf); cifs_small_buf_release(smb_buf);
return -ENOMEM; return -ENOMEM;
} }
...@@ -456,8 +459,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -456,8 +459,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
/* calculate session key */ /* calculate session key */
setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
if(first_time) /* should this be moved into common code if (first_time) /* should this be moved into common code
with similar ntlmv2 path? */ with similar ntlmv2 path? */
/* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key, /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
response BB FIXME, v2_sess_key); */ response BB FIXME, v2_sess_key); */
...@@ -465,11 +468,12 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -465,11 +468,12 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
/* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE); /* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
bcc_ptr += LM2_SESS_KEY_SIZE; */ bcc_ptr += LM2_SESS_KEY_SIZE; */
memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp)); memcpy(bcc_ptr, (char *)v2_sess_key,
sizeof(struct ntlmv2_resp));
bcc_ptr += sizeof(struct ntlmv2_resp); bcc_ptr += sizeof(struct ntlmv2_resp);
kfree(v2_sess_key); kfree(v2_sess_key);
if(ses->capabilities & CAP_UNICODE) { if (ses->capabilities & CAP_UNICODE) {
if(iov[0].iov_len % 2) { if (iov[0].iov_len % 2) {
*bcc_ptr = 0; *bcc_ptr = 0;
} bcc_ptr++; } bcc_ptr++;
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
...@@ -488,20 +492,20 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -488,20 +492,20 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
BCC_LE(smb_buf) = cpu_to_le16(count); BCC_LE(smb_buf) = cpu_to_le16(count);
iov[1].iov_base = str_area; 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); rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
/* SMB request buf freed in SendReceive2 */ /* SMB request buf freed in SendReceive2 */
cFYI(1,("ssetup rc from sendrecv2 is %d",rc)); cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
if(rc) if (rc)
goto ssetup_exit; goto ssetup_exit;
pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base; pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
smb_buf = (struct smb_hdr *)iov[0].iov_base; smb_buf = (struct smb_hdr *)iov[0].iov_base;
if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) { if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
rc = -EIO; rc = -EIO;
cERROR(1,("bad word count %d", smb_buf->WordCount)); cERROR(1, ("bad word count %d", smb_buf->WordCount));
goto ssetup_exit; goto ssetup_exit;
} }
action = le16_to_cpu(pSMB->resp.Action); action = le16_to_cpu(pSMB->resp.Action);
...@@ -514,31 +518,32 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -514,31 +518,32 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
bytes_remaining = BCC(smb_buf); bytes_remaining = BCC(smb_buf);
bcc_ptr = pByteArea(smb_buf); bcc_ptr = pByteArea(smb_buf);
if(smb_buf->WordCount == 4) { if (smb_buf->WordCount == 4) {
__u16 blob_len; __u16 blob_len;
blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength); blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
bcc_ptr += blob_len; bcc_ptr += blob_len;
if(blob_len > bytes_remaining) { if (blob_len > bytes_remaining) {
cERROR(1,("bad security blob length %d", blob_len)); cERROR(1, ("bad security blob length %d", blob_len));
rc = -EINVAL; rc = -EINVAL;
goto ssetup_exit; goto ssetup_exit;
} }
bytes_remaining -= blob_len; bytes_remaining -= blob_len;
} }
/* BB check if Unicode and decode strings */ /* BB check if Unicode and decode strings */
if(smb_buf->Flags2 & SMBFLG2_UNICODE) if (smb_buf->Flags2 & SMBFLG2_UNICODE)
rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining, rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
ses, nls_cp); ses, nls_cp);
else else
rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp); rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining,
ses, nls_cp);
ssetup_exit: ssetup_exit:
kfree(str_area); kfree(str_area);
if(resp_buf_type == CIFS_SMALL_BUFFER) { if (resp_buf_type == CIFS_SMALL_BUFFER) {
cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base)); cFYI(1, ("ssetup freeing small buf %p", iov[0].iov_base));
cifs_small_buf_release(iov[0].iov_base); cifs_small_buf_release(iov[0].iov_base);
} else if(resp_buf_type == CIFS_LARGE_BUFFER) } else if (resp_buf_type == CIFS_LARGE_BUFFER)
cifs_buf_release(iov[0].iov_base); cifs_buf_release(iov[0].iov_base);
return rc; return rc;
......
/* /*
Unix SMB/Netbios implementation. Unix SMB/Netbios implementation.
Version 1.9. 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 SMB authentication protocol
Copyright (C) Andrew Tridgell 1998 Copyright (C) Andrew Tridgell 1998
Modified by Steve French (sfrench@us.ibm.com) 2002,2004 Modified by Steve French (sfrench@us.ibm.com) 2002,2004
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License 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., 675 Mass Ave, Cambridge, MA 02139, USA. 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 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 This code is NOT a complete DES implementation. It implements only
the minimum necessary for SMB authentication, as used by all SMB the minimum necessary for SMB authentication, as used by all SMB
...@@ -153,7 +153,7 @@ static uchar sbox[8][4][16] = { ...@@ -153,7 +153,7 @@ static uchar sbox[8][4][16] = {
}; };
static void static void
permute(char *out, char *in, uchar * p, int n) permute(char *out, char *in, uchar *p, int n)
{ {
int i; int i;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
...@@ -202,18 +202,18 @@ dohash(char *out, char *in, char *key, int forw) ...@@ -202,18 +202,18 @@ dohash(char *out, char *in, char *key, int forw)
char *rl; char *rl;
/* Have to reduce stack usage */ /* Have to reduce stack usage */
pk1 = kmalloc(56+56+64+64,GFP_KERNEL); pk1 = kmalloc(56+56+64+64, GFP_KERNEL);
if(pk1 == NULL) if (pk1 == NULL)
return; return;
ki = kmalloc(16*48, GFP_KERNEL); ki = kmalloc(16*48, GFP_KERNEL);
if(ki == NULL) { if (ki == NULL) {
kfree(pk1); kfree(pk1);
return; return;
} }
cd = pk1 + 56; cd = pk1 + 56;
pd1= cd + 56; pd1 = cd + 56;
rl = pd1 + 64; rl = pd1 + 64;
permute(pk1, key, perm1, 56); permute(pk1, key, perm1, 56);
...@@ -247,7 +247,7 @@ dohash(char *out, char *in, char *key, int forw) ...@@ -247,7 +247,7 @@ dohash(char *out, char *in, char *key, int forw)
char *r2; /* r2[32] */ char *r2; /* r2[32] */
er = kmalloc(48+48+32+32+32, GFP_KERNEL); er = kmalloc(48+48+32+32+32, GFP_KERNEL);
if(er == NULL) { if (er == NULL) {
kfree(pk1); kfree(pk1);
kfree(ki); kfree(ki);
return; return;
...@@ -327,8 +327,8 @@ smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw) ...@@ -327,8 +327,8 @@ smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
char *keyb; /* keyb[64] */ char *keyb; /* keyb[64] */
unsigned char key2[8]; unsigned char key2[8];
outb = kmalloc(64 * 3,GFP_KERNEL); outb = kmalloc(64 * 3, GFP_KERNEL);
if(outb == NULL) if (outb == NULL)
return; return;
inb = outb + 64; inb = outb + 64;
......
/* /*
Unix SMB/Netbios implementation. Unix SMB/Netbios implementation.
Version 1.9. Version 1.9.
SMB parameters and setup SMB parameters and setup
...@@ -7,17 +7,17 @@ ...@@ -7,17 +7,17 @@
Modified by Jeremy Allison 1995. Modified by Jeremy Allison 1995.
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
Modified by Steve French (sfrench@us.ibm.com) 2002-2003 Modified by Steve French (sfrench@us.ibm.com) 2002-2003
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License 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., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
...@@ -57,7 +57,7 @@ void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); ...@@ -57,7 +57,7 @@ void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
/* /*
This implements the X/Open SMB password encryption 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 */ encrypted password into p24 */
/* Note that password must be uppercased and null terminated */ /* Note that password must be uppercased and null terminated */
void void
...@@ -73,9 +73,9 @@ SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) ...@@ -73,9 +73,9 @@ SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
E_P16(p14, p21); E_P16(p14, p21);
SMBOWFencrypt(p21, c8, p24); SMBOWFencrypt(p21, c8, p24);
memset(p14,0,15); memset(p14, 0, 15);
memset(p21,0,21); memset(p21, 0, 21);
} }
/* Routines for Windows NT MD4 Hash functions. */ /* Routines for Windows NT MD4 Hash functions. */
...@@ -90,14 +90,14 @@ _my_wcslen(__u16 * str) ...@@ -90,14 +90,14 @@ _my_wcslen(__u16 * str)
/* /*
* Convert a string into an NT UNICODE string. * 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) * this must be in intel (little-endian)
* format. * format.
*/ */
static int static int
_my_mbstowcs(__u16 * dst, const unsigned char *src, int len) _my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
{ /* not a very good conversion routine - change/fix */ { /* BB not a very good conversion routine - change/fix */
int i; int i;
__u16 val; __u16 val;
...@@ -112,7 +112,7 @@ _my_mbstowcs(__u16 * dst, const unsigned char *src, int len) ...@@ -112,7 +112,7 @@ _my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
return i; return i;
} }
/* /*
* Creates the MD4 Hash of the users password in NT UNICODE. * Creates the MD4 Hash of the users password in NT UNICODE.
*/ */
...@@ -123,7 +123,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16) ...@@ -123,7 +123,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16)
__u16 wpwd[129]; __u16 wpwd[129];
/* Password cannot be longer than 128 characters */ /* Password cannot be longer than 128 characters */
if(passwd) { if (passwd) {
len = strlen((char *) passwd); len = strlen((char *) passwd);
if (len > 128) { if (len > 128) {
len = 128; len = 128;
...@@ -138,7 +138,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16) ...@@ -138,7 +138,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16)
len = _my_wcslen(wpwd) * sizeof (__u16); len = _my_wcslen(wpwd) * sizeof (__u16);
mdfour(p16, (unsigned char *) wpwd, len); mdfour(p16, (unsigned char *) wpwd, len);
memset(wpwd,0,129 * 2); memset(wpwd, 0, 129 * 2);
} }
#if 0 /* currently unused */ #if 0 /* currently unused */
...@@ -178,17 +178,17 @@ ntv2_owf_gen(const unsigned char owf[16], const char *user_n, ...@@ -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 char *domain_n, unsigned char kr_buf[16],
const struct nls_table *nls_codepage) const struct nls_table *nls_codepage)
{ {
wchar_t * user_u; wchar_t *user_u;
wchar_t * dom_u; wchar_t *dom_u;
int user_l, domain_l; int user_l, domain_l;
struct HMACMD5Context ctx; struct HMACMD5Context ctx;
/* might as well do one alloc to hold both (user_u and dom_u) */ /* might as well do one alloc to hold both (user_u and dom_u) */
user_u = kmalloc(2048 * sizeof(wchar_t),GFP_KERNEL); user_u = kmalloc(2048 * sizeof(wchar_t), GFP_KERNEL);
if(user_u == NULL) if (user_u == NULL)
return; return;
dom_u = user_u + 1024; dom_u = user_u + 1024;
/* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); /* 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); */ 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, ...@@ -206,7 +206,7 @@ ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
kfree(user_u); kfree(user_u);
} }
#endif #endif
/* Does the des encryption from the NT or LM MD4 hash. */ /* Does the des encryption from the NT or LM MD4 hash. */
static void static void
...@@ -256,15 +256,15 @@ SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) ...@@ -256,15 +256,15 @@ SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
#if 0 #if 0
static void static void
SMBOWFencrypt_ntv2(const unsigned char kr[16], SMBOWFencrypt_ntv2(const unsigned char kr[16],
const struct data_blob * srv_chal, const struct data_blob *srv_chal,
const struct data_blob * cli_chal, unsigned char resp_buf[16]) const struct data_blob *cli_chal, unsigned char resp_buf[16])
{ {
struct HMACMD5Context ctx; struct HMACMD5Context ctx;
hmac_md5_init_limK_to_64(kr, 16, &ctx); hmac_md5_init_limK_to_64(kr, 16, &ctx);
hmac_md5_update(srv_chal->data, srv_chal->length, &ctx); hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
hmac_md5_update(cli_chal->data, cli_chal->length, &ctx); hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
hmac_md5_final(resp_buf, &ctx); hmac_md5_final(resp_buf, &ctx);
} }
static void static void
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
* Copyright (c) International Business Machines Corp., 2002,2004 * Copyright (c) International Business Machines Corp., 2002,2004
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* See Error Codes section of the SNIA CIFS Specification * See Error Codes section of the SNIA CIFS Specification
* for more information * for more information
* *
* This library is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU Lesser General Public License as published
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software * 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. */ #define SUCCESS 0x00 /* The request was successful. */
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
/* Below errors are used internally (do not come over the wire) for passthrough /* Below errors are used internally (do not come over the wire) for passthrough
from STATUS codes to POSIX only */ from STATUS codes to POSIX only */
#define ErrTooManyLinks 0xFFFE #define ErrTooManyLinks 0xFFFE
/* Following error codes may be generated with the ERRSRV error class.*/ /* Following error codes may be generated with the ERRSRV error class.*/
......
/* /*
* fs/cifs/transport.c * fs/cifs/transport.c
* *
* Copyright (C) International Business Machines Corp., 2002,2005 * Copyright (C) International Business Machines Corp., 2002,2007
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* Jeremy Allison (jra@samba.org) 2006. * Jeremy Allison (jra@samba.org) 2006.
* *
* This library is free software; you can redistribute it and/or modify * 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 * 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 * by the Free Software Foundation; either version 2.1 of the License, or
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software * 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> #include <linux/fs.h>
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include "cifsglob.h" #include "cifsglob.h"
#include "cifsproto.h" #include "cifsproto.h"
#include "cifs_debug.h" #include "cifs_debug.h"
extern mempool_t *cifs_mid_poolp; extern mempool_t *cifs_mid_poolp;
extern struct kmem_cache *cifs_oplock_cachep; extern struct kmem_cache *cifs_oplock_cachep;
...@@ -49,7 +49,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) ...@@ -49,7 +49,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
cERROR(1, ("Null TCP session in AllocMidQEntry")); cERROR(1, ("Null TCP session in AllocMidQEntry"));
return NULL; return NULL;
} }
temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp, temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,
GFP_KERNEL | GFP_NOFS); GFP_KERNEL | GFP_NOFS);
if (temp == NULL) if (temp == NULL)
...@@ -86,7 +86,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) ...@@ -86,7 +86,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
list_del(&midEntry->qhead); list_del(&midEntry->qhead);
atomic_dec(&midCount); atomic_dec(&midCount);
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
if(midEntry->largeBuf) if (midEntry->largeBuf)
cifs_buf_release(midEntry->resp_buf); cifs_buf_release(midEntry->resp_buf);
else else
cifs_small_buf_release(midEntry->resp_buf); cifs_small_buf_release(midEntry->resp_buf);
...@@ -94,8 +94,8 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) ...@@ -94,8 +94,8 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
now = jiffies; now = jiffies;
/* commands taking longer than one second are indications that /* commands taking longer than one second are indications that
something is wrong, unless it is quite a slow link or server */ something is wrong, unless it is quite a slow link or server */
if((now - midEntry->when_alloc) > HZ) { if ((now - midEntry->when_alloc) > HZ) {
if((cifsFYI & CIFS_TIMER) && if ((cifsFYI & CIFS_TIMER) &&
(midEntry->command != SMB_COM_LOCKING_ANDX)) { (midEntry->command != SMB_COM_LOCKING_ANDX)) {
printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d", printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
midEntry->command, midEntry->mid); midEntry->command, midEntry->mid);
...@@ -110,10 +110,10 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) ...@@ -110,10 +110,10 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
} }
struct oplock_q_entry * struct oplock_q_entry *
AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon) AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon)
{ {
struct oplock_q_entry *temp; struct oplock_q_entry *temp;
if ((pinode== NULL) || (tcon == NULL)) { if ((pinode == NULL) || (tcon == NULL)) {
cERROR(1, ("Null parms passed to AllocOplockQEntry")); cERROR(1, ("Null parms passed to AllocOplockQEntry"));
return NULL; return NULL;
} }
...@@ -133,9 +133,9 @@ AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon) ...@@ -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? */ /* should we check if list empty first? */
list_del(&oplockEntry->qhead); list_del(&oplockEntry->qhead);
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
...@@ -152,7 +152,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, ...@@ -152,7 +152,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
struct kvec iov; struct kvec iov;
unsigned len = smb_buf_length + 4; unsigned len = smb_buf_length + 4;
if(ssocket == NULL) if (ssocket == NULL)
return -ENOTSOCK; /* BB eventually add reconnect code here */ return -ENOTSOCK; /* BB eventually add reconnect code here */
iov.iov_base = smb_buffer; iov.iov_base = smb_buffer;
iov.iov_len = len; iov.iov_len = len;
...@@ -164,8 +164,8 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, ...@@ -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_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
/* smb header is converted in header_assemble. bcc and rest of SMB word /* smb header is converted in header_assemble. bcc and rest of SMB word
area, and byte area if necessary, is converted to littleendian in area, and byte area if necessary, is converted to littleendian in
cifssmb.c and RFC1001 len is converted to bigendian in smb_send cifssmb.c and RFC1001 len is converted to bigendian in smb_send
Flags2 is converted in SendReceive */ Flags2 is converted in SendReceive */
smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length); 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, ...@@ -177,9 +177,9 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
if ((rc == -ENOSPC) || (rc == -EAGAIN)) { if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
i++; i++;
/* smaller timeout here than send2 since smaller size */ /* smaller timeout here than send2 since smaller size */
/* Although it may not be required, this also is smaller /* Although it may not be required, this also is smaller
oplock break time */ oplock break time */
if(i > 12) { if (i > 12) {
cERROR(1, cERROR(1,
("sends on sock %p stuck for 7 seconds", ("sends on sock %p stuck for 7 seconds",
ssocket)); ssocket));
...@@ -189,7 +189,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, ...@@ -189,7 +189,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
msleep(1 << i); msleep(1 << i);
continue; continue;
} }
if (rc < 0) if (rc < 0)
break; break;
else else
i = 0; /* reset i after each successful send */ i = 0; /* reset i after each successful send */
...@@ -199,7 +199,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, ...@@ -199,7 +199,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
} }
if (rc < 0) { if (rc < 0) {
cERROR(1,("Error %d sending data on socket to server", rc)); cERROR(1, ("Error %d sending data on socket to server", rc));
} else { } else {
rc = 0; rc = 0;
} }
...@@ -223,8 +223,8 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, ...@@ -223,8 +223,8 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
unsigned int total_len; unsigned int total_len;
int first_vec = 0; int first_vec = 0;
unsigned int smb_buf_length = smb_buffer->smb_buf_length; unsigned int smb_buf_length = smb_buffer->smb_buf_length;
if(ssocket == NULL) if (ssocket == NULL)
return -ENOTSOCK; /* BB eventually add reconnect code here */ return -ENOTSOCK; /* BB eventually add reconnect code here */
smb_msg.msg_name = sin; smb_msg.msg_name = sin;
...@@ -234,8 +234,8 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, ...@@ -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_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
/* smb header is converted in header_assemble. bcc and rest of SMB word /* smb header is converted in header_assemble. bcc and rest of SMB word
area, and byte area if necessary, is converted to littleendian in area, and byte area if necessary, is converted to littleendian in
cifssmb.c and RFC1001 len is converted to bigendian in smb_send cifssmb.c and RFC1001 len is converted to bigendian in smb_send
Flags2 is converted in SendReceive */ Flags2 is converted in SendReceive */
...@@ -252,7 +252,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, ...@@ -252,7 +252,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
n_vec - first_vec, total_len); n_vec - first_vec, total_len);
if ((rc == -ENOSPC) || (rc == -EAGAIN)) { if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
i++; i++;
if(i >= 14) { if (i >= 14) {
cERROR(1, cERROR(1,
("sends on sock %p stuck for 15 seconds", ("sends on sock %p stuck for 15 seconds",
ssocket)); ssocket));
...@@ -262,17 +262,17 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, ...@@ -262,17 +262,17 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
msleep(1 << i); msleep(1 << i);
continue; continue;
} }
if (rc < 0) if (rc < 0)
break; break;
if (rc >= total_len) { if (rc >= total_len) {
WARN_ON(rc > total_len); WARN_ON(rc > total_len);
break; break;
} }
if(rc == 0) { if (rc == 0) {
/* should never happen, letting socket clear before /* should never happen, letting socket clear before
retrying is our only obvious option here */ retrying is our only obvious option here */
cERROR(1,("tcp sent no data")); cERROR(1, ("tcp sent no data"));
msleep(500); msleep(500);
continue; continue;
} }
...@@ -295,7 +295,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, ...@@ -295,7 +295,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
} }
if (rc < 0) { if (rc < 0) {
cERROR(1,("Error %d sending data on socket to server", rc)); cERROR(1, ("Error %d sending data on socket to server", rc));
} else } else
rc = 0; rc = 0;
...@@ -308,13 +308,13 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, ...@@ -308,13 +308,13 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
{ {
if(long_op == -1) { if (long_op == -1) {
/* oplock breaks must not be held up */ /* oplock breaks must not be held up */
atomic_inc(&ses->server->inFlight); atomic_inc(&ses->server->inFlight);
} else { } else {
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
while(1) { while (1) {
if(atomic_read(&ses->server->inFlight) >= if (atomic_read(&ses->server->inFlight) >=
cifs_max_pending){ cifs_max_pending){
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
...@@ -328,14 +328,14 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) ...@@ -328,14 +328,14 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
#endif #endif
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
} else { } else {
if(ses->server->tcpStatus == CifsExiting) { if (ses->server->tcpStatus == CifsExiting) {
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
return -ENOENT; return -ENOENT;
} }
/* can not count locking commands against total since /* can not count locking commands against total
they are allowed to block on server */ as they are allowed to block on server */
/* update # of requests on the wire to server */ /* update # of requests on the wire to server */
if (long_op < 3) if (long_op < 3)
atomic_inc(&ses->server->inFlight); atomic_inc(&ses->server->inFlight);
...@@ -353,11 +353,11 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf, ...@@ -353,11 +353,11 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
if (ses->server->tcpStatus == CifsExiting) { if (ses->server->tcpStatus == CifsExiting) {
return -ENOENT; return -ENOENT;
} else if (ses->server->tcpStatus == CifsNeedReconnect) { } else if (ses->server->tcpStatus == CifsNeedReconnect) {
cFYI(1,("tcp session dead - return to caller to retry")); cFYI(1, ("tcp session dead - return to caller to retry"));
return -EAGAIN; return -EAGAIN;
} else if (ses->status != CifsGood) { } else if (ses->status != CifsGood) {
/* check if SMB session is bad because we are setting it up */ /* check if SMB session is bad because we are setting it up */
if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
(in_buf->Command != SMB_COM_NEGOTIATE)) { (in_buf->Command != SMB_COM_NEGOTIATE)) {
return -EAGAIN; return -EAGAIN;
} /* else ok - we are setting up session */ } /* else ok - we are setting up session */
...@@ -369,7 +369,7 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf, ...@@ -369,7 +369,7 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
return 0; return 0;
} }
static int wait_for_response(struct cifsSesInfo *ses, static int wait_for_response(struct cifsSesInfo *ses,
struct mid_q_entry *midQ, struct mid_q_entry *midQ,
unsigned long timeout, unsigned long timeout,
unsigned long time_to_wait) unsigned long time_to_wait)
...@@ -379,8 +379,8 @@ static int wait_for_response(struct cifsSesInfo *ses, ...@@ -379,8 +379,8 @@ static int wait_for_response(struct cifsSesInfo *ses,
for (;;) { for (;;) {
curr_timeout = timeout + jiffies; curr_timeout = timeout + jiffies;
wait_event(ses->server->response_q, wait_event(ses->server->response_q,
(!(midQ->midState == MID_REQUEST_SUBMITTED)) || (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
time_after(jiffies, curr_timeout) || time_after(jiffies, curr_timeout) ||
((ses->server->tcpStatus != CifsGood) && ((ses->server->tcpStatus != CifsGood) &&
(ses->server->tcpStatus != CifsNew))); (ses->server->tcpStatus != CifsNew)));
...@@ -398,16 +398,16 @@ static int wait_for_response(struct cifsSesInfo *ses, ...@@ -398,16 +398,16 @@ static int wait_for_response(struct cifsSesInfo *ses,
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
/* Calculate time_to_wait past last receive time. /* 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 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 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 */ other threads on the client within 10 seconds */
lrt += time_to_wait; lrt += time_to_wait;
if (time_after(jiffies, lrt)) { if (time_after(jiffies, lrt)) {
/* No replies for time_to_wait. */ /* No replies for time_to_wait. */
cERROR(1,("server not responding")); cERROR(1, ("server not responding"));
return -1; return -1;
} }
} else { } else {
...@@ -417,8 +417,8 @@ static int wait_for_response(struct cifsSesInfo *ses, ...@@ -417,8 +417,8 @@ static int wait_for_response(struct cifsSesInfo *ses,
} }
int int
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
struct kvec *iov, int n_vec, int * pRespBufType /* ret */, struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
const int long_op) const int long_op)
{ {
int rc = 0; int rc = 0;
...@@ -426,21 +426,21 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -426,21 +426,21 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
unsigned long timeout; unsigned long timeout;
struct mid_q_entry *midQ; struct mid_q_entry *midQ;
struct smb_hdr *in_buf = iov[0].iov_base; struct smb_hdr *in_buf = iov[0].iov_base;
*pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
if ((ses == NULL) || (ses->server == NULL)) { if ((ses == NULL) || (ses->server == NULL)) {
cifs_small_buf_release(in_buf); cifs_small_buf_release(in_buf);
cERROR(1,("Null session")); cERROR(1, ("Null session"));
return -EIO; return -EIO;
} }
if(ses->server->tcpStatus == CifsExiting) { if (ses->server->tcpStatus == CifsExiting) {
cifs_small_buf_release(in_buf); cifs_small_buf_release(in_buf);
return -ENOENT; return -ENOENT;
} }
/* 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 to the same server. We may make this configurable later or
use ses->maxReq */ use ses->maxReq */
...@@ -450,23 +450,23 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -450,23 +450,23 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
return 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 and avoid races inside tcp sendmsg code that could cause corruption
of smb data */ of smb data */
down(&ses->server->tcpSem); down(&ses->server->tcpSem);
rc = allocate_mid(ses, in_buf, &midQ); rc = allocate_mid(ses, in_buf, &midQ);
if (rc) { if (rc) {
up(&ses->server->tcpSem); up(&ses->server->tcpSem);
cifs_small_buf_release(in_buf); cifs_small_buf_release(in_buf);
/* Update # of requests on wire to server */ /* Update # of requests on wire to server */
atomic_dec(&ses->server->inFlight); atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q); wake_up(&ses->server->request_q);
return rc; 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; midQ->midState = MID_REQUEST_SUBMITTED;
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
...@@ -482,7 +482,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -482,7 +482,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
up(&ses->server->tcpSem); up(&ses->server->tcpSem);
cifs_small_buf_release(in_buf); cifs_small_buf_release(in_buf);
if(rc < 0) if (rc < 0)
goto out; goto out;
if (long_op == -1) if (long_op == -1)
...@@ -490,18 +490,18 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -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 */ else if (long_op == 2) /* writes past end of file can take loong time */
timeout = 180 * HZ; timeout = 180 * HZ;
else if (long_op == 1) 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) */ servers oplock break timeout (about 43 seconds) */
else else
timeout = 15 * HZ; 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 */ due to last connection to this server being unmounted */
if (signal_pending(current)) { if (signal_pending(current)) {
/* if signal pending do not hold up user for full smb timeout /* if signal pending do not hold up user for full smb timeout
but we still give response a chance to complete */ but we still give response a chance to complete */
timeout = 2 * HZ; timeout = 2 * HZ;
} }
/* No user interrupts in wait - wreaks havoc with performance */ /* No user interrupts in wait - wreaks havoc with performance */
wait_for_response(ses, midQ, timeout, 10 * HZ); wait_for_response(ses, midQ, timeout, 10 * HZ);
...@@ -511,10 +511,10 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -511,10 +511,10 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
receive_len = midQ->resp_buf->smb_buf_length; receive_len = midQ->resp_buf->smb_buf_length;
} else { } else {
cERROR(1,("No response to cmd %d mid %d", cERROR(1, ("No response to cmd %d mid %d",
midQ->command, midQ->mid)); midQ->command, midQ->mid));
if(midQ->midState == MID_REQUEST_SUBMITTED) { if (midQ->midState == MID_REQUEST_SUBMITTED) {
if(ses->server->tcpStatus == CifsExiting) if (ses->server->tcpStatus == CifsExiting)
rc = -EHOSTDOWN; rc = -EHOSTDOWN;
else { else {
ses->server->tcpStatus = CifsNeedReconnect; ses->server->tcpStatus = CifsNeedReconnect;
...@@ -523,9 +523,9 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -523,9 +523,9 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
} }
if (rc != -EHOSTDOWN) { if (rc != -EHOSTDOWN) {
if(midQ->midState == MID_RETRY_NEEDED) { if (midQ->midState == MID_RETRY_NEEDED) {
rc = -EAGAIN; rc = -EAGAIN;
cFYI(1,("marking request for retry")); cFYI(1, ("marking request for retry"));
} else { } else {
rc = -EIO; rc = -EIO;
} }
...@@ -533,21 +533,21 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -533,21 +533,21 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
DeleteMidQEntry(midQ); DeleteMidQEntry(midQ);
/* Update # of requests on wire to server */ /* Update # of requests on wire to server */
atomic_dec(&ses->server->inFlight); atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q); wake_up(&ses->server->request_q);
return rc; return rc;
} }
if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
cERROR(1, ("Frame too large received. Length: %d Xid: %d", cERROR(1, ("Frame too large received. Length: %d Xid: %d",
receive_len, xid)); receive_len, xid));
rc = -EIO; rc = -EIO;
} else { /* rcvd frame is ok */ } else { /* rcvd frame is ok */
if (midQ->resp_buf && if (midQ->resp_buf &&
(midQ->midState == MID_RESPONSE_RECEIVED)) { (midQ->midState == MID_RESPONSE_RECEIVED)) {
iov[0].iov_base = (char *)midQ->resp_buf; iov[0].iov_base = (char *)midQ->resp_buf;
if(midQ->largeBuf) if (midQ->largeBuf)
*pRespBufType = CIFS_LARGE_BUFFER; *pRespBufType = CIFS_LARGE_BUFFER;
else else
*pRespBufType = CIFS_SMALL_BUFFER; *pRespBufType = CIFS_SMALL_BUFFER;
...@@ -555,14 +555,14 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -555,14 +555,14 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
dump_smb(midQ->resp_buf, 80); dump_smb(midQ->resp_buf, 80);
/* convert the length into a more usable form */ /* convert the length into a more usable form */
if((receive_len > 24) && if ((receive_len > 24) &&
(ses->server->secMode & (SECMODE_SIGN_REQUIRED | (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
SECMODE_SIGN_ENABLED))) { SECMODE_SIGN_ENABLED))) {
rc = cifs_verify_signature(midQ->resp_buf, rc = cifs_verify_signature(midQ->resp_buf,
ses->server->mac_signing_key, &ses->server->mac_signing_key,
midQ->sequence_number+1); midQ->sequence_number+1);
if(rc) { if (rc) {
cERROR(1,("Unexpected SMB signature")); cERROR(1, ("Unexpected SMB signature"));
/* BB FIXME add code to kill session */ /* BB FIXME add code to kill session */
} }
} }
...@@ -576,19 +576,19 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -576,19 +576,19 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
sizeof (struct smb_hdr) - sizeof (struct smb_hdr) -
4 /* do not count RFC1001 header */ + 4 /* do not count RFC1001 header */ +
(2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
BCC(midQ->resp_buf) = BCC(midQ->resp_buf) =
le16_to_cpu(BCC_LE(midQ->resp_buf)); le16_to_cpu(BCC_LE(midQ->resp_buf));
midQ->resp_buf = NULL; /* mark it so will not be freed midQ->resp_buf = NULL; /* mark it so will not be freed
by DeleteMidQEntry */ by DeleteMidQEntry */
} else { } else {
rc = -EIO; rc = -EIO;
cFYI(1,("Bad MID state?")); cFYI(1, ("Bad MID state?"));
} }
} }
out: out:
DeleteMidQEntry(midQ); DeleteMidQEntry(midQ);
atomic_dec(&ses->server->inFlight); atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q); wake_up(&ses->server->request_q);
return rc; return rc;
...@@ -605,18 +605,18 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -605,18 +605,18 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
struct mid_q_entry *midQ; struct mid_q_entry *midQ;
if (ses == NULL) { if (ses == NULL) {
cERROR(1,("Null smb session")); cERROR(1, ("Null smb session"));
return -EIO; return -EIO;
} }
if(ses->server == NULL) { if (ses->server == NULL) {
cERROR(1,("Null tcp session")); cERROR(1, ("Null tcp session"));
return -EIO; return -EIO;
} }
if(ses->server->tcpStatus == CifsExiting) if (ses->server->tcpStatus == CifsExiting)
return -ENOENT; return -ENOENT;
/* Ensure that we do not send more than 50 overlapping requests /* Ensure that we do not send more than 50 overlapping requests
to the same server. We may make this configurable later or to the same server. We may make this configurable later or
use ses->maxReq */ use ses->maxReq */
...@@ -624,17 +624,17 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -624,17 +624,17 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
if (rc) if (rc)
return 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 and avoid races inside tcp sendmsg code that could cause corruption
of smb data */ of smb data */
down(&ses->server->tcpSem); down(&ses->server->tcpSem);
rc = allocate_mid(ses, in_buf, &midQ); rc = allocate_mid(ses, in_buf, &midQ);
if (rc) { if (rc) {
up(&ses->server->tcpSem); up(&ses->server->tcpSem);
/* Update # of requests on wire to server */ /* Update # of requests on wire to server */
atomic_dec(&ses->server->inFlight); atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q); wake_up(&ses->server->request_q);
return rc; return rc;
} }
...@@ -645,7 +645,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -645,7 +645,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
DeleteMidQEntry(midQ); DeleteMidQEntry(midQ);
up(&ses->server->tcpSem); up(&ses->server->tcpSem);
/* Update # of requests on wire to server */ /* Update # of requests on wire to server */
atomic_dec(&ses->server->inFlight); atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q); wake_up(&ses->server->request_q);
return -EIO; return -EIO;
} }
...@@ -664,7 +664,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -664,7 +664,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
#endif #endif
up(&ses->server->tcpSem); up(&ses->server->tcpSem);
if(rc < 0) if (rc < 0)
goto out; goto out;
if (long_op == -1) if (long_op == -1)
...@@ -672,17 +672,17 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -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 */ else if (long_op == 2) /* writes past end of file can take loong time */
timeout = 180 * HZ; timeout = 180 * HZ;
else if (long_op == 1) 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) */ servers oplock break timeout (about 43 seconds) */
else else
timeout = 15 * HZ; 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 */ due to last connection to this server being unmounted */
if (signal_pending(current)) { if (signal_pending(current)) {
/* if signal pending do not hold up user for full smb timeout /* if signal pending do not hold up user for full smb timeout
but we still give response a chance to complete */ but we still give response a chance to complete */
timeout = 2 * HZ; timeout = 2 * HZ;
} }
/* No user interrupts in wait - wreaks havoc with performance */ /* No user interrupts in wait - wreaks havoc with performance */
wait_for_response(ses, midQ, timeout, 10 * HZ); wait_for_response(ses, midQ, timeout, 10 * HZ);
...@@ -692,10 +692,10 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -692,10 +692,10 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
receive_len = midQ->resp_buf->smb_buf_length; receive_len = midQ->resp_buf->smb_buf_length;
} else { } else {
cERROR(1,("No response for cmd %d mid %d", cERROR(1, ("No response for cmd %d mid %d",
midQ->command, midQ->mid)); midQ->command, midQ->mid));
if(midQ->midState == MID_REQUEST_SUBMITTED) { if (midQ->midState == MID_REQUEST_SUBMITTED) {
if(ses->server->tcpStatus == CifsExiting) if (ses->server->tcpStatus == CifsExiting)
rc = -EHOSTDOWN; rc = -EHOSTDOWN;
else { else {
ses->server->tcpStatus = CifsNeedReconnect; ses->server->tcpStatus = CifsNeedReconnect;
...@@ -704,9 +704,9 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -704,9 +704,9 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
} }
if (rc != -EHOSTDOWN) { if (rc != -EHOSTDOWN) {
if(midQ->midState == MID_RETRY_NEEDED) { if (midQ->midState == MID_RETRY_NEEDED) {
rc = -EAGAIN; rc = -EAGAIN;
cFYI(1,("marking request for retry")); cFYI(1, ("marking request for retry"));
} else { } else {
rc = -EIO; rc = -EIO;
} }
...@@ -714,11 +714,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -714,11 +714,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
DeleteMidQEntry(midQ); DeleteMidQEntry(midQ);
/* Update # of requests on wire to server */ /* Update # of requests on wire to server */
atomic_dec(&ses->server->inFlight); atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q); wake_up(&ses->server->request_q);
return rc; return rc;
} }
if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
cERROR(1, ("Frame too large received. Length: %d Xid: %d", cERROR(1, ("Frame too large received. Length: %d Xid: %d",
receive_len, xid)); receive_len, xid));
...@@ -734,14 +734,14 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -734,14 +734,14 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
dump_smb(out_buf, 92); dump_smb(out_buf, 92);
/* convert the length into a more usable form */ /* convert the length into a more usable form */
if((receive_len > 24) && if ((receive_len > 24) &&
(ses->server->secMode & (SECMODE_SIGN_REQUIRED | (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
SECMODE_SIGN_ENABLED))) { SECMODE_SIGN_ENABLED))) {
rc = cifs_verify_signature(out_buf, rc = cifs_verify_signature(out_buf,
ses->server->mac_signing_key, &ses->server->mac_signing_key,
midQ->sequence_number+1); midQ->sequence_number+1);
if(rc) { if (rc) {
cERROR(1,("Unexpected SMB signature")); cERROR(1, ("Unexpected SMB signature"));
/* BB FIXME add code to kill session */ /* BB FIXME add code to kill session */
} }
} }
...@@ -759,13 +759,13 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -759,13 +759,13 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
} else { } else {
rc = -EIO; rc = -EIO;
cERROR(1,("Bad MID state?")); cERROR(1, ("Bad MID state?"));
} }
} }
out: out:
DeleteMidQEntry(midQ); DeleteMidQEntry(midQ);
atomic_dec(&ses->server->inFlight); atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q); wake_up(&ses->server->request_q);
return rc; return rc;
...@@ -783,7 +783,7 @@ send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf, ...@@ -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); header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
in_buf->Mid = mid; in_buf->Mid = mid;
down(&ses->server->tcpSem); down(&ses->server->tcpSem);
rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
if (rc) { if (rc) {
up(&ses->server->tcpSem); up(&ses->server->tcpSem);
...@@ -832,20 +832,20 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, ...@@ -832,20 +832,20 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
struct cifsSesInfo *ses; struct cifsSesInfo *ses;
if (tcon == NULL || tcon->ses == NULL) { if (tcon == NULL || tcon->ses == NULL) {
cERROR(1,("Null smb session")); cERROR(1, ("Null smb session"));
return -EIO; return -EIO;
} }
ses = tcon->ses; ses = tcon->ses;
if(ses->server == NULL) { if (ses->server == NULL) {
cERROR(1,("Null tcp session")); cERROR(1, ("Null tcp session"));
return -EIO; return -EIO;
} }
if(ses->server->tcpStatus == CifsExiting) if (ses->server->tcpStatus == CifsExiting)
return -ENOENT; return -ENOENT;
/* Ensure that we do not send more than 50 overlapping requests /* Ensure that we do not send more than 50 overlapping requests
to the same server. We may make this configurable later or to the same server. We may make this configurable later or
use ses->maxReq */ use ses->maxReq */
...@@ -853,11 +853,11 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, ...@@ -853,11 +853,11 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
if (rc) if (rc)
return 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 and avoid races inside tcp sendmsg code that could cause corruption
of smb data */ of smb data */
down(&ses->server->tcpSem); down(&ses->server->tcpSem);
rc = allocate_mid(ses, in_buf, &midQ); rc = allocate_mid(ses, in_buf, &midQ);
if (rc) { if (rc) {
...@@ -887,14 +887,14 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, ...@@ -887,14 +887,14 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
#endif #endif
up(&ses->server->tcpSem); up(&ses->server->tcpSem);
if(rc < 0) { if (rc < 0) {
DeleteMidQEntry(midQ); DeleteMidQEntry(midQ);
return rc; return rc;
} }
/* Wait for a reply - allow signals to interrupt. */ /* Wait for a reply - allow signals to interrupt. */
rc = wait_event_interruptible(ses->server->response_q, 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 != CifsGood) &&
(ses->server->tcpStatus != CifsNew))); (ses->server->tcpStatus != CifsNew)));
...@@ -928,7 +928,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, ...@@ -928,7 +928,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
} }
/* Wait 5 seconds for the response. */ /* Wait 5 seconds for the response. */
if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ)==0) { if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
/* We got the response - restart system call. */ /* We got the response - restart system call. */
rstart = 1; rstart = 1;
} }
...@@ -939,10 +939,10 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, ...@@ -939,10 +939,10 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
receive_len = midQ->resp_buf->smb_buf_length; receive_len = midQ->resp_buf->smb_buf_length;
} else { } else {
cERROR(1,("No response for cmd %d mid %d", cERROR(1, ("No response for cmd %d mid %d",
midQ->command, midQ->mid)); midQ->command, midQ->mid));
if(midQ->midState == MID_REQUEST_SUBMITTED) { if (midQ->midState == MID_REQUEST_SUBMITTED) {
if(ses->server->tcpStatus == CifsExiting) if (ses->server->tcpStatus == CifsExiting)
rc = -EHOSTDOWN; rc = -EHOSTDOWN;
else { else {
ses->server->tcpStatus = CifsNeedReconnect; ses->server->tcpStatus = CifsNeedReconnect;
...@@ -951,9 +951,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, ...@@ -951,9 +951,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
} }
if (rc != -EHOSTDOWN) { if (rc != -EHOSTDOWN) {
if(midQ->midState == MID_RETRY_NEEDED) { if (midQ->midState == MID_RETRY_NEEDED) {
rc = -EAGAIN; rc = -EAGAIN;
cFYI(1,("marking request for retry")); cFYI(1, ("marking request for retry"));
} else { } else {
rc = -EIO; rc = -EIO;
} }
...@@ -962,7 +962,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, ...@@ -962,7 +962,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
DeleteMidQEntry(midQ); DeleteMidQEntry(midQ);
return rc; return rc;
} }
if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
cERROR(1, ("Frame too large received. Length: %d Xid: %d", cERROR(1, ("Frame too large received. Length: %d Xid: %d",
receive_len, xid)); receive_len, xid));
...@@ -978,14 +978,14 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, ...@@ -978,14 +978,14 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
dump_smb(out_buf, 92); dump_smb(out_buf, 92);
/* convert the length into a more usable form */ /* convert the length into a more usable form */
if((receive_len > 24) && if ((receive_len > 24) &&
(ses->server->secMode & (SECMODE_SIGN_REQUIRED | (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
SECMODE_SIGN_ENABLED))) { SECMODE_SIGN_ENABLED))) {
rc = cifs_verify_signature(out_buf, rc = cifs_verify_signature(out_buf,
ses->server->mac_signing_key, &ses->server->mac_signing_key,
midQ->sequence_number+1); midQ->sequence_number+1);
if(rc) { if (rc) {
cERROR(1,("Unexpected SMB signature")); cERROR(1, ("Unexpected SMB signature"));
/* BB FIXME add code to kill session */ /* BB FIXME add code to kill session */
} }
} }
...@@ -1003,7 +1003,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, ...@@ -1003,7 +1003,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
} else { } else {
rc = -EIO; rc = -EIO;
cERROR(1,("Bad MID state?")); cERROR(1, ("Bad MID state?"));
} }
} }
DeleteMidQEntry(midQ); DeleteMidQEntry(midQ);
......
/* /*
* fs/cifs/xattr.c * fs/cifs/xattr.c
* *
* Copyright (c) International Business Machines Corp., 2003 * Copyright (c) International Business Machines Corp., 2003, 2007
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -37,50 +37,52 @@ ...@@ -37,50 +37,52 @@
#define XATTR_TRUSTED_PREFIX_LEN 8 #define XATTR_TRUSTED_PREFIX_LEN 8
#define XATTR_SECURITY_PREFIX_LEN 9 #define XATTR_SECURITY_PREFIX_LEN 9
/* BB need to add server (Samba e.g) support for security and trusted prefix */ /* 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; int rc = -EOPNOTSUPP;
#ifdef CONFIG_CIFS_XATTR #ifdef CONFIG_CIFS_XATTR
int xid; int xid;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct super_block * sb; struct super_block *sb;
char * full_path; char *full_path;
if(direntry == NULL) if (direntry == NULL)
return -EIO; return -EIO;
if(direntry->d_inode == NULL) if (direntry->d_inode == NULL)
return -EIO; return -EIO;
sb = direntry->d_inode->i_sb; sb = direntry->d_inode->i_sb;
if(sb == NULL) if (sb == NULL)
return -EIO; return -EIO;
xid = GetXid(); xid = GetXid();
cifs_sb = CIFS_SB(sb); cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) { if (full_path == NULL) {
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return -ENOMEM;
} }
if(ea_name == NULL) { if (ea_name == NULL) {
cFYI(1,("Null xattr names not supported")); cFYI(1, ("Null xattr names not supported"));
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5)
&& (strncmp(ea_name,CIFS_XATTR_OS2_PREFIX,4))) { && (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4))) {
cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name)); cFYI(1,
("illegal xattr request %s (only user namespace supported)",
ea_name));
/* BB what if no namespace prefix? */ /* BB what if no namespace prefix? */
/* Should we just pass them to server, except for /* Should we just pass them to server, except for
system and perhaps security prefixes? */ system and perhaps security prefixes? */
} else { } else {
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
goto remove_ea_exit; goto remove_ea_exit;
ea_name+=5; /* skip past user. prefix */ ea_name += 5; /* skip past user. prefix */
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL, rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL,
(__u16)0, cifs_sb->local_nls, (__u16)0, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
} }
...@@ -91,23 +93,23 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name) ...@@ -91,23 +93,23 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name)
return rc; return rc;
} }
int cifs_setxattr(struct dentry * direntry, const char * ea_name, int cifs_setxattr(struct dentry *direntry, const char *ea_name,
const void * ea_value, size_t value_size, int flags) const void *ea_value, size_t value_size, int flags)
{ {
int rc = -EOPNOTSUPP; int rc = -EOPNOTSUPP;
#ifdef CONFIG_CIFS_XATTR #ifdef CONFIG_CIFS_XATTR
int xid; int xid;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct super_block * sb; struct super_block *sb;
char * full_path; char *full_path;
if(direntry == NULL) if (direntry == NULL)
return -EIO; return -EIO;
if(direntry->d_inode == NULL) if (direntry->d_inode == NULL)
return -EIO; return -EIO;
sb = direntry->d_inode->i_sb; sb = direntry->d_inode->i_sb;
if(sb == NULL) if (sb == NULL)
return -EIO; return -EIO;
xid = GetXid(); xid = GetXid();
...@@ -115,7 +117,7 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name, ...@@ -115,7 +117,7 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) { if (full_path == NULL) {
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return -ENOMEM;
} }
...@@ -123,67 +125,69 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name, ...@@ -123,67 +125,69 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
/* return alt name if available as pseudo attr */ /* return alt name if available as pseudo attr */
/* if proc/fs/cifs/streamstoxattr is set then /* if proc/fs/cifs/streamstoxattr is set then
search server for EAs or streams to search server for EAs or streams to
returns as xattrs */ returns as xattrs */
if(value_size > MAX_EA_VALUE_SIZE) { if (value_size > MAX_EA_VALUE_SIZE) {
cFYI(1,("size of EA value too large")); cFYI(1, ("size of EA value too large"));
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if(ea_name == NULL) { if (ea_name == NULL) {
cFYI(1,("Null xattr names not supported")); cFYI(1, ("Null xattr names not supported"));
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) { } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) {
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
goto set_ea_exit; goto set_ea_exit;
if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) { if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) {
cFYI(1,("attempt to set cifs inode metadata")); cFYI(1, ("attempt to set cifs inode metadata"));
} }
ea_name += 5; /* skip past user. prefix */ ea_name += 5; /* skip past user. prefix */
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value, rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
(__u16)value_size, cifs_sb->local_nls, (__u16)value_size, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) { } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) {
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
goto set_ea_exit; goto set_ea_exit;
ea_name += 4; /* skip past os2. prefix */ ea_name += 4; /* skip past os2. prefix */
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value, rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
(__u16)value_size, cifs_sb->local_nls, (__u16)value_size, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
} else { } else {
int temp; int temp;
temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS, temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
strlen(POSIX_ACL_XATTR_ACCESS)); strlen(POSIX_ACL_XATTR_ACCESS));
if (temp == 0) { if (temp == 0) {
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
if(sb->s_flags & MS_POSIXACL) if (sb->s_flags & MS_POSIXACL)
rc = CIFSSMBSetPosixACL(xid, pTcon,full_path, rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
ea_value, (const int)value_size, ea_value, (const int)value_size,
ACL_TYPE_ACCESS,cifs_sb->local_nls, ACL_TYPE_ACCESS, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
cFYI(1,("set POSIX ACL rc %d",rc)); cFYI(1, ("set POSIX ACL rc %d", rc));
#else #else
cFYI(1,("set POSIX ACL not supported")); cFYI(1, ("set POSIX ACL not supported"));
#endif #endif
} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
if(sb->s_flags & MS_POSIXACL) if (sb->s_flags & MS_POSIXACL)
rc = CIFSSMBSetPosixACL(xid, pTcon,full_path, rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
ea_value, (const int)value_size, ea_value, (const int)value_size,
ACL_TYPE_DEFAULT, cifs_sb->local_nls, ACL_TYPE_DEFAULT, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
cFYI(1,("set POSIX default ACL rc %d",rc)); cFYI(1, ("set POSIX default ACL rc %d", rc));
#else #else
cFYI(1,("set default POSIX ACL not supported")); cFYI(1, ("set default POSIX ACL not supported"));
#endif #endif
} else { } else {
cFYI(1,("illegal xattr request %s (only user namespace supported)",ea_name)); cFYI(1, ("illegal xattr request %s (only user namespace"
" supported)", ea_name));
/* BB what if no namespace prefix? */ /* BB what if no namespace prefix? */
/* Should we just pass them to server, except for /* Should we just pass them to server, except for
system and perhaps security prefixes? */ system and perhaps security prefixes? */
} }
} }
...@@ -195,23 +199,23 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name, ...@@ -195,23 +199,23 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
return rc; return rc;
} }
ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
void * ea_value, size_t buf_size) void *ea_value, size_t buf_size)
{ {
ssize_t rc = -EOPNOTSUPP; ssize_t rc = -EOPNOTSUPP;
#ifdef CONFIG_CIFS_XATTR #ifdef CONFIG_CIFS_XATTR
int xid; int xid;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct super_block * sb; struct super_block *sb;
char * full_path; char *full_path;
if(direntry == NULL) if (direntry == NULL)
return -EIO; return -EIO;
if(direntry->d_inode == NULL) if (direntry->d_inode == NULL)
return -EIO; return -EIO;
sb = direntry->d_inode->i_sb; sb = direntry->d_inode->i_sb;
if(sb == NULL) if (sb == NULL)
return -EIO; return -EIO;
xid = GetXid(); xid = GetXid();
...@@ -220,42 +224,42 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, ...@@ -220,42 +224,42 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) { if (full_path == NULL) {
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return -ENOMEM;
} }
/* return dos attributes as pseudo xattr */ /* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */ /* return alt name if available as pseudo attr */
if(ea_name == NULL) { if (ea_name == NULL) {
cFYI(1,("Null xattr names not supported")); cFYI(1, ("Null xattr names not supported"));
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) { } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) {
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
goto get_ea_exit; goto get_ea_exit;
if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) { if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) {
cFYI(1,("attempt to query cifs inode metadata")); cFYI(1, ("attempt to query cifs inode metadata"));
/* revalidate/getattr then populate from inode */ /* revalidate/getattr then populate from inode */
} /* BB add else when above is implemented */ } /* BB add else when above is implemented */
ea_name += 5; /* skip past user. prefix */ ea_name += 5; /* skip past user. prefix */
rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, rc = CIFSSMBQueryEA(xid, pTcon, full_path, ea_name, ea_value,
buf_size, cifs_sb->local_nls, buf_size, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) { } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) {
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
goto get_ea_exit; goto get_ea_exit;
ea_name += 4; /* skip past os2. prefix */ ea_name += 4; /* skip past os2. prefix */
rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, rc = CIFSSMBQueryEA(xid, pTcon, full_path, ea_name, ea_value,
buf_size, cifs_sb->local_nls, buf_size, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
} else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS, } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
if(sb->s_flags & MS_POSIXACL) if (sb->s_flags & MS_POSIXACL)
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
ea_value, buf_size, ACL_TYPE_ACCESS, ea_value, buf_size, ACL_TYPE_ACCESS,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
/* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { /* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
__u16 fid; __u16 fid;
...@@ -272,39 +276,40 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, ...@@ -272,39 +276,40 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
CIFSSMBClose(xid, pTcon, fid); CIFSSMBClose(xid, pTcon, fid);
} }
} */ /* BB enable after fixing up return data */ } */ /* BB enable after fixing up return data */
#else
#else cFYI(1, ("query POSIX ACL not supported yet"));
cFYI(1,("query POSIX ACL not supported yet"));
#endif /* CONFIG_CIFS_POSIX */ #endif /* CONFIG_CIFS_POSIX */
} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT, } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
if(sb->s_flags & MS_POSIXACL) if (sb->s_flags & MS_POSIXACL)
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
ea_value, buf_size, ACL_TYPE_DEFAULT, ea_value, buf_size, ACL_TYPE_DEFAULT,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
#else #else
cFYI(1,("query POSIX default ACL not supported yet")); cFYI(1, ("query POSIX default ACL not supported yet"));
#endif #endif
} else if(strncmp(ea_name, } else if (strncmp(ea_name,
CIFS_XATTR_TRUSTED_PREFIX,XATTR_TRUSTED_PREFIX_LEN) == 0) { CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) {
cFYI(1,("Trusted xattr namespace not supported yet")); cFYI(1, ("Trusted xattr namespace not supported yet"));
} else if(strncmp(ea_name, } else if (strncmp(ea_name,
CIFS_XATTR_SECURITY_PREFIX,XATTR_SECURITY_PREFIX_LEN) == 0) { CIFS_XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) {
cFYI(1,("Security xattr namespace not supported yet")); cFYI(1, ("Security xattr namespace not supported yet"));
} else { } else {
cFYI(1,("illegal xattr name request %s (only user namespace supported)",ea_name)); cFYI(1,
("illegal xattr request %s (only user namespace supported)",
ea_name));
} }
/* We could add an additional check for streams ie /* We could add an additional check for streams ie
if proc/fs/cifs/streamstoxattr is set then if proc/fs/cifs/streamstoxattr is set then
search server for EAs or streams to search server for EAs or streams to
returns as xattrs */ returns as xattrs */
if(rc == -EINVAL) if (rc == -EINVAL)
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
get_ea_exit: get_ea_exit:
kfree(full_path); kfree(full_path);
...@@ -313,34 +318,34 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, ...@@ -313,34 +318,34 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
return rc; return rc;
} }
ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size) ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
{ {
ssize_t rc = -EOPNOTSUPP; ssize_t rc = -EOPNOTSUPP;
#ifdef CONFIG_CIFS_XATTR #ifdef CONFIG_CIFS_XATTR
int xid; int xid;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct super_block * sb; struct super_block *sb;
char * full_path; char *full_path;
if(direntry == NULL) if (direntry == NULL)
return -EIO; return -EIO;
if(direntry->d_inode == NULL) if (direntry->d_inode == NULL)
return -EIO; return -EIO;
sb = direntry->d_inode->i_sb; sb = direntry->d_inode->i_sb;
if(sb == NULL) if (sb == NULL)
return -EIO; return -EIO;
cifs_sb = CIFS_SB(sb); cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
return -EOPNOTSUPP; return -EOPNOTSUPP;
xid = GetXid(); xid = GetXid();
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) { if (full_path == NULL) {
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return -ENOMEM;
} }
...@@ -348,11 +353,11 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size) ...@@ -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 */ /* return alt name if available as pseudo attr */
/* if proc/fs/cifs/streamstoxattr is set then /* if proc/fs/cifs/streamstoxattr is set then
search server for EAs or streams to search server for EAs or streams to
returns as xattrs */ returns as xattrs */
rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size, rc = CIFSSMBQAllEAs(xid, pTcon, full_path, data, buf_size,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
kfree(full_path); kfree(full_path);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment