aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/AUTHORS24
-rw-r--r--fs/cifs/CHANGES39
-rw-r--r--fs/cifs/README49
-rw-r--r--fs/cifs/TODO30
-rw-r--r--fs/cifs/cifs_debug.c43
-rw-r--r--fs/cifs/cifs_fs_sb.h1
-rw-r--r--fs/cifs/cifs_unicode.c4
-rw-r--r--fs/cifs/cifsencrypt.c16
-rw-r--r--fs/cifs/cifsfs.c34
-rw-r--r--fs/cifs/cifsfs.h8
-rw-r--r--fs/cifs/cifsglob.h18
-rw-r--r--fs/cifs/cifspdu.h71
-rw-r--r--fs/cifs/cifsproto.h109
-rw-r--r--fs/cifs/cifssmb.c436
-rw-r--r--fs/cifs/connect.c743
-rw-r--r--fs/cifs/dir.c189
-rw-r--r--fs/cifs/fcntl.c3
-rw-r--r--fs/cifs/file.c15
-rw-r--r--fs/cifs/inode.c106
-rw-r--r--fs/cifs/ioctl.c75
-rw-r--r--fs/cifs/link.c18
-rw-r--r--fs/cifs/misc.c160
-rw-r--r--fs/cifs/netmisc.c5
-rw-r--r--fs/cifs/readdir.c120
-rw-r--r--fs/cifs/smberr.h231
-rw-r--r--fs/cifs/transport.c54
-rw-r--r--fs/cifs/xattr.c51
27 files changed, 1788 insertions, 864 deletions
diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS
index acce36e25d2e..72fdc10dfdd7 100644
--- a/fs/cifs/AUTHORS
+++ b/fs/cifs/AUTHORS
@@ -4,13 +4,16 @@ Steve French (sfrench@samba.org)
4 4
5The author wishes to express his appreciation and thanks to: 5The author wishes to express his appreciation and thanks to:
6Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS 6Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS
7improvements. Thanks to IBM for allowing me the time and test resources to pursue 7improvements. Thanks to IBM for allowing me time and test resources to pursue
8this project. Jim McDonough from IBM (and the Samba Team) for his help. 8this project, to Jim McDonough from IBM (and the Samba Team) for his help, to
9The IBM Linux JFS team for explaining many esoteric Linux filesystem features. 9the IBM Linux JFS team for explaining many esoteric Linux filesystem features.
10Jeremy Allison of the Samba team has done invaluable work in adding the server
11side of the original CIFS Unix extensions and reviewing and implementing
12portions of the newer CIFS POSIX extensions into the Samba 3 file server. Thank
10Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client) 13Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client)
11for proving years ago that a very good smb/cifs client could be done on a Unix like 14for proving years ago that very good smb/cifs clients could be done on Unix-like
12operating system. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin 15operating systems. Volker Lendecke, Andrew Tridgell, Urban Widmark, John
13and others for their work on the Linux smbfs module over the years. Thanks to 16Newbigin and others for their work on the Linux smbfs module. Thanks to
14the other members of the Storage Network Industry Association CIFS Technical 17the other members of the Storage Network Industry Association CIFS Technical
15Workgroup for their work specifying this highly complex protocol and finally 18Workgroup for their work specifying this highly complex protocol and finally
16thanks to the Samba team for their technical advice and encouragement. 19thanks to the Samba team for their technical advice and encouragement.
@@ -24,9 +27,11 @@ Shobhit Dayal
24Sergey Vlasov 27Sergey Vlasov
25Richard Hughes 28Richard Hughes
26Yury Umanets 29Yury Umanets
27Mark Hamzy 30Mark Hamzy (for some of the early cifs IPv6 work)
28Domen Puncer 31Domen Puncer
29Jesper Juhl 32Jesper Juhl (in particular for lots of whitespace/formatting cleanup)
33Vince Negri and Dave Stahl (for finding an important caching bug)
34Adrian Bunk (kcalloc cleanups)
30 35
31Test case and Bug Report contributors 36Test case and Bug Report contributors
32------------------------------------- 37-------------------------------------
@@ -36,7 +41,8 @@ Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
36Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen, 41Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
37Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special 42Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special
38mention to the Stanford Checker (SWAT) which pointed out many minor 43mention to the Stanford Checker (SWAT) which pointed out many minor
39bugs in error paths. 44bugs in error paths. Valuable suggestions also have come from Al Viro
45and Dave Miller.
40 46
41And thanks to the IBM LTC and Power test teams and SuSE testers for 47And thanks to the IBM LTC and Power test teams and SuSE testers for
42finding multiple bugs during excellent stress test runs. 48finding multiple bugs during excellent stress test runs.
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 5316c8dd6bff..95483baab706 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,7 +1,44 @@
1Version 1.31 1Version 1.34
2------------
3Fix error mapping of the TOO_MANY_LINKS (hardlinks) case.
4Do not oops if root user kills cifs oplock kernel thread or
5kills the cifsd thread (NB: killing the cifs kernel threads is not
6recommended, unmount and rmmod cifs will kill them when they are
7no longer needed). Fix readdir to ASCII servers (ie older servers
8which do not support Unicode) and also require asterik.
9
10
11Version 1.33
12------------
13Fix caching problem, in which readdir of directory containing a file
14which was cached could cause the file's time stamp to be updated
15without invalidating the readahead data (so we could get stale
16file data on the client for that file even as the server copy changed).
17Cleanup response processing so cifsd can not loop when abnormally
18terminated.
19
20
21Version 1.32
2------------ 22------------
3Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one 23Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one
4transact response for an SMB request and search entry split across two frames. 24transact response for an SMB request and search entry split across two frames.
25Add support for lsattr (getting ext2/ext3/reiserfs attr flags from the server)
26as new protocol extensions. Do not send Get/Set calls for POSIX ACLs
27unless server explicitly claims to support them in CIFS Unix extensions
28POSIX ACL capability bit. Fix packet signing when multiuser mounting with
29different users from the same client to the same server. Fix oops in
30cifs_close. Add mount option for remapping reserved characters in
31filenames (also allow recognizing files with created by SFU which have any
32of these seven reserved characters, except backslash, to be recognized).
33Fix invalid transact2 message (we were sometimes trying to interpret
34oplock breaks as SMB responses). Add ioctl for checking that the
35current uid matches the uid of the mounter (needed by umount.cifs).
36Reduce the number of large buffer allocations in cifs response processing
37(significantly reduces memory pressure under heavy stress with multiple
38processes accessing the same server at the same time).
39
40Version 1.31
41------------
5Fix updates of DOS attributes and time fields so that files on NT4 servers 42Fix updates of DOS attributes and time fields so that files on NT4 servers
6do not get marked delete on close. Display sizes of cifs buffer pools in 43do not get marked delete on close. Display sizes of cifs buffer pools in
7cifs stats. Fix oops in unmount when cifsd thread being killed by 44cifs stats. Fix oops in unmount when cifsd thread being killed by
diff --git a/fs/cifs/README b/fs/cifs/README
index 0f20edc935b5..e74df0c73256 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -32,9 +32,9 @@ the cifs download to your kernel build directory e.g.
326) make modules (or "make" if CIFS VFS not to be built as a module) 326) make modules (or "make" if CIFS VFS not to be built as a module)
33 33
34For Linux 2.6: 34For Linux 2.6:
351) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper 351) Download the kernel (e.g. from http://www.kernel.org)
36at bk://linux.bkbits.net/linux-2.5) and change directory into the top 36and change directory into the top of the kernel directory tree
37of the kernel directory tree (e.g. /usr/src/linux-2.5.73) 37(e.g. /usr/src/linux-2.5.73)
382) make menuconfig (or make xconfig) 382) make menuconfig (or make xconfig)
393) select cifs from within the network filesystem choices 393) select cifs from within the network filesystem choices
404) save and exit 404) save and exit
@@ -75,7 +75,7 @@ Allowing User Mounts
75==================== 75====================
76To permit users to mount and unmount over directories they own is possible 76To permit users to mount and unmount over directories they own is possible
77with the cifs vfs. A way to enable such mounting is to mark the mount.cifs 77with the cifs vfs. A way to enable such mounting is to mark the mount.cifs
78utility as suid (e.g. "chmod +s /sbin/mount/cifs). To enable users to 78utility as suid (e.g. "chmod +s /sbin/mount.cifs). To enable users to
79umount shares they mount requires 79umount shares they mount requires
801) mount.cifs version 1.4 or later 801) mount.cifs version 1.4 or later
812) an entry for the share in /etc/fstab indicating that a user may 812) an entry for the share in /etc/fstab indicating that a user may
@@ -97,6 +97,26 @@ mount.cifs with the following flag:
97There is a corresponding manual page for cifs mounting in the Samba 3.0 and 97There is a corresponding manual page for cifs mounting in the Samba 3.0 and
98later source tree in docs/manpages/mount.cifs.8 98later source tree in docs/manpages/mount.cifs.8
99 99
100Allowing User Unmounts
101======================
102To permit users to ummount directories that they have user mounted (see above),
103the utility umount.cifs may be used. It may be invoked directly, or if
104umount.cifs is placed in /sbin, umount can invoke the cifs umount helper
105(at least for most versions of the umount utility) for umount of cifs
106mounts, unless umount is invoked with -i (which will avoid invoking a umount
107helper). As with mount.cifs, to enable user unmounts umount.cifs must be marked
108as suid (e.g. "chmod +s /sbin/umount.cifs") or equivalent (some distributions
109allow adding entries to a file to the /etc/permissions file to achieve the
110equivalent suid effect). For this utility to succeed the target path
111must be a cifs mount, and the uid of the current user must match the uid
112of the user who mounted the resource.
113
114Also note that the customary way of allowing user mounts and unmounts is
115(instead of using mount.cifs and unmount.cifs as suid) to add a line
116to the file /etc/fstab for each //server/share you wish to mount, but
117this can become unwieldy when potential mount targets include many
118or unpredictable UNC names.
119
100Samba Considerations 120Samba Considerations
101==================== 121====================
102To get the maximum benefit from the CIFS VFS, we recommend using a server that 122To get the maximum benefit from the CIFS VFS, we recommend using a server that
@@ -376,6 +396,19 @@ A partial list of the supported mount options follows:
376 attributes) to the server (default) e.g. via setfattr 396 attributes) to the server (default) e.g. via setfattr
377 and getfattr utilities. 397 and getfattr utilities.
378 nouser_xattr Do not allow getfattr/setfattr to get/set xattrs 398 nouser_xattr Do not allow getfattr/setfattr to get/set xattrs
399 mapchars Translate six of the seven reserved characters (not backslash)
400 *?<>|:
401 to the remap range (above 0xF000), which also
402 allows the CIFS client to recognize files created with
403 such characters by Windows's POSIX emulation. This can
404 also be useful when mounting to most versions of Samba
405 (which also forbids creating and opening files
406 whose names contain any of these seven characters).
407 This has no effect if the server does not support
408 Unicode on the wire.
409 nomapchars Do not translate any of these seven characters (default).
410 remount remount the share (often used to change from ro to rw mounts
411 or vice versa)
379 412
380The mount.cifs mount helper also accepts a few mount options before -o 413The mount.cifs mount helper also accepts a few mount options before -o
381including: 414including:
@@ -392,7 +425,7 @@ Misc /proc/fs/cifs Flags and Debug Info
392======================================= 425=======================================
393Informational pseudo-files: 426Informational pseudo-files:
394DebugData Displays information about active CIFS sessions 427DebugData Displays information about active CIFS sessions
395 and shares. 428 and shares, as well as the cifs.ko version.
396Stats Lists summary resource usage information as well as per 429Stats Lists summary resource usage information as well as per
397 share statistics, if CONFIG_CIFS_STATS in enabled 430 share statistics, if CONFIG_CIFS_STATS in enabled
398 in the kernel configuration. 431 in the kernel configuration.
@@ -449,7 +482,7 @@ and for more extensive tracing including the start of smb requests and responses
449Two other experimental features are under development and to test 482Two other experimental features are under development and to test
450require enabling CONFIG_CIFS_EXPERIMENTAL 483require enabling CONFIG_CIFS_EXPERIMENTAL
451 484
452 More efficient write operations and SMB buffer handling 485 More efficient write operations
453 486
454 DNOTIFY fcntl: needed for support of directory change 487 DNOTIFY fcntl: needed for support of directory change
455 notification and perhaps later for file leases) 488 notification and perhaps later for file leases)
@@ -467,8 +500,8 @@ returned success.
467 500
468Also note that "cat /proc/fs/cifs/DebugData" will display information about 501Also note that "cat /proc/fs/cifs/DebugData" will display information about
469the active sessions and the shares that are mounted. Note: NTLMv2 enablement 502the active sessions and the shares that are mounted. Note: NTLMv2 enablement
470will not work since they its implementation is not quite complete yet. 503will not work since its implementation is not quite complete yet. Do not alter
471Do not alter these configuration values unless you are doing specific testing. 504the ExtendedSecurity configuration value unless you are doing specific testing.
472Enabling extended security works to Windows 2000 Workstations and XP but not to 505Enabling extended security works to Windows 2000 Workstations and XP but not to
473Windows 2000 server or Samba since it does not usually send "raw NTLMSSP" 506Windows 2000 server or Samba since it does not usually send "raw NTLMSSP"
474(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not 507(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not
diff --git a/fs/cifs/TODO b/fs/cifs/TODO
index f4e3e1f67ee4..8cc881694e29 100644
--- a/fs/cifs/TODO
+++ b/fs/cifs/TODO
@@ -1,4 +1,4 @@
1version 1.22 July 30, 2004 1version 1.34 April 29, 2005
2 2
3A Partial List of Missing Features 3A Partial List of Missing Features
4================================== 4==================================
@@ -14,7 +14,7 @@ b) Better pam/winbind integration (e.g. to handle uid mapping
14better) 14better)
15 15
16c) multi-user mounts - multiplexed sessionsetups over single vc 16c) multi-user mounts - multiplexed sessionsetups over single vc
17(ie tcp session) - prettying up needed, and more testing needed 17(ie tcp session) - more testing needed
18 18
19d) Kerberos/SPNEGO session setup support - (started) 19d) Kerberos/SPNEGO session setup support - (started)
20 20
@@ -67,12 +67,26 @@ q) implement support for security and trusted categories of xattrs
67 67
68r) Implement O_DIRECT flag on open (already supported on mount) 68r) Implement O_DIRECT flag on open (already supported on mount)
69 69
70KNOWN BUGS (updated December 10, 2004) 70s) Allow remapping of last remaining character (\) to +0xF000 which
71(this character is valid for POSIX but not for Windows)
72
73t) Create UID mapping facility so server UIDs can be mapped on a per
74mount or a per server basis to client UIDs or nobody if no mapping
75exists. This is helpful when Unix extensions are negotiated to
76allow better permission checking when UIDs differ on the server
77and client. Add new protocol request to the CIFS protocol
78standard for asking the server for the corresponding name of a
79particular uid.
80
81KNOWN BUGS (updated April 29, 2005)
71==================================== 82====================================
83See http://bugzilla.samba.org - search on product "CifsVFS" for
84current bug list.
85
721) existing symbolic links (Windows reparse points) are recognized but 861) existing symbolic links (Windows reparse points) are recognized but
73can not be created remotely. They are implemented for Samba and those that 87can not be created remotely. They are implemented for Samba and those that
74support the CIFS Unix extensions but Samba has a bug currently handling 88support the CIFS Unix extensions, although earlier versions of Samba
75symlink text beginning with slash 89overly restrict the pathnames.
762) follow_link and readdir code does not follow dfs junctions 902) follow_link and readdir code does not follow dfs junctions
77but recognizes them 91but recognizes them
783) create of new files to FAT partitions on Windows servers can 923) create of new files to FAT partitions on Windows servers can
@@ -98,7 +112,5 @@ there are some easy changes that can be done to parallelize sequential writes,
98and when signing is disabled to request larger read sizes (larger than 112and when signing is disabled to request larger read sizes (larger than
99negotiated size) and send larger write sizes to modern servers. 113negotiated size) and send larger write sizes to modern servers.
100 114
1014) More exhaustively test the recently added NT4 support against various 1154) More exhaustively test against less common servers. More testing
102NT4 service pack levels, and fix cifs_setattr for setting file times and 116against Windows 9x, Windows ME servers.
103size to fall back to level 1 when error invalid level returned.
104
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index db28b561cd4b..4061e43471c1 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs_debug.c 2 * fs/cifs_debug.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2000,2003 4 * Copyright (C) International Business Machines Corp., 2000,2005
5 * 5 *
6 * Modified by Steve French (sfrench@us.ibm.com) 6 * Modified by Steve French (sfrench@us.ibm.com)
7 * 7 *
@@ -29,6 +29,7 @@
29#include "cifsglob.h" 29#include "cifsglob.h"
30#include "cifsproto.h" 30#include "cifsproto.h"
31#include "cifs_debug.h" 31#include "cifs_debug.h"
32#include "cifsfs.h"
32 33
33void 34void
34cifs_dump_mem(char *label, void *data, int length) 35cifs_dump_mem(char *label, void *data, int length)
@@ -78,8 +79,9 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
78 "Display Internal CIFS Data Structures for Debugging\n" 79 "Display Internal CIFS Data Structures for Debugging\n"
79 "---------------------------------------------------\n"); 80 "---------------------------------------------------\n");
80 buf += length; 81 buf += length;
81 82 length = sprintf(buf,"CIFS Version %s\n",CIFS_VERSION);
82 length = sprintf(buf, "Servers:\n"); 83 buf += length;
84 length = sprintf(buf, "Servers:");
83 buf += length; 85 buf += length;
84 86
85 i = 0; 87 i = 0;
@@ -87,12 +89,21 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
87 list_for_each(tmp, &GlobalSMBSessionList) { 89 list_for_each(tmp, &GlobalSMBSessionList) {
88 i++; 90 i++;
89 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); 91 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
90 length = 92 if((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
91 sprintf(buf, 93 (ses->serverNOS == NULL)) {
92 "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\t", 94 buf += sprintf("\nentry for %s not fully displayed\n\t",
93 i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse), 95 ses->serverName);
94 ses->serverOS, ses->serverNOS, ses->capabilities,ses->status); 96
95 buf += length; 97 } else {
98 length =
99 sprintf(buf,
100 "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\t",
101 i, ses->serverName, ses->serverDomain,
102 atomic_read(&ses->inUse),
103 ses->serverOS, ses->serverNOS,
104 ses->capabilities,ses->status);
105 buf += length;
106 }
96 if(ses->server) { 107 if(ses->server) {
97 buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d", 108 buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d",
98 ses->server->tcpStatus, 109 ses->server->tcpStatus,
@@ -100,7 +111,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
100 ses->server->secMode, 111 ses->server->secMode,
101 atomic_read(&ses->server->inFlight)); 112 atomic_read(&ses->server->inFlight));
102 113
103 length = sprintf(buf, "\nMIDs: \n"); 114 length = sprintf(buf, "\nMIDs:\n");
104 buf += length; 115 buf += length;
105 116
106 spin_lock(&GlobalMid_Lock); 117 spin_lock(&GlobalMid_Lock);
@@ -109,7 +120,12 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
109 mid_q_entry, 120 mid_q_entry,
110 qhead); 121 qhead);
111 if(mid_entry) { 122 if(mid_entry) {
112 length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk,mid_entry->mid); 123 length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",
124 mid_entry->midState,
125 (int)mid_entry->command,
126 mid_entry->pid,
127 mid_entry->tsk,
128 mid_entry->mid);
113 buf += length; 129 buf += length;
114 } 130 }
115 } 131 }
@@ -121,7 +137,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
121 sprintf(buf, "\n"); 137 sprintf(buf, "\n");
122 buf++; 138 buf++;
123 139
124 length = sprintf(buf, "\nShares:\n"); 140 length = sprintf(buf, "Shares:");
125 buf += length; 141 buf += length;
126 142
127 i = 0; 143 i = 0;
@@ -200,7 +216,8 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
200 buf += item_length; 216 buf += item_length;
201 item_length = 217 item_length =
202 sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n", 218 sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n",
203 bufAllocCount.counter,cifs_min_rcv + tcpSesAllocCount.counter); 219 bufAllocCount.counter,
220 cifs_min_rcv + tcpSesAllocCount.counter);
204 length += item_length; 221 length += item_length;
205 buf += item_length; 222 buf += item_length;
206 item_length = 223 item_length =
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 77da902d8f32..ec00d61d5308 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -23,6 +23,7 @@
23#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */ 23#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */
24#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ 24#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
25#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ 25#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
26#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
26 27
27struct cifs_sb_info { 28struct cifs_sb_info {
28 struct cifsTconInfo *tcon; /* primary mount */ 29 struct cifsTconInfo *tcon; /* primary mount */
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index a17adf4cb9ba..99a096d3f84d 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -76,8 +76,8 @@ cifs_strtoUCS(wchar_t * to, const char *from, int len,
76 charlen)); 76 charlen));
77 to[i] = cpu_to_le16(0x003f); /* a question mark */ 77 to[i] = cpu_to_le16(0x003f); /* a question mark */
78 charlen = 1; 78 charlen = 1;
79 } 79 } else
80 to[i] = cpu_to_le16(to[i]); 80 to[i] = cpu_to_le16(to[i]);
81 81
82 } 82 }
83 83
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 78829e7d8cd0..1959c7c4b185 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -50,7 +50,7 @@ static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char
50 return 0; 50 return 0;
51} 51}
52 52
53int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses, 53int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
54 __u32 * pexpected_response_sequence_number) 54 __u32 * pexpected_response_sequence_number)
55{ 55{
56 int rc = 0; 56 int rc = 0;
@@ -59,21 +59,21 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
59 /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */ 59 /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
60 /* BB remember to add code to save expected sequence number in midQ entry BB */ 60 /* BB remember to add code to save expected sequence number in midQ entry BB */
61 61
62 if((cifs_pdu == NULL) || (ses == NULL)) 62 if((cifs_pdu == NULL) || (server == NULL))
63 return -EINVAL; 63 return -EINVAL;
64 64
65 if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) 65 if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
66 return rc; 66 return rc;
67 67
68 spin_lock(&GlobalMid_Lock); 68 spin_lock(&GlobalMid_Lock);
69 cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number); 69 cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(server->sequence_number);
70 cifs_pdu->Signature.Sequence.Reserved = 0; 70 cifs_pdu->Signature.Sequence.Reserved = 0;
71 71
72 *pexpected_response_sequence_number = ses->sequence_number++; 72 *pexpected_response_sequence_number = server->sequence_number++;
73 ses->sequence_number++; 73 server->sequence_number++;
74 spin_unlock(&GlobalMid_Lock); 74 spin_unlock(&GlobalMid_Lock);
75 75
76 rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature); 76 rc = cifs_calculate_signature(cifs_pdu, server->mac_signing_key,smb_signature);
77 if(rc) 77 if(rc)
78 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 78 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
79 else 79 else
@@ -190,7 +190,7 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
190 hmac_md5_update((const unsigned char *) unicode_buf, 190 hmac_md5_update((const unsigned char *) unicode_buf,
191 (user_name_len+dom_name_len)*2,&ctx); 191 (user_name_len+dom_name_len)*2,&ctx);
192 192
193 hmac_md5_final(ses->mac_signing_key,&ctx); 193 hmac_md5_final(ses->server->mac_signing_key,&ctx);
194 kfree(ucase_buf); 194 kfree(ucase_buf);
195 kfree(unicode_buf); 195 kfree(unicode_buf);
196 return 0; 196 return 0;
@@ -200,7 +200,7 @@ void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_respon
200 struct HMACMD5Context context; 200 struct HMACMD5Context context;
201 memcpy(v2_session_response + 8, ses->server->cryptKey,8); 201 memcpy(v2_session_response + 8, ses->server->cryptKey,8);
202 /* gen_blob(v2_session_response + 16); */ 202 /* gen_blob(v2_session_response + 16); */
203 hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context); 203 hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context);
204 204
205 hmac_md5_update(ses->server->cryptKey,8,&context); 205 hmac_md5_update(ses->server->cryptKey,8,&context);
206/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ 206/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 5082fce3c566..8cc23e7d0d5d 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -169,7 +169,8 @@ cifs_put_super(struct super_block *sb)
169static int 169static int
170cifs_statfs(struct super_block *sb, struct kstatfs *buf) 170cifs_statfs(struct super_block *sb, struct kstatfs *buf)
171{ 171{
172 int xid, rc = -EOPNOTSUPP; 172 int xid;
173 int rc = -EOPNOTSUPP;
173 struct cifs_sb_info *cifs_sb; 174 struct cifs_sb_info *cifs_sb;
174 struct cifsTconInfo *pTcon; 175 struct cifsTconInfo *pTcon;
175 176
@@ -181,31 +182,34 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf)
181 buf->f_type = CIFS_MAGIC_NUMBER; 182 buf->f_type = CIFS_MAGIC_NUMBER;
182 183
183 /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */ 184 /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
184 buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would presumably 185 buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would
185 be length of total path, note that some servers may be 186 presumably be total path, but note
186 able to support more than this, but best to be safe 187 that some servers (includinng Samba 3)
187 since Win2k and others can not handle very long filenames */ 188 have a shorter maximum path */
188 buf->f_files = 0; /* undefined */ 189 buf->f_files = 0; /* undefined */
189 buf->f_ffree = 0; /* unlimited */ 190 buf->f_ffree = 0; /* unlimited */
190 191
191#ifdef CONFIG_CIFS_EXPERIMENTAL 192#ifdef CONFIG_CIFS_EXPERIMENTAL
192/* BB we could add a second check for a QFS Unix capability bit */ 193/* BB we could add a second check for a QFS Unix capability bit */
193 if (pTcon->ses->capabilities & CAP_UNIX) 194/* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */
194 rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf, cifs_sb->local_nls); 195 if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS &
196 le64_to_cpu(pTcon->fsUnixInfo.Capability)))
197 rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf);
195 198
196 /* Only need to call the old QFSInfo if failed 199 /* Only need to call the old QFSInfo if failed
197 on newer one */ 200 on newer one */
198 if(rc) 201 if(rc)
199#endif /* CIFS_EXPERIMENTAL */ 202#endif /* CIFS_EXPERIMENTAL */
200 rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls); 203 rc = CIFSSMBQFSInfo(xid, pTcon, buf);
201 204
202 /* 205 /*
203 int f_type; 206 int f_type;
204 __fsid_t f_fsid; 207 __fsid_t f_fsid;
205 int f_namelen; */ 208 int f_namelen; */
206 /* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */ 209 /* BB get from info in tcon struct at mount time call to QFSAttrInfo */
207 FreeXid(xid); 210 FreeXid(xid);
208 return 0; /* always return success? what if volume is no longer available? */ 211 return 0; /* always return success? what if volume is no
212 longer available? */
209} 213}
210 214
211static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd) 215static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
@@ -559,6 +563,10 @@ struct file_operations cifs_file_ops = {
559 .flush = cifs_flush, 563 .flush = cifs_flush,
560 .mmap = cifs_file_mmap, 564 .mmap = cifs_file_mmap,
561 .sendfile = generic_file_sendfile, 565 .sendfile = generic_file_sendfile,
566#ifdef CONFIG_CIFS_POSIX
567 .ioctl = cifs_ioctl,
568#endif /* CONFIG_CIFS_POSIX */
569
562#ifdef CONFIG_CIFS_EXPERIMENTAL 570#ifdef CONFIG_CIFS_EXPERIMENTAL
563 .readv = generic_file_readv, 571 .readv = generic_file_readv,
564 .writev = generic_file_writev, 572 .writev = generic_file_writev,
@@ -579,6 +587,10 @@ struct file_operations cifs_file_direct_ops = {
579 .fsync = cifs_fsync, 587 .fsync = cifs_fsync,
580 .flush = cifs_flush, 588 .flush = cifs_flush,
581 .sendfile = generic_file_sendfile, /* BB removeme BB */ 589 .sendfile = generic_file_sendfile, /* BB removeme BB */
590#ifdef CONFIG_CIFS_POSIX
591 .ioctl = cifs_ioctl,
592#endif /* CONFIG_CIFS_POSIX */
593
582#ifdef CONFIG_CIFS_EXPERIMENTAL 594#ifdef CONFIG_CIFS_EXPERIMENTAL
583 .dir_notify = cifs_dir_notify, 595 .dir_notify = cifs_dir_notify,
584#endif /* CONFIG_CIFS_EXPERIMENTAL */ 596#endif /* CONFIG_CIFS_EXPERIMENTAL */
@@ -591,6 +603,7 @@ struct file_operations cifs_dir_ops = {
591#ifdef CONFIG_CIFS_EXPERIMENTAL 603#ifdef CONFIG_CIFS_EXPERIMENTAL
592 .dir_notify = cifs_dir_notify, 604 .dir_notify = cifs_dir_notify,
593#endif /* CONFIG_CIFS_EXPERIMENTAL */ 605#endif /* CONFIG_CIFS_EXPERIMENTAL */
606 .ioctl = cifs_ioctl,
594}; 607};
595 608
596static void 609static void
@@ -822,6 +835,7 @@ static int cifs_oplock_thread(void * dummyarg)
822 } 835 }
823 } while(!signal_pending(current)); 836 } while(!signal_pending(current));
824 complete_and_exit (&cifs_oplock_exited, 0); 837 complete_and_exit (&cifs_oplock_exited, 0);
838 oplockThread = NULL;
825} 839}
826 840
827static int __init 841static int __init
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 451f18af3206..d00b3bfe1a52 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifsfs.h 2 * fs/cifs/cifsfs.h
3 * 3 *
4 * Copyright (c) International Business Machines Corp., 2002 4 * Copyright (c) International Business Machines Corp., 2002, 2005
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -91,8 +91,10 @@ extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
91 const char *symname); 91 const char *symname);
92extern int cifs_removexattr(struct dentry *, const char *); 92extern int cifs_removexattr(struct dentry *, const char *);
93extern int cifs_setxattr(struct dentry *, const char *, const void *, 93extern int cifs_setxattr(struct dentry *, const char *, const void *,
94 size_t, int); 94 size_t, int);
95extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); 95extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
96extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 96extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
97#define CIFS_VERSION "1.31" 97extern int cifs_ioctl (struct inode * inode, struct file * filep,
98 unsigned int command, unsigned long arg);
99#define CIFS_VERSION "1.34"
98#endif /* _CIFSFS_H */ 100#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 69aff1a7da9b..81babab265e1 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifsglob.h 2 * fs/cifs/cifsglob.h
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2003 4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -149,6 +149,8 @@ struct TCP_Server_Info {
149 __u16 timeZone; 149 __u16 timeZone;
150 char cryptKey[CIFS_CRYPTO_KEY_SIZE]; 150 char cryptKey[CIFS_CRYPTO_KEY_SIZE];
151 char workstation_RFC1001_name[16]; /* 16th byte is always zero */ 151 char workstation_RFC1001_name[16]; /* 16th byte is always zero */
152 __u32 sequence_number; /* needed for CIFS PDU signature */
153 char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
152}; 154};
153 155
154/* 156/*
@@ -174,17 +176,16 @@ struct cifsSesInfo {
174 struct TCP_Server_Info *server; /* pointer to server info */ 176 struct TCP_Server_Info *server; /* pointer to server info */
175 atomic_t inUse; /* # of mounts (tree connections) on this ses */ 177 atomic_t inUse; /* # of mounts (tree connections) on this ses */
176 enum statusEnum status; 178 enum statusEnum status;
177 __u32 sequence_number; /* needed for CIFS PDU signature */
178 __u16 ipc_tid; /* special tid for connection to IPC share */ 179 __u16 ipc_tid; /* special tid for connection to IPC share */
179 __u16 flags; 180 __u16 flags;
180 char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; 181 char *serverOS; /* name of operating system underlying server */
181 char *serverOS; /* name of operating system underlying the server */ 182 char *serverNOS; /* name of network operating system of server */
182 char *serverNOS; /* name of network operating system that the server is running */
183 char *serverDomain; /* security realm of server */ 183 char *serverDomain; /* security realm of server */
184 int Suid; /* remote smb uid */ 184 int Suid; /* remote smb uid */
185 uid_t linux_uid; /* local Linux uid */ 185 uid_t linux_uid; /* local Linux uid */
186 int capabilities; 186 int capabilities;
187 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */ 187 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
188 TCP names - will ipv6 and sctp addresses fit? */
188 char userName[MAX_USERNAME_SIZE + 1]; 189 char userName[MAX_USERNAME_SIZE + 1];
189 char domainName[MAX_USERNAME_SIZE + 1]; 190 char domainName[MAX_USERNAME_SIZE + 1];
190 char * password; 191 char * password;
@@ -312,12 +313,15 @@ struct mid_q_entry {
312 __u16 mid; /* multiplex id */ 313 __u16 mid; /* multiplex id */
313 __u16 pid; /* process id */ 314 __u16 pid; /* process id */
314 __u32 sequence_number; /* for CIFS signing */ 315 __u32 sequence_number; /* for CIFS signing */
315 __u16 command; /* smb command code */
316 struct timeval when_sent; /* time when smb sent */ 316 struct timeval when_sent; /* time when smb sent */
317 struct cifsSesInfo *ses; /* smb was sent to this server */ 317 struct cifsSesInfo *ses; /* smb was sent to this server */
318 struct task_struct *tsk; /* task waiting for response */ 318 struct task_struct *tsk; /* task waiting for response */
319 struct smb_hdr *resp_buf; /* response buffer */ 319 struct smb_hdr *resp_buf; /* response buffer */
320 int midState; /* wish this were enum but can not pass to wait_event */ 320 int midState; /* wish this were enum but can not pass to wait_event */
321 __u8 command; /* smb command code */
322 unsigned multiPart:1; /* multiple responses to one SMB request */
323 unsigned largeBuf:1; /* if valid response, is pointer to large buf */
324 unsigned multiResp:1; /* multiple trans2 responses for one request */
321}; 325};
322 326
323struct oplock_q_entry { 327struct oplock_q_entry {
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index bcd4a6136f08..aede6a813167 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -330,7 +330,7 @@ struct smb_hdr {
330}; 330};
331/* given a pointer to an smb_hdr retrieve the value of byte count */ 331/* given a pointer to an smb_hdr retrieve the value of byte count */
332#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) 332#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
333 333#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
334/* given a pointer to an smb_hdr retrieve the pointer to the byte area */ 334/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
335#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 ) 335#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
336 336
@@ -762,6 +762,16 @@ typedef struct smb_com_lock_req {
762 LOCKING_ANDX_RANGE Locks[1]; 762 LOCKING_ANDX_RANGE Locks[1];
763} LOCK_REQ; 763} LOCK_REQ;
764 764
765
766typedef struct cifs_posix_lock {
767 __le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */
768 __le16 lock_flags; /* 1 = Wait (only valid for setlock) */
769 __le32 pid;
770 __le64 start;
771 __le64 length;
772 /* BB what about additional owner info to identify network client */
773} CIFS_POSIX_LOCK;
774
765typedef struct smb_com_lock_rsp { 775typedef struct smb_com_lock_rsp {
766 struct smb_hdr hdr; /* wct = 2 */ 776 struct smb_hdr hdr; /* wct = 2 */
767 __u8 AndXCommand; 777 __u8 AndXCommand;
@@ -1098,6 +1108,8 @@ struct smb_t2_rsp {
1098#define SMB_QUERY_POSIX_ACL 0x204 1108#define SMB_QUERY_POSIX_ACL 0x204
1099#define SMB_QUERY_XATTR 0x205 1109#define SMB_QUERY_XATTR 0x205
1100#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */ 1110#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */
1111#define SMB_QUERY_POSIX_PERMISSION 0x207
1112#define SMB_QUERY_POSIX_LOCK 0x208
1101#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee 1113#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
1102#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 1114#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
1103#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ 1115#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
@@ -1116,6 +1128,7 @@ struct smb_t2_rsp {
1116#define SMB_SET_POSIX_ACL 0x204 1128#define SMB_SET_POSIX_ACL 0x204
1117#define SMB_SET_XATTR 0x205 1129#define SMB_SET_XATTR 0x205
1118#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */ 1130#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */
1131#define SMB_SET_POSIX_LOCK 0x208
1119#define SMB_SET_FILE_BASIC_INFO2 0x3ec 1132#define SMB_SET_FILE_BASIC_INFO2 0x3ec
1120#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */ 1133#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */
1121#define SMB_FILE_ALL_INFO2 0x3fa 1134#define SMB_FILE_ALL_INFO2 0x3fa
@@ -1237,9 +1250,25 @@ struct smb_com_transaction2_sfi_rsp {
1237 struct smb_hdr hdr; /* wct = 10 + SetupCount */ 1250 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1238 struct trans2_resp t2; 1251 struct trans2_resp t2;
1239 __u16 ByteCount; 1252 __u16 ByteCount;
1240 __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ 1253 __u16 Reserved2; /* parameter word reserved -
1254 present for infolevels > 100 */
1255};
1256
1257struct smb_t2_qfi_req {
1258 struct smb_hdr hdr;
1259 struct trans2_req t2;
1260 __u8 Pad;
1261 __u16 Fid;
1262 __le16 InformationLevel;
1241}; 1263};
1242 1264
1265struct smb_t2_qfi_rsp {
1266 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1267 struct trans2_resp t2;
1268 __u16 ByteCount;
1269 __u16 Reserved2; /* parameter word reserved -
1270 present for infolevels > 100 */
1271};
1243 1272
1244/* 1273/*
1245 * Flags on T2 FINDFIRST and FINDNEXT 1274 * Flags on T2 FINDFIRST and FINDNEXT
@@ -1524,9 +1553,10 @@ typedef struct {
1524} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */ 1553} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
1525/* Linux/Unix extensions capability flags */ 1554/* Linux/Unix extensions capability flags */
1526#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */ 1555#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
1527#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 1556#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
1528#define CIFS_UNIX_XATTR_CAP 0x00000004 /*support for new namespace*/ 1557#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
1529 1558#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
1559#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */
1530typedef struct { 1560typedef struct {
1531 /* For undefined recommended transfer size return -1 in that field */ 1561 /* For undefined recommended transfer size return -1 in that field */
1532 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */ 1562 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
@@ -1971,14 +2001,39 @@ struct xsymlink {
1971 char path[1024]; 2001 char path[1024];
1972}; 2002};
1973 2003
1974typedef struct { 2004typedef struct file_xattr_info {
1975 /* BB do we need another field for flags? BB */ 2005 /* BB do we need another field for flags? BB */
1976 __u32 xattr_name_len; 2006 __u32 xattr_name_len;
1977 __u32 xattr_value_len; 2007 __u32 xattr_value_len;
1978 char xattr_name[0]; 2008 char xattr_name[0];
1979 /* followed by xattr_value[xattr_value_len], no pad */ 2009 /* followed by xattr_value[xattr_value_len], no pad */
1980} FILE_XATTR_INFO; /* extended attribute, info level 205 */ 2010} FILE_XATTR_INFO; /* extended attribute, info level 0x205 */
1981 2011
2012
2013/* flags for chattr command */
2014#define EXT_SECURE_DELETE 0x00000001 /* EXT3_SECRM_FL */
2015#define EXT_ENABLE_UNDELETE 0x00000002 /* EXT3_UNRM_FL */
2016/* Reserved for compress file 0x4 */
2017#define EXT_SYNCHRONOUS 0x00000008 /* EXT3_SYNC_FL */
2018#define EXT_IMMUTABLE_FL 0x00000010 /* EXT3_IMMUTABLE_FL */
2019#define EXT_OPEN_APPEND_ONLY 0x00000020 /* EXT3_APPEND_FL */
2020#define EXT_DO_NOT_BACKUP 0x00000040 /* EXT3_NODUMP_FL */
2021#define EXT_NO_UPDATE_ATIME 0x00000080 /* EXT3_NOATIME_FL */
2022/* 0x100 through 0x800 reserved for compression flags and are GET-ONLY */
2023#define EXT_HASH_TREE_INDEXED_DIR 0x00001000 /* GET-ONLY EXT3_INDEX_FL */
2024/* 0x2000 reserved for IMAGIC_FL */
2025#define EXT_JOURNAL_THIS_FILE 0x00004000 /* GET-ONLY EXT3_JOURNAL_DATA_FL */
2026/* 0x8000 reserved for EXT3_NOTAIL_FL */
2027#define EXT_SYNCHRONOUS_DIR 0x00010000 /* EXT3_DIRSYNC_FL */
2028#define EXT_TOPDIR 0x00020000 /* EXT3_TOPDIR_FL */
2029
2030#define EXT_SET_MASK 0x000300FF
2031#define EXT_GET_MASK 0x0003DFFF
2032
2033typedef struct file_chattr_info {
2034 __le64 mask; /* list of all possible attribute bits */
2035 __le64 mode; /* list of actual attribute bits on this inode */
2036} FILE_CHATTR_INFO; /* ext attributes (chattr, chflags) level 0x206 */
1982 2037
1983#endif 2038#endif
1984 2039
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 787eef4d86d3..0010511083fc 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -57,10 +57,11 @@ extern int decode_negTokenInit(unsigned char *security_blob, int length,
57extern int cifs_inet_pton(int, char * source, void *dst); 57extern int cifs_inet_pton(int, char * source, void *dst);
58extern int map_smb_to_linux_error(struct smb_hdr *smb); 58extern int map_smb_to_linux_error(struct smb_hdr *smb);
59extern void header_assemble(struct smb_hdr *, char /* command */ , 59extern void header_assemble(struct smb_hdr *, char /* command */ ,
60 const struct cifsTconInfo *, int 60 const struct cifsTconInfo *, int /* specifies length
61 /* length of fixed section (word count) in two byte units */ 61 of fixed section (word count) in two byte units */
62 ); 62 );
63extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *); 63extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
64 struct cifsTconInfo *);
64extern void DeleteOplockQEntry(struct oplock_q_entry *); 65extern void DeleteOplockQEntry(struct oplock_q_entry *);
65extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ ); 66extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
66extern u64 cifs_UnixTimeToNT(struct timespec); 67extern u64 cifs_UnixTimeToNT(struct timespec);
@@ -88,7 +89,7 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
88 89
89extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, 90extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
90 const char *searchName, const struct nls_table *nls_codepage, 91 const char *searchName, const struct nls_table *nls_codepage,
91 __u16 *searchHandle, struct cifs_search_info * psrch_inf); 92 __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map);
92 93
93extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, 94extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
94 __u16 searchHandle, struct cifs_search_info * psrch_inf); 95 __u16 searchHandle, struct cifs_search_info * psrch_inf);
@@ -99,42 +100,42 @@ extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
99extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, 100extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
100 const unsigned char *searchName, 101 const unsigned char *searchName,
101 FILE_ALL_INFO * findData, 102 FILE_ALL_INFO * findData,
102 const struct nls_table *nls_codepage); 103 const struct nls_table *nls_codepage, int remap);
103 104
104extern int CIFSSMBUnixQPathInfo(const int xid, 105extern int CIFSSMBUnixQPathInfo(const int xid,
105 struct cifsTconInfo *tcon, 106 struct cifsTconInfo *tcon,
106 const unsigned char *searchName, 107 const unsigned char *searchName,
107 FILE_UNIX_BASIC_INFO * pFindData, 108 FILE_UNIX_BASIC_INFO * pFindData,
108 const struct nls_table *nls_codepage); 109 const struct nls_table *nls_codepage, int remap);
109 110
110extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, 111extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
111 const unsigned char *searchName, 112 const unsigned char *searchName,
112 unsigned char **targetUNCs, 113 unsigned char **targetUNCs,
113 unsigned int *number_of_UNC_in_array, 114 unsigned int *number_of_UNC_in_array,
114 const struct nls_table *nls_codepage); 115 const struct nls_table *nls_codepage, int remap);
115 116
116extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, 117extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
117 const char *old_path, 118 const char *old_path,
118 const struct nls_table *nls_codepage); 119 const struct nls_table *nls_codepage, int remap);
119extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, 120extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
120 const char *old_path, const struct nls_table *nls_codepage, 121 const char *old_path,
121 unsigned int *pnum_referrals, unsigned char ** preferrals); 122 const struct nls_table *nls_codepage,
123 unsigned int *pnum_referrals,
124 unsigned char ** preferrals,
125 int remap);
122extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, 126extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
123 struct kstatfs *FSData, 127 struct kstatfs *FSData);
124 const struct nls_table *nls_codepage);
125extern int CIFSSMBQFSAttributeInfo(const int xid, 128extern int CIFSSMBQFSAttributeInfo(const int xid,
126 struct cifsTconInfo *tcon, 129 struct cifsTconInfo *tcon);
127 const struct nls_table *nls_codepage); 130extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon);
128extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon, 131extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon);
129 const struct nls_table *nls_codepage);
130extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
131 const struct nls_table *nls_codepage);
132extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, 132extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
133 struct kstatfs *FSData, const struct nls_table *nls_codepage); 133 struct kstatfs *FSData);
134 134
135extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, 135extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
136 const char *fileName, const FILE_BASIC_INFO * data, 136 const char *fileName, const FILE_BASIC_INFO * data,
137 const struct nls_table *nls_codepage); 137 const struct nls_table *nls_codepage,
138 int remap_special_chars);
138extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, 139extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
139 const FILE_BASIC_INFO * data, __u16 fid); 140 const FILE_BASIC_INFO * data, __u16 fid);
140#if 0 141#if 0
@@ -143,36 +144,49 @@ extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon,
143 const struct nls_table *nls_codepage); 144 const struct nls_table *nls_codepage);
144#endif /* possibly unneeded function */ 145#endif /* possibly unneeded function */
145extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, 146extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
146 const char *fileName, __u64 size,int setAllocationSizeFlag, 147 const char *fileName, __u64 size,
147 const struct nls_table *nls_codepage); 148 int setAllocationSizeFlag,
149 const struct nls_table *nls_codepage,
150 int remap_special_chars);
148extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, 151extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
149 __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag); 152 __u64 size, __u16 fileHandle,__u32 opener_pid,
153 int AllocSizeFlag);
150extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon, 154extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
151 char *full_path, __u64 mode, __u64 uid, 155 char *full_path, __u64 mode, __u64 uid,
152 __u64 gid, dev_t dev, const struct nls_table *nls_codepage); 156 __u64 gid, dev_t dev,
157 const struct nls_table *nls_codepage,
158 int remap_special_chars);
153 159
154extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, 160extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
155 const char *newName, 161 const char *newName,
156 const struct nls_table *nls_codepage); 162 const struct nls_table *nls_codepage,
163 int remap_special_chars);
157extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, 164extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
158 const char *name, const struct nls_table *nls_codepage); 165 const char *name, const struct nls_table *nls_codepage,
166 int remap_special_chars);
159 167
160extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, 168extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
161 const char *name, 169 const char *name,
162 const struct nls_table *nls_codepage); 170 const struct nls_table *nls_codepage,
171 int remap_special_chars);
163extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, 172extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
164 const char *fromName, const char *toName, 173 const char *fromName, const char *toName,
165 const struct nls_table *nls_codepage); 174 const struct nls_table *nls_codepage,
175 int remap_special_chars);
166extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, 176extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
167 int netfid, char * target_name, const struct nls_table *nls_codepage); 177 int netfid, char * target_name,
178 const struct nls_table *nls_codepage,
179 int remap_special_chars);
168extern int CIFSCreateHardLink(const int xid, 180extern int CIFSCreateHardLink(const int xid,
169 struct cifsTconInfo *tcon, 181 struct cifsTconInfo *tcon,
170 const char *fromName, const char *toName, 182 const char *fromName, const char *toName,
171 const struct nls_table *nls_codepage); 183 const struct nls_table *nls_codepage,
184 int remap_special_chars);
172extern int CIFSUnixCreateHardLink(const int xid, 185extern int CIFSUnixCreateHardLink(const int xid,
173 struct cifsTconInfo *tcon, 186 struct cifsTconInfo *tcon,
174 const char *fromName, const char *toName, 187 const char *fromName, const char *toName,
175 const struct nls_table *nls_codepage); 188 const struct nls_table *nls_codepage,
189 int remap_special_chars);
176extern int CIFSUnixCreateSymLink(const int xid, 190extern int CIFSUnixCreateSymLink(const int xid,
177 struct cifsTconInfo *tcon, 191 struct cifsTconInfo *tcon,
178 const char *fromName, const char *toName, 192 const char *fromName, const char *toName,
@@ -192,7 +206,7 @@ extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
192 const char *fileName, const int disposition, 206 const char *fileName, const int disposition,
193 const int access_flags, const int omode, 207 const int access_flags, const int omode,
194 __u16 * netfid, int *pOplock, FILE_ALL_INFO *, 208 __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
195 const struct nls_table *nls_codepage); 209 const struct nls_table *nls_codepage, int remap);
196extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, 210extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
197 const int smb_file_id); 211 const int smb_file_id);
198 212
@@ -211,8 +225,13 @@ extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
211 const char __user *buf,const int long_op); 225 const char __user *buf,const int long_op);
212extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, 226extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
213 const unsigned char *searchName, __u64 * inode_number, 227 const unsigned char *searchName, __u64 * inode_number,
214 const struct nls_table *nls_codepage); 228 const struct nls_table *nls_codepage,
229 int remap_special_chars);
215#endif /* CONFIG_CIFS_EXPERIMENTAL */ 230#endif /* CONFIG_CIFS_EXPERIMENTAL */
231extern int cifs_convertUCSpath(char *target, const __u16 *source, int maxlen,
232 const struct nls_table * codepage);
233extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
234 const struct nls_table * cp, int mapChars);
216 235
217extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, 236extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
218 const __u16 netfid, const __u64 len, 237 const __u16 netfid, const __u64 len,
@@ -230,7 +249,7 @@ extern void tconInfoFree(struct cifsTconInfo *);
230 249
231extern int cifs_reconnect(struct TCP_Server_Info *server); 250extern int cifs_reconnect(struct TCP_Server_Info *server);
232 251
233extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *); 252extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *);
234extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, 253extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
235 __u32 expected_sequence_number); 254 __u32 expected_sequence_number);
236extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); 255extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
@@ -241,29 +260,31 @@ extern int CIFSSMBCopy(int xid,
241 const char *fromName, 260 const char *fromName,
242 const __u16 target_tid, 261 const __u16 target_tid,
243 const char *toName, const int flags, 262 const char *toName, const int flags,
244 const struct nls_table *nls_codepage); 263 const struct nls_table *nls_codepage,
264 int remap_special_chars);
245extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 265extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
246 const int notify_subdirs,const __u16 netfid,__u32 filter, 266 const int notify_subdirs,const __u16 netfid,
247 const struct nls_table *nls_codepage); 267 __u32 filter, const struct nls_table *nls_codepage);
248extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, 268extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
249 const unsigned char *searchName, char * EAData, 269 const unsigned char *searchName, char * EAData,
250 size_t bufsize, const struct nls_table *nls_codepage); 270 size_t bufsize, const struct nls_table *nls_codepage,
271 int remap_special_chars);
251extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon, 272extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
252 const unsigned char * searchName,const unsigned char * ea_name, 273 const unsigned char * searchName,const unsigned char * ea_name,
253 unsigned char * ea_value, size_t buf_size, 274 unsigned char * ea_value, size_t buf_size,
254 const struct nls_table *nls_codepage); 275 const struct nls_table *nls_codepage, int remap_special_chars);
255extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, 276extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
256 const char *fileName, const char * ea_name, 277 const char *fileName, const char * ea_name,
257 const void * ea_value, const __u16 ea_value_len, 278 const void * ea_value, const __u16 ea_value_len,
258 const struct nls_table *nls_codepage); 279 const struct nls_table *nls_codepage, int remap_special_chars);
259extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, 280extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
260 const unsigned char *searchName, 281 const unsigned char *searchName,
261 char *acl_inf, const int buflen,const int acl_type, 282 char *acl_inf, const int buflen,const int acl_type,
262 const struct nls_table *nls_codepage); 283 const struct nls_table *nls_codepage, int remap_special_chars);
263extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, 284extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
264 const unsigned char *fileName, 285 const unsigned char *fileName,
265 const char *local_acl, const int buflen, const int acl_type, 286 const char *local_acl, const int buflen, const int acl_type,
266 const struct nls_table *nls_codepage); 287 const struct nls_table *nls_codepage, int remap_special_chars);
267int cifs_ioctl (struct inode * inode, struct file * filep, 288extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
268 unsigned int command, unsigned long arg); 289 const int netfid, __u64 * pExtAttrBits, __u64 *pMask);
269#endif /* _CIFSPROTO_H */ 290#endif /* _CIFSPROTO_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index df6a619a6821..741ff0c69f37 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -75,7 +75,8 @@ static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
75 } 75 }
76 } 76 }
77 write_unlock(&GlobalSMBSeslock); 77 write_unlock(&GlobalSMBSeslock);
78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */ 78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
79 to this tcon */
79} 80}
80 81
81/* If the return code is zero, this function must fill in request_buf pointer */ 82/* If the return code is zero, this function must fill in request_buf pointer */
@@ -89,11 +90,12 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
89 check for tcp and smb session status done differently 90 check for tcp and smb session status done differently
90 for those three - in the calling routine */ 91 for those three - in the calling routine */
91 if(tcon) { 92 if(tcon) {
92 if((tcon->ses) && (tcon->ses->server)){ 93 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
94 (tcon->ses->server)){
93 struct nls_table *nls_codepage; 95 struct nls_table *nls_codepage;
94 /* Give Demultiplex thread up to 10 seconds to 96 /* Give Demultiplex thread up to 10 seconds to
95 reconnect, should be greater than cifs socket 97 reconnect, should be greater than cifs socket
96 timeout which is 7 seconds */ 98 timeout which is 7 seconds */
97 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) { 99 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
98 wait_event_interruptible_timeout(tcon->ses->server->response_q, 100 wait_event_interruptible_timeout(tcon->ses->server->response_q,
99 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ); 101 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
@@ -103,8 +105,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
103 (tcon->ses->status == CifsExiting)) { 105 (tcon->ses->status == CifsExiting)) {
104 cFYI(1,("gave up waiting on reconnect in smb_init")); 106 cFYI(1,("gave up waiting on reconnect in smb_init"));
105 return -EHOSTDOWN; 107 return -EHOSTDOWN;
106 } /* else "hard" mount - keep retrying until 108 } /* else "hard" mount - keep retrying
107 process is killed or server comes back up */ 109 until process is killed or server
110 comes back on-line */
108 } else /* TCP session is reestablished now */ 111 } else /* TCP session is reestablished now */
109 break; 112 break;
110 113
@@ -115,23 +118,24 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
115 simultaneously reconnect the same SMB session */ 118 simultaneously reconnect the same SMB session */
116 down(&tcon->ses->sesSem); 119 down(&tcon->ses->sesSem);
117 if(tcon->ses->status == CifsNeedReconnect) 120 if(tcon->ses->status == CifsNeedReconnect)
118 rc = cifs_setup_session(0, tcon->ses, nls_codepage); 121 rc = cifs_setup_session(0, tcon->ses,
122 nls_codepage);
119 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { 123 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
120 mark_open_files_invalid(tcon); 124 mark_open_files_invalid(tcon);
121 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, 125 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
122 nls_codepage); 126 , nls_codepage);
123 up(&tcon->ses->sesSem); 127 up(&tcon->ses->sesSem);
124 if(rc == 0) 128 if(rc == 0)
125 atomic_inc(&tconInfoReconnectCount); 129 atomic_inc(&tconInfoReconnectCount);
126 130
127 cFYI(1, ("reconnect tcon rc = %d", rc)); 131 cFYI(1, ("reconnect tcon rc = %d", rc));
128 /* Removed call to reopen open files here - 132 /* Removed call to reopen open files here -
129 it is safer (and faster) to reopen files 133 it is safer (and faster) to reopen files
130 one at a time as needed in read and write */ 134 one at a time as needed in read and write */
131 135
132 /* Check if handle based operation so we 136 /* Check if handle based operation so we
133 know whether we can continue or not without 137 know whether we can continue or not without
134 returning to caller to reset file handle */ 138 returning to caller to reset file handle */
135 switch(smb_command) { 139 switch(smb_command) {
136 case SMB_COM_READ_ANDX: 140 case SMB_COM_READ_ANDX:
137 case SMB_COM_WRITE_ANDX: 141 case SMB_COM_WRITE_ANDX:
@@ -182,22 +186,25 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
182 check for tcp and smb session status done differently 186 check for tcp and smb session status done differently
183 for those three - in the calling routine */ 187 for those three - in the calling routine */
184 if(tcon) { 188 if(tcon) {
185 if((tcon->ses) && (tcon->ses->server)){ 189 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
190 (tcon->ses->server)){
186 struct nls_table *nls_codepage; 191 struct nls_table *nls_codepage;
187 /* Give Demultiplex thread up to 10 seconds to 192 /* Give Demultiplex thread up to 10 seconds to
188 reconnect, should be greater than cifs socket 193 reconnect, should be greater than cifs socket
189 timeout which is 7 seconds */ 194 timeout which is 7 seconds */
190 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) { 195 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
191 wait_event_interruptible_timeout(tcon->ses->server->response_q, 196 wait_event_interruptible_timeout(tcon->ses->server->response_q,
192 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ); 197 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
193 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) { 198 if(tcon->ses->server->tcpStatus ==
199 CifsNeedReconnect) {
194 /* on "soft" mounts we wait once */ 200 /* on "soft" mounts we wait once */
195 if((tcon->retry == FALSE) || 201 if((tcon->retry == FALSE) ||
196 (tcon->ses->status == CifsExiting)) { 202 (tcon->ses->status == CifsExiting)) {
197 cFYI(1,("gave up waiting on reconnect in smb_init")); 203 cFYI(1,("gave up waiting on reconnect in smb_init"));
198 return -EHOSTDOWN; 204 return -EHOSTDOWN;
199 } /* else "hard" mount - keep retrying until 205 } /* else "hard" mount - keep retrying
200 process is killed or server comes back up */ 206 until process is killed or server
207 comes on-line */
201 } else /* TCP session is reestablished now */ 208 } else /* TCP session is reestablished now */
202 break; 209 break;
203 210
@@ -208,23 +215,24 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
208 simultaneously reconnect the same SMB session */ 215 simultaneously reconnect the same SMB session */
209 down(&tcon->ses->sesSem); 216 down(&tcon->ses->sesSem);
210 if(tcon->ses->status == CifsNeedReconnect) 217 if(tcon->ses->status == CifsNeedReconnect)
211 rc = cifs_setup_session(0, tcon->ses, nls_codepage); 218 rc = cifs_setup_session(0, tcon->ses,
219 nls_codepage);
212 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { 220 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
213 mark_open_files_invalid(tcon); 221 mark_open_files_invalid(tcon);
214 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, 222 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
215 nls_codepage); 223 tcon, nls_codepage);
216 up(&tcon->ses->sesSem); 224 up(&tcon->ses->sesSem);
217 if(rc == 0) 225 if(rc == 0)
218 atomic_inc(&tconInfoReconnectCount); 226 atomic_inc(&tconInfoReconnectCount);
219 227
220 cFYI(1, ("reconnect tcon rc = %d", rc)); 228 cFYI(1, ("reconnect tcon rc = %d", rc));
221 /* Removed call to reopen open files here - 229 /* Removed call to reopen open files here -
222 it is safer (and faster) to reopen files 230 it is safer (and faster) to reopen files
223 one at a time as needed in read and write */ 231 one at a time as needed in read and write */
224 232
225 /* Check if handle based operation so we 233 /* Check if handle based operation so we
226 know whether we can continue or not without 234 know whether we can continue or not without
227 returning to caller to reset file handle */ 235 returning to caller to reset file handle */
228 switch(smb_command) { 236 switch(smb_command) {
229 case SMB_COM_READ_ANDX: 237 case SMB_COM_READ_ANDX:
230 case SMB_COM_WRITE_ANDX: 238 case SMB_COM_WRITE_ANDX:
@@ -286,7 +294,8 @@ static int validate_t2(struct smb_t2_rsp * pSMB)
286 if(total_size < 512) { 294 if(total_size < 512) {
287 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount); 295 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
288 /* BCC le converted in SendReceive */ 296 /* BCC le converted in SendReceive */
289 pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) + 297 pBCC = (pSMB->hdr.WordCount * 2) +
298 sizeof(struct smb_hdr) +
290 (char *)pSMB; 299 (char *)pSMB;
291 if((total_size <= (*(u16 *)pBCC)) && 300 if((total_size <= (*(u16 *)pBCC)) &&
292 (total_size < 301 (total_size <
@@ -337,8 +346,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
337 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 346 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
338 if (rc == 0) { 347 if (rc == 0) {
339 server->secMode = pSMBr->SecurityMode; 348 server->secMode = pSMBr->SecurityMode;
340 server->secType = NTLM; /* BB override default for NTLMv2 or krb*/ 349 server->secType = NTLM; /* BB override default for
341 /* one byte - no need to convert this or EncryptionKeyLen from le,*/ 350 NTLMv2 or kerberos v5 */
351 /* one byte - no need to convert this or EncryptionKeyLen
352 from little endian */
342 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); 353 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
343 /* probably no need to store and check maxvcs */ 354 /* probably no need to store and check maxvcs */
344 server->maxBuf = 355 server->maxBuf =
@@ -374,7 +385,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
374 pSMBr->u.extended_response. 385 pSMBr->u.extended_response.
375 GUID, 16) != 0) { 386 GUID, 16) != 0) {
376 cFYI(1, 387 cFYI(1,
377 ("UID of server does not match previous connection to same ip address")); 388 ("UID of server does not match previous connection to same ip address"));
378 memcpy(server-> 389 memcpy(server->
379 server_GUID, 390 server_GUID,
380 pSMBr->u. 391 pSMBr->u.
@@ -454,17 +465,18 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
454 up(&tcon->tconSem); 465 up(&tcon->tconSem);
455 return -EIO; 466 return -EIO;
456 } 467 }
457 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **)&smb_buffer); 468 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
469 (void **)&smb_buffer);
458 if (rc) { 470 if (rc) {
459 up(&tcon->tconSem); 471 up(&tcon->tconSem);
460 return rc; 472 return rc;
461 } else { 473 } else {
462 smb_buffer_response = smb_buffer; /* BB removeme BB */ 474 smb_buffer_response = smb_buffer; /* BB removeme BB */
463 } 475 }
464 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response, 476 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
465 &length, 0); 477 &length, 0);
466 if (rc) 478 if (rc)
467 cFYI(1, (" Tree disconnect failed %d", rc)); 479 cFYI(1, ("Tree disconnect failed %d", rc));
468 480
469 if (smb_buffer) 481 if (smb_buffer)
470 cifs_small_buf_release(smb_buffer); 482 cifs_small_buf_release(smb_buffer);
@@ -538,8 +550,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
538} 550}
539 551
540int 552int
541CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, 553CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
542 const char *fileName, const struct nls_table *nls_codepage) 554 const struct nls_table *nls_codepage, int remap)
543{ 555{
544 DELETE_FILE_REQ *pSMB = NULL; 556 DELETE_FILE_REQ *pSMB = NULL;
545 DELETE_FILE_RSP *pSMBr = NULL; 557 DELETE_FILE_RSP *pSMBr = NULL;
@@ -555,12 +567,11 @@ DelFileRetry:
555 567
556 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 568 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
557 name_len = 569 name_len =
558 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, PATH_MAX 570 cifsConvertToUCS((__u16 *) pSMB->fileName, fileName,
559 /* find define for this maxpathcomponent */ 571 PATH_MAX, nls_codepage, remap);
560 , nls_codepage);
561 name_len++; /* trailing null */ 572 name_len++; /* trailing null */
562 name_len *= 2; 573 name_len *= 2;
563 } else { /* BB improve the check for buffer overruns BB */ 574 } else { /* BB improve check for buffer overruns BB */
564 name_len = strnlen(fileName, PATH_MAX); 575 name_len = strnlen(fileName, PATH_MAX);
565 name_len++; /* trailing null */ 576 name_len++; /* trailing null */
566 strncpy(pSMB->fileName, fileName, name_len); 577 strncpy(pSMB->fileName, fileName, name_len);
@@ -589,8 +600,8 @@ DelFileRetry:
589} 600}
590 601
591int 602int
592CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, 603CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
593 const char *dirName, const struct nls_table *nls_codepage) 604 const struct nls_table *nls_codepage, int remap)
594{ 605{
595 DELETE_DIRECTORY_REQ *pSMB = NULL; 606 DELETE_DIRECTORY_REQ *pSMB = NULL;
596 DELETE_DIRECTORY_RSP *pSMBr = NULL; 607 DELETE_DIRECTORY_RSP *pSMBr = NULL;
@@ -606,12 +617,11 @@ RmDirRetry:
606 return rc; 617 return rc;
607 618
608 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 619 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
609 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, PATH_MAX 620 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
610 /* find define for this maxpathcomponent */ 621 PATH_MAX, nls_codepage, remap);
611 , nls_codepage);
612 name_len++; /* trailing null */ 622 name_len++; /* trailing null */
613 name_len *= 2; 623 name_len *= 2;
614 } else { /* BB improve the check for buffer overruns BB */ 624 } else { /* BB improve check for buffer overruns BB */
615 name_len = strnlen(dirName, PATH_MAX); 625 name_len = strnlen(dirName, PATH_MAX);
616 name_len++; /* trailing null */ 626 name_len++; /* trailing null */
617 strncpy(pSMB->DirName, dirName, name_len); 627 strncpy(pSMB->DirName, dirName, name_len);
@@ -639,7 +649,7 @@ RmDirRetry:
639 649
640int 650int
641CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, 651CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
642 const char *name, const struct nls_table *nls_codepage) 652 const char *name, const struct nls_table *nls_codepage, int remap)
643{ 653{
644 int rc = 0; 654 int rc = 0;
645 CREATE_DIRECTORY_REQ *pSMB = NULL; 655 CREATE_DIRECTORY_REQ *pSMB = NULL;
@@ -655,12 +665,11 @@ MkDirRetry:
655 return rc; 665 return rc;
656 666
657 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 667 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
658 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, PATH_MAX 668 name_len = cifsConvertToUCS((__u16 *) pSMB->DirName, name,
659 /* find define for this maxpathcomponent */ 669 PATH_MAX, nls_codepage, remap);
660 , nls_codepage);
661 name_len++; /* trailing null */ 670 name_len++; /* trailing null */
662 name_len *= 2; 671 name_len *= 2;
663 } else { /* BB improve the check for buffer overruns BB */ 672 } else { /* BB improve check for buffer overruns BB */
664 name_len = strnlen(name, PATH_MAX); 673 name_len = strnlen(name, PATH_MAX);
665 name_len++; /* trailing null */ 674 name_len++; /* trailing null */
666 strncpy(pSMB->DirName, name, name_len); 675 strncpy(pSMB->DirName, name, name_len);
@@ -690,7 +699,7 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
690 const char *fileName, const int openDisposition, 699 const char *fileName, const int openDisposition,
691 const int access_flags, const int create_options, __u16 * netfid, 700 const int access_flags, const int create_options, __u16 * netfid,
692 int *pOplock, FILE_ALL_INFO * pfile_info, 701 int *pOplock, FILE_ALL_INFO * pfile_info,
693 const struct nls_table *nls_codepage) 702 const struct nls_table *nls_codepage, int remap)
694{ 703{
695 int rc = -EACCES; 704 int rc = -EACCES;
696 OPEN_REQ *pSMB = NULL; 705 OPEN_REQ *pSMB = NULL;
@@ -710,14 +719,12 @@ openRetry:
710 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 719 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
711 count = 1; /* account for one byte pad to word boundary */ 720 count = 1; /* account for one byte pad to word boundary */
712 name_len = 721 name_len =
713 cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1), 722 cifsConvertToUCS((__u16 *) (pSMB->fileName + 1),
714 fileName, PATH_MAX 723 fileName, PATH_MAX, nls_codepage, remap);
715 /* find define for this maxpathcomponent */
716 , nls_codepage);
717 name_len++; /* trailing null */ 724 name_len++; /* trailing null */
718 name_len *= 2; 725 name_len *= 2;
719 pSMB->NameLength = cpu_to_le16(name_len); 726 pSMB->NameLength = cpu_to_le16(name_len);
720 } else { /* BB improve the check for buffer overruns BB */ 727 } else { /* BB improve check for buffer overruns BB */
721 count = 0; /* no pad */ 728 count = 0; /* no pad */
722 name_len = strnlen(fileName, PATH_MAX); 729 name_len = strnlen(fileName, PATH_MAX);
723 name_len++; /* trailing null */ 730 name_len++; /* trailing null */
@@ -746,7 +753,8 @@ openRetry:
746 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); 753 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
747 pSMB->CreateDisposition = cpu_to_le32(openDisposition); 754 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
748 pSMB->CreateOptions = cpu_to_le32(create_options); 755 pSMB->CreateOptions = cpu_to_le32(create_options);
749 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/ 756 /* BB Expirement with various impersonation levels and verify */
757 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
750 pSMB->SecurityFlags = 758 pSMB->SecurityFlags =
751 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; 759 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
752 760
@@ -760,7 +768,7 @@ openRetry:
760 if (rc) { 768 if (rc) {
761 cFYI(1, ("Error in Open = %d", rc)); 769 cFYI(1, ("Error in Open = %d", rc));
762 } else { 770 } else {
763 *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */ 771 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
764 *netfid = pSMBr->Fid; /* cifs fid stays in le */ 772 *netfid = pSMBr->Fid; /* cifs fid stays in le */
765 /* Let caller know file was created so we can set the mode. */ 773 /* Let caller know file was created so we can set the mode. */
766 /* Do we care about the CreateAction in any other cases? */ 774 /* Do we care about the CreateAction in any other cases? */
@@ -1017,11 +1025,13 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1017 __u16 count; 1025 __u16 count;
1018 1026
1019 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock)); 1027 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1020 rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB, 1028 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1021 (void **) &pSMBr); 1029
1022 if (rc) 1030 if (rc)
1023 return rc; 1031 return rc;
1024 1032
1033 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1034
1025 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) { 1035 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1026 timeout = -1; /* no response expected */ 1036 timeout = -1; /* no response expected */
1027 pSMB->Timeout = 0; 1037 pSMB->Timeout = 0;
@@ -1059,7 +1069,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1059 if (rc) { 1069 if (rc) {
1060 cFYI(1, ("Send error in Lock = %d", rc)); 1070 cFYI(1, ("Send error in Lock = %d", rc));
1061 } 1071 }
1062 cifs_buf_release(pSMB); 1072 cifs_small_buf_release(pSMB);
1063 1073
1064 /* Note: On -EAGAIN error only caller can retry on handle based calls 1074 /* Note: On -EAGAIN error only caller can retry on handle based calls
1065 since file handle passed in no longer valid */ 1075 since file handle passed in no longer valid */
@@ -1108,7 +1118,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1108int 1118int
1109CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, 1119CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1110 const char *fromName, const char *toName, 1120 const char *fromName, const char *toName,
1111 const struct nls_table *nls_codepage) 1121 const struct nls_table *nls_codepage, int remap)
1112{ 1122{
1113 int rc = 0; 1123 int rc = 0;
1114 RENAME_REQ *pSMB = NULL; 1124 RENAME_REQ *pSMB = NULL;
@@ -1131,18 +1141,16 @@ renameRetry:
1131 1141
1132 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1142 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1133 name_len = 1143 name_len =
1134 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX 1144 cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName,
1135 /* find define for this maxpathcomponent */ 1145 PATH_MAX, nls_codepage, remap);
1136 , nls_codepage);
1137 name_len++; /* trailing null */ 1146 name_len++; /* trailing null */
1138 name_len *= 2; 1147 name_len *= 2;
1139 pSMB->OldFileName[name_len] = 0x04; /* pad */ 1148 pSMB->OldFileName[name_len] = 0x04; /* pad */
1140 /* protocol requires ASCII signature byte on Unicode string */ 1149 /* protocol requires ASCII signature byte on Unicode string */
1141 pSMB->OldFileName[name_len + 1] = 0x00; 1150 pSMB->OldFileName[name_len + 1] = 0x00;
1142 name_len2 = 1151 name_len2 =
1143 cifs_strtoUCS((wchar_t *) & pSMB-> 1152 cifsConvertToUCS((__u16 *) &pSMB->OldFileName[name_len + 2],
1144 OldFileName[name_len + 2], toName, PATH_MAX, 1153 toName, PATH_MAX, nls_codepage, remap);
1145 nls_codepage);
1146 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 1154 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1147 name_len2 *= 2; /* convert to bytes */ 1155 name_len2 *= 2; /* convert to bytes */
1148 } else { /* BB improve the check for buffer overruns BB */ 1156 } else { /* BB improve the check for buffer overruns BB */
@@ -1182,7 +1190,8 @@ renameRetry:
1182} 1190}
1183 1191
1184int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, 1192int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1185 int netfid, char * target_name, const struct nls_table * nls_codepage) 1193 int netfid, char * target_name,
1194 const struct nls_table * nls_codepage, int remap)
1186{ 1195{
1187 struct smb_com_transaction2_sfi_req *pSMB = NULL; 1196 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1188 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; 1197 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
@@ -1227,9 +1236,11 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1227 /* unicode only call */ 1236 /* unicode only call */
1228 if(target_name == NULL) { 1237 if(target_name == NULL) {
1229 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid); 1238 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1230 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage); 1239 len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name,
1240 dummy_string, 24, nls_codepage, remap);
1231 } else { 1241 } else {
1232 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, PATH_MAX, nls_codepage); 1242 len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name,
1243 target_name, PATH_MAX, nls_codepage, remap);
1233 } 1244 }
1234 rename_info->target_name_len = cpu_to_le32(2 * len_of_str); 1245 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1235 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2; 1246 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
@@ -1263,7 +1274,7 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1263int 1274int
1264CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, 1275CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1265 const __u16 target_tid, const char *toName, const int flags, 1276 const __u16 target_tid, const char *toName, const int flags,
1266 const struct nls_table *nls_codepage) 1277 const struct nls_table *nls_codepage, int remap)
1267{ 1278{
1268 int rc = 0; 1279 int rc = 0;
1269 COPY_REQ *pSMB = NULL; 1280 COPY_REQ *pSMB = NULL;
@@ -1285,18 +1296,16 @@ copyRetry:
1285 pSMB->Flags = cpu_to_le16(flags & COPY_TREE); 1296 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1286 1297
1287 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1298 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1288 name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, 1299 name_len = cifsConvertToUCS((__u16 *) pSMB->OldFileName,
1289 fromName, 1300 fromName, PATH_MAX, nls_codepage,
1290 PATH_MAX /* find define for this maxpathcomponent */, 1301 remap);
1291 nls_codepage);
1292 name_len++; /* trailing null */ 1302 name_len++; /* trailing null */
1293 name_len *= 2; 1303 name_len *= 2;
1294 pSMB->OldFileName[name_len] = 0x04; /* pad */ 1304 pSMB->OldFileName[name_len] = 0x04; /* pad */
1295 /* protocol requires ASCII signature byte on Unicode string */ 1305 /* protocol requires ASCII signature byte on Unicode string */
1296 pSMB->OldFileName[name_len + 1] = 0x00; 1306 pSMB->OldFileName[name_len + 1] = 0x00;
1297 name_len2 = cifs_strtoUCS((wchar_t *) & pSMB-> 1307 name_len2 = cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2],
1298 OldFileName[name_len + 2], toName, PATH_MAX, 1308 toName, PATH_MAX, nls_codepage, remap);
1299 nls_codepage);
1300 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 1309 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1301 name_len2 *= 2; /* convert to bytes */ 1310 name_len2 *= 2; /* convert to bytes */
1302 } else { /* BB improve the check for buffer overruns BB */ 1311 } else { /* BB improve the check for buffer overruns BB */
@@ -1425,7 +1434,7 @@ createSymLinkRetry:
1425int 1434int
1426CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon, 1435CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1427 const char *fromName, const char *toName, 1436 const char *fromName, const char *toName,
1428 const struct nls_table *nls_codepage) 1437 const struct nls_table *nls_codepage, int remap)
1429{ 1438{
1430 TRANSACTION2_SPI_REQ *pSMB = NULL; 1439 TRANSACTION2_SPI_REQ *pSMB = NULL;
1431 TRANSACTION2_SPI_RSP *pSMBr = NULL; 1440 TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -1444,9 +1453,8 @@ createHardLinkRetry:
1444 return rc; 1453 return rc;
1445 1454
1446 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1455 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1447 name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, PATH_MAX 1456 name_len = cifsConvertToUCS((__u16 *) pSMB->FileName, toName,
1448 /* find define for this maxpathcomponent */ 1457 PATH_MAX, nls_codepage, remap);
1449 , nls_codepage);
1450 name_len++; /* trailing null */ 1458 name_len++; /* trailing null */
1451 name_len *= 2; 1459 name_len *= 2;
1452 1460
@@ -1468,9 +1476,8 @@ createHardLinkRetry:
1468 data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 1476 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1469 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1477 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1470 name_len_target = 1478 name_len_target =
1471 cifs_strtoUCS((wchar_t *) data_offset, fromName, PATH_MAX 1479 cifsConvertToUCS((__u16 *) data_offset, fromName, PATH_MAX,
1472 /* find define for this maxpathcomponent */ 1480 nls_codepage, remap);
1473 , nls_codepage);
1474 name_len_target++; /* trailing null */ 1481 name_len_target++; /* trailing null */
1475 name_len_target *= 2; 1482 name_len_target *= 2;
1476 } else { /* BB improve the check for buffer overruns BB */ 1483 } else { /* BB improve the check for buffer overruns BB */
@@ -1512,7 +1519,7 @@ createHardLinkRetry:
1512int 1519int
1513CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon, 1520CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1514 const char *fromName, const char *toName, 1521 const char *fromName, const char *toName,
1515 const struct nls_table *nls_codepage) 1522 const struct nls_table *nls_codepage, int remap)
1516{ 1523{
1517 int rc = 0; 1524 int rc = 0;
1518 NT_RENAME_REQ *pSMB = NULL; 1525 NT_RENAME_REQ *pSMB = NULL;
@@ -1539,17 +1546,15 @@ winCreateHardLinkRetry:
1539 1546
1540 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1547 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1541 name_len = 1548 name_len =
1542 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX 1549 cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName,
1543 /* find define for this maxpathcomponent */ 1550 PATH_MAX, nls_codepage, remap);
1544 , nls_codepage);
1545 name_len++; /* trailing null */ 1551 name_len++; /* trailing null */
1546 name_len *= 2; 1552 name_len *= 2;
1547 pSMB->OldFileName[name_len] = 0; /* pad */ 1553 pSMB->OldFileName[name_len] = 0; /* pad */
1548 pSMB->OldFileName[name_len + 1] = 0x04; 1554 pSMB->OldFileName[name_len + 1] = 0x04;
1549 name_len2 = 1555 name_len2 =
1550 cifs_strtoUCS((wchar_t *) & pSMB-> 1556 cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2],
1551 OldFileName[name_len + 2], toName, PATH_MAX, 1557 toName, PATH_MAX, nls_codepage, remap);
1552 nls_codepage);
1553 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 1558 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1554 name_len2 *= 2; /* convert to bytes */ 1559 name_len2 *= 2; /* convert to bytes */
1555 } else { /* BB improve the check for buffer overruns BB */ 1560 } else { /* BB improve the check for buffer overruns BB */
@@ -1659,6 +1664,7 @@ querySymLinkRetry:
1659 name_len = UniStrnlen((wchar_t *) ((char *) 1664 name_len = UniStrnlen((wchar_t *) ((char *)
1660 &pSMBr->hdr.Protocol +data_offset), 1665 &pSMBr->hdr.Protocol +data_offset),
1661 min_t(const int, buflen,count) / 2); 1666 min_t(const int, buflen,count) / 2);
1667 /* BB FIXME investigate remapping reserved chars here */
1662 cifs_strfromUCS_le(symlinkinfo, 1668 cifs_strfromUCS_le(symlinkinfo,
1663 (wchar_t *) ((char *)&pSMBr->hdr.Protocol + 1669 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1664 data_offset), 1670 data_offset),
@@ -1793,7 +1799,8 @@ static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace
1793} 1799}
1794 1800
1795/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */ 1801/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1796static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const int acl_type,const int size_of_data_area) 1802static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
1803 const int acl_type,const int size_of_data_area)
1797{ 1804{
1798 int size = 0; 1805 int size = 0;
1799 int i; 1806 int i;
@@ -1912,7 +1919,7 @@ int
1912CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, 1919CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
1913 const unsigned char *searchName, 1920 const unsigned char *searchName,
1914 char *acl_inf, const int buflen, const int acl_type, 1921 char *acl_inf, const int buflen, const int acl_type,
1915 const struct nls_table *nls_codepage) 1922 const struct nls_table *nls_codepage, int remap)
1916{ 1923{
1917/* SMB_QUERY_POSIX_ACL */ 1924/* SMB_QUERY_POSIX_ACL */
1918 TRANSACTION2_QPI_REQ *pSMB = NULL; 1925 TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -1932,8 +1939,8 @@ queryAclRetry:
1932 1939
1933 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1940 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1934 name_len = 1941 name_len =
1935 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 1942 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
1936 , nls_codepage); 1943 PATH_MAX, nls_codepage, remap);
1937 name_len++; /* trailing null */ 1944 name_len++; /* trailing null */
1938 name_len *= 2; 1945 name_len *= 2;
1939 pSMB->FileName[name_len] = 0; 1946 pSMB->FileName[name_len] = 0;
@@ -1997,8 +2004,9 @@ queryAclRetry:
1997int 2004int
1998CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, 2005CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
1999 const unsigned char *fileName, 2006 const unsigned char *fileName,
2000 const char *local_acl, const int buflen, const int acl_type, 2007 const char *local_acl, const int buflen,
2001 const struct nls_table *nls_codepage) 2008 const int acl_type,
2009 const struct nls_table *nls_codepage, int remap)
2002{ 2010{
2003 struct smb_com_transaction2_spi_req *pSMB = NULL; 2011 struct smb_com_transaction2_spi_req *pSMB = NULL;
2004 struct smb_com_transaction2_spi_rsp *pSMBr = NULL; 2012 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -2016,8 +2024,8 @@ setAclRetry:
2016 return rc; 2024 return rc;
2017 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2025 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2018 name_len = 2026 name_len =
2019 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX 2027 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
2020 , nls_codepage); 2028 PATH_MAX, nls_codepage, remap);
2021 name_len++; /* trailing null */ 2029 name_len++; /* trailing null */
2022 name_len *= 2; 2030 name_len *= 2;
2023 } else { /* BB improve the check for buffer overruns BB */ 2031 } else { /* BB improve the check for buffer overruns BB */
@@ -2072,13 +2080,96 @@ setACLerrorExit:
2072 return rc; 2080 return rc;
2073} 2081}
2074 2082
2075#endif 2083/* BB fix tabs in this function FIXME BB */
2084int
2085CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2086 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2087{
2088 int rc = 0;
2089 struct smb_t2_qfi_req *pSMB = NULL;
2090 struct smb_t2_qfi_rsp *pSMBr = NULL;
2091 int bytes_returned;
2092 __u16 params, byte_count;
2093
2094 cFYI(1,("In GetExtAttr"));
2095 if(tcon == NULL)
2096 return -ENODEV;
2097
2098GetExtAttrRetry:
2099 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2100 (void **) &pSMBr);
2101 if (rc)
2102 return rc;
2103
2104 params = 2 /* level */ +2 /* fid */;
2105 pSMB->t2.TotalDataCount = 0;
2106 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2107 /* BB find exact max data count below from sess structure BB */
2108 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2109 pSMB->t2.MaxSetupCount = 0;
2110 pSMB->t2.Reserved = 0;
2111 pSMB->t2.Flags = 0;
2112 pSMB->t2.Timeout = 0;
2113 pSMB->t2.Reserved2 = 0;
2114 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2115 Fid) - 4);
2116 pSMB->t2.DataCount = 0;
2117 pSMB->t2.DataOffset = 0;
2118 pSMB->t2.SetupCount = 1;
2119 pSMB->t2.Reserved3 = 0;
2120 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2121 byte_count = params + 1 /* pad */ ;
2122 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2123 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2124 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2125 pSMB->Pad = 0;
2126 pSMB->Fid = netfid;
2127 pSMB->hdr.smb_buf_length += byte_count;
2128 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2129
2130 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2131 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2132 if (rc) {
2133 cFYI(1, ("error %d in GetExtAttr", rc));
2134 } else {
2135 /* decode response */
2136 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2137 if (rc || (pSMBr->ByteCount < 2))
2138 /* BB also check enough total bytes returned */
2139 /* If rc should we check for EOPNOSUPP and
2140 disable the srvino flag? or in caller? */
2141 rc = -EIO; /* bad smb */
2142 else {
2143 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2144 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2145 struct file_chattr_info * pfinfo;
2146 /* BB Do we need a cast or hash here ? */
2147 if(count != 16) {
2148 cFYI(1, ("Illegal size ret in GetExtAttr"));
2149 rc = -EIO;
2150 goto GetExtAttrOut;
2151 }
2152 pfinfo = (struct file_chattr_info *)
2153 (data_offset + (char *) &pSMBr->hdr.Protocol);
2154 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2155 *pMask = le64_to_cpu(pfinfo->mask);
2156 }
2157 }
2158GetExtAttrOut:
2159 cifs_buf_release(pSMB);
2160 if (rc == -EAGAIN)
2161 goto GetExtAttrRetry;
2162 return rc;
2163}
2164
2165
2166#endif /* CONFIG_POSIX */
2076 2167
2077int 2168int
2078CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, 2169CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2079 const unsigned char *searchName, 2170 const unsigned char *searchName,
2080 FILE_ALL_INFO * pFindData, 2171 FILE_ALL_INFO * pFindData,
2081 const struct nls_table *nls_codepage) 2172 const struct nls_table *nls_codepage, int remap)
2082{ 2173{
2083/* level 263 SMB_QUERY_FILE_ALL_INFO */ 2174/* level 263 SMB_QUERY_FILE_ALL_INFO */
2084 TRANSACTION2_QPI_REQ *pSMB = NULL; 2175 TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -2097,9 +2188,8 @@ QPathInfoRetry:
2097 2188
2098 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2189 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2099 name_len = 2190 name_len =
2100 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 2191 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
2101 /* find define for this maxpathcomponent */ 2192 PATH_MAX, nls_codepage, remap);
2102 , nls_codepage);
2103 name_len++; /* trailing null */ 2193 name_len++; /* trailing null */
2104 name_len *= 2; 2194 name_len *= 2;
2105 } else { /* BB improve the check for buffer overruns BB */ 2195 } else { /* BB improve the check for buffer overruns BB */
@@ -2160,7 +2250,7 @@ int
2160CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, 2250CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2161 const unsigned char *searchName, 2251 const unsigned char *searchName,
2162 FILE_UNIX_BASIC_INFO * pFindData, 2252 FILE_UNIX_BASIC_INFO * pFindData,
2163 const struct nls_table *nls_codepage) 2253 const struct nls_table *nls_codepage, int remap)
2164{ 2254{
2165/* SMB_QUERY_FILE_UNIX_BASIC */ 2255/* SMB_QUERY_FILE_UNIX_BASIC */
2166 TRANSACTION2_QPI_REQ *pSMB = NULL; 2256 TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -2179,9 +2269,8 @@ UnixQPathInfoRetry:
2179 2269
2180 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2270 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2181 name_len = 2271 name_len =
2182 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 2272 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
2183 /* find define for this maxpathcomponent */ 2273 PATH_MAX, nls_codepage, remap);
2184 , nls_codepage);
2185 name_len++; /* trailing null */ 2274 name_len++; /* trailing null */
2186 name_len *= 2; 2275 name_len *= 2;
2187 } else { /* BB improve the check for buffer overruns BB */ 2276 } else { /* BB improve the check for buffer overruns BB */
@@ -2261,7 +2350,7 @@ findUniqueRetry:
2261 2350
2262 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2351 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2263 name_len = 2352 name_len =
2264 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 2353 cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
2265 /* find define for this maxpathcomponent */ 2354 /* find define for this maxpathcomponent */
2266 , nls_codepage); 2355 , nls_codepage);
2267 name_len++; /* trailing null */ 2356 name_len++; /* trailing null */
@@ -2325,7 +2414,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2325 const char *searchName, 2414 const char *searchName,
2326 const struct nls_table *nls_codepage, 2415 const struct nls_table *nls_codepage,
2327 __u16 * pnetfid, 2416 __u16 * pnetfid,
2328 struct cifs_search_info * psrch_inf) 2417 struct cifs_search_info * psrch_inf, int remap)
2329{ 2418{
2330/* level 257 SMB_ */ 2419/* level 257 SMB_ */
2331 TRANSACTION2_FFIRST_REQ *pSMB = NULL; 2420 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -2336,7 +2425,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2336 int name_len; 2425 int name_len;
2337 __u16 params, byte_count; 2426 __u16 params, byte_count;
2338 2427
2339 cFYI(1, ("In FindFirst")); 2428 cFYI(1, ("In FindFirst for %s",searchName));
2340 2429
2341findFirstRetry: 2430findFirstRetry:
2342 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, 2431 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -2346,20 +2435,30 @@ findFirstRetry:
2346 2435
2347 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2436 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2348 name_len = 2437 name_len =
2349 cifs_strtoUCS((wchar_t *) pSMB->FileName,searchName, 2438 cifsConvertToUCS((__u16 *) pSMB->FileName,searchName,
2350 PATH_MAX, nls_codepage); 2439 PATH_MAX, nls_codepage, remap);
2351 name_len++; /* trailing null */ 2440 /* We can not add the asterik earlier in case
2441 it got remapped to 0xF03A as if it were part of the
2442 directory name instead of a wildcard */
2352 name_len *= 2; 2443 name_len *= 2;
2444 pSMB->FileName[name_len] = '\\';
2445 pSMB->FileName[name_len+1] = 0;
2446 pSMB->FileName[name_len+2] = '*';
2447 pSMB->FileName[name_len+3] = 0;
2448 name_len += 4; /* now the trailing null */
2353 pSMB->FileName[name_len] = 0; /* null terminate just in case */ 2449 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2354 pSMB->FileName[name_len+1] = 0; 2450 pSMB->FileName[name_len+1] = 0;
2451 name_len += 2;
2355 } else { /* BB add check for overrun of SMB buf BB */ 2452 } else { /* BB add check for overrun of SMB buf BB */
2356 name_len = strnlen(searchName, PATH_MAX); 2453 name_len = strnlen(searchName, PATH_MAX);
2357 name_len++; /* trailing null */
2358/* BB fix here and in unicode clause above ie 2454/* BB fix here and in unicode clause above ie
2359 if(name_len > buffersize-header) 2455 if(name_len > buffersize-header)
2360 free buffer exit; BB */ 2456 free buffer exit; BB */
2361 strncpy(pSMB->FileName, searchName, name_len); 2457 strncpy(pSMB->FileName, searchName, name_len);
2362 pSMB->FileName[name_len] = 0; /* just in case */ 2458 pSMB->FileName[name_len] = '\\';
2459 pSMB->FileName[name_len+1] = '*';
2460 pSMB->FileName[name_len+2] = 0;
2461 name_len += 3;
2363 } 2462 }
2364 2463
2365 params = 12 + name_len /* includes null */ ; 2464 params = 12 + name_len /* includes null */ ;
@@ -2422,7 +2521,6 @@ findFirstRetry:
2422 psrch_inf->srch_entries_start = 2521 psrch_inf->srch_entries_start =
2423 (char *) &pSMBr->hdr.Protocol + 2522 (char *) &pSMBr->hdr.Protocol +
2424 le16_to_cpu(pSMBr->t2.DataOffset); 2523 le16_to_cpu(pSMBr->t2.DataOffset);
2425
2426 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol + 2524 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2427 le16_to_cpu(pSMBr->t2.ParameterOffset)); 2525 le16_to_cpu(pSMBr->t2.ParameterOffset));
2428 2526
@@ -2434,7 +2532,6 @@ findFirstRetry:
2434 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount); 2532 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2435 psrch_inf->index_of_last_entry = 2533 psrch_inf->index_of_last_entry =
2436 psrch_inf->entries_in_buffer; 2534 psrch_inf->entries_in_buffer;
2437/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2438 *pnetfid = parms->SearchHandle; 2535 *pnetfid = parms->SearchHandle;
2439 } else { 2536 } else {
2440 cifs_buf_release(pSMB); 2537 cifs_buf_release(pSMB);
@@ -2608,7 +2705,7 @@ int
2608CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, 2705CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2609 const unsigned char *searchName, 2706 const unsigned char *searchName,
2610 __u64 * inode_number, 2707 __u64 * inode_number,
2611 const struct nls_table *nls_codepage) 2708 const struct nls_table *nls_codepage, int remap)
2612{ 2709{
2613 int rc = 0; 2710 int rc = 0;
2614 TRANSACTION2_QPI_REQ *pSMB = NULL; 2711 TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -2629,8 +2726,8 @@ GetInodeNumberRetry:
2629 2726
2630 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2727 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2631 name_len = 2728 name_len =
2632 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 2729 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
2633 PATH_MAX,nls_codepage); 2730 PATH_MAX,nls_codepage, remap);
2634 name_len++; /* trailing null */ 2731 name_len++; /* trailing null */
2635 name_len *= 2; 2732 name_len *= 2;
2636 } else { /* BB improve the check for buffer overruns BB */ 2733 } else { /* BB improve the check for buffer overruns BB */
@@ -2704,7 +2801,7 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2704 const unsigned char *searchName, 2801 const unsigned char *searchName,
2705 unsigned char **targetUNCs, 2802 unsigned char **targetUNCs,
2706 unsigned int *number_of_UNC_in_array, 2803 unsigned int *number_of_UNC_in_array,
2707 const struct nls_table *nls_codepage) 2804 const struct nls_table *nls_codepage, int remap)
2708{ 2805{
2709/* TRANS2_GET_DFS_REFERRAL */ 2806/* TRANS2_GET_DFS_REFERRAL */
2710 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL; 2807 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
@@ -2740,10 +2837,8 @@ getDFSRetry:
2740 if (ses->capabilities & CAP_UNICODE) { 2837 if (ses->capabilities & CAP_UNICODE) {
2741 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; 2838 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2742 name_len = 2839 name_len =
2743 cifs_strtoUCS((wchar_t *) pSMB->RequestFileName, 2840 cifsConvertToUCS((__u16 *) pSMB->RequestFileName,
2744 searchName, PATH_MAX 2841 searchName, PATH_MAX, nls_codepage, remap);
2745 /* find define for this maxpathcomponent */
2746 , nls_codepage);
2747 name_len++; /* trailing null */ 2842 name_len++; /* trailing null */
2748 name_len *= 2; 2843 name_len *= 2;
2749 } else { /* BB improve the check for buffer overruns BB */ 2844 } else { /* BB improve the check for buffer overruns BB */
@@ -2871,8 +2966,7 @@ GetDFSRefExit:
2871} 2966}
2872 2967
2873int 2968int
2874CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, 2969CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
2875 struct kstatfs *FSData, const struct nls_table *nls_codepage)
2876{ 2970{
2877/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */ 2971/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2878 TRANSACTION2_QFSI_REQ *pSMB = NULL; 2972 TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -2955,8 +3049,7 @@ QFSInfoRetry:
2955} 3049}
2956 3050
2957int 3051int
2958CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon, 3052CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
2959 const struct nls_table *nls_codepage)
2960{ 3053{
2961/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */ 3054/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
2962 TRANSACTION2_QFSI_REQ *pSMB = NULL; 3055 TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3024,8 +3117,7 @@ QFSAttributeRetry:
3024} 3117}
3025 3118
3026int 3119int
3027CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon, 3120CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3028 const struct nls_table *nls_codepage)
3029{ 3121{
3030/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */ 3122/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3031 TRANSACTION2_QFSI_REQ *pSMB = NULL; 3123 TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3078,8 +3170,8 @@ QFSDeviceRetry:
3078 else { 3170 else {
3079 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); 3171 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3080 response_data = 3172 response_data =
3081 (FILE_SYSTEM_DEVICE_INFO 3173 (FILE_SYSTEM_DEVICE_INFO *)
3082 *) (((char *) &pSMBr->hdr.Protocol) + 3174 (((char *) &pSMBr->hdr.Protocol) +
3083 data_offset); 3175 data_offset);
3084 memcpy(&tcon->fsDevInfo, response_data, 3176 memcpy(&tcon->fsDevInfo, response_data,
3085 sizeof (FILE_SYSTEM_DEVICE_INFO)); 3177 sizeof (FILE_SYSTEM_DEVICE_INFO));
@@ -3094,8 +3186,7 @@ QFSDeviceRetry:
3094} 3186}
3095 3187
3096int 3188int
3097CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon, 3189CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3098 const struct nls_table *nls_codepage)
3099{ 3190{
3100/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */ 3191/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3101 TRANSACTION2_QFSI_REQ *pSMB = NULL; 3192 TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3166,7 +3257,7 @@ QFSUnixRetry:
3166 3257
3167int 3258int
3168CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, 3259CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3169 struct kstatfs *FSData, const struct nls_table *nls_codepage) 3260 struct kstatfs *FSData)
3170{ 3261{
3171/* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */ 3262/* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3172 TRANSACTION2_QFSI_REQ *pSMB = NULL; 3263 TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3258,7 +3349,8 @@ QFSPosixRetry:
3258 3349
3259int 3350int
3260CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName, 3351CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3261 __u64 size, int SetAllocation, const struct nls_table *nls_codepage) 3352 __u64 size, int SetAllocation,
3353 const struct nls_table *nls_codepage, int remap)
3262{ 3354{
3263 struct smb_com_transaction2_spi_req *pSMB = NULL; 3355 struct smb_com_transaction2_spi_req *pSMB = NULL;
3264 struct smb_com_transaction2_spi_rsp *pSMBr = NULL; 3356 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -3277,9 +3369,8 @@ SetEOFRetry:
3277 3369
3278 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3370 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3279 name_len = 3371 name_len =
3280 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX 3372 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
3281 /* find define for this maxpathcomponent */ 3373 PATH_MAX, nls_codepage, remap);
3282 , nls_codepage);
3283 name_len++; /* trailing null */ 3374 name_len++; /* trailing null */
3284 name_len *= 2; 3375 name_len *= 2;
3285 } else { /* BB improve the check for buffer overruns BB */ 3376 } else { /* BB improve the check for buffer overruns BB */
@@ -3360,11 +3451,13 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3360 3451
3361 cFYI(1, ("SetFileSize (via SetFileInfo) %lld", 3452 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3362 (long long)size)); 3453 (long long)size));
3363 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, 3454 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3364 (void **) &pSMBr); 3455
3365 if (rc) 3456 if (rc)
3366 return rc; 3457 return rc;
3367 3458
3459 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3460
3368 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); 3461 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3369 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); 3462 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3370 3463
@@ -3424,7 +3517,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3424 } 3517 }
3425 3518
3426 if (pSMB) 3519 if (pSMB)
3427 cifs_buf_release(pSMB); 3520 cifs_small_buf_release(pSMB);
3428 3521
3429 /* Note: On -EAGAIN error only caller can retry on handle based calls 3522 /* Note: On -EAGAIN error only caller can retry on handle based calls
3430 since file handle passed in no longer valid */ 3523 since file handle passed in no longer valid */
@@ -3450,11 +3543,13 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_I
3450 __u16 params, param_offset, offset, byte_count, count; 3543 __u16 params, param_offset, offset, byte_count, count;
3451 3544
3452 cFYI(1, ("Set Times (via SetFileInfo)")); 3545 cFYI(1, ("Set Times (via SetFileInfo)"));
3453 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, 3546 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3454 (void **) &pSMBr); 3547
3455 if (rc) 3548 if (rc)
3456 return rc; 3549 return rc;
3457 3550
3551 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3552
3458 /* At this point there is no need to override the current pid 3553 /* At this point there is no need to override the current pid
3459 with the pid of the opener, but that could change if we someday 3554 with the pid of the opener, but that could change if we someday
3460 use an existing handle (rather than opening one on the fly) */ 3555 use an existing handle (rather than opening one on the fly) */
@@ -3500,7 +3595,7 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_I
3500 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc)); 3595 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
3501 } 3596 }
3502 3597
3503 cifs_buf_release(pSMB); 3598 cifs_small_buf_release(pSMB);
3504 3599
3505 /* Note: On -EAGAIN error only caller can retry on handle based calls 3600 /* Note: On -EAGAIN error only caller can retry on handle based calls
3506 since file handle passed in no longer valid */ 3601 since file handle passed in no longer valid */
@@ -3512,7 +3607,7 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_I
3512int 3607int
3513CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName, 3608CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3514 const FILE_BASIC_INFO * data, 3609 const FILE_BASIC_INFO * data,
3515 const struct nls_table *nls_codepage) 3610 const struct nls_table *nls_codepage, int remap)
3516{ 3611{
3517 TRANSACTION2_SPI_REQ *pSMB = NULL; 3612 TRANSACTION2_SPI_REQ *pSMB = NULL;
3518 TRANSACTION2_SPI_RSP *pSMBr = NULL; 3613 TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -3532,9 +3627,8 @@ SetTimesRetry:
3532 3627
3533 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3628 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3534 name_len = 3629 name_len =
3535 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX 3630 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
3536 /* find define for this maxpathcomponent */ 3631 PATH_MAX, nls_codepage, remap);
3537 , nls_codepage);
3538 name_len++; /* trailing null */ 3632 name_len++; /* trailing null */
3539 name_len *= 2; 3633 name_len *= 2;
3540 } else { /* BB improve the check for buffer overruns BB */ 3634 } else { /* BB improve the check for buffer overruns BB */
@@ -3614,7 +3708,7 @@ SetAttrLgcyRetry:
3614 3708
3615 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3709 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3616 name_len = 3710 name_len =
3617 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 3711 ConvertToUCS((wchar_t *) pSMB->fileName, fileName,
3618 PATH_MAX, nls_codepage); 3712 PATH_MAX, nls_codepage);
3619 name_len++; /* trailing null */ 3713 name_len++; /* trailing null */
3620 name_len *= 2; 3714 name_len *= 2;
@@ -3644,8 +3738,9 @@ SetAttrLgcyRetry:
3644 3738
3645int 3739int
3646CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon, 3740CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
3647 char *fileName, __u64 mode, __u64 uid, __u64 gid, 3741 char *fileName, __u64 mode, __u64 uid, __u64 gid,
3648 dev_t device, const struct nls_table *nls_codepage) 3742 dev_t device, const struct nls_table *nls_codepage,
3743 int remap)
3649{ 3744{
3650 TRANSACTION2_SPI_REQ *pSMB = NULL; 3745 TRANSACTION2_SPI_REQ *pSMB = NULL;
3651 TRANSACTION2_SPI_RSP *pSMBr = NULL; 3746 TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -3664,9 +3759,8 @@ setPermsRetry:
3664 3759
3665 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3760 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3666 name_len = 3761 name_len =
3667 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX 3762 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
3668 /* find define for this maxpathcomponent */ 3763 PATH_MAX, nls_codepage, remap);
3669 , nls_codepage);
3670 name_len++; /* trailing null */ 3764 name_len++; /* trailing null */
3671 name_len *= 2; 3765 name_len *= 2;
3672 } else { /* BB improve the check for buffer overruns BB */ 3766 } else { /* BB improve the check for buffer overruns BB */
@@ -3789,7 +3883,7 @@ ssize_t
3789CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, 3883CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
3790 const unsigned char *searchName, 3884 const unsigned char *searchName,
3791 char * EAData, size_t buf_size, 3885 char * EAData, size_t buf_size,
3792 const struct nls_table *nls_codepage) 3886 const struct nls_table *nls_codepage, int remap)
3793{ 3887{
3794 /* BB assumes one setup word */ 3888 /* BB assumes one setup word */
3795 TRANSACTION2_QPI_REQ *pSMB = NULL; 3889 TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -3810,9 +3904,8 @@ QAllEAsRetry:
3810 3904
3811 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3905 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3812 name_len = 3906 name_len =
3813 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 3907 cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName,
3814 /* find define for this maxpathcomponent */ 3908 PATH_MAX, nls_codepage, remap);
3815 , nls_codepage);
3816 name_len++; /* trailing null */ 3909 name_len++; /* trailing null */
3817 name_len *= 2; 3910 name_len *= 2;
3818 } else { /* BB improve the check for buffer overruns BB */ 3911 } else { /* BB improve the check for buffer overruns BB */
@@ -3934,7 +4027,7 @@ QAllEAsRetry:
3934ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon, 4027ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
3935 const unsigned char * searchName,const unsigned char * ea_name, 4028 const unsigned char * searchName,const unsigned char * ea_name,
3936 unsigned char * ea_value, size_t buf_size, 4029 unsigned char * ea_value, size_t buf_size,
3937 const struct nls_table *nls_codepage) 4030 const struct nls_table *nls_codepage, int remap)
3938{ 4031{
3939 TRANSACTION2_QPI_REQ *pSMB = NULL; 4032 TRANSACTION2_QPI_REQ *pSMB = NULL;
3940 TRANSACTION2_QPI_RSP *pSMBr = NULL; 4033 TRANSACTION2_QPI_RSP *pSMBr = NULL;
@@ -3954,9 +4047,8 @@ QEARetry:
3954 4047
3955 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 4048 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3956 name_len = 4049 name_len =
3957 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX 4050 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
3958 /* find define for this maxpathcomponent */ 4051 PATH_MAX, nls_codepage, remap);
3959 , nls_codepage);
3960 name_len++; /* trailing null */ 4052 name_len++; /* trailing null */
3961 name_len *= 2; 4053 name_len *= 2;
3962 } else { /* BB improve the check for buffer overruns BB */ 4054 } else { /* BB improve the check for buffer overruns BB */
@@ -4082,7 +4174,8 @@ QEARetry:
4082int 4174int
4083CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName, 4175CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4084 const char * ea_name, const void * ea_value, 4176 const char * ea_name, const void * ea_value,
4085 const __u16 ea_value_len, const struct nls_table *nls_codepage) 4177 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4178 int remap)
4086{ 4179{
4087 struct smb_com_transaction2_spi_req *pSMB = NULL; 4180 struct smb_com_transaction2_spi_req *pSMB = NULL;
4088 struct smb_com_transaction2_spi_rsp *pSMBr = NULL; 4181 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -4101,9 +4194,8 @@ SetEARetry:
4101 4194
4102 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 4195 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4103 name_len = 4196 name_len =
4104 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX 4197 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
4105 /* find define for this maxpathcomponent */ 4198 PATH_MAX, nls_codepage, remap);
4106 , nls_codepage);
4107 name_len++; /* trailing null */ 4199 name_len++; /* trailing null */
4108 name_len *= 2; 4200 name_len *= 2;
4109 } else { /* BB improve the check for buffer overruns BB */ 4201 } else { /* BB improve the check for buffer overruns BB */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 40470b9d5477..e568cc47a7f9 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/connect.c 2 * fs/cifs/connect.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2004 4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -28,6 +28,7 @@
28#include <linux/ctype.h> 28#include <linux/ctype.h>
29#include <linux/utsname.h> 29#include <linux/utsname.h>
30#include <linux/mempool.h> 30#include <linux/mempool.h>
31#include <linux/delay.h>
31#include <asm/uaccess.h> 32#include <asm/uaccess.h>
32#include <asm/processor.h> 33#include <asm/processor.h>
33#include "cifspdu.h" 34#include "cifspdu.h"
@@ -72,6 +73,7 @@ struct smb_vol {
72 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/ 73 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
73 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ 74 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
74 unsigned direct_io:1; 75 unsigned direct_io:1;
76 unsigned remap:1; /* set to remap seven reserved chars in filenames */
75 unsigned int rsize; 77 unsigned int rsize;
76 unsigned int wsize; 78 unsigned int wsize;
77 unsigned int sockopt; 79 unsigned int sockopt;
@@ -114,7 +116,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
114 spin_unlock(&GlobalMid_Lock); 116 spin_unlock(&GlobalMid_Lock);
115 server->maxBuf = 0; 117 server->maxBuf = 0;
116 118
117 cFYI(1, ("Reconnecting tcp session ")); 119 cFYI(1, ("Reconnecting tcp session"));
118 120
119 /* before reconnecting the tcp session, mark the smb session (uid) 121 /* before reconnecting the tcp session, mark the smb session (uid)
120 and the tid bad so they are not used until reconnected */ 122 and the tid bad so they are not used until reconnected */
@@ -155,9 +157,10 @@ cifs_reconnect(struct TCP_Server_Info *server)
155 qhead); 157 qhead);
156 if(mid_entry) { 158 if(mid_entry) {
157 if(mid_entry->midState == MID_REQUEST_SUBMITTED) { 159 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
158 /* Mark other intransit requests as needing retry so 160 /* Mark other intransit requests as needing
159 we do not immediately mark the session bad again 161 retry so we do not immediately mark the
160 (ie after we reconnect below) as they timeout too */ 162 session bad again (ie after we reconnect
163 below) as they timeout too */
161 mid_entry->midState = MID_RETRY_NEEDED; 164 mid_entry->midState = MID_RETRY_NEEDED;
162 } 165 }
163 } 166 }
@@ -175,14 +178,14 @@ cifs_reconnect(struct TCP_Server_Info *server)
175 server->workstation_RFC1001_name); 178 server->workstation_RFC1001_name);
176 } 179 }
177 if(rc) { 180 if(rc) {
178 set_current_state(TASK_INTERRUPTIBLE); 181 msleep(3000);
179 schedule_timeout(3 * HZ);
180 } else { 182 } else {
181 atomic_inc(&tcpSesReconnectCount); 183 atomic_inc(&tcpSesReconnectCount);
182 spin_lock(&GlobalMid_Lock); 184 spin_lock(&GlobalMid_Lock);
183 if(server->tcpStatus != CifsExiting) 185 if(server->tcpStatus != CifsExiting)
184 server->tcpStatus = CifsGood; 186 server->tcpStatus = CifsGood;
185 spin_unlock(&GlobalMid_Lock); 187 server->sequence_number = 0;
188 spin_unlock(&GlobalMid_Lock);
186 /* atomic_set(&server->inFlight,0);*/ 189 /* atomic_set(&server->inFlight,0);*/
187 wake_up(&server->response_q); 190 wake_up(&server->response_q);
188 } 191 }
@@ -190,12 +193,129 @@ cifs_reconnect(struct TCP_Server_Info *server)
190 return rc; 193 return rc;
191} 194}
192 195
196/*
197 return codes:
198 0 not a transact2, or all data present
199 >0 transact2 with that much data missing
200 -EINVAL = invalid transact2
201
202 */
203static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
204{
205 struct smb_t2_rsp * pSMBt;
206 int total_data_size;
207 int data_in_this_rsp;
208 int remaining;
209
210 if(pSMB->Command != SMB_COM_TRANSACTION2)
211 return 0;
212
213 /* check for plausible wct, bcc and t2 data and parm sizes */
214 /* check for parm and data offset going beyond end of smb */
215 if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
216 cFYI(1,("invalid transact2 word count"));
217 return -EINVAL;
218 }
219
220 pSMBt = (struct smb_t2_rsp *)pSMB;
221
222 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
223 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
224
225 remaining = total_data_size - data_in_this_rsp;
226
227 if(remaining == 0)
228 return 0;
229 else if(remaining < 0) {
230 cFYI(1,("total data %d smaller than data in frame %d",
231 total_data_size, data_in_this_rsp));
232 return -EINVAL;
233 } else {
234 cFYI(1,("missing %d bytes from transact2, check next response",
235 remaining));
236 if(total_data_size > maxBufSize) {
237 cERROR(1,("TotalDataSize %d is over maximum buffer %d",
238 total_data_size,maxBufSize));
239 return -EINVAL;
240 }
241 return remaining;
242 }
243}
244
245static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
246{
247 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
248 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
249 int total_data_size;
250 int total_in_buf;
251 int remaining;
252 int total_in_buf2;
253 char * data_area_of_target;
254 char * data_area_of_buf2;
255 __u16 byte_count;
256
257 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
258
259 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
260 cFYI(1,("total data sizes of primary and secondary t2 differ"));
261 }
262
263 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
264
265 remaining = total_data_size - total_in_buf;
266
267 if(remaining < 0)
268 return -EINVAL;
269
270 if(remaining == 0) /* nothing to do, ignore */
271 return 0;
272
273 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
274 if(remaining < total_in_buf2) {
275 cFYI(1,("transact2 2nd response contains too much data"));
276 }
277
278 /* find end of first SMB data area */
279 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
280 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
281 /* validate target area */
282
283 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
284 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
285
286 data_area_of_target += total_in_buf;
287
288 /* copy second buffer into end of first buffer */
289 memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
290 total_in_buf += total_in_buf2;
291 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
292 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
293 byte_count += total_in_buf2;
294 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
295
296 byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
297 byte_count += total_in_buf2;
298
299 /* BB also add check that we are not beyond maximum buffer size */
300
301 pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
302
303 if(remaining == total_in_buf2) {
304 cFYI(1,("found the last secondary response"));
305 return 0; /* we are done */
306 } else /* more responses to go */
307 return 1;
308
309}
310
193static int 311static int
194cifs_demultiplex_thread(struct TCP_Server_Info *server) 312cifs_demultiplex_thread(struct TCP_Server_Info *server)
195{ 313{
196 int length; 314 int length;
197 unsigned int pdu_length, total_read; 315 unsigned int pdu_length, total_read;
198 struct smb_hdr *smb_buffer = NULL; 316 struct smb_hdr *smb_buffer = NULL;
317 struct smb_hdr *bigbuf = NULL;
318 struct smb_hdr *smallbuf = NULL;
199 struct msghdr smb_msg; 319 struct msghdr smb_msg;
200 struct kvec iov; 320 struct kvec iov;
201 struct socket *csocket = server->ssocket; 321 struct socket *csocket = server->ssocket;
@@ -204,6 +324,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
204 struct task_struct *task_to_wake = NULL; 324 struct task_struct *task_to_wake = NULL;
205 struct mid_q_entry *mid_entry; 325 struct mid_q_entry *mid_entry;
206 char *temp; 326 char *temp;
327 int isLargeBuf = FALSE;
328 int isMultiRsp;
329 int reconnect;
207 330
208 daemonize("cifsd"); 331 daemonize("cifsd");
209 allow_signal(SIGKILL); 332 allow_signal(SIGKILL);
@@ -221,17 +344,34 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
221 } 344 }
222 345
223 while (server->tcpStatus != CifsExiting) { 346 while (server->tcpStatus != CifsExiting) {
224 if (smb_buffer == NULL) 347 if (bigbuf == NULL) {
225 smb_buffer = cifs_buf_get(); 348 bigbuf = cifs_buf_get();
226 else 349 if(bigbuf == NULL) {
227 memset(smb_buffer, 0, sizeof (struct smb_hdr)); 350 cERROR(1,("No memory for large SMB response"));
228 351 msleep(3000);
229 if (smb_buffer == NULL) { 352 /* retry will check if exiting */
230 cERROR(1,("Can not get memory for SMB response")); 353 continue;
231 set_current_state(TASK_INTERRUPTIBLE); 354 }
232 schedule_timeout(HZ * 3); /* give system time to free memory */ 355 } else if(isLargeBuf) {
233 continue; 356 /* we are reusing a dirtry large buf, clear its start */
357 memset(bigbuf, 0, sizeof (struct smb_hdr));
234 } 358 }
359
360 if (smallbuf == NULL) {
361 smallbuf = cifs_small_buf_get();
362 if(smallbuf == NULL) {
363 cERROR(1,("No memory for SMB response"));
364 msleep(1000);
365 /* retry will check if exiting */
366 continue;
367 }
368 /* beginning of smb buffer is cleared in our buf_get */
369 } else /* if existing small buf clear beginning */
370 memset(smallbuf, 0, sizeof (struct smb_hdr));
371
372 isLargeBuf = FALSE;
373 isMultiRsp = FALSE;
374 smb_buffer = smallbuf;
235 iov.iov_base = smb_buffer; 375 iov.iov_base = smb_buffer;
236 iov.iov_len = 4; 376 iov.iov_len = 4;
237 smb_msg.msg_control = NULL; 377 smb_msg.msg_control = NULL;
@@ -243,176 +383,257 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
243 if(server->tcpStatus == CifsExiting) { 383 if(server->tcpStatus == CifsExiting) {
244 break; 384 break;
245 } else if (server->tcpStatus == CifsNeedReconnect) { 385 } else if (server->tcpStatus == CifsNeedReconnect) {
246 cFYI(1,("Reconnecting after server stopped responding")); 386 cFYI(1,("Reconnect after server stopped responding"));
247 cifs_reconnect(server); 387 cifs_reconnect(server);
248 cFYI(1,("call to reconnect done")); 388 cFYI(1,("call to reconnect done"));
249 csocket = server->ssocket; 389 csocket = server->ssocket;
250 continue; 390 continue;
251 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { 391 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
252 set_current_state(TASK_INTERRUPTIBLE); 392 msleep(1); /* minimum sleep to prevent looping
253 schedule_timeout(1); /* minimum sleep to prevent looping
254 allowing socket to clear and app threads to set 393 allowing socket to clear and app threads to set
255 tcpStatus CifsNeedReconnect if server hung */ 394 tcpStatus CifsNeedReconnect if server hung */
256 continue; 395 continue;
257 } else if (length <= 0) { 396 } else if (length <= 0) {
258 if(server->tcpStatus == CifsNew) { 397 if(server->tcpStatus == CifsNew) {
259 cFYI(1,("tcp session abended prematurely (after SMBnegprot)")); 398 cFYI(1,("tcp session abend after SMBnegprot"));
260 /* some servers kill tcp session rather than returning 399 /* some servers kill the TCP session rather than
261 smb negprot error in which case reconnecting here is 400 returning an SMB negprot error, in which
262 not going to help - return error to mount */ 401 case reconnecting here is not going to help,
402 and so simply return error to mount */
263 break; 403 break;
264 } 404 }
265 if(length == -EINTR) { 405 if(length == -EINTR) {
266 cFYI(1,("cifsd thread killed")); 406 cFYI(1,("cifsd thread killed"));
267 break; 407 break;
268 } 408 }
269 cFYI(1,("Reconnecting after unexpected peek error %d",length)); 409 cFYI(1,("Reconnect after unexpected peek error %d",
410 length));
270 cifs_reconnect(server); 411 cifs_reconnect(server);
271 csocket = server->ssocket; 412 csocket = server->ssocket;
272 wake_up(&server->response_q); 413 wake_up(&server->response_q);
273 continue; 414 continue;
274 } else if (length > 3) { 415 } else if (length < 4) {
275 pdu_length = ntohl(smb_buffer->smb_buf_length); 416 cFYI(1,
276 /* Only read pdu_length after below checks for too short (due 417 ("Frame under four bytes received (%d bytes long)",
277 to e.g. int overflow) and too long ie beyond end of buf */ 418 length));
278 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); 419 cifs_reconnect(server);
279 420 csocket = server->ssocket;
280 temp = (char *) smb_buffer; 421 wake_up(&server->response_q);
281 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { 422 continue;
282 cFYI(0,("Received 4 byte keep alive packet")); 423 }
283 } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
284 cFYI(1,("Good RFC 1002 session rsp"));
285 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
286 /* we get this from Windows 98 instead of error on SMB negprot response */
287 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
288 if(server->tcpStatus == CifsNew) {
289 /* if nack on negprot (rather than
290 ret of smb negprot error) reconnecting
291 not going to help, ret error to mount */
292 break;
293 } else {
294 /* give server a second to
295 clean up before reconnect attempt */
296 set_current_state(TASK_INTERRUPTIBLE);
297 schedule_timeout(HZ);
298 /* always try 445 first on reconnect
299 since we get NACK on some if we ever
300 connected to port 139 (the NACK is
301 since we do not begin with RFC1001
302 session initialize frame) */
303 server->addr.sockAddr.sin_port = htons(CIFS_PORT);
304 cifs_reconnect(server);
305 csocket = server->ssocket;
306 wake_up(&server->response_q);
307 continue;
308 }
309 } else if (temp[0] != (char) 0) {
310 cERROR(1,("Unknown RFC 1002 frame"));
311 cifs_dump_mem(" Received Data: ", temp, length);
312 cifs_reconnect(server);
313 csocket = server->ssocket;
314 continue;
315 } else {
316 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
317 || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
318 cERROR(1,
319 ("Invalid size SMB length %d and pdu_length %d",
320 length, pdu_length+4));
321 cifs_reconnect(server);
322 csocket = server->ssocket;
323 wake_up(&server->response_q);
324 continue;
325 } else { /* length ok */
326 length = 0;
327 iov.iov_base = 4 + (char *)smb_buffer;
328 iov.iov_len = pdu_length;
329 for (total_read = 0;
330 total_read < pdu_length;
331 total_read += length) {
332 length = kernel_recvmsg(csocket, &smb_msg,
333 &iov, 1,
334 pdu_length - total_read, 0);
335 if (length == 0) {
336 cERROR(1,
337 ("Zero length receive when expecting %d ",
338 pdu_length - total_read));
339 cifs_reconnect(server);
340 csocket = server->ssocket;
341 wake_up(&server->response_q);
342 continue;
343 }
344 }
345 length += 4; /* account for rfc1002 hdr */
346 }
347 424
348 dump_smb(smb_buffer, length); 425 /* the right amount was read from socket - 4 bytes */
349 if (checkSMB
350 (smb_buffer, smb_buffer->Mid, total_read+4)) {
351 cERROR(1, ("Bad SMB Received "));
352 continue;
353 }
354 426
355 task_to_wake = NULL; 427 pdu_length = ntohl(smb_buffer->smb_buf_length);
356 spin_lock(&GlobalMid_Lock); 428 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
357 list_for_each(tmp, &server->pending_mid_q) {
358 mid_entry = list_entry(tmp, struct
359 mid_q_entry,
360 qhead);
361 429
362 if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) { 430 temp = (char *) smb_buffer;
363 cFYI(1, 431 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
364 (" Mid 0x%x matched - waking up ",mid_entry->mid)); 432 continue;
365 task_to_wake = mid_entry->tsk; 433 } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
366 mid_entry->resp_buf = 434 cFYI(1,("Good RFC 1002 session rsp"));
367 smb_buffer; 435 continue;
368 mid_entry->midState = 436 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
369 MID_RESPONSE_RECEIVED; 437 /* we get this from Windows 98 instead of
370 } 438 an error on SMB negprot response */
371 } 439 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
372 spin_unlock(&GlobalMid_Lock); 440 temp[4]));
373 if (task_to_wake) { 441 if(server->tcpStatus == CifsNew) {
374 smb_buffer = NULL; /* will be freed by users thread after he is done */ 442 /* if nack on negprot (rather than
375 wake_up_process(task_to_wake); 443 ret of smb negprot error) reconnecting
376 } else if (is_valid_oplock_break(smb_buffer) == FALSE) { 444 not going to help, ret error to mount */
377 cERROR(1, ("No task to wake, unknown frame rcvd!")); 445 break;
378 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); 446 } else {
379 } 447 /* give server a second to
448 clean up before reconnect attempt */
449 msleep(1000);
450 /* always try 445 first on reconnect
451 since we get NACK on some if we ever
452 connected to port 139 (the NACK is
453 since we do not begin with RFC1001
454 session initialize frame) */
455 server->addr.sockAddr.sin_port =
456 htons(CIFS_PORT);
457 cifs_reconnect(server);
458 csocket = server->ssocket;
459 wake_up(&server->response_q);
460 continue;
380 } 461 }
381 } else { 462 } else if (temp[0] != (char) 0) {
382 cFYI(1, 463 cERROR(1,("Unknown RFC 1002 frame"));
383 ("Frame less than four bytes received %d bytes long.", 464 cifs_dump_mem(" Received Data: ", temp, length);
384 length)); 465 cifs_reconnect(server);
466 csocket = server->ssocket;
467 continue;
468 }
469
470 /* else we have an SMB response */
471 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
472 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
473 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
474 length, pdu_length+4));
385 cifs_reconnect(server); 475 cifs_reconnect(server);
386 csocket = server->ssocket; 476 csocket = server->ssocket;
387 wake_up(&server->response_q); 477 wake_up(&server->response_q);
388 continue; 478 continue;
479 }
480
481 /* else length ok */
482 reconnect = 0;
483
484 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
485 isLargeBuf = TRUE;
486 memcpy(bigbuf, smallbuf, 4);
487 smb_buffer = bigbuf;
389 } 488 }
390 } 489 length = 0;
490 iov.iov_base = 4 + (char *)smb_buffer;
491 iov.iov_len = pdu_length;
492 for (total_read = 0; total_read < pdu_length;
493 total_read += length) {
494 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
495 pdu_length - total_read, 0);
496 if((server->tcpStatus == CifsExiting) ||
497 (length == -EINTR)) {
498 /* then will exit */
499 reconnect = 2;
500 break;
501 } else if (server->tcpStatus == CifsNeedReconnect) {
502 cifs_reconnect(server);
503 csocket = server->ssocket;
504 /* Reconnect wakes up rspns q */
505 /* Now we will reread sock */
506 reconnect = 1;
507 break;
508 } else if ((length == -ERESTARTSYS) ||
509 (length == -EAGAIN)) {
510 msleep(1); /* minimum sleep to prevent looping,
511 allowing socket to clear and app
512 threads to set tcpStatus
513 CifsNeedReconnect if server hung*/
514 continue;
515 } else if (length <= 0) {
516 cERROR(1,("Received no data, expecting %d",
517 pdu_length - total_read));
518 cifs_reconnect(server);
519 csocket = server->ssocket;
520 reconnect = 1;
521 break;
522 }
523 }
524 if(reconnect == 2)
525 break;
526 else if(reconnect == 1)
527 continue;
528
529 length += 4; /* account for rfc1002 hdr */
530
531
532 dump_smb(smb_buffer, length);
533 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
534 cERROR(1, ("Bad SMB Received "));
535 continue;
536 }
537
538
539 task_to_wake = NULL;
540 spin_lock(&GlobalMid_Lock);
541 list_for_each(tmp, &server->pending_mid_q) {
542 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
543
544 if ((mid_entry->mid == smb_buffer->Mid) &&
545 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
546 (mid_entry->command == smb_buffer->Command)) {
547 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
548 /* We have a multipart transact2 resp */
549 isMultiRsp = TRUE;
550 if(mid_entry->resp_buf) {
551 /* merge response - fix up 1st*/
552 if(coalesce_t2(smb_buffer,
553 mid_entry->resp_buf)) {
554 break;
555 } else {
556 /* all parts received */
557 goto multi_t2_fnd;
558 }
559 } else {
560 if(!isLargeBuf) {
561 cERROR(1,("1st trans2 resp needs bigbuf"));
562 /* BB maybe we can fix this up, switch
563 to already allocated large buffer? */
564 } else {
565 /* Have first buffer */
566 mid_entry->resp_buf =
567 smb_buffer;
568 mid_entry->largeBuf = 1;
569 bigbuf = NULL;
570 }
571 }
572 break;
573 }
574 mid_entry->resp_buf = smb_buffer;
575 if(isLargeBuf)
576 mid_entry->largeBuf = 1;
577 else
578 mid_entry->largeBuf = 0;
579multi_t2_fnd:
580 task_to_wake = mid_entry->tsk;
581 mid_entry->midState = MID_RESPONSE_RECEIVED;
582 break;
583 }
584 }
585 spin_unlock(&GlobalMid_Lock);
586 if (task_to_wake) {
587 /* Was previous buf put in mpx struct for multi-rsp? */
588 if(!isMultiRsp) {
589 /* smb buffer will be freed by user thread */
590 if(isLargeBuf) {
591 bigbuf = NULL;
592 } else
593 smallbuf = NULL;
594 }
595 wake_up_process(task_to_wake);
596 } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
597 && (isMultiRsp == FALSE)) {
598 cERROR(1, ("No task to wake, unknown frame rcvd!"));
599 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
600 }
601 } /* end while !EXITING */
602
391 spin_lock(&GlobalMid_Lock); 603 spin_lock(&GlobalMid_Lock);
392 server->tcpStatus = CifsExiting; 604 server->tcpStatus = CifsExiting;
393 server->tsk = NULL; 605 server->tsk = NULL;
394 atomic_set(&server->inFlight, 0); 606 /* check if we have blocked requests that need to free */
607 /* Note that cifs_max_pending is normally 50, but
608 can be set at module install time to as little as two */
609 if(atomic_read(&server->inFlight) >= cifs_max_pending)
610 atomic_set(&server->inFlight, cifs_max_pending - 1);
611 /* We do not want to set the max_pending too low or we
612 could end up with the counter going negative */
395 spin_unlock(&GlobalMid_Lock); 613 spin_unlock(&GlobalMid_Lock);
396 /* Although there should not be any requests blocked on 614 /* Although there should not be any requests blocked on
397 this queue it can not hurt to be paranoid and try to wake up requests 615 this queue it can not hurt to be paranoid and try to wake up requests
398 that may haven been blocked when more than 50 at time were on the wire 616 that may haven been blocked when more than 50 at time were on the wire
399 to the same server - they now will see the session is in exit state 617 to the same server - they now will see the session is in exit state
400 and get out of SendReceive. */ 618 and get out of SendReceive. */
401 wake_up_all(&server->request_q); 619 wake_up_all(&server->request_q);
402 /* give those requests time to exit */ 620 /* give those requests time to exit */
403 set_current_state(TASK_INTERRUPTIBLE); 621 msleep(125);
404 schedule_timeout(HZ/8); 622
405
406 if(server->ssocket) { 623 if(server->ssocket) {
407 sock_release(csocket); 624 sock_release(csocket);
408 server->ssocket = NULL; 625 server->ssocket = NULL;
409 } 626 }
410 if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */ 627 /* buffer usuallly freed in free_mid - need to free it here on exit */
411 cifs_buf_release(smb_buffer); 628 if (bigbuf != NULL)
629 cifs_buf_release(bigbuf);
630 if (smallbuf != NULL)
631 cifs_small_buf_release(smallbuf);
412 632
413 read_lock(&GlobalSMBSeslock); 633 read_lock(&GlobalSMBSeslock);
414 if (list_empty(&server->pending_mid_q)) { 634 if (list_empty(&server->pending_mid_q)) {
415 /* loop through server session structures attached to this and mark them dead */ 635 /* loop through server session structures attached to this and
636 mark them dead */
416 list_for_each(tmp, &GlobalSMBSessionList) { 637 list_for_each(tmp, &GlobalSMBSessionList) {
417 ses = 638 ses =
418 list_entry(tmp, struct cifsSesInfo, 639 list_entry(tmp, struct cifsSesInfo,
@@ -424,12 +645,23 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
424 } 645 }
425 read_unlock(&GlobalSMBSeslock); 646 read_unlock(&GlobalSMBSeslock);
426 } else { 647 } else {
648 /* although we can not zero the server struct pointer yet,
649 since there are active requests which may depnd on them,
650 mark the corresponding SMB sessions as exiting too */
651 list_for_each(tmp, &GlobalSMBSessionList) {
652 ses = list_entry(tmp, struct cifsSesInfo,
653 cifsSessionList);
654 if (ses->server == server) {
655 ses->status = CifsExiting;
656 }
657 }
658
427 spin_lock(&GlobalMid_Lock); 659 spin_lock(&GlobalMid_Lock);
428 list_for_each(tmp, &server->pending_mid_q) { 660 list_for_each(tmp, &server->pending_mid_q) {
429 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 661 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
430 if (mid_entry->midState == MID_REQUEST_SUBMITTED) { 662 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
431 cFYI(1, 663 cFYI(1,
432 (" Clearing Mid 0x%x - waking up ",mid_entry->mid)); 664 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
433 task_to_wake = mid_entry->tsk; 665 task_to_wake = mid_entry->tsk;
434 if(task_to_wake) { 666 if(task_to_wake) {
435 wake_up_process(task_to_wake); 667 wake_up_process(task_to_wake);
@@ -438,47 +670,51 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
438 } 670 }
439 spin_unlock(&GlobalMid_Lock); 671 spin_unlock(&GlobalMid_Lock);
440 read_unlock(&GlobalSMBSeslock); 672 read_unlock(&GlobalSMBSeslock);
441 set_current_state(TASK_INTERRUPTIBLE);
442 /* 1/8th of sec is more than enough time for them to exit */ 673 /* 1/8th of sec is more than enough time for them to exit */
443 schedule_timeout(HZ/8); 674 msleep(125);
444 } 675 }
445 676
446 if (list_empty(&server->pending_mid_q)) { 677 if (list_empty(&server->pending_mid_q)) {
447 /* mpx threads have not exited yet give them 678 /* mpx threads have not exited yet give them
448 at least the smb send timeout time for long ops */ 679 at least the smb send timeout time for long ops */
680 /* due to delays on oplock break requests, we need
681 to wait at least 45 seconds before giving up
682 on a request getting a response and going ahead
683 and killing cifsd */
449 cFYI(1, ("Wait for exit from demultiplex thread")); 684 cFYI(1, ("Wait for exit from demultiplex thread"));
450 set_current_state(TASK_INTERRUPTIBLE); 685 msleep(46000);
451 schedule_timeout(46 * HZ);
452 /* if threads still have not exited they are probably never 686 /* if threads still have not exited they are probably never
453 coming home not much else we can do but free the memory */ 687 coming home not much else we can do but free the memory */
454 } 688 }
455 kfree(server);
456 689
457 write_lock(&GlobalSMBSeslock); 690 write_lock(&GlobalSMBSeslock);
458 atomic_dec(&tcpSesAllocCount); 691 atomic_dec(&tcpSesAllocCount);
459 length = tcpSesAllocCount.counter; 692 length = tcpSesAllocCount.counter;
693
694 /* last chance to mark ses pointers invalid
695 if there are any pointing to this (e.g
696 if a crazy root user tried to kill cifsd
697 kernel thread explicitly this might happen) */
698 list_for_each(tmp, &GlobalSMBSessionList) {
699 ses = list_entry(tmp, struct cifsSesInfo,
700 cifsSessionList);
701 if (ses->server == server) {
702 ses->server = NULL;
703 }
704 }
460 write_unlock(&GlobalSMBSeslock); 705 write_unlock(&GlobalSMBSeslock);
706
707 kfree(server);
461 if(length > 0) { 708 if(length > 0) {
462 mempool_resize(cifs_req_poolp, 709 mempool_resize(cifs_req_poolp,
463 length + cifs_min_rcv, 710 length + cifs_min_rcv,
464 GFP_KERNEL); 711 GFP_KERNEL);
465 } 712 }
466 713
467 set_current_state(TASK_INTERRUPTIBLE); 714 msleep(250);
468 schedule_timeout(HZ/4);
469 return 0; 715 return 0;
470} 716}
471 717
472static void *
473cifs_kcalloc(size_t size, unsigned int __nocast type)
474{
475 void *addr;
476 addr = kmalloc(size, type);
477 if (addr)
478 memset(addr, 0, size);
479 return addr;
480}
481
482static int 718static int
483cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) 719cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
484{ 720{
@@ -495,7 +731,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
495 /* does not have to be a perfect mapping since the field is 731 /* does not have to be a perfect mapping since the field is
496 informational, only used for servers that do not support 732 informational, only used for servers that do not support
497 port 445 and it can be overridden at mount time */ 733 port 445 and it can be overridden at mount time */
498 vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]); 734 vol->source_rfc1001_name[i] =
735 toupper(system_utsname.nodename[i]);
499 } 736 }
500 vol->source_rfc1001_name[15] = 0; 737 vol->source_rfc1001_name[15] = 0;
501 738
@@ -570,14 +807,17 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
570 /* NB: password legally can have multiple commas and 807 /* NB: password legally can have multiple commas and
571 the only illegal character in a password is null */ 808 the only illegal character in a password is null */
572 809
573 if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) { 810 if ((value[temp_len] == 0) &&
811 (value[temp_len+1] == separator[0])) {
574 /* reinsert comma */ 812 /* reinsert comma */
575 value[temp_len] = separator[0]; 813 value[temp_len] = separator[0];
576 temp_len+=2; /* move after the second comma */ 814 temp_len+=2; /* move after the second comma */
577 while(value[temp_len] != 0) { 815 while(value[temp_len] != 0) {
578 if (value[temp_len] == separator[0]) { 816 if (value[temp_len] == separator[0]) {
579 if (value[temp_len+1] == separator[0]) { 817 if (value[temp_len+1] ==
580 temp_len++; /* skip second comma */ 818 separator[0]) {
819 /* skip second comma */
820 temp_len++;
581 } else { 821 } else {
582 /* single comma indicating start 822 /* single comma indicating start
583 of next parm */ 823 of next parm */
@@ -596,17 +836,26 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
596 /* go from value to value + temp_len condensing 836 /* go from value to value + temp_len condensing
597 double commas to singles. Note that this ends up 837 double commas to singles. Note that this ends up
598 allocating a few bytes too many, which is ok */ 838 allocating a few bytes too many, which is ok */
599 vol->password = cifs_kcalloc(temp_len, GFP_KERNEL); 839 vol->password = kcalloc(1, temp_len, GFP_KERNEL);
840 if(vol->password == NULL) {
841 printk("CIFS: no memory for pass\n");
842 return 1;
843 }
600 for(i=0,j=0;i<temp_len;i++,j++) { 844 for(i=0,j=0;i<temp_len;i++,j++) {
601 vol->password[j] = value[i]; 845 vol->password[j] = value[i];
602 if(value[i] == separator[0] && value[i+1] == separator[0]) { 846 if(value[i] == separator[0]
847 && value[i+1] == separator[0]) {
603 /* skip second comma */ 848 /* skip second comma */
604 i++; 849 i++;
605 } 850 }
606 } 851 }
607 vol->password[j] = 0; 852 vol->password[j] = 0;
608 } else { 853 } else {
609 vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL); 854 vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
855 if(vol->password == NULL) {
856 printk("CIFS: no memory for pass\n");
857 return 1;
858 }
610 strcpy(vol->password, value); 859 strcpy(vol->password, value);
611 } 860 }
612 } else if (strnicmp(data, "ip", 2) == 0) { 861 } else if (strnicmp(data, "ip", 2) == 0) {
@@ -770,6 +1019,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
770 vol->noperm = 0; 1019 vol->noperm = 0;
771 } else if (strnicmp(data, "noperm", 6) == 0) { 1020 } else if (strnicmp(data, "noperm", 6) == 0) {
772 vol->noperm = 1; 1021 vol->noperm = 1;
1022 } else if (strnicmp(data, "mapchars", 8) == 0) {
1023 vol->remap = 1;
1024 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1025 vol->remap = 0;
773 } else if (strnicmp(data, "setuids", 7) == 0) { 1026 } else if (strnicmp(data, "setuids", 7) == 0) {
774 vol->setuids = 1; 1027 vol->setuids = 1;
775 } else if (strnicmp(data, "nosetuids", 9) == 0) { 1028 } else if (strnicmp(data, "nosetuids", 9) == 0) {
@@ -918,14 +1171,15 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
918 1171
919int 1172int
920connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, 1173connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
921 const char *old_path, const struct nls_table *nls_codepage) 1174 const char *old_path, const struct nls_table *nls_codepage,
1175 int remap)
922{ 1176{
923 unsigned char *referrals = NULL; 1177 unsigned char *referrals = NULL;
924 unsigned int num_referrals; 1178 unsigned int num_referrals;
925 int rc = 0; 1179 int rc = 0;
926 1180
927 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage, 1181 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
928 &num_referrals, &referrals); 1182 &num_referrals, &referrals, remap);
929 1183
930 /* BB Add in code to: if valid refrl, if not ip address contact 1184 /* BB Add in code to: if valid refrl, if not ip address contact
931 the helper that resolves tcp names, mount to it, try to 1185 the helper that resolves tcp names, mount to it, try to
@@ -940,7 +1194,8 @@ connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
940int 1194int
941get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, 1195get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
942 const char *old_path, const struct nls_table *nls_codepage, 1196 const char *old_path, const struct nls_table *nls_codepage,
943 unsigned int *pnum_referrals, unsigned char ** preferrals) 1197 unsigned int *pnum_referrals,
1198 unsigned char ** preferrals, int remap)
944{ 1199{
945 char *temp_unc; 1200 char *temp_unc;
946 int rc = 0; 1201 int rc = 0;
@@ -965,7 +1220,7 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
965 } 1220 }
966 if (rc == 0) 1221 if (rc == 0)
967 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals, 1222 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
968 pnum_referrals, nls_codepage); 1223 pnum_referrals, nls_codepage, remap);
969 1224
970 return rc; 1225 return rc;
971} 1226}
@@ -1062,7 +1317,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1062 sessinit is sent but no second negprot */ 1317 sessinit is sent but no second negprot */
1063 struct rfc1002_session_packet * ses_init_buf; 1318 struct rfc1002_session_packet * ses_init_buf;
1064 struct smb_hdr * smb_buf; 1319 struct smb_hdr * smb_buf;
1065 ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL); 1320 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1066 if(ses_init_buf) { 1321 if(ses_init_buf) {
1067 ses_init_buf->trailer.session_req.called_len = 32; 1322 ses_init_buf->trailer.session_req.called_len = 32;
1068 rfc1002mangle(ses_init_buf->trailer.session_req.called_name, 1323 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
@@ -1352,6 +1607,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1352 } else 1607 } else
1353 rc = 0; 1608 rc = 0;
1354 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); 1609 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1610 srvTcp->sequence_number = 0;
1355 } 1611 }
1356 } 1612 }
1357 1613
@@ -1419,6 +1675,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1419 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; 1675 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1420 if(volume_info.server_ino) 1676 if(volume_info.server_ino)
1421 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; 1677 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1678 if(volume_info.remap)
1679 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1422 if(volume_info.no_xattr) 1680 if(volume_info.no_xattr)
1423 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; 1681 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1424 if(volume_info.direct_io) { 1682 if(volume_info.direct_io) {
@@ -1447,11 +1705,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1447 if ((strchr(volume_info.UNC + 3, '\\') == NULL) 1705 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1448 && (strchr(volume_info.UNC + 3, '/') == 1706 && (strchr(volume_info.UNC + 3, '/') ==
1449 NULL)) { 1707 NULL)) {
1450 rc = connect_to_dfs_path(xid, 1708 rc = connect_to_dfs_path(xid, pSesInfo,
1451 pSesInfo, 1709 "", cifs_sb->local_nls,
1452 "", 1710 cifs_sb->mnt_cifs_flags &
1453 cifs_sb-> 1711 CIFS_MOUNT_MAP_SPECIAL_CHR);
1454 local_nls);
1455 if(volume_info.UNC) 1712 if(volume_info.UNC)
1456 kfree(volume_info.UNC); 1713 kfree(volume_info.UNC);
1457 FreeXid(xid); 1714 FreeXid(xid);
@@ -1514,10 +1771,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1514 tcon->ses = pSesInfo; 1771 tcon->ses = pSesInfo;
1515 1772
1516 /* do not care if following two calls succeed - informational only */ 1773 /* do not care if following two calls succeed - informational only */
1517 CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls); 1774 CIFSSMBQFSDeviceInfo(xid, tcon);
1518 CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls); 1775 CIFSSMBQFSAttributeInfo(xid, tcon);
1519 if (tcon->ses->capabilities & CAP_UNIX) { 1776 if (tcon->ses->capabilities & CAP_UNIX) {
1520 if(!CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls)) { 1777 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1521 if(!volume_info.no_psx_acl) { 1778 if(!volume_info.no_psx_acl) {
1522 if(CIFS_UNIX_POSIX_ACL_CAP & 1779 if(CIFS_UNIX_POSIX_ACL_CAP &
1523 le64_to_cpu(tcon->fsUnixInfo.Capability)) 1780 le64_to_cpu(tcon->fsUnixInfo.Capability))
@@ -1707,7 +1964,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1707/* We look for obvious messed up bcc or strings in response so we do not go off 1964/* We look for obvious messed up bcc or strings in response so we do not go off
1708 the end since (at least) WIN2K and Windows XP have a major bug in not null 1965 the end since (at least) WIN2K and Windows XP have a major bug in not null
1709 terminating last Unicode string in response */ 1966 terminating last Unicode string in response */
1710 ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL); 1967 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
1968 if(ses->serverOS == NULL)
1969 goto sesssetup_nomem;
1711 cifs_strfromUCS_le(ses->serverOS, 1970 cifs_strfromUCS_le(ses->serverOS,
1712 (wchar_t *)bcc_ptr, len,nls_codepage); 1971 (wchar_t *)bcc_ptr, len,nls_codepage);
1713 bcc_ptr += 2 * (len + 1); 1972 bcc_ptr += 2 * (len + 1);
@@ -1717,7 +1976,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1717 if (remaining_words > 0) { 1976 if (remaining_words > 0) {
1718 len = UniStrnlen((wchar_t *)bcc_ptr, 1977 len = UniStrnlen((wchar_t *)bcc_ptr,
1719 remaining_words-1); 1978 remaining_words-1);
1720 ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL); 1979 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
1980 if(ses->serverNOS == NULL)
1981 goto sesssetup_nomem;
1721 cifs_strfromUCS_le(ses->serverNOS, 1982 cifs_strfromUCS_le(ses->serverNOS,
1722 (wchar_t *)bcc_ptr,len,nls_codepage); 1983 (wchar_t *)bcc_ptr,len,nls_codepage);
1723 bcc_ptr += 2 * (len + 1); 1984 bcc_ptr += 2 * (len + 1);
@@ -1730,10 +1991,12 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1730 } 1991 }
1731 remaining_words -= len + 1; 1992 remaining_words -= len + 1;
1732 if (remaining_words > 0) { 1993 if (remaining_words > 0) {
1733 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 1994 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1734 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ 1995 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1735 ses->serverDomain = 1996 ses->serverDomain =
1736 cifs_kcalloc(2*(len+1),GFP_KERNEL); 1997 kcalloc(1, 2*(len+1),GFP_KERNEL);
1998 if(ses->serverDomain == NULL)
1999 goto sesssetup_nomem;
1737 cifs_strfromUCS_le(ses->serverDomain, 2000 cifs_strfromUCS_le(ses->serverDomain,
1738 (wchar_t *)bcc_ptr,len,nls_codepage); 2001 (wchar_t *)bcc_ptr,len,nls_codepage);
1739 bcc_ptr += 2 * (len + 1); 2002 bcc_ptr += 2 * (len + 1);
@@ -1741,21 +2004,25 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1741 ses->serverDomain[1+(2*len)] = 0; 2004 ses->serverDomain[1+(2*len)] = 0;
1742 } /* else no more room so create dummy domain string */ 2005 } /* else no more room so create dummy domain string */
1743 else 2006 else
1744 ses->serverDomain = 2007 ses->serverDomain =
1745 cifs_kcalloc(2, 2008 kcalloc(1, 2, GFP_KERNEL);
1746 GFP_KERNEL);
1747 } else { /* no room so create dummy domain and NOS string */ 2009 } else { /* no room so create dummy domain and NOS string */
2010 /* if these kcallocs fail not much we
2011 can do, but better to not fail the
2012 sesssetup itself */
1748 ses->serverDomain = 2013 ses->serverDomain =
1749 cifs_kcalloc(2, GFP_KERNEL); 2014 kcalloc(1, 2, GFP_KERNEL);
1750 ses->serverNOS = 2015 ses->serverNOS =
1751 cifs_kcalloc(2, GFP_KERNEL); 2016 kcalloc(1, 2, GFP_KERNEL);
1752 } 2017 }
1753 } else { /* ASCII */ 2018 } else { /* ASCII */
1754 len = strnlen(bcc_ptr, 1024); 2019 len = strnlen(bcc_ptr, 1024);
1755 if (((long) bcc_ptr + len) - (long) 2020 if (((long) bcc_ptr + len) - (long)
1756 pByteArea(smb_buffer_response) 2021 pByteArea(smb_buffer_response)
1757 <= BCC(smb_buffer_response)) { 2022 <= BCC(smb_buffer_response)) {
1758 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL); 2023 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2024 if(ses->serverOS == NULL)
2025 goto sesssetup_nomem;
1759 strncpy(ses->serverOS,bcc_ptr, len); 2026 strncpy(ses->serverOS,bcc_ptr, len);
1760 2027
1761 bcc_ptr += len; 2028 bcc_ptr += len;
@@ -1763,14 +2030,18 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1763 bcc_ptr++; 2030 bcc_ptr++;
1764 2031
1765 len = strnlen(bcc_ptr, 1024); 2032 len = strnlen(bcc_ptr, 1024);
1766 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL); 2033 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2034 if(ses->serverNOS == NULL)
2035 goto sesssetup_nomem;
1767 strncpy(ses->serverNOS, bcc_ptr, len); 2036 strncpy(ses->serverNOS, bcc_ptr, len);
1768 bcc_ptr += len; 2037 bcc_ptr += len;
1769 bcc_ptr[0] = 0; 2038 bcc_ptr[0] = 0;
1770 bcc_ptr++; 2039 bcc_ptr++;
1771 2040
1772 len = strnlen(bcc_ptr, 1024); 2041 len = strnlen(bcc_ptr, 1024);
1773 ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL); 2042 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
2043 if(ses->serverDomain == NULL)
2044 goto sesssetup_nomem;
1774 strncpy(ses->serverDomain, bcc_ptr, len); 2045 strncpy(ses->serverDomain, bcc_ptr, len);
1775 bcc_ptr += len; 2046 bcc_ptr += len;
1776 bcc_ptr[0] = 0; 2047 bcc_ptr[0] = 0;
@@ -1790,7 +2061,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1790 smb_buffer_response->WordCount)); 2061 smb_buffer_response->WordCount));
1791 rc = -EIO; 2062 rc = -EIO;
1792 } 2063 }
1793 2064sesssetup_nomem: /* do not return an error on nomem for the info strings,
2065 since that could make reconnection harder, and
2066 reconnection might be needed to free memory */
1794 if (smb_buffer) 2067 if (smb_buffer)
1795 cifs_buf_release(smb_buffer); 2068 cifs_buf_release(smb_buffer);
1796 2069
@@ -1967,7 +2240,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1967 the end since (at least) WIN2K and Windows XP have a major bug in not null 2240 the end since (at least) WIN2K and Windows XP have a major bug in not null
1968 terminating last Unicode string in response */ 2241 terminating last Unicode string in response */
1969 ses->serverOS = 2242 ses->serverOS =
1970 cifs_kcalloc(2 * (len + 1), GFP_KERNEL); 2243 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
1971 cifs_strfromUCS_le(ses->serverOS, 2244 cifs_strfromUCS_le(ses->serverOS,
1972 (wchar_t *) 2245 (wchar_t *)
1973 bcc_ptr, len, 2246 bcc_ptr, len,
@@ -1981,7 +2254,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1981 remaining_words 2254 remaining_words
1982 - 1); 2255 - 1);
1983 ses->serverNOS = 2256 ses->serverNOS =
1984 cifs_kcalloc(2 * (len + 1), 2257 kcalloc(1, 2 * (len + 1),
1985 GFP_KERNEL); 2258 GFP_KERNEL);
1986 cifs_strfromUCS_le(ses->serverNOS, 2259 cifs_strfromUCS_le(ses->serverNOS,
1987 (wchar_t *)bcc_ptr, 2260 (wchar_t *)bcc_ptr,
@@ -1994,7 +2267,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1994 if (remaining_words > 0) { 2267 if (remaining_words > 0) {
1995 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 2268 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1996 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ 2269 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1997 ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL); 2270 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
1998 cifs_strfromUCS_le(ses->serverDomain, 2271 cifs_strfromUCS_le(ses->serverDomain,
1999 (wchar_t *)bcc_ptr, 2272 (wchar_t *)bcc_ptr,
2000 len, 2273 len,
@@ -2005,10 +2278,10 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2005 } /* else no more room so create dummy domain string */ 2278 } /* else no more room so create dummy domain string */
2006 else 2279 else
2007 ses->serverDomain = 2280 ses->serverDomain =
2008 cifs_kcalloc(2,GFP_KERNEL); 2281 kcalloc(1, 2,GFP_KERNEL);
2009 } else { /* no room so create dummy domain and NOS string */ 2282 } else { /* no room so create dummy domain and NOS string */
2010 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL); 2283 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2011 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL); 2284 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2012 } 2285 }
2013 } else { /* ASCII */ 2286 } else { /* ASCII */
2014 2287
@@ -2016,7 +2289,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2016 if (((long) bcc_ptr + len) - (long) 2289 if (((long) bcc_ptr + len) - (long)
2017 pByteArea(smb_buffer_response) 2290 pByteArea(smb_buffer_response)
2018 <= BCC(smb_buffer_response)) { 2291 <= BCC(smb_buffer_response)) {
2019 ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL); 2292 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2020 strncpy(ses->serverOS, bcc_ptr, len); 2293 strncpy(ses->serverOS, bcc_ptr, len);
2021 2294
2022 bcc_ptr += len; 2295 bcc_ptr += len;
@@ -2024,14 +2297,14 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2024 bcc_ptr++; 2297 bcc_ptr++;
2025 2298
2026 len = strnlen(bcc_ptr, 1024); 2299 len = strnlen(bcc_ptr, 1024);
2027 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL); 2300 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2028 strncpy(ses->serverNOS, bcc_ptr, len); 2301 strncpy(ses->serverNOS, bcc_ptr, len);
2029 bcc_ptr += len; 2302 bcc_ptr += len;
2030 bcc_ptr[0] = 0; 2303 bcc_ptr[0] = 0;
2031 bcc_ptr++; 2304 bcc_ptr++;
2032 2305
2033 len = strnlen(bcc_ptr, 1024); 2306 len = strnlen(bcc_ptr, 1024);
2034 ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL); 2307 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2035 strncpy(ses->serverDomain, bcc_ptr, len); 2308 strncpy(ses->serverDomain, bcc_ptr, len);
2036 bcc_ptr += len; 2309 bcc_ptr += len;
2037 bcc_ptr[0] = 0; 2310 bcc_ptr[0] = 0;
@@ -2281,7 +2554,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2281 the end since (at least) WIN2K and Windows XP have a major bug in not null 2554 the end since (at least) WIN2K and Windows XP have a major bug in not null
2282 terminating last Unicode string in response */ 2555 terminating last Unicode string in response */
2283 ses->serverOS = 2556 ses->serverOS =
2284 cifs_kcalloc(2 * (len + 1), GFP_KERNEL); 2557 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2285 cifs_strfromUCS_le(ses->serverOS, 2558 cifs_strfromUCS_le(ses->serverOS,
2286 (wchar_t *) 2559 (wchar_t *)
2287 bcc_ptr, len, 2560 bcc_ptr, len,
@@ -2296,7 +2569,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2296 remaining_words 2569 remaining_words
2297 - 1); 2570 - 1);
2298 ses->serverNOS = 2571 ses->serverNOS =
2299 cifs_kcalloc(2 * (len + 1), 2572 kcalloc(1, 2 * (len + 1),
2300 GFP_KERNEL); 2573 GFP_KERNEL);
2301 cifs_strfromUCS_le(ses-> 2574 cifs_strfromUCS_le(ses->
2302 serverNOS, 2575 serverNOS,
@@ -2313,7 +2586,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2313 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 2586 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2314 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ 2587 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2315 ses->serverDomain = 2588 ses->serverDomain =
2316 cifs_kcalloc(2 * 2589 kcalloc(1, 2 *
2317 (len + 2590 (len +
2318 1), 2591 1),
2319 GFP_KERNEL); 2592 GFP_KERNEL);
@@ -2339,13 +2612,13 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2339 } /* else no more room so create dummy domain string */ 2612 } /* else no more room so create dummy domain string */
2340 else 2613 else
2341 ses->serverDomain = 2614 ses->serverDomain =
2342 cifs_kcalloc(2, 2615 kcalloc(1, 2,
2343 GFP_KERNEL); 2616 GFP_KERNEL);
2344 } else { /* no room so create dummy domain and NOS string */ 2617 } else { /* no room so create dummy domain and NOS string */
2345 ses->serverDomain = 2618 ses->serverDomain =
2346 cifs_kcalloc(2, GFP_KERNEL); 2619 kcalloc(1, 2, GFP_KERNEL);
2347 ses->serverNOS = 2620 ses->serverNOS =
2348 cifs_kcalloc(2, GFP_KERNEL); 2621 kcalloc(1, 2, GFP_KERNEL);
2349 } 2622 }
2350 } else { /* ASCII */ 2623 } else { /* ASCII */
2351 len = strnlen(bcc_ptr, 1024); 2624 len = strnlen(bcc_ptr, 1024);
@@ -2353,7 +2626,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2353 pByteArea(smb_buffer_response) 2626 pByteArea(smb_buffer_response)
2354 <= BCC(smb_buffer_response)) { 2627 <= BCC(smb_buffer_response)) {
2355 ses->serverOS = 2628 ses->serverOS =
2356 cifs_kcalloc(len + 1, 2629 kcalloc(1, len + 1,
2357 GFP_KERNEL); 2630 GFP_KERNEL);
2358 strncpy(ses->serverOS, 2631 strncpy(ses->serverOS,
2359 bcc_ptr, len); 2632 bcc_ptr, len);
@@ -2364,7 +2637,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2364 2637
2365 len = strnlen(bcc_ptr, 1024); 2638 len = strnlen(bcc_ptr, 1024);
2366 ses->serverNOS = 2639 ses->serverNOS =
2367 cifs_kcalloc(len + 1, 2640 kcalloc(1, len + 1,
2368 GFP_KERNEL); 2641 GFP_KERNEL);
2369 strncpy(ses->serverNOS, bcc_ptr, len); 2642 strncpy(ses->serverNOS, bcc_ptr, len);
2370 bcc_ptr += len; 2643 bcc_ptr += len;
@@ -2373,7 +2646,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2373 2646
2374 len = strnlen(bcc_ptr, 1024); 2647 len = strnlen(bcc_ptr, 1024);
2375 ses->serverDomain = 2648 ses->serverDomain =
2376 cifs_kcalloc(len + 1, 2649 kcalloc(1, len + 1,
2377 GFP_KERNEL); 2650 GFP_KERNEL);
2378 strncpy(ses->serverDomain, bcc_ptr, len); 2651 strncpy(ses->serverDomain, bcc_ptr, len);
2379 bcc_ptr += len; 2652 bcc_ptr += len;
@@ -2675,7 +2948,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2675 the end since (at least) WIN2K and Windows XP have a major bug in not null 2948 the end since (at least) WIN2K and Windows XP have a major bug in not null
2676 terminating last Unicode string in response */ 2949 terminating last Unicode string in response */
2677 ses->serverOS = 2950 ses->serverOS =
2678 cifs_kcalloc(2 * (len + 1), GFP_KERNEL); 2951 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2679 cifs_strfromUCS_le(ses->serverOS, 2952 cifs_strfromUCS_le(ses->serverOS,
2680 (wchar_t *) 2953 (wchar_t *)
2681 bcc_ptr, len, 2954 bcc_ptr, len,
@@ -2690,7 +2963,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2690 remaining_words 2963 remaining_words
2691 - 1); 2964 - 1);
2692 ses->serverNOS = 2965 ses->serverNOS =
2693 cifs_kcalloc(2 * (len + 1), 2966 kcalloc(1, 2 * (len + 1),
2694 GFP_KERNEL); 2967 GFP_KERNEL);
2695 cifs_strfromUCS_le(ses-> 2968 cifs_strfromUCS_le(ses->
2696 serverNOS, 2969 serverNOS,
@@ -2706,7 +2979,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2706 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 2979 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2707 /* last string not always null terminated (e.g. for Windows XP & 2000) */ 2980 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2708 ses->serverDomain = 2981 ses->serverDomain =
2709 cifs_kcalloc(2 * 2982 kcalloc(1, 2 *
2710 (len + 2983 (len +
2711 1), 2984 1),
2712 GFP_KERNEL); 2985 GFP_KERNEL);
@@ -2731,17 +3004,17 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2731 = 0; 3004 = 0;
2732 } /* else no more room so create dummy domain string */ 3005 } /* else no more room so create dummy domain string */
2733 else 3006 else
2734 ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL); 3007 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
2735 } else { /* no room so create dummy domain and NOS string */ 3008 } else { /* no room so create dummy domain and NOS string */
2736 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL); 3009 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2737 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL); 3010 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2738 } 3011 }
2739 } else { /* ASCII */ 3012 } else { /* ASCII */
2740 len = strnlen(bcc_ptr, 1024); 3013 len = strnlen(bcc_ptr, 1024);
2741 if (((long) bcc_ptr + len) - 3014 if (((long) bcc_ptr + len) -
2742 (long) pByteArea(smb_buffer_response) 3015 (long) pByteArea(smb_buffer_response)
2743 <= BCC(smb_buffer_response)) { 3016 <= BCC(smb_buffer_response)) {
2744 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL); 3017 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2745 strncpy(ses->serverOS,bcc_ptr, len); 3018 strncpy(ses->serverOS,bcc_ptr, len);
2746 3019
2747 bcc_ptr += len; 3020 bcc_ptr += len;
@@ -2749,14 +3022,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2749 bcc_ptr++; 3022 bcc_ptr++;
2750 3023
2751 len = strnlen(bcc_ptr, 1024); 3024 len = strnlen(bcc_ptr, 1024);
2752 ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL); 3025 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
2753 strncpy(ses->serverNOS, bcc_ptr, len); 3026 strncpy(ses->serverNOS, bcc_ptr, len);
2754 bcc_ptr += len; 3027 bcc_ptr += len;
2755 bcc_ptr[0] = 0; 3028 bcc_ptr[0] = 0;
2756 bcc_ptr++; 3029 bcc_ptr++;
2757 3030
2758 len = strnlen(bcc_ptr, 1024); 3031 len = strnlen(bcc_ptr, 1024);
2759 ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL); 3032 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
2760 strncpy(ses->serverDomain, bcc_ptr, len); 3033 strncpy(ses->serverDomain, bcc_ptr, len);
2761 bcc_ptr += len; 3034 bcc_ptr += len;
2762 bcc_ptr[0] = 0; 3035 bcc_ptr[0] = 0;
@@ -2868,7 +3141,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2868 if(tcon->nativeFileSystem) 3141 if(tcon->nativeFileSystem)
2869 kfree(tcon->nativeFileSystem); 3142 kfree(tcon->nativeFileSystem);
2870 tcon->nativeFileSystem = 3143 tcon->nativeFileSystem =
2871 cifs_kcalloc(length + 2, GFP_KERNEL); 3144 kcalloc(1, length + 2, GFP_KERNEL);
2872 cifs_strfromUCS_le(tcon->nativeFileSystem, 3145 cifs_strfromUCS_le(tcon->nativeFileSystem,
2873 (wchar_t *) bcc_ptr, 3146 (wchar_t *) bcc_ptr,
2874 length, nls_codepage); 3147 length, nls_codepage);
@@ -2886,7 +3159,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2886 if(tcon->nativeFileSystem) 3159 if(tcon->nativeFileSystem)
2887 kfree(tcon->nativeFileSystem); 3160 kfree(tcon->nativeFileSystem);
2888 tcon->nativeFileSystem = 3161 tcon->nativeFileSystem =
2889 cifs_kcalloc(length + 1, GFP_KERNEL); 3162 kcalloc(1, length + 1, GFP_KERNEL);
2890 strncpy(tcon->nativeFileSystem, bcc_ptr, 3163 strncpy(tcon->nativeFileSystem, bcc_ptr,
2891 length); 3164 length);
2892 } 3165 }
@@ -2959,6 +3232,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2959 int rc = 0; 3232 int rc = 0;
2960 char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; 3233 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
2961 int ntlmv2_flag = FALSE; 3234 int ntlmv2_flag = FALSE;
3235 int first_time = 0;
2962 3236
2963 /* what if server changes its buffer size after dropping the session? */ 3237 /* what if server changes its buffer size after dropping the session? */
2964 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ { 3238 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
@@ -2977,12 +3251,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2977 spin_unlock(&GlobalMid_Lock); 3251 spin_unlock(&GlobalMid_Lock);
2978 3252
2979 } 3253 }
3254 first_time = 1;
2980 } 3255 }
2981 if (!rc) { 3256 if (!rc) {
2982 pSesInfo->capabilities = pSesInfo->server->capabilities; 3257 pSesInfo->capabilities = pSesInfo->server->capabilities;
2983 if(linuxExtEnabled == 0) 3258 if(linuxExtEnabled == 0)
2984 pSesInfo->capabilities &= (~CAP_UNIX); 3259 pSesInfo->capabilities &= (~CAP_UNIX);
2985 pSesInfo->sequence_number = 0; 3260 /* pSesInfo->sequence_number = 0;*/
2986 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d", 3261 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
2987 pSesInfo->server->secMode, 3262 pSesInfo->server->secMode,
2988 pSesInfo->server->capabilities, 3263 pSesInfo->server->capabilities,
@@ -3015,7 +3290,10 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3015 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL); 3290 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3016 if(v2_response) { 3291 if(v2_response) {
3017 CalcNTLMv2_response(pSesInfo,v2_response); 3292 CalcNTLMv2_response(pSesInfo,v2_response);
3018/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */ 3293 /* if(first_time)
3294 cifs_calculate_ntlmv2_mac_key(
3295 pSesInfo->server->mac_signing_key,
3296 response, ntlm_session_key, */
3019 kfree(v2_response); 3297 kfree(v2_response);
3020 /* BB Put dummy sig in SessSetup PDU? */ 3298 /* BB Put dummy sig in SessSetup PDU? */
3021 } else { 3299 } else {
@@ -3028,9 +3306,11 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3028 pSesInfo->server->cryptKey, 3306 pSesInfo->server->cryptKey,
3029 ntlm_session_key); 3307 ntlm_session_key);
3030 3308
3031 cifs_calculate_mac_key(pSesInfo->mac_signing_key, 3309 if(first_time)
3032 ntlm_session_key, 3310 cifs_calculate_mac_key(
3033 pSesInfo->password); 3311 pSesInfo->server->mac_signing_key,
3312 ntlm_session_key,
3313 pSesInfo->password);
3034 } 3314 }
3035 /* for better security the weaker lanman hash not sent 3315 /* for better security the weaker lanman hash not sent
3036 in AuthSessSetup so we no longer calculate it */ 3316 in AuthSessSetup so we no longer calculate it */
@@ -3046,8 +3326,11 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3046 pSesInfo->server->cryptKey, 3326 pSesInfo->server->cryptKey,
3047 ntlm_session_key); 3327 ntlm_session_key);
3048 3328
3049 cifs_calculate_mac_key(pSesInfo->mac_signing_key, 3329 if(first_time)
3050 ntlm_session_key, pSesInfo->password); 3330 cifs_calculate_mac_key(
3331 pSesInfo->server->mac_signing_key,
3332 ntlm_session_key, pSesInfo->password);
3333
3051 rc = CIFSSessSetup(xid, pSesInfo, 3334 rc = CIFSSessSetup(xid, pSesInfo,
3052 ntlm_session_key, nls_info); 3335 ntlm_session_key, nls_info);
3053 } 3336 }
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index f54e1866f0f4..e3137aa48cdd 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -101,68 +101,15 @@ cifs_bp_rename_retry:
101 return full_path; 101 return full_path;
102} 102}
103 103
104/* Note: caller must free return buffer */ 104/* char * build_wildcard_path_from_dentry(struct dentry *direntry)
105char *
106build_wildcard_path_from_dentry(struct dentry *direntry)
107{ 105{
108 struct dentry *temp;
109 int namelen = 0;
110 char *full_path;
111
112 if(direntry == NULL)
113 return NULL; /* not much we can do if dentry is freed and
114 we need to reopen the file after it was closed implicitly
115 when the server crashed */
116
117cifs_bwp_rename_retry:
118 for (temp = direntry; !IS_ROOT(temp);) {
119 namelen += (1 + temp->d_name.len);
120 temp = temp->d_parent;
121 if(temp == NULL) {
122 cERROR(1,("corrupt dentry"));
123 return NULL;
124 }
125 }
126
127 full_path = kmalloc(namelen+3, GFP_KERNEL);
128 if(full_path == NULL) 106 if(full_path == NULL)
129 return full_path; 107 return full_path;
130 108
131 full_path[namelen] = '\\'; 109 full_path[namelen] = '\\';
132 full_path[namelen+1] = '*'; 110 full_path[namelen+1] = '*';
133 full_path[namelen+2] = 0; /* trailing null */ 111 full_path[namelen+2] = 0;
134 112BB remove above eight lines BB */
135 for (temp = direntry; !IS_ROOT(temp);) {
136 namelen -= 1 + temp->d_name.len;
137 if (namelen < 0) {
138 break;
139 } else {
140 full_path[namelen] = '\\';
141 strncpy(full_path + namelen + 1, temp->d_name.name,
142 temp->d_name.len);
143 cFYI(0, (" name: %s ", full_path + namelen));
144 }
145 temp = temp->d_parent;
146 if(temp == NULL) {
147 cERROR(1,("corrupt dentry"));
148 kfree(full_path);
149 return NULL;
150 }
151 }
152 if (namelen != 0) {
153 cERROR(1,
154 ("We did not end path lookup where we expected namelen is %d",
155 namelen));
156 /* presumably this is only possible if we were racing with a rename
157 of one of the parent directories (we can not lock the dentries
158 above us to prevent this, but retrying should be harmless) */
159 kfree(full_path);
160 namelen = 0;
161 goto cifs_bwp_rename_retry;
162 }
163
164 return full_path;
165}
166 113
167/* Inode operations in similar order to how they appear in the Linux file fs.h */ 114/* Inode operations in similar order to how they appear in the Linux file fs.h */
168 115
@@ -235,7 +182,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
235 182
236 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, 183 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
237 desiredAccess, CREATE_NOT_DIR, 184 desiredAccess, CREATE_NOT_DIR,
238 &fileHandle, &oplock, buf, cifs_sb->local_nls); 185 &fileHandle, &oplock, buf, cifs_sb->local_nls,
186 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
239 if (rc) { 187 if (rc) {
240 cFYI(1, ("cifs_create returned 0x%x ", rc)); 188 cFYI(1, ("cifs_create returned 0x%x ", rc));
241 } else { 189 } else {
@@ -248,13 +196,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
248 (__u64)current->euid, 196 (__u64)current->euid,
249 (__u64)current->egid, 197 (__u64)current->egid,
250 0 /* dev */, 198 0 /* dev */,
251 cifs_sb->local_nls); 199 cifs_sb->local_nls,
200 cifs_sb->mnt_cifs_flags &
201 CIFS_MOUNT_MAP_SPECIAL_CHR);
252 } else { 202 } else {
253 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, 203 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
254 (__u64)-1, 204 (__u64)-1,
255 (__u64)-1, 205 (__u64)-1,
256 0 /* dev */, 206 0 /* dev */,
257 cifs_sb->local_nls); 207 cifs_sb->local_nls,
208 cifs_sb->mnt_cifs_flags &
209 CIFS_MOUNT_MAP_SPECIAL_CHR);
258 } 210 }
259 else { 211 else {
260 /* BB implement via Windows security descriptors */ 212 /* BB implement via Windows security descriptors */
@@ -284,51 +236,48 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
284 /* mknod case - do not leave file open */ 236 /* mknod case - do not leave file open */
285 CIFSSMBClose(xid, pTcon, fileHandle); 237 CIFSSMBClose(xid, pTcon, fileHandle);
286 } else if(newinode) { 238 } else if(newinode) {
287 pCifsFile = (struct cifsFileInfo *) 239 pCifsFile =
288 kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); 240 kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
289 241
290 if (pCifsFile) { 242 if(pCifsFile == NULL)
291 memset((char *)pCifsFile, 0, 243 goto cifs_create_out;
292 sizeof (struct cifsFileInfo)); 244 memset((char *)pCifsFile, 0,
293 pCifsFile->netfid = fileHandle; 245 sizeof (struct cifsFileInfo));
294 pCifsFile->pid = current->tgid; 246 pCifsFile->netfid = fileHandle;
295 pCifsFile->pInode = newinode; 247 pCifsFile->pid = current->tgid;
296 pCifsFile->invalidHandle = FALSE; 248 pCifsFile->pInode = newinode;
297 pCifsFile->closePend = FALSE; 249 pCifsFile->invalidHandle = FALSE;
298 init_MUTEX(&pCifsFile->fh_sem); 250 pCifsFile->closePend = FALSE;
299 /* put the following in at open now */ 251 init_MUTEX(&pCifsFile->fh_sem);
300 /* pCifsFile->pfile = file; */ 252 /* set the following in open now
301 write_lock(&GlobalSMBSeslock); 253 pCifsFile->pfile = file; */
302 list_add(&pCifsFile->tlist,&pTcon->openFileList); 254 write_lock(&GlobalSMBSeslock);
303 pCifsInode = CIFS_I(newinode); 255 list_add(&pCifsFile->tlist,&pTcon->openFileList);
304 if(pCifsInode) { 256 pCifsInode = CIFS_I(newinode);
257 if(pCifsInode) {
305 /* if readable file instance put first in list*/ 258 /* if readable file instance put first in list*/
306 if (write_only == TRUE) { 259 if (write_only == TRUE) {
307 list_add_tail(&pCifsFile->flist, 260 list_add_tail(&pCifsFile->flist,
308 &pCifsInode->openFileList); 261 &pCifsInode->openFileList);
309 } else { 262 } else {
310 list_add(&pCifsFile->flist, 263 list_add(&pCifsFile->flist,
311 &pCifsInode->openFileList); 264 &pCifsInode->openFileList);
312 }
313 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
314 pCifsInode->clientCanCacheAll = TRUE;
315 pCifsInode->clientCanCacheRead = TRUE;
316 cFYI(1,("Exclusive Oplock granted on inode %p",
317 newinode));
318 } else if((oplock & 0xF) == OPLOCK_READ)
319 pCifsInode->clientCanCacheRead = TRUE;
320 } 265 }
321 write_unlock(&GlobalSMBSeslock); 266 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
267 pCifsInode->clientCanCacheAll = TRUE;
268 pCifsInode->clientCanCacheRead = TRUE;
269 cFYI(1,("Exclusive Oplock for inode %p",
270 newinode));
271 } else if((oplock & 0xF) == OPLOCK_READ)
272 pCifsInode->clientCanCacheRead = TRUE;
322 } 273 }
274 write_unlock(&GlobalSMBSeslock);
323 } 275 }
324 } 276 }
325 277cifs_create_out:
326 if (buf) 278 kfree(buf);
327 kfree(buf); 279 kfree(full_path);
328 if (full_path)
329 kfree(full_path);
330 FreeXid(xid); 280 FreeXid(xid);
331
332 return rc; 281 return rc;
333} 282}
334 283
@@ -359,11 +308,15 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
359 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 308 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
360 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, 309 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
361 mode,(__u64)current->euid,(__u64)current->egid, 310 mode,(__u64)current->euid,(__u64)current->egid,
362 device_number, cifs_sb->local_nls); 311 device_number, cifs_sb->local_nls,
312 cifs_sb->mnt_cifs_flags &
313 CIFS_MOUNT_MAP_SPECIAL_CHR);
363 } else { 314 } else {
364 rc = CIFSSMBUnixSetPerms(xid, pTcon, 315 rc = CIFSSMBUnixSetPerms(xid, pTcon,
365 full_path, mode, (__u64)-1, (__u64)-1, 316 full_path, mode, (__u64)-1, (__u64)-1,
366 device_number, cifs_sb->local_nls); 317 device_number, cifs_sb->local_nls,
318 cifs_sb->mnt_cifs_flags &
319 CIFS_MOUNT_MAP_SPECIAL_CHR);
367 } 320 }
368 321
369 if(!rc) { 322 if(!rc) {
@@ -375,10 +328,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
375 } 328 }
376 } 329 }
377 330
378 if (full_path) 331 kfree(full_path);
379 kfree(full_path);
380 FreeXid(xid); 332 FreeXid(xid);
381
382 return rc; 333 return rc;
383} 334}
384 335
@@ -447,43 +398,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
447 if file exists or not but no access BB */ 398 if file exists or not but no access BB */
448 } 399 }
449 400
450 if (full_path) 401 kfree(full_path);
451 kfree(full_path);
452 FreeXid(xid); 402 FreeXid(xid);
453 return ERR_PTR(rc); 403 return ERR_PTR(rc);
454} 404}
455 405
456int
457cifs_dir_open(struct inode *inode, struct file *file)
458{ /* NB: currently unused since searches are opened in readdir */
459 int rc = 0;
460 int xid;
461 struct cifs_sb_info *cifs_sb;
462 struct cifsTconInfo *pTcon;
463 char *full_path = NULL;
464
465 xid = GetXid();
466
467 cifs_sb = CIFS_SB(inode->i_sb);
468 pTcon = cifs_sb->tcon;
469
470 if(file->f_dentry) {
471 down(&file->f_dentry->d_sb->s_vfs_rename_sem);
472 full_path = build_wildcard_path_from_dentry(file->f_dentry);
473 up(&file->f_dentry->d_sb->s_vfs_rename_sem);
474 } else {
475 FreeXid(xid);
476 return -EIO;
477 }
478
479 cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path));
480
481 if (full_path)
482 kfree(full_path);
483 FreeXid(xid);
484 return rc;
485}
486
487static int 406static int
488cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) 407cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
489{ 408{
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index 9d24c40f1967..7d2a9202c39a 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -92,7 +92,8 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
92 cERROR(1,("cifs dir notify on file %s with arg 0x%lx",full_path,arg)); /* BB removeme BB */ 92 cERROR(1,("cifs dir notify on file %s with arg 0x%lx",full_path,arg)); /* BB removeme BB */
93 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, 93 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
94 GENERIC_READ | SYNCHRONIZE, 0 /* create options */, 94 GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
95 &netfid, &oplock,NULL, cifs_sb->local_nls); 95 &netfid, &oplock,NULL, cifs_sb->local_nls,
96 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
96 /* BB fixme - add this handle to a notify handle list */ 97 /* BB fixme - add this handle to a notify handle list */
97 if(rc) { 98 if(rc) {
98 cERROR(1,("Could not open directory for notify")); /* BB remove BB */ 99 cERROR(1,("Could not open directory for notify")); /* BB remove BB */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index dcab7cf1b53b..dde2d251fc3d 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -254,7 +254,8 @@ int cifs_open(struct inode *inode, struct file *file)
254 } 254 }
255 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, 255 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
256 CREATE_NOT_DIR, &netfid, &oplock, buf, 256 CREATE_NOT_DIR, &netfid, &oplock, buf,
257 cifs_sb->local_nls); 257 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
258 & CIFS_MOUNT_MAP_SPECIAL_CHR);
258 if (rc) { 259 if (rc) {
259 cFYI(1, ("cifs_open returned 0x%x ", rc)); 260 cFYI(1, ("cifs_open returned 0x%x ", rc));
260 goto out; 261 goto out;
@@ -287,7 +288,9 @@ int cifs_open(struct inode *inode, struct file *file)
287 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 288 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
288 inode->i_mode, 289 inode->i_mode,
289 (__u64)-1, (__u64)-1, 0 /* dev */, 290 (__u64)-1, (__u64)-1, 0 /* dev */,
290 cifs_sb->local_nls); 291 cifs_sb->local_nls,
292 cifs_sb->mnt_cifs_flags &
293 CIFS_MOUNT_MAP_SPECIAL_CHR);
291 } else { 294 } else {
292 /* BB implement via Windows security descriptors eg 295 /* BB implement via Windows security descriptors eg
293 CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, 296 CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
@@ -387,7 +390,8 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
387 } */ 390 } */
388 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, 391 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
389 CREATE_NOT_DIR, &netfid, &oplock, NULL, 392 CREATE_NOT_DIR, &netfid, &oplock, NULL,
390 cifs_sb->local_nls); 393 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
394 CIFS_MOUNT_MAP_SPECIAL_CHR);
391 if (rc) { 395 if (rc) {
392 up(&pCifsFile->fh_sem); 396 up(&pCifsFile->fh_sem);
393 cFYI(1, ("cifs_open returned 0x%x ", rc)); 397 cFYI(1, ("cifs_open returned 0x%x ", rc));
@@ -465,8 +469,10 @@ int cifs_close(struct inode *inode, struct file *file)
465 write_lock(&file->f_owner.lock); 469 write_lock(&file->f_owner.lock);
466 } 470 }
467 } 471 }
472 write_lock(&GlobalSMBSeslock);
468 list_del(&pSMBFile->flist); 473 list_del(&pSMBFile->flist);
469 list_del(&pSMBFile->tlist); 474 list_del(&pSMBFile->tlist);
475 write_unlock(&GlobalSMBSeslock);
470 write_unlock(&file->f_owner.lock); 476 write_unlock(&file->f_owner.lock);
471 kfree(pSMBFile->search_resume_name); 477 kfree(pSMBFile->search_resume_name);
472 kfree(file->private_data); 478 kfree(file->private_data);
@@ -506,7 +512,8 @@ int cifs_closedir(struct inode *inode, struct file *file)
506 pTcon = cifs_sb->tcon; 512 pTcon = cifs_sb->tcon;
507 513
508 cFYI(1, ("Freeing private data in close dir")); 514 cFYI(1, ("Freeing private data in close dir"));
509 if (pCFileStruct->srch_inf.endOfSearch == FALSE) { 515 if ((pCFileStruct->srch_inf.endOfSearch == FALSE) &&
516 (pCFileStruct->invalidHandle == FALSE)) {
510 pCFileStruct->invalidHandle = TRUE; 517 pCFileStruct->invalidHandle = TRUE;
511 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid); 518 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
512 cFYI(1, ("Closing uncompleted readdir with rc %d", 519 cFYI(1, ("Closing uncompleted readdir with rc %d",
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index d73b0aa86775..670947288262 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -44,7 +44,8 @@ int cifs_get_inode_info_unix(struct inode **pinode,
44 cFYI(1, (" Getting info on %s ", search_path)); 44 cFYI(1, (" Getting info on %s ", search_path));
45 /* could have done a find first instead but this returns more info */ 45 /* could have done a find first instead but this returns more info */
46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, 46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
47 cifs_sb->local_nls); 47 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
48 CIFS_MOUNT_MAP_SPECIAL_CHR);
48/* dump_mem("\nUnixQPathInfo return data", &findData, 49/* dump_mem("\nUnixQPathInfo return data", &findData,
49 sizeof(findData)); */ 50 sizeof(findData)); */
50 if (rc) { 51 if (rc) {
@@ -63,7 +64,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
63 strncat(tmp_path, search_path, MAX_PATHCONF); 64 strncat(tmp_path, search_path, MAX_PATHCONF);
64 rc = connect_to_dfs_path(xid, pTcon->ses, 65 rc = connect_to_dfs_path(xid, pTcon->ses,
65 /* treename + */ tmp_path, 66 /* treename + */ tmp_path,
66 cifs_sb->local_nls); 67 cifs_sb->local_nls,
68 cifs_sb->mnt_cifs_flags &
69 CIFS_MOUNT_MAP_SPECIAL_CHR);
67 kfree(tmp_path); 70 kfree(tmp_path);
68 71
69 /* BB fix up inode etc. */ 72 /* BB fix up inode etc. */
@@ -210,7 +213,8 @@ int cifs_get_inode_info(struct inode **pinode,
210 pfindData = (FILE_ALL_INFO *)buf; 213 pfindData = (FILE_ALL_INFO *)buf;
211 /* could do find first instead but this returns more info */ 214 /* could do find first instead but this returns more info */
212 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, 215 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
213 cifs_sb->local_nls); 216 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
217 CIFS_MOUNT_MAP_SPECIAL_CHR);
214 } 218 }
215 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ 219 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
216 if (rc) { 220 if (rc) {
@@ -230,7 +234,9 @@ int cifs_get_inode_info(struct inode **pinode,
230 strncat(tmp_path, search_path, MAX_PATHCONF); 234 strncat(tmp_path, search_path, MAX_PATHCONF);
231 rc = connect_to_dfs_path(xid, pTcon->ses, 235 rc = connect_to_dfs_path(xid, pTcon->ses,
232 /* treename + */ tmp_path, 236 /* treename + */ tmp_path,
233 cifs_sb->local_nls); 237 cifs_sb->local_nls,
238 cifs_sb->mnt_cifs_flags &
239 CIFS_MOUNT_MAP_SPECIAL_CHR);
234 kfree(tmp_path); 240 kfree(tmp_path);
235 /* BB fix up inode etc. */ 241 /* BB fix up inode etc. */
236 } else if (rc) { 242 } else if (rc) {
@@ -268,7 +274,9 @@ int cifs_get_inode_info(struct inode **pinode,
268 274
269 rc1 = CIFSGetSrvInodeNumber(xid, pTcon, 275 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
270 search_path, &inode_num, 276 search_path, &inode_num,
271 cifs_sb->local_nls); 277 cifs_sb->local_nls,
278 cifs_sb->mnt_cifs_flags &
279 CIFS_MOUNT_MAP_SPECIAL_CHR);
272 if(rc1) { 280 if(rc1) {
273 cFYI(1,("GetSrvInodeNum rc %d", rc1)); 281 cFYI(1,("GetSrvInodeNum rc %d", rc1));
274 /* BB EOPNOSUPP disable SERVER_INUM? */ 282 /* BB EOPNOSUPP disable SERVER_INUM? */
@@ -410,7 +418,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
410 FreeXid(xid); 418 FreeXid(xid);
411 return -ENOMEM; 419 return -ENOMEM;
412 } 420 }
413 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls); 421 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
422 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
414 423
415 if (!rc) { 424 if (!rc) {
416 direntry->d_inode->i_nlink--; 425 direntry->d_inode->i_nlink--;
@@ -422,10 +431,14 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
422 431
423 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE, 432 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
424 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, 433 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
425 &netfid, &oplock, NULL, cifs_sb->local_nls); 434 &netfid, &oplock, NULL, cifs_sb->local_nls,
435 cifs_sb->mnt_cifs_flags &
436 CIFS_MOUNT_MAP_SPECIAL_CHR);
426 if (rc==0) { 437 if (rc==0) {
427 CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL, 438 CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
428 cifs_sb->local_nls); 439 cifs_sb->local_nls,
440 cifs_sb->mnt_cifs_flags &
441 CIFS_MOUNT_MAP_SPECIAL_CHR);
429 CIFSSMBClose(xid, pTcon, netfid); 442 CIFSSMBClose(xid, pTcon, netfid);
430 direntry->d_inode->i_nlink--; 443 direntry->d_inode->i_nlink--;
431 } 444 }
@@ -439,7 +452,9 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
439 if (!(pTcon->ses->flags & CIFS_SES_NT4)) 452 if (!(pTcon->ses->flags & CIFS_SES_NT4))
440 rc = CIFSSMBSetTimes(xid, pTcon, full_path, 453 rc = CIFSSMBSetTimes(xid, pTcon, full_path,
441 pinfo_buf, 454 pinfo_buf,
442 cifs_sb->local_nls); 455 cifs_sb->local_nls,
456 cifs_sb->mnt_cifs_flags &
457 CIFS_MOUNT_MAP_SPECIAL_CHR);
443 else 458 else
444 rc = -EOPNOTSUPP; 459 rc = -EOPNOTSUPP;
445 460
@@ -461,7 +476,9 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
461 FILE_OPEN, SYNCHRONIZE | 476 FILE_OPEN, SYNCHRONIZE |
462 FILE_WRITE_ATTRIBUTES, 0, 477 FILE_WRITE_ATTRIBUTES, 0,
463 &netfid, &oplock, NULL, 478 &netfid, &oplock, NULL,
464 cifs_sb->local_nls); 479 cifs_sb->local_nls,
480 cifs_sb->mnt_cifs_flags &
481 CIFS_MOUNT_MAP_SPECIAL_CHR);
465 if (rc==0) { 482 if (rc==0) {
466 rc = CIFSSMBSetFileTimes(xid, pTcon, 483 rc = CIFSSMBSetFileTimes(xid, pTcon,
467 pinfo_buf, 484 pinfo_buf,
@@ -472,8 +489,10 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
472 kfree(pinfo_buf); 489 kfree(pinfo_buf);
473 } 490 }
474 if (rc==0) { 491 if (rc==0) {
475 rc = CIFSSMBDelFile(xid, pTcon, full_path, 492 rc = CIFSSMBDelFile(xid, pTcon, full_path,
476 cifs_sb->local_nls); 493 cifs_sb->local_nls,
494 cifs_sb->mnt_cifs_flags &
495 CIFS_MOUNT_MAP_SPECIAL_CHR);
477 if (!rc) { 496 if (!rc) {
478 direntry->d_inode->i_nlink--; 497 direntry->d_inode->i_nlink--;
479 } else if (rc == -ETXTBSY) { 498 } else if (rc == -ETXTBSY) {
@@ -485,11 +504,15 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
485 CREATE_NOT_DIR | 504 CREATE_NOT_DIR |
486 CREATE_DELETE_ON_CLOSE, 505 CREATE_DELETE_ON_CLOSE,
487 &netfid, &oplock, NULL, 506 &netfid, &oplock, NULL,
488 cifs_sb->local_nls); 507 cifs_sb->local_nls,
508 cifs_sb->mnt_cifs_flags &
509 CIFS_MOUNT_MAP_SPECIAL_CHR);
489 if (rc==0) { 510 if (rc==0) {
490 CIFSSMBRenameOpenFile(xid, pTcon, 511 CIFSSMBRenameOpenFile(xid, pTcon,
491 netfid, NULL, 512 netfid, NULL,
492 cifs_sb->local_nls); 513 cifs_sb->local_nls,
514 cifs_sb->mnt_cifs_flags &
515 CIFS_MOUNT_MAP_SPECIAL_CHR);
493 CIFSSMBClose(xid, pTcon, netfid); 516 CIFSSMBClose(xid, pTcon, netfid);
494 direntry->d_inode->i_nlink--; 517 direntry->d_inode->i_nlink--;
495 } 518 }
@@ -534,7 +557,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
534 return -ENOMEM; 557 return -ENOMEM;
535 } 558 }
536 /* BB add setting the equivalent of mode via CreateX w/ACLs */ 559 /* BB add setting the equivalent of mode via CreateX w/ACLs */
537 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls); 560 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
561 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
538 if (rc) { 562 if (rc) {
539 cFYI(1, ("cifs_mkdir returned 0x%x ", rc)); 563 cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
540 d_drop(direntry); 564 d_drop(direntry);
@@ -558,12 +582,16 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
558 (__u64)current->euid, 582 (__u64)current->euid,
559 (__u64)current->egid, 583 (__u64)current->egid,
560 0 /* dev_t */, 584 0 /* dev_t */,
561 cifs_sb->local_nls); 585 cifs_sb->local_nls,
586 cifs_sb->mnt_cifs_flags &
587 CIFS_MOUNT_MAP_SPECIAL_CHR);
562 } else { 588 } else {
563 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 589 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
564 mode, (__u64)-1, 590 mode, (__u64)-1,
565 (__u64)-1, 0 /* dev_t */, 591 (__u64)-1, 0 /* dev_t */,
566 cifs_sb->local_nls); 592 cifs_sb->local_nls,
593 cifs_sb->mnt_cifs_flags &
594 CIFS_MOUNT_MAP_SPECIAL_CHR);
567 } 595 }
568 else { 596 else {
569 /* BB to be implemented via Windows secrty descriptors 597 /* BB to be implemented via Windows secrty descriptors
@@ -600,7 +628,8 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
600 return -ENOMEM; 628 return -ENOMEM;
601 } 629 }
602 630
603 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls); 631 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
632 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
604 633
605 if (!rc) { 634 if (!rc) {
606 inode->i_nlink--; 635 inode->i_nlink--;
@@ -653,7 +682,9 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
653 } 682 }
654 683
655 rc = CIFSSMBRename(xid, pTcon, fromName, toName, 684 rc = CIFSSMBRename(xid, pTcon, fromName, toName,
656 cifs_sb_source->local_nls); 685 cifs_sb_source->local_nls,
686 cifs_sb_source->mnt_cifs_flags &
687 CIFS_MOUNT_MAP_SPECIAL_CHR);
657 if (rc == -EEXIST) { 688 if (rc == -EEXIST) {
658 /* check if they are the same file because rename of hardlinked 689 /* check if they are the same file because rename of hardlinked
659 files is a noop */ 690 files is a noop */
@@ -665,11 +696,16 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
665 if (info_buf_source != NULL) { 696 if (info_buf_source != NULL) {
666 info_buf_target = info_buf_source + 1; 697 info_buf_target = info_buf_source + 1;
667 rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName, 698 rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
668 info_buf_source, cifs_sb_source->local_nls); 699 info_buf_source, cifs_sb_source->local_nls,
700 cifs_sb_source->mnt_cifs_flags &
701 CIFS_MOUNT_MAP_SPECIAL_CHR);
669 if (rc == 0) { 702 if (rc == 0) {
670 rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName, 703 rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
671 info_buf_target, 704 info_buf_target,
672 cifs_sb_target->local_nls); 705 cifs_sb_target->local_nls,
706 /* remap based on source sb */
707 cifs_sb_source->mnt_cifs_flags &
708 CIFS_MOUNT_MAP_SPECIAL_CHR);
673 } 709 }
674 if ((rc == 0) && 710 if ((rc == 0) &&
675 (info_buf_source->UniqueId == 711 (info_buf_source->UniqueId ==
@@ -685,7 +721,9 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
685 cifs_unlink(target_inode, target_direntry); 721 cifs_unlink(target_inode, target_direntry);
686 rc = CIFSSMBRename(xid, pTcon, fromName, 722 rc = CIFSSMBRename(xid, pTcon, fromName,
687 toName, 723 toName,
688 cifs_sb_source->local_nls); 724 cifs_sb_source->local_nls,
725 cifs_sb_source->mnt_cifs_flags
726 & CIFS_MOUNT_MAP_SPECIAL_CHR);
689 } 727 }
690 kfree(info_buf_source); 728 kfree(info_buf_source);
691 } /* if we can not get memory just leave rc as EEXIST */ 729 } /* if we can not get memory just leave rc as EEXIST */
@@ -705,10 +743,14 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
705 might not right be right access to request */ 743 might not right be right access to request */
706 rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ, 744 rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
707 CREATE_NOT_DIR, &netfid, &oplock, NULL, 745 CREATE_NOT_DIR, &netfid, &oplock, NULL,
708 cifs_sb_source->local_nls); 746 cifs_sb_source->local_nls,
747 cifs_sb_source->mnt_cifs_flags &
748 CIFS_MOUNT_MAP_SPECIAL_CHR);
709 if (rc==0) { 749 if (rc==0) {
710 CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName, 750 CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
711 cifs_sb_source->local_nls); 751 cifs_sb_source->local_nls,
752 cifs_sb_source->mnt_cifs_flags &
753 CIFS_MOUNT_MAP_SPECIAL_CHR);
712 CIFSSMBClose(xid, pTcon, netfid); 754 CIFSSMBClose(xid, pTcon, netfid);
713 } 755 }
714 } 756 }
@@ -962,7 +1004,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
962 it by handle */ 1004 it by handle */
963 rc = CIFSSMBSetEOF(xid, pTcon, full_path, 1005 rc = CIFSSMBSetEOF(xid, pTcon, full_path,
964 attrs->ia_size, FALSE, 1006 attrs->ia_size, FALSE,
965 cifs_sb->local_nls); 1007 cifs_sb->local_nls,
1008 cifs_sb->mnt_cifs_flags &
1009 CIFS_MOUNT_MAP_SPECIAL_CHR);
966 cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc)); 1010 cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc));
967 } 1011 }
968 1012
@@ -999,7 +1043,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
999 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) 1043 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
1000 && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID))) 1044 && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
1001 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid, 1045 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
1002 0 /* dev_t */, cifs_sb->local_nls); 1046 0 /* dev_t */, cifs_sb->local_nls,
1047 cifs_sb->mnt_cifs_flags &
1048 CIFS_MOUNT_MAP_SPECIAL_CHR);
1003 else if (attrs->ia_valid & ATTR_MODE) { 1049 else if (attrs->ia_valid & ATTR_MODE) {
1004 if ((mode & S_IWUGO) == 0) /* not writeable */ { 1050 if ((mode & S_IWUGO) == 0) /* not writeable */ {
1005 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) 1051 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
@@ -1048,7 +1094,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1048 via Handle (SetFileInfo) instead of by path */ 1094 via Handle (SetFileInfo) instead of by path */
1049 if (!(pTcon->ses->flags & CIFS_SES_NT4)) 1095 if (!(pTcon->ses->flags & CIFS_SES_NT4))
1050 rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf, 1096 rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
1051 cifs_sb->local_nls); 1097 cifs_sb->local_nls,
1098 cifs_sb->mnt_cifs_flags &
1099 CIFS_MOUNT_MAP_SPECIAL_CHR);
1052 else 1100 else
1053 rc = -EOPNOTSUPP; 1101 rc = -EOPNOTSUPP;
1054 1102
@@ -1063,7 +1111,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1063 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, 1111 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
1064 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, 1112 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1065 CREATE_NOT_DIR, &netfid, &oplock, 1113 CREATE_NOT_DIR, &netfid, &oplock,
1066 NULL, cifs_sb->local_nls); 1114 NULL, cifs_sb->local_nls,
1115 cifs_sb->mnt_cifs_flags &
1116 CIFS_MOUNT_MAP_SPECIAL_CHR);
1067 if (rc==0) { 1117 if (rc==0) {
1068 rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf, 1118 rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
1069 netfid); 1119 netfid);
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index b4b8e201d428..b0ea6687ab55 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -20,30 +20,93 @@
20 * along with this library; if not, write to the Free Software 20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */ 22 */
23
23#include <linux/fs.h> 24#include <linux/fs.h>
24#include <linux/ext2_fs.h> 25#include <linux/ext2_fs.h>
25#include "cifspdu.h" 26#include "cifspdu.h"
26#include "cifsglob.h" 27#include "cifsglob.h"
27#include "cifsproto.h" 28#include "cifsproto.h"
28#include "cifs_debug.h" 29#include "cifs_debug.h"
30#include "cifsfs.h"
31
32#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
29 33
30int cifs_ioctl (struct inode * inode, struct file * filep, 34int cifs_ioctl (struct inode * inode, struct file * filep,
31 unsigned int command, unsigned long arg) 35 unsigned int command, unsigned long arg)
32{ 36{
33 int rc = -ENOTTY; /* strange error - but the precedent */ 37 int rc = -ENOTTY; /* strange error - but the precedent */
38 int xid;
39 struct cifs_sb_info *cifs_sb;
40#ifdef CONFIG_CIFS_POSIX
41 __u64 ExtAttrBits = 0;
42 __u64 ExtAttrMask = 0;
43 __u64 caps;
44 struct cifsTconInfo *tcon;
45 struct cifsFileInfo *pSMBFile =
46 (struct cifsFileInfo *)filep->private_data;
47#endif /* CONFIG_CIFS_POSIX */
48
49 xid = GetXid();
50
51 cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg));
52
53 cifs_sb = CIFS_SB(inode->i_sb);
54
34#ifdef CONFIG_CIFS_POSIX 55#ifdef CONFIG_CIFS_POSIX
35 cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg)); 56 tcon = cifs_sb->tcon;
57 if(tcon)
58 caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
59 else {
60 rc = -EIO;
61 FreeXid(xid);
62 return -EIO;
63 }
64#endif /* CONFIG_CIFS_POSIX */
65
36 switch(command) { 66 switch(command) {
67 case CIFS_IOC_CHECKUMOUNT:
68 cFYI(1,("User unmount attempted"));
69 if(cifs_sb->mnt_uid == current->uid)
70 rc = 0;
71 else {
72 rc = -EACCES;
73 cFYI(1,("uids do not match"));
74 }
75 break;
76#ifdef CONFIG_CIFS_POSIX
37 case EXT2_IOC_GETFLAGS: 77 case EXT2_IOC_GETFLAGS:
38 cFYI(1,("get flags not implemented yet")); 78 if(CIFS_UNIX_EXTATTR_CAP & caps) {
39 return -EOPNOTSUPP; 79 if (pSMBFile == NULL)
80 break;
81 rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid,
82 &ExtAttrBits, &ExtAttrMask);
83 if(rc == 0)
84 rc = put_user(ExtAttrBits &
85 EXT2_FL_USER_VISIBLE,
86 (int __user *)arg);
87 }
88 break;
89
40 case EXT2_IOC_SETFLAGS: 90 case EXT2_IOC_SETFLAGS:
91 if(CIFS_UNIX_EXTATTR_CAP & caps) {
92 if(get_user(ExtAttrBits,(int __user *)arg)) {
93 rc = -EFAULT;
94 break;
95 }
96 if (pSMBFile == NULL)
97 break;
98 /* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid,
99 extAttrBits, &ExtAttrMask);*/
100
101 }
41 cFYI(1,("set flags not implemented yet")); 102 cFYI(1,("set flags not implemented yet"));
42 return -EOPNOTSUPP; 103 break;
104#endif /* CONFIG_CIFS_POSIX */
43 default: 105 default:
44 cFYI(1,("unsupported ioctl")); 106 cFYI(1,("unsupported ioctl"));
45 return rc; 107 break;
46 } 108 }
47#endif /* CONFIG_CIFS_POSIX */ 109
110 FreeXid(xid);
48 return rc; 111 return rc;
49} 112}
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 1455810ba1cb..bde0fabfece0 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -59,10 +59,14 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
59 59
60 if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX) 60 if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
61 rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, 61 rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
62 cifs_sb_target->local_nls); 62 cifs_sb_target->local_nls,
63 cifs_sb_target->mnt_cifs_flags &
64 CIFS_MOUNT_MAP_SPECIAL_CHR);
63 else { 65 else {
64 rc = CIFSCreateHardLink(xid, pTcon, fromName, toName, 66 rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
65 cifs_sb_target->local_nls); 67 cifs_sb_target->local_nls,
68 cifs_sb_target->mnt_cifs_flags &
69 CIFS_MOUNT_MAP_SPECIAL_CHR);
66 if(rc == -EIO) 70 if(rc == -EIO)
67 rc = -EOPNOTSUPP; 71 rc = -EOPNOTSUPP;
68 } 72 }
@@ -260,7 +264,10 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
260 cifs_sb->local_nls); 264 cifs_sb->local_nls);
261 else { 265 else {
262 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, 266 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
263 OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls); 267 OPEN_REPARSE_POINT,&fid, &oplock, NULL,
268 cifs_sb->local_nls,
269 cifs_sb->mnt_cifs_flags &
270 CIFS_MOUNT_MAP_SPECIAL_CHR);
264 if(!rc) { 271 if(!rc) {
265 rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path, 272 rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
266 tmpbuffer, 273 tmpbuffer,
@@ -279,7 +286,10 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
279 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); 286 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
280 strncat(tmp_path, full_path, MAX_PATHCONF); 287 strncat(tmp_path, full_path, MAX_PATHCONF);
281 rc = get_dfs_path(xid, pTcon->ses, tmp_path, 288 rc = get_dfs_path(xid, pTcon->ses, tmp_path,
282 cifs_sb->local_nls, &num_referrals, &referrals); 289 cifs_sb->local_nls,
290 &num_referrals, &referrals,
291 cifs_sb->mnt_cifs_flags &
292 CIFS_MOUNT_MAP_SPECIAL_CHR);
283 cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc)); 293 cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
284 if((num_referrals == 0) && (rc == 0)) 294 if((num_referrals == 0) && (rc == 0))
285 rc = -EACCES; 295 rc = -EACCES;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 7b38d3059a83..db14b503d89e 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -28,6 +28,7 @@
28#include "cifs_debug.h" 28#include "cifs_debug.h"
29#include "smberr.h" 29#include "smberr.h"
30#include "nterr.h" 30#include "nterr.h"
31#include "cifs_unicode.h"
31 32
32extern mempool_t *cifs_sm_req_poolp; 33extern mempool_t *cifs_sm_req_poolp;
33extern mempool_t *cifs_req_poolp; 34extern mempool_t *cifs_req_poolp;
@@ -451,25 +452,30 @@ is_valid_oplock_break(struct smb_hdr *buf)
451 atomic_inc(&tcon->num_oplock_brks); 452 atomic_inc(&tcon->num_oplock_brks);
452#endif 453#endif
453 list_for_each(tmp1,&tcon->openFileList){ 454 list_for_each(tmp1,&tcon->openFileList){
454 netfile = list_entry(tmp1,struct cifsFileInfo,tlist); 455 netfile = list_entry(tmp1,struct cifsFileInfo,
456 tlist);
455 if(pSMB->Fid == netfile->netfid) { 457 if(pSMB->Fid == netfile->netfid) {
456 struct cifsInodeInfo *pCifsInode; 458 struct cifsInodeInfo *pCifsInode;
457 read_unlock(&GlobalSMBSeslock); 459 read_unlock(&GlobalSMBSeslock);
458 cFYI(1,("Matching file id, processing oplock break")); 460 cFYI(1,("file id match, oplock break"));
459 pCifsInode = 461 pCifsInode =
460 CIFS_I(netfile->pInode); 462 CIFS_I(netfile->pInode);
461 pCifsInode->clientCanCacheAll = FALSE; 463 pCifsInode->clientCanCacheAll = FALSE;
462 if(pSMB->OplockLevel == 0) 464 if(pSMB->OplockLevel == 0)
463 pCifsInode->clientCanCacheRead = FALSE; 465 pCifsInode->clientCanCacheRead
466 = FALSE;
464 pCifsInode->oplockPending = TRUE; 467 pCifsInode->oplockPending = TRUE;
465 AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon); 468 AllocOplockQEntry(netfile->pInode,
469 netfile->netfid,
470 tcon);
466 cFYI(1,("about to wake up oplock thd")); 471 cFYI(1,("about to wake up oplock thd"));
467 wake_up_process(oplockThread); 472 if(oplockThread)
473 wake_up_process(oplockThread);
468 return TRUE; 474 return TRUE;
469 } 475 }
470 } 476 }
471 read_unlock(&GlobalSMBSeslock); 477 read_unlock(&GlobalSMBSeslock);
472 cFYI(1,("No matching file for oplock break on connection")); 478 cFYI(1,("No matching file for oplock break"));
473 return TRUE; 479 return TRUE;
474 } 480 }
475 } 481 }
@@ -490,7 +496,7 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
490 496
491 buffer = (unsigned char *) smb_buf; 497 buffer = (unsigned char *) smb_buf;
492 for (i = 0, j = 0; i < smb_buf_length; i++, j++) { 498 for (i = 0, j = 0; i < smb_buf_length; i++, j++) {
493 if (i % 8 == 0) { /* we have reached the beginning of line */ 499 if (i % 8 == 0) { /* have reached the beginning of line */
494 printk(KERN_DEBUG "| "); 500 printk(KERN_DEBUG "| ");
495 j = 0; 501 j = 0;
496 } 502 }
@@ -501,7 +507,7 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
501 else 507 else
502 debug_line[1 + (2 * j)] = '_'; 508 debug_line[1 + (2 * j)] = '_';
503 509
504 if (i % 8 == 7) { /* we have reached end of line, time to print ascii */ 510 if (i % 8 == 7) { /* reached end of line, time to print ascii */
505 debug_line[16] = 0; 511 debug_line[16] = 0;
506 printk(" | %s\n", debug_line); 512 printk(" | %s\n", debug_line);
507 } 513 }
@@ -514,3 +520,141 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
514 printk( " | %s\n", debug_line); 520 printk( " | %s\n", debug_line);
515 return; 521 return;
516} 522}
523
524/* Windows maps these to the user defined 16 bit Unicode range since they are
525 reserved symbols (along with \ and /), otherwise illegal to store
526 in filenames in NTFS */
527#define UNI_ASTERIK (__u16) ('*' + 0xF000)
528#define UNI_QUESTION (__u16) ('?' + 0xF000)
529#define UNI_COLON (__u16) (':' + 0xF000)
530#define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
531#define UNI_LESSTHAN (__u16) ('<' + 0xF000)
532#define UNI_PIPE (__u16) ('|' + 0xF000)
533#define UNI_SLASH (__u16) ('\\' + 0xF000)
534
535/* Convert 16 bit Unicode pathname from wire format to string in current code
536 page. Conversion may involve remapping up the seven characters that are
537 only legal in POSIX-like OS (if they are present in the string). Path
538 names are little endian 16 bit Unicode on the wire */
539int
540cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
541 const struct nls_table * cp)
542{
543 int i,j,len;
544 __u16 src_char;
545
546 for(i = 0, j = 0; i < maxlen; i++) {
547 src_char = le16_to_cpu(source[i]);
548 switch (src_char) {
549 case 0:
550 goto cUCS_out; /* BB check this BB */
551 case UNI_COLON:
552 target[j] = ':';
553 break;
554 case UNI_ASTERIK:
555 target[j] = '*';
556 break;
557 case UNI_QUESTION:
558 target[j] = '?';
559 break;
560 /* BB We can not handle remapping slash until
561 all the calls to build_path_from_dentry
562 are modified, as they use slash as separator BB */
563 /* case UNI_SLASH:
564 target[j] = '\\';
565 break;*/
566 case UNI_PIPE:
567 target[j] = '|';
568 break;
569 case UNI_GRTRTHAN:
570 target[j] = '>';
571 break;
572 case UNI_LESSTHAN:
573 target[j] = '<';
574 default:
575 len = cp->uni2char(src_char, &target[j],
576 NLS_MAX_CHARSET_SIZE);
577 if(len > 0) {
578 j += len;
579 continue;
580 } else {
581 target[j] = '?';
582 }
583 }
584 j++;
585 /* make sure we do not overrun callers allocated temp buffer */
586 if(j >= (2 * NAME_MAX))
587 break;
588 }
589cUCS_out:
590 target[j] = 0;
591 return j;
592}
593
594/* Convert 16 bit Unicode pathname to wire format from string in current code
595 page. Conversion may involve remapping up the seven characters that are
596 only legal in POSIX-like OS (if they are present in the string). Path
597 names are little endian 16 bit Unicode on the wire */
598int
599cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
600 const struct nls_table * cp, int mapChars)
601{
602 int i,j,charlen;
603 int len_remaining = maxlen;
604 char src_char;
605
606 if(!mapChars)
607 return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp);
608
609 for(i = 0, j = 0; i < maxlen; j++) {
610 src_char = source[i];
611 switch (src_char) {
612 case 0:
613 goto ctoUCS_out;
614 case ':':
615 target[j] = cpu_to_le16(UNI_COLON);
616 break;
617 case '*':
618 target[j] = cpu_to_le16(UNI_ASTERIK);
619 break;
620 case '?':
621 target[j] = cpu_to_le16(UNI_QUESTION);
622 break;
623 case '<':
624 target[j] = cpu_to_le16(UNI_LESSTHAN);
625 break;
626 case '>':
627 target[j] = cpu_to_le16(UNI_GRTRTHAN);
628 break;
629 case '|':
630 target[j] = cpu_to_le16(UNI_PIPE);
631 break;
632 /* BB We can not handle remapping slash until
633 all the calls to build_path_from_dentry
634 are modified, as they use slash as separator BB */
635 /* case '\\':
636 target[j] = cpu_to_le16(UNI_SLASH);
637 break;*/
638 default:
639 charlen = cp->char2uni(source+i,
640 len_remaining, target+j);
641 /* if no match, use question mark, which
642 at least in some cases servers as wild card */
643 if(charlen < 1) {
644 target[j] = cpu_to_le16(0x003f);
645 charlen = 1;
646 }
647 len_remaining -= charlen;
648 /* character may take more than one byte in the
649 the source string, but will take exactly two
650 bytes in the target string */
651 i+= charlen;
652 continue;
653 }
654 i++; /* move to next char in source string */
655 len_remaining--;
656 }
657
658ctoUCS_out:
659 return i;
660}
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 4e34c89cec5d..a92af41d4411 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -78,6 +78,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
78 {ErrQuota, -EDQUOT}, 78 {ErrQuota, -EDQUOT},
79 {ErrNotALink, -ENOLINK}, 79 {ErrNotALink, -ENOLINK},
80 {ERRnetlogonNotStarted,-ENOPROTOOPT}, 80 {ERRnetlogonNotStarted,-ENOPROTOOPT},
81 {ErrTooManyLinks,-EMLINK},
81 {0, 0} 82 {0, 0}
82}; 83};
83 84
@@ -206,7 +207,7 @@ static const struct {
206 { 207 {
207 ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, { 208 ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, {
208 ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, { 209 ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, {
209 ERRDOS, 87, NT_STATUS_INVALID_INFO_CLASS}, { 210 ERRDOS, ERRinvlevel, NT_STATUS_INVALID_INFO_CLASS}, {
210 ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, { 211 ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, {
211 ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, { 212 ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, {
212 ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, { 213 ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, {
@@ -742,7 +743,7 @@ static const struct {
742 ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, { 743 ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, {
743 ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, { 744 ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, {
744 ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, { 745 ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, {
745 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LINKS}, { 746 ERRDOS, ErrTooManyLinks, NT_STATUS_TOO_MANY_LINKS}, {
746 ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, { 747 ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, {
747 ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, { 748 ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, {
748 ERRDOS, 21, 0xc000026e}, { 749 ERRDOS, 21, 0xc000026e}, {
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index f8bea395ec9e..22557716f9af 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Directory search handling 4 * Directory search handling
5 * 5 *
6 * Copyright (C) International Business Machines Corp., 2004 6 * Copyright (C) International Business Machines Corp., 2004, 2005
7 * Author(s): Steve French (sfrench@us.ibm.com) 7 * Author(s): Steve French (sfrench@us.ibm.com)
8 * 8 *
9 * This library is free software; you can redistribute it and/or modify 9 * This library is free software; you can redistribute it and/or modify
@@ -65,14 +65,14 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
65 struct cifsTconInfo *pTcon; 65 struct cifsTconInfo *pTcon;
66 int rc = 0; 66 int rc = 0;
67 67
68 cFYI(1, ("For %s ", qstring->name)); 68 cFYI(1, ("For %s", qstring->name));
69 cifs_sb = CIFS_SB(file->f_dentry->d_sb); 69 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
70 pTcon = cifs_sb->tcon; 70 pTcon = cifs_sb->tcon;
71 71
72 qstring->hash = full_name_hash(qstring->name, qstring->len); 72 qstring->hash = full_name_hash(qstring->name, qstring->len);
73 tmp_dentry = d_lookup(file->f_dentry, qstring); 73 tmp_dentry = d_lookup(file->f_dentry, qstring);
74 if (tmp_dentry) { 74 if (tmp_dentry) {
75 cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode)); 75 cFYI(0, ("existing dentry with inode 0x%p", tmp_dentry->d_inode));
76 *ptmp_inode = tmp_dentry->d_inode; 76 *ptmp_inode = tmp_dentry->d_inode;
77/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/ 77/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
78 if(*ptmp_inode == NULL) { 78 if(*ptmp_inode == NULL) {
@@ -105,8 +105,11 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
105} 105}
106 106
107static void fill_in_inode(struct inode *tmp_inode, 107static void fill_in_inode(struct inode *tmp_inode,
108 FILE_DIRECTORY_INFO *pfindData, int *pobject_type) 108 FILE_DIRECTORY_INFO *pfindData, int *pobject_type, int isNewInode)
109{ 109{
110 loff_t local_size;
111 struct timespec local_mtime;
112
110 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); 113 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
111 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); 114 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
112 __u32 attr = le32_to_cpu(pfindData->ExtFileAttributes); 115 __u32 attr = le32_to_cpu(pfindData->ExtFileAttributes);
@@ -116,6 +119,10 @@ static void fill_in_inode(struct inode *tmp_inode,
116 cifsInfo->cifsAttrs = attr; 119 cifsInfo->cifsAttrs = attr;
117 cifsInfo->time = jiffies; 120 cifsInfo->time = jiffies;
118 121
122 /* save mtime and size */
123 local_mtime = tmp_inode->i_mtime;
124 local_size = tmp_inode->i_size;
125
119 /* Linux can not store file creation time unfortunately so ignore it */ 126 /* Linux can not store file creation time unfortunately so ignore it */
120 tmp_inode->i_atime = 127 tmp_inode->i_atime =
121 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); 128 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
@@ -134,7 +141,6 @@ static void fill_in_inode(struct inode *tmp_inode,
134 tmp_inode->i_mode = cifs_sb->mnt_file_mode; 141 tmp_inode->i_mode = cifs_sb->mnt_file_mode;
135 } 142 }
136 143
137 cFYI(0,("CIFS FFIRST: Attributes came in as 0x%x",attr));
138 if (attr & ATTR_DIRECTORY) { 144 if (attr & ATTR_DIRECTORY) {
139 *pobject_type = DT_DIR; 145 *pobject_type = DT_DIR;
140 /* override default perms since we do not lock dirs */ 146 /* override default perms since we do not lock dirs */
@@ -175,30 +181,46 @@ static void fill_in_inode(struct inode *tmp_inode,
175 (unsigned long)tmp_inode->i_size, tmp_inode->i_blocks, 181 (unsigned long)tmp_inode->i_size, tmp_inode->i_blocks,
176 tmp_inode->i_blksize)); 182 tmp_inode->i_blksize));
177 if (S_ISREG(tmp_inode->i_mode)) { 183 if (S_ISREG(tmp_inode->i_mode)) {
178 cFYI(1, (" File inode ")); 184 cFYI(1, ("File inode"));
179 tmp_inode->i_op = &cifs_file_inode_ops; 185 tmp_inode->i_op = &cifs_file_inode_ops;
180 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 186 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
181 tmp_inode->i_fop = &cifs_file_direct_ops; 187 tmp_inode->i_fop = &cifs_file_direct_ops;
182 else 188 else
183 tmp_inode->i_fop = &cifs_file_ops; 189 tmp_inode->i_fop = &cifs_file_ops;
184 tmp_inode->i_data.a_ops = &cifs_addr_ops; 190 tmp_inode->i_data.a_ops = &cifs_addr_ops;
191
192 if(isNewInode)
193 return; /* No sense invalidating pages for new inode since we
194 have not started caching readahead file data yet */
195
196 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
197 (local_size == tmp_inode->i_size)) {
198 cFYI(1, ("inode exists but unchanged"));
199 } else {
200 /* file may have changed on server */
201 cFYI(1, ("invalidate inode, readdir detected change"));
202 invalidate_remote_inode(tmp_inode);
203 }
185 } else if (S_ISDIR(tmp_inode->i_mode)) { 204 } else if (S_ISDIR(tmp_inode->i_mode)) {
186 cFYI(1, (" Directory inode")); 205 cFYI(1, ("Directory inode"));
187 tmp_inode->i_op = &cifs_dir_inode_ops; 206 tmp_inode->i_op = &cifs_dir_inode_ops;
188 tmp_inode->i_fop = &cifs_dir_ops; 207 tmp_inode->i_fop = &cifs_dir_ops;
189 } else if (S_ISLNK(tmp_inode->i_mode)) { 208 } else if (S_ISLNK(tmp_inode->i_mode)) {
190 cFYI(1, (" Symbolic Link inode ")); 209 cFYI(1, ("Symbolic Link inode"));
191 tmp_inode->i_op = &cifs_symlink_inode_ops; 210 tmp_inode->i_op = &cifs_symlink_inode_ops;
192 } else { 211 } else {
193 cFYI(1, (" Init special inode ")); 212 cFYI(1, ("Init special inode"));
194 init_special_inode(tmp_inode, tmp_inode->i_mode, 213 init_special_inode(tmp_inode, tmp_inode->i_mode,
195 tmp_inode->i_rdev); 214 tmp_inode->i_rdev);
196 } 215 }
197} 216}
198 217
199static void unix_fill_in_inode(struct inode *tmp_inode, 218static void unix_fill_in_inode(struct inode *tmp_inode,
200 FILE_UNIX_INFO *pfindData, int *pobject_type) 219 FILE_UNIX_INFO *pfindData, int *pobject_type, int isNewInode)
201{ 220{
221 loff_t local_size;
222 struct timespec local_mtime;
223
202 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); 224 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
203 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); 225 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
204 226
@@ -208,6 +230,10 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
208 cifsInfo->time = jiffies; 230 cifsInfo->time = jiffies;
209 atomic_inc(&cifsInfo->inUse); 231 atomic_inc(&cifsInfo->inUse);
210 232
233 /* save mtime and size */
234 local_mtime = tmp_inode->i_mtime;
235 local_size = tmp_inode->i_size;
236
211 tmp_inode->i_atime = 237 tmp_inode->i_atime =
212 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); 238 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
213 tmp_inode->i_mtime = 239 tmp_inode->i_mtime =
@@ -265,6 +291,19 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
265 else 291 else
266 tmp_inode->i_fop = &cifs_file_ops; 292 tmp_inode->i_fop = &cifs_file_ops;
267 tmp_inode->i_data.a_ops = &cifs_addr_ops; 293 tmp_inode->i_data.a_ops = &cifs_addr_ops;
294
295 if(isNewInode)
296 return; /* No sense invalidating pages for new inode since we
297 have not started caching readahead file data yet */
298
299 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
300 (local_size == tmp_inode->i_size)) {
301 cFYI(1, ("inode exists but unchanged"));
302 } else {
303 /* file may have changed on server */
304 cFYI(1, ("invalidate inode, readdir detected change"));
305 invalidate_remote_inode(tmp_inode);
306 }
268 } else if (S_ISDIR(tmp_inode->i_mode)) { 307 } else if (S_ISDIR(tmp_inode->i_mode)) {
269 cFYI(1, ("Directory inode")); 308 cFYI(1, ("Directory inode"));
270 tmp_inode->i_op = &cifs_dir_inode_ops; 309 tmp_inode->i_op = &cifs_dir_inode_ops;
@@ -314,15 +353,16 @@ static int initiate_cifs_search(const int xid, struct file *file)
314 return -EINVAL; 353 return -EINVAL;
315 354
316 down(&file->f_dentry->d_sb->s_vfs_rename_sem); 355 down(&file->f_dentry->d_sb->s_vfs_rename_sem);
317 full_path = build_wildcard_path_from_dentry(file->f_dentry); 356 full_path = build_path_from_dentry(file->f_dentry);
318 up(&file->f_dentry->d_sb->s_vfs_rename_sem); 357 up(&file->f_dentry->d_sb->s_vfs_rename_sem);
319 358
320 if(full_path == NULL) { 359 if(full_path == NULL) {
321 return -ENOMEM; 360 return -ENOMEM;
322 } 361 }
323 362
324 cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos)); 363 cFYI(1, ("Full path: %s start at: %lld", full_path, file->f_pos));
325 364
365ffirst_retry:
326 /* test for Unix extensions */ 366 /* test for Unix extensions */
327 if (pTcon->ses->capabilities & CAP_UNIX) { 367 if (pTcon->ses->capabilities & CAP_UNIX) {
328 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; 368 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
@@ -332,10 +372,16 @@ static int initiate_cifs_search(const int xid, struct file *file)
332 cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; 372 cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
333 } 373 }
334 374
335 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, 375 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls,
336 &cifsFile->netfid, &cifsFile->srch_inf); 376 &cifsFile->netfid, &cifsFile->srch_inf,
377 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
337 if(rc == 0) 378 if(rc == 0)
338 cifsFile->invalidHandle = FALSE; 379 cifsFile->invalidHandle = FALSE;
380 if((rc == -EOPNOTSUPP) &&
381 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
382 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
383 goto ffirst_retry;
384 }
339 kfree(full_path); 385 kfree(full_path);
340 return rc; 386 return rc;
341} 387}
@@ -363,10 +409,15 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb)
363 cFYI(1,("new entry %p old entry %p",new_entry,old_entry)); 409 cFYI(1,("new entry %p old entry %p",new_entry,old_entry));
364 /* validate that new_entry is not past end of SMB */ 410 /* validate that new_entry is not past end of SMB */
365 if(new_entry >= end_of_smb) { 411 if(new_entry >= end_of_smb) {
366 cFYI(1,("search entry %p began after end of SMB %p old entry %p", 412 cERROR(1,
367 new_entry,end_of_smb,old_entry)); 413 ("search entry %p began after end of SMB %p old entry %p",
414 new_entry, end_of_smb, old_entry));
368 return NULL; 415 return NULL;
369 } else 416 } else if (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb) {
417 cERROR(1,("search entry %p extends after end of SMB %p",
418 new_entry, end_of_smb));
419 return NULL;
420 } else
370 return new_entry; 421 return new_entry;
371 422
372} 423}
@@ -594,7 +645,12 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
594 if(unicode) { 645 if(unicode) {
595 /* BB fixme - test with long names */ 646 /* BB fixme - test with long names */
596 /* Note converted filename can be longer than in unicode */ 647 /* Note converted filename can be longer than in unicode */
597 pqst->len = cifs_strfromUCS_le((char *)pqst->name,(wchar_t *)filename,len/2,nlt); 648 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
649 pqst->len = cifs_convertUCSpath((char *)pqst->name,
650 (__le16 *)filename, len/2, nlt);
651 else
652 pqst->len = cifs_strfromUCS_le((char *)pqst->name,
653 (wchar_t *)filename,len/2,nlt);
598 } else { 654 } else {
599 pqst->name = filename; 655 pqst->name = filename;
600 pqst->len = len; 656 pqst->len = len;
@@ -654,10 +710,15 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
654 insert_inode_hash(tmp_inode); 710 insert_inode_hash(tmp_inode);
655 } 711 }
656 712
713 /* we pass in rc below, indicating whether it is a new inode,
714 so we can figure out whether to invalidate the inode cached
715 data if the file has changed */
657 if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) { 716 if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
658 unix_fill_in_inode(tmp_inode,(FILE_UNIX_INFO *)pfindEntry,&obj_type); 717 unix_fill_in_inode(tmp_inode,
718 (FILE_UNIX_INFO *)pfindEntry,&obj_type, rc);
659 } else { 719 } else {
660 fill_in_inode(tmp_inode,(FILE_DIRECTORY_INFO *)pfindEntry,&obj_type); 720 fill_in_inode(tmp_inode,
721 (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc);
661 } 722 }
662 723
663 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type); 724 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type);
@@ -823,7 +884,11 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
823 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + 884 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
824 smbCalcSize((struct smb_hdr *) 885 smbCalcSize((struct smb_hdr *)
825 cifsFile->srch_inf.ntwrk_buf_start); 886 cifsFile->srch_inf.ntwrk_buf_start);
826 tmp_buf = kmalloc(NAME_MAX+1,GFP_KERNEL); 887 /* To be safe - for UCS to UTF-8 with strings loaded
888 with the rare long characters alloc more to account for
889 such multibyte target UTF-8 characters. cifs_unicode.c,
890 which actually does the conversion, has the same limit */
891 tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL);
827 for(i=0;(i<num_to_fill) && (rc == 0);i++) { 892 for(i=0;(i<num_to_fill) && (rc == 0);i++) {
828 if(current_entry == NULL) { 893 if(current_entry == NULL) {
829 /* evaluate whether this case is an error */ 894 /* evaluate whether this case is an error */
@@ -832,19 +897,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
832 break; 897 break;
833 } 898 }
834 899
835 /* BB FIXME - need to enable the below code BB */
836
837 /* if((!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) ||
838 (cifsFile->srch_inf.info_level !=
839 something that supports server inodes)) {
840 create dentry
841 create inode
842 fill in inode new_inode (getting local i_ino)
843 }
844 also create local inode for performance reasons (so we
845 have a cache of inode metadata) unless this new mount
846 parm says otherwise */
847
848 rc = cifs_filldir(current_entry, file, 900 rc = cifs_filldir(current_entry, file,
849 filldir, direntry,tmp_buf); 901 filldir, direntry,tmp_buf);
850 file->f_pos++; 902 file->f_pos++;
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index e21f1384661f..cd41c67ff8d3 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -22,94 +22,159 @@
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */ 23 */
24 24
25#define SUCCESS 0 /* The request was successful. */ 25#define SUCCESS 0x00 /* The request was successful. */
26#define ERRDOS 0x01 /* Error is from the core DOS operating system set */ 26#define ERRDOS 0x01 /* Error is from the core DOS operating system set */
27#define ERRSRV 0x02 /* Error is generated by the file server daemon */ 27#define ERRSRV 0x02 /* Error is generated by the file server daemon */
28#define ERRHRD 0x03 /* Error is a hardware error. */ 28#define ERRHRD 0x03 /* Error is a hardware error. */
29#define ERRCMD 0xFF /* Command was not in the "SMB" format. */ 29#define ERRCMD 0xFF /* Command was not in the "SMB" format. */
30 30
31/* The following error codes may be generated with the SUCCESS error class.*/ 31/* The following error codes may be generated with the SUCCESS error class.*/
32 32
33#define SUCCESS 0 /* The request was successful. */ 33/*#define SUCCESS 0 The request was successful. */
34 34
35/* The following error codes may be generated with the ERRDOS error class.*/ 35/* The following error codes may be generated with the ERRDOS error class.*/
36 36
37#define ERRbadfunc 1 /* Invalid function. The server did not recognize or could not perform a system call generated by the server, e.g., set the DIRECTORY attribute on a data file, invalid seek mode. */ 37#define ERRbadfunc 1 /* Invalid function. The server did not
38#define ERRbadfile 2 /*File not found. The last component of a file's pathname could not be found. */ 38 recognize or could not perform a
39#define ERRbadpath 3 /* Directory invalid. A directory component in a pathname could not be found. */ 39 system call generated by the server,
40#define ERRnofids 4 /* Too many open files. The server has no file handles available. */ 40 e.g., set the DIRECTORY attribute on
41#define ERRnoaccess 5 /* Access denied, the client's context does not permit the requested function. This includes the following conditions: invalid rename command, write to Fid open for read only, read on Fid open for write only, attempt to delete a non-empty directory */ 41 a data file, invalid seek mode. */
42#define ERRbadfid 6 /* Invalid file handle. The file handle specified was not recognized by the server. */ 42#define ERRbadfile 2 /* File not found. The last component
43#define ERRbadmcb 7 /* Memory control blocks destroyed. */ 43 of a file's pathname could not be
44#define ERRnomem 8 /* Insufficient server memory to perform the requested function. */ 44 found. */
45#define ERRbadmem 9 /* Invalid memory block address. */ 45#define ERRbadpath 3 /* Directory invalid. A directory
46#define ERRbadenv 10 /* Invalid environment. */ 46 component in a pathname could not be
47#define ERRbadformat 11 /* Invalid format. */ 47 found. */
48#define ERRbadaccess 12 /* Invalid open mode. */ 48#define ERRnofids 4 /* Too many open files. The server has
49#define ERRbaddata 13 /* Invalid data (generated only by IOCTL calls within the server). */ 49 no file handles available. */
50#define ERRbaddrive 15 /* Invalid drive specified. */ 50#define ERRnoaccess 5 /* Access denied, the client's context
51#define ERRremcd 16 /* A Delete Directory request attempted to remove the server's current directory. */ 51 does not permit the requested
52#define ERRdiffdevice 17 /* Not same device (e.g., a cross volume rename was attempted */ 52 function. This includes the
53#define ERRnofiles 18 /* A File Search command can find no more files matching the specified criteria. */ 53 following conditions: invalid rename
54#define ERRgeneral 31 54 command, write to Fid open for read
55#define ERRbadshare 32 /* The sharing mode specified for an Open conflicts with existing FIDs on the file. */ 55 only, read on Fid open for write
56#define ERRlock 33 /* A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process. */ 56 only, attempt to delete a non-empty
57#define ERRunsup 50 57 directory */
58#define ERRnosuchshare 67 58#define ERRbadfid 6 /* Invalid file handle. The file handle
59#define ERRfilexists 80 /* The file named in the request already exists. */ 59 specified was not recognized by the
60#define ERRinvparm 87 60 server. */
61#define ERRdiskfull 112 61#define ERRbadmcb 7 /* Memory control blocks destroyed. */
62#define ERRinvname 123 62#define ERRnomem 8 /* Insufficient server memory to
63#define ERRinvlevel 124 63 perform the requested function. */
64#define ERRdirnotempty 145 64#define ERRbadmem 9 /* Invalid memory block address. */
65#define ERRnotlocked 158 65#define ERRbadenv 10 /* Invalid environment. */
66#define ERRalreadyexists 183 66#define ERRbadformat 11 /* Invalid format. */
67#define ERRbadpipe 230 67#define ERRbadaccess 12 /* Invalid open mode. */
68#define ERRpipebusy 231 68#define ERRbaddata 13 /* Invalid data (generated only by
69#define ERRpipeclosing 232 69 IOCTL calls within the server). */
70#define ERRnotconnected 233 70#define ERRbaddrive 15 /* Invalid drive specified. */
71#define ERRmoredata 234 71#define ERRremcd 16 /* A Delete Directory request attempted
72#define ERReasnotsupported 282 72 to remove the server's current
73#define ErrQuota 0x200 /* The operation would cause a quota limit to be exceeded. */ 73 directory. */
74#define ErrNotALink 0x201 /* A link operation was performed on a pathname that 74#define ERRdiffdevice 17 /* Not same device (e.g., a cross
75 was not a link. */ 75 volume rename was attempted */
76#define ERRnofiles 18 /* A File Search command can find no
77 more files matching the specified
78 criteria. */
79#define ERRgeneral 31
80#define ERRbadshare 32 /* The sharing mode specified for an
81 Open conflicts with existing FIDs on
82 the file. */
83#define ERRlock 33 /* A Lock request conflicted with an
84 existing lock or specified an
85 invalid mode, or an Unlock requested
86 attempted to remove a lock held by
87 another process. */
88#define ERRunsup 50
89#define ERRnosuchshare 67
90#define ERRfilexists 80 /* The file named in the request
91 already exists. */
92#define ERRinvparm 87
93#define ERRdiskfull 112
94#define ERRinvname 123
95#define ERRinvlevel 124
96#define ERRdirnotempty 145
97#define ERRnotlocked 158
98#define ERRalreadyexists 183
99#define ERRbadpipe 230
100#define ERRpipebusy 231
101#define ERRpipeclosing 232
102#define ERRnotconnected 233
103#define ERRmoredata 234
104#define ERReasnotsupported 282
105#define ErrQuota 0x200 /* The operation would cause a quota
106 limit to be exceeded. */
107#define ErrNotALink 0x201 /* A link operation was performed on a
108 pathname that was not a link. */
76 109
77/* Following error codes may be generated with the ERRSRV error 110/* Below errors are used internally (do not come over the wire) for passthrough
78class.*/ 111 from STATUS codes to POSIX only */
112#define ErrTooManyLinks 0xFFFE
79 113
80#define ERRerror 1 /* Non-specific error code. It is returned under the following conditions: resource other than disk space exhausted (e.g. TIDs), first SMB command was not negotiate, multiple negotiates attempted, and internal server error. */ 114/* Following error codes may be generated with the ERRSRV error class.*/
81#define ERRbadpw 2 /* Bad password - name/password pair in a TreeConnect or Session Setup are invalid. */ 115
82#define ERRbadtype 3 /* used for indicating DFS referral needed */ 116#define ERRerror 1 /* Non-specific error code. It is
83#define ERRaccess 4 /* The client does not have the necessary access rights within the specified context for requested function. */ 117 returned under the following
84#define ERRinvtid 5 /* The Tid specified in a command was invalid. */ 118 conditions: resource other than disk
85#define ERRinvnetname 6 /* Invalid network name in tree connect. */ 119 space exhausted (e.g. TIDs), first
86#define ERRinvdevice 7 /* Invalid device - printer request made to non-printer connection or non-printer request made to printer connection. */ 120 SMB command was not negotiate,
87#define ERRqfull 49 /* Print queue full (files) -- returned by open print file. */ 121 multiple negotiates attempted, and
88#define ERRqtoobig 50 /* Print queue full -- no space. */ 122 internal server error. */
89#define ERRqeof 51 /* EOF on print queue dump */ 123#define ERRbadpw 2 /* Bad password - name/password pair in
90#define ERRinvpfid 52 /* Invalid print file FID. */ 124 a TreeConnect or Session Setup are
91#define ERRsmbcmd 64 /* The server did not recognize the command received. */ 125 invalid. */
92#define ERRsrverror 65 /* The server encountered an internal error, e.g., system file unavailable. */ 126#define ERRbadtype 3 /* used for indicating DFS referral
93#define ERRbadBID 66 /* (obsolete) */ 127 needed */
94#define ERRfilespecs 67 /* The Fid and pathname parameters contained an invalid combination of values. */ 128#define ERRaccess 4 /* The client does not have the
95#define ERRbadLink 68 /* (obsolete) */ 129 necessary access rights within the
96#define ERRbadpermits 69 /* The access permissions specified for a file or directory are not a valid combination. */ 130 specified context for requested
97#define ERRbadPID 70 131 function. */
98#define ERRsetattrmode 71 /* attribute (mode) is invalid */ 132#define ERRinvtid 5 /* The Tid specified in a command was
99#define ERRpaused 81 /* Server is paused */ 133 invalid. */
100#define ERRmsgoff 82 /* reserved - messaging off */ 134#define ERRinvnetname 6 /* Invalid network name in tree
101#define ERRnoroom 83 /* reserved - no room for message */ 135 connect. */
102#define ERRrmuns 87 /* reserved - too many remote names */ 136#define ERRinvdevice 7 /* Invalid device - printer request
103#define ERRtimeout 88 /* operation timed out */ 137 made to non-printer connection or
104#define ERRnoresource 89 /* No resources available for request */ 138 non-printer request made to printer
105#define ERRtoomanyuids 90 /* Too many UIDs active on this session */ 139 connection. */
106#define ERRbaduid 91 /* The UID is not known as a valid user */ 140#define ERRqfull 49 /* Print queue full (files) -- returned
107#define ERRusempx 250 /* temporarily unable to use raw */ 141 by open print file. */
108#define ERRusestd 251 /* temporarily unable to use either raw or mpx */ 142#define ERRqtoobig 50 /* Print queue full -- no space. */
109#define ERR_NOTIFY_ENUM_DIR 1024 143#define ERRqeof 51 /* EOF on print queue dump */
110#define ERRaccountexpired 2239 144#define ERRinvpfid 52 /* Invalid print file FID. */
111#define ERRbadclient 2240 145#define ERRsmbcmd 64 /* The server did not recognize the
112#define ERRbadLogonTime 2241 146 command received. */
113#define ERRpasswordExpired 2242 147#define ERRsrverror 65 /* The server encountered an internal
114#define ERRnetlogonNotStarted 2455 148 error, e.g., system file
115#define ERRnosupport 0xFFFF 149 unavailable. */
150#define ERRbadBID 66 /* (obsolete) */
151#define ERRfilespecs 67 /* The Fid and pathname parameters
152 contained an invalid combination of
153 values. */
154#define ERRbadLink 68 /* (obsolete) */
155#define ERRbadpermits 69 /* The access permissions specified for
156 a file or directory are not a valid
157 combination. */
158#define ERRbadPID 70
159#define ERRsetattrmode 71 /* attribute (mode) is invalid */
160#define ERRpaused 81 /* Server is paused */
161#define ERRmsgoff 82 /* reserved - messaging off */
162#define ERRnoroom 83 /* reserved - no room for message */
163#define ERRrmuns 87 /* reserved - too many remote names */
164#define ERRtimeout 88 /* operation timed out */
165#define ERRnoresource 89 /* No resources available for request
166 */
167#define ERRtoomanyuids 90 /* Too many UIDs active on this session
168 */
169#define ERRbaduid 91 /* The UID is not known as a valid user
170 */
171#define ERRusempx 250 /* temporarily unable to use raw */
172#define ERRusestd 251 /* temporarily unable to use either raw
173 or mpx */
174#define ERR_NOTIFY_ENUM_DIR 1024
175#define ERRaccountexpired 2239
176#define ERRbadclient 2240
177#define ERRbadLogonTime 2241
178#define ERRpasswordExpired 2242
179#define ERRnetlogonNotStarted 2455
180#define ERRnosupport 0xFFFF
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index af13e526b150..0046c219833d 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/transport.c 2 * fs/cifs/transport.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2004 4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -41,7 +41,7 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
41 struct mid_q_entry *temp; 41 struct mid_q_entry *temp;
42 42
43 if (ses == NULL) { 43 if (ses == NULL) {
44 cERROR(1, ("Null session passed in to AllocMidQEntry ")); 44 cERROR(1, ("Null session passed in to AllocMidQEntry"));
45 return NULL; 45 return NULL;
46 } 46 }
47 if (ses->server == NULL) { 47 if (ses->server == NULL) {
@@ -79,7 +79,10 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
79 list_del(&midEntry->qhead); 79 list_del(&midEntry->qhead);
80 atomic_dec(&midCount); 80 atomic_dec(&midCount);
81 spin_unlock(&GlobalMid_Lock); 81 spin_unlock(&GlobalMid_Lock);
82 cifs_buf_release(midEntry->resp_buf); 82 if(midEntry->largeBuf)
83 cifs_buf_release(midEntry->resp_buf);
84 else
85 cifs_small_buf_release(midEntry->resp_buf);
83 mempool_free(midEntry, cifs_mid_poolp); 86 mempool_free(midEntry, cifs_mid_poolp);
84} 87}
85 88
@@ -182,14 +185,14 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
182 185
183int 186int
184smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer, 187smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
185 unsigned int smb_buf_length, struct kvec * write_vector /* page list */, struct sockaddr *sin) 188 unsigned int smb_buf_length, struct kvec * write_vector
189 /* page list */, struct sockaddr *sin)
186{ 190{
187 int rc = 0; 191 int rc = 0;
188 int i = 0; 192 int i = 0;
189 struct msghdr smb_msg; 193 struct msghdr smb_msg;
190 number_of_pages += 1; /* account for SMB header */ 194 number_of_pages += 1; /* account for SMB header */
191 struct kvec * piov = kmalloc(number_of_pages * sizeof(struct kvec)); 195 struct kvec * piov = kmalloc(number_of_pages * sizeof(struct kvec));
192 if(i=0;i<num_pages-1;i++
193 unsigned len = smb_buf_length + 4; 196 unsigned len = smb_buf_length + 4;
194 197
195 if(ssocket == NULL) 198 if(ssocket == NULL)
@@ -213,7 +216,8 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
213 dump_smb(smb_buffer, len); 216 dump_smb(smb_buffer, len);
214 217
215 while (len > 0) { 218 while (len > 0) {
216 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, len?); 219 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages,
220 len);
217 if ((rc == -ENOSPC) || (rc == -EAGAIN)) { 221 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
218 i++; 222 i++;
219 if(i > 60) { 223 if(i > 60) {
@@ -266,6 +270,9 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
266 270
267 271
268 272
273 if(ses->server->tcpStatus == CIFS_EXITING)
274 return -ENOENT;
275
269 /* Ensure that we do not send more than 50 overlapping requests 276 /* Ensure that we do not send more than 50 overlapping requests
270 to the same server. We may make this configurable later or 277 to the same server. We may make this configurable later or
271 use ses->maxReq */ 278 use ses->maxReq */
@@ -346,11 +353,12 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
346 } 353 }
347 354
348 /* BB can we sign efficiently in this path? */ 355 /* BB can we sign efficiently in this path? */
349 rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number); 356 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
350 357
351 midQ->midState = MID_REQUEST_SUBMITTED; 358 midQ->midState = MID_REQUEST_SUBMITTED;
352/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec, 359/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
353 (struct sockaddr *) &(ses->server->addr.sockAddr));*/ 360 piovec,
361 (struct sockaddr *) &(ses->server->addr.sockAddr));*/
354 if(rc < 0) { 362 if(rc < 0) {
355 DeleteMidQEntry(midQ); 363 DeleteMidQEntry(midQ);
356 up(&ses->server->tcpSem); 364 up(&ses->server->tcpSem);
@@ -396,6 +404,9 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
396 return -EIO; 404 return -EIO;
397 } 405 }
398 406
407 if(ses->server->tcpStatus == CifsExiting)
408 return -ENOENT;
409
399 /* Ensure that we do not send more than 50 overlapping requests 410 /* Ensure that we do not send more than 50 overlapping requests
400 to the same server. We may make this configurable later or 411 to the same server. We may make this configurable later or
401 use ses->maxReq */ 412 use ses->maxReq */
@@ -405,7 +416,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
405 } else { 416 } else {
406 spin_lock(&GlobalMid_Lock); 417 spin_lock(&GlobalMid_Lock);
407 while(1) { 418 while(1) {
408 if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){ 419 if(atomic_read(&ses->server->inFlight) >=
420 cifs_max_pending){
409 spin_unlock(&GlobalMid_Lock); 421 spin_unlock(&GlobalMid_Lock);
410 wait_event(ses->server->request_q, 422 wait_event(ses->server->request_q,
411 atomic_read(&ses->server->inFlight) 423 atomic_read(&ses->server->inFlight)
@@ -475,7 +487,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
475 return -EIO; 487 return -EIO;
476 } 488 }
477 489
478 rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number); 490 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
479 491
480 midQ->midState = MID_REQUEST_SUBMITTED; 492 midQ->midState = MID_REQUEST_SUBMITTED;
481 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, 493 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
@@ -493,7 +505,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
493 up(&ses->server->tcpSem); 505 up(&ses->server->tcpSem);
494 if (long_op == -1) 506 if (long_op == -1)
495 goto cifs_no_response_exit; 507 goto cifs_no_response_exit;
496 else if (long_op == 2) /* writes past end of file can take looooong time */ 508 else if (long_op == 2) /* writes past end of file can take loong time */
497 timeout = 300 * HZ; 509 timeout = 300 * HZ;
498 else if (long_op == 1) 510 else if (long_op == 1)
499 timeout = 45 * HZ; /* should be greater than 511 timeout = 45 * HZ; /* should be greater than
@@ -559,8 +571,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
559 } 571 }
560 572
561 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 573 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
562 cERROR(1, 574 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
563 ("Frame too large received. Length: %d Xid: %d",
564 receive_len, xid)); 575 receive_len, xid));
565 rc = -EIO; 576 rc = -EIO;
566 } else { /* rcvd frame is ok */ 577 } else { /* rcvd frame is ok */
@@ -575,15 +586,20 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
575 dump_smb(out_buf, 92); 586 dump_smb(out_buf, 92);
576 /* convert the length into a more usable form */ 587 /* convert the length into a more usable form */
577 if((receive_len > 24) && 588 if((receive_len > 24) &&
578 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) { 589 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
579 rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */ 590 SECMODE_SIGN_ENABLED))) {
580 if(rc) 591 rc = cifs_verify_signature(out_buf,
581 cFYI(1,("Unexpected signature received from server")); 592 ses->server->mac_signing_key,
593 midQ->sequence_number+1);
594 if(rc) {
595 cERROR(1,("Unexpected SMB signature"));
596 /* BB FIXME add code to kill session */
597 }
582 } 598 }
583 599
584 *pbytes_returned = out_buf->smb_buf_length; 600 *pbytes_returned = out_buf->smb_buf_length;
585 601
586 /* BB special case reconnect tid and reconnect uid here? */ 602 /* BB special case reconnect tid and uid here? */
587 rc = map_smb_to_linux_error(out_buf); 603 rc = map_smb_to_linux_error(out_buf);
588 604
589 /* convert ByteCount if necessary */ 605 /* convert ByteCount if necessary */
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 549afa184fd6..c1e02eff1d25 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -83,7 +83,8 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name)
83 83
84 ea_name+=5; /* skip past user. prefix */ 84 ea_name+=5; /* skip past user. prefix */
85 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL, 85 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL,
86 (__u16)0, cifs_sb->local_nls); 86 (__u16)0, cifs_sb->local_nls,
87 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
87 } 88 }
88remove_ea_exit: 89remove_ea_exit:
89 if (full_path) 90 if (full_path)
@@ -147,32 +148,40 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
147 } 148 }
148 ea_name += 5; /* skip past user. prefix */ 149 ea_name += 5; /* skip past user. prefix */
149 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value, 150 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
150 (__u16)value_size, cifs_sb->local_nls); 151 (__u16)value_size, cifs_sb->local_nls,
152 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
151 } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) { 153 } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
152 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 154 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
153 goto set_ea_exit; 155 goto set_ea_exit;
154 156
155 ea_name += 4; /* skip past os2. prefix */ 157 ea_name += 4; /* skip past os2. prefix */
156 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value, 158 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
157 (__u16)value_size, cifs_sb->local_nls); 159 (__u16)value_size, cifs_sb->local_nls,
160 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
158 } else { 161 } else {
159 int temp; 162 int temp;
160 temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS, 163 temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
161 strlen(POSIX_ACL_XATTR_ACCESS)); 164 strlen(POSIX_ACL_XATTR_ACCESS));
162 if (temp == 0) { 165 if (temp == 0) {
163#ifdef CONFIG_CIFS_POSIX 166#ifdef CONFIG_CIFS_POSIX
164 rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,ea_value, 167 if(sb->s_flags & MS_POSIXACL)
165 (const int)value_size, ACL_TYPE_ACCESS, 168 rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
166 cifs_sb->local_nls); 169 ea_value, (const int)value_size,
170 ACL_TYPE_ACCESS,cifs_sb->local_nls,
171 cifs_sb->mnt_cifs_flags &
172 CIFS_MOUNT_MAP_SPECIAL_CHR);
167 cFYI(1,("set POSIX ACL rc %d",rc)); 173 cFYI(1,("set POSIX ACL rc %d",rc));
168#else 174#else
169 cFYI(1,("set POSIX ACL not supported")); 175 cFYI(1,("set POSIX ACL not supported"));
170#endif 176#endif
171 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { 177 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
172#ifdef CONFIG_CIFS_POSIX 178#ifdef CONFIG_CIFS_POSIX
173 rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,ea_value, 179 if(sb->s_flags & MS_POSIXACL)
174 (const int)value_size, ACL_TYPE_DEFAULT, 180 rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
175 cifs_sb->local_nls); 181 ea_value, (const int)value_size,
182 ACL_TYPE_DEFAULT, cifs_sb->local_nls,
183 cifs_sb->mnt_cifs_flags &
184 CIFS_MOUNT_MAP_SPECIAL_CHR);
176 cFYI(1,("set POSIX default ACL rc %d",rc)); 185 cFYI(1,("set POSIX default ACL rc %d",rc));
177#else 186#else
178 cFYI(1,("set default POSIX ACL not supported")); 187 cFYI(1,("set default POSIX ACL not supported"));
@@ -238,27 +247,35 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
238 } /* BB add else when above is implemented */ 247 } /* BB add else when above is implemented */
239 ea_name += 5; /* skip past user. prefix */ 248 ea_name += 5; /* skip past user. prefix */
240 rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, 249 rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
241 buf_size, cifs_sb->local_nls); 250 buf_size, cifs_sb->local_nls,
251 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
242 } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) { 252 } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
243 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 253 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
244 goto get_ea_exit; 254 goto get_ea_exit;
245 255
246 ea_name += 4; /* skip past os2. prefix */ 256 ea_name += 4; /* skip past os2. prefix */
247 rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, 257 rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
248 buf_size, cifs_sb->local_nls); 258 buf_size, cifs_sb->local_nls,
259 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
249 } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { 260 } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
250#ifdef CONFIG_CIFS_POSIX 261#ifdef CONFIG_CIFS_POSIX
251 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, 262 if(sb->s_flags & MS_POSIXACL)
263 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
252 ea_value, buf_size, ACL_TYPE_ACCESS, 264 ea_value, buf_size, ACL_TYPE_ACCESS,
253 cifs_sb->local_nls); 265 cifs_sb->local_nls,
266 cifs_sb->mnt_cifs_flags &
267 CIFS_MOUNT_MAP_SPECIAL_CHR);
254#else 268#else
255 cFYI(1,("query POSIX ACL not supported yet")); 269 cFYI(1,("query POSIX ACL not supported yet"));
256#endif /* CONFIG_CIFS_POSIX */ 270#endif /* CONFIG_CIFS_POSIX */
257 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { 271 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
258#ifdef CONFIG_CIFS_POSIX 272#ifdef CONFIG_CIFS_POSIX
259 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, 273 if(sb->s_flags & MS_POSIXACL)
274 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
260 ea_value, buf_size, ACL_TYPE_DEFAULT, 275 ea_value, buf_size, ACL_TYPE_DEFAULT,
261 cifs_sb->local_nls); 276 cifs_sb->local_nls,
277 cifs_sb->mnt_cifs_flags &
278 CIFS_MOUNT_MAP_SPECIAL_CHR);
262#else 279#else
263 cFYI(1,("query POSIX default ACL not supported yet")); 280 cFYI(1,("query POSIX default ACL not supported yet"));
264#endif 281#endif
@@ -324,7 +341,9 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
324 search server for EAs or streams to 341 search server for EAs or streams to
325 returns as xattrs */ 342 returns as xattrs */
326 rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size, 343 rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size,
327 cifs_sb->local_nls); 344 cifs_sb->local_nls,
345 cifs_sb->mnt_cifs_flags &
346 CIFS_MOUNT_MAP_SPECIAL_CHR);
328 347
329 if (full_path) 348 if (full_path)
330 kfree(full_path); 349 kfree(full_path);