diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/AUTHORS | 24 | ||||
-rw-r--r-- | fs/cifs/CHANGES | 39 | ||||
-rw-r--r-- | fs/cifs/README | 49 | ||||
-rw-r--r-- | fs/cifs/TODO | 30 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.c | 43 | ||||
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifs_unicode.c | 4 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 16 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 34 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 8 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 18 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 71 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 109 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 436 | ||||
-rw-r--r-- | fs/cifs/connect.c | 743 | ||||
-rw-r--r-- | fs/cifs/dir.c | 189 | ||||
-rw-r--r-- | fs/cifs/fcntl.c | 3 | ||||
-rw-r--r-- | fs/cifs/file.c | 15 | ||||
-rw-r--r-- | fs/cifs/inode.c | 106 | ||||
-rw-r--r-- | fs/cifs/ioctl.c | 75 | ||||
-rw-r--r-- | fs/cifs/link.c | 18 | ||||
-rw-r--r-- | fs/cifs/misc.c | 160 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 5 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 120 | ||||
-rw-r--r-- | fs/cifs/smberr.h | 231 | ||||
-rw-r--r-- | fs/cifs/transport.c | 54 | ||||
-rw-r--r-- | fs/cifs/xattr.c | 51 |
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 | ||
5 | The author wishes to express his appreciation and thanks to: | 5 | The author wishes to express his appreciation and thanks to: |
6 | Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS | 6 | Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS |
7 | improvements. Thanks to IBM for allowing me the time and test resources to pursue | 7 | improvements. Thanks to IBM for allowing me time and test resources to pursue |
8 | this project. Jim McDonough from IBM (and the Samba Team) for his help. | 8 | this project, to Jim McDonough from IBM (and the Samba Team) for his help, to |
9 | The IBM Linux JFS team for explaining many esoteric Linux filesystem features. | 9 | the IBM Linux JFS team for explaining many esoteric Linux filesystem features. |
10 | Jeremy Allison of the Samba team has done invaluable work in adding the server | ||
11 | side of the original CIFS Unix extensions and reviewing and implementing | ||
12 | portions of the newer CIFS POSIX extensions into the Samba 3 file server. Thank | ||
10 | Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client) | 13 | Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client) |
11 | for proving years ago that a very good smb/cifs client could be done on a Unix like | 14 | for proving years ago that very good smb/cifs clients could be done on Unix-like |
12 | operating system. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin | 15 | operating systems. Volker Lendecke, Andrew Tridgell, Urban Widmark, John |
13 | and others for their work on the Linux smbfs module over the years. Thanks to | 16 | Newbigin and others for their work on the Linux smbfs module. Thanks to |
14 | the other members of the Storage Network Industry Association CIFS Technical | 17 | the other members of the Storage Network Industry Association CIFS Technical |
15 | Workgroup for their work specifying this highly complex protocol and finally | 18 | Workgroup for their work specifying this highly complex protocol and finally |
16 | thanks to the Samba team for their technical advice and encouragement. | 19 | thanks to the Samba team for their technical advice and encouragement. |
@@ -24,9 +27,11 @@ Shobhit Dayal | |||
24 | Sergey Vlasov | 27 | Sergey Vlasov |
25 | Richard Hughes | 28 | Richard Hughes |
26 | Yury Umanets | 29 | Yury Umanets |
27 | Mark Hamzy | 30 | Mark Hamzy (for some of the early cifs IPv6 work) |
28 | Domen Puncer | 31 | Domen Puncer |
29 | Jesper Juhl | 32 | Jesper Juhl (in particular for lots of whitespace/formatting cleanup) |
33 | Vince Negri and Dave Stahl (for finding an important caching bug) | ||
34 | Adrian Bunk (kcalloc cleanups) | ||
30 | 35 | ||
31 | Test case and Bug Report contributors | 36 | Test case and Bug Report contributors |
32 | ------------------------------------- | 37 | ------------------------------------- |
@@ -36,7 +41,8 @@ Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori, | |||
36 | Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen, | 41 | Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen, |
37 | Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special | 42 | Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special |
38 | mention to the Stanford Checker (SWAT) which pointed out many minor | 43 | mention to the Stanford Checker (SWAT) which pointed out many minor |
39 | bugs in error paths. | 44 | bugs in error paths. Valuable suggestions also have come from Al Viro |
45 | and Dave Miller. | ||
40 | 46 | ||
41 | And thanks to the IBM LTC and Power test teams and SuSE testers for | 47 | And thanks to the IBM LTC and Power test teams and SuSE testers for |
42 | finding multiple bugs during excellent stress test runs. | 48 | finding 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 @@ | |||
1 | Version 1.31 | 1 | Version 1.34 |
2 | ------------ | ||
3 | Fix error mapping of the TOO_MANY_LINKS (hardlinks) case. | ||
4 | Do not oops if root user kills cifs oplock kernel thread or | ||
5 | kills the cifsd thread (NB: killing the cifs kernel threads is not | ||
6 | recommended, unmount and rmmod cifs will kill them when they are | ||
7 | no longer needed). Fix readdir to ASCII servers (ie older servers | ||
8 | which do not support Unicode) and also require asterik. | ||
9 | |||
10 | |||
11 | Version 1.33 | ||
12 | ------------ | ||
13 | Fix caching problem, in which readdir of directory containing a file | ||
14 | which was cached could cause the file's time stamp to be updated | ||
15 | without invalidating the readahead data (so we could get stale | ||
16 | file data on the client for that file even as the server copy changed). | ||
17 | Cleanup response processing so cifsd can not loop when abnormally | ||
18 | terminated. | ||
19 | |||
20 | |||
21 | Version 1.32 | ||
2 | ------------ | 22 | ------------ |
3 | Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one | 23 | Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one |
4 | transact response for an SMB request and search entry split across two frames. | 24 | transact response for an SMB request and search entry split across two frames. |
25 | Add support for lsattr (getting ext2/ext3/reiserfs attr flags from the server) | ||
26 | as new protocol extensions. Do not send Get/Set calls for POSIX ACLs | ||
27 | unless server explicitly claims to support them in CIFS Unix extensions | ||
28 | POSIX ACL capability bit. Fix packet signing when multiuser mounting with | ||
29 | different users from the same client to the same server. Fix oops in | ||
30 | cifs_close. Add mount option for remapping reserved characters in | ||
31 | filenames (also allow recognizing files with created by SFU which have any | ||
32 | of these seven reserved characters, except backslash, to be recognized). | ||
33 | Fix invalid transact2 message (we were sometimes trying to interpret | ||
34 | oplock breaks as SMB responses). Add ioctl for checking that the | ||
35 | current uid matches the uid of the mounter (needed by umount.cifs). | ||
36 | Reduce the number of large buffer allocations in cifs response processing | ||
37 | (significantly reduces memory pressure under heavy stress with multiple | ||
38 | processes accessing the same server at the same time). | ||
39 | |||
40 | Version 1.31 | ||
41 | ------------ | ||
5 | Fix updates of DOS attributes and time fields so that files on NT4 servers | 42 | Fix updates of DOS attributes and time fields so that files on NT4 servers |
6 | do not get marked delete on close. Display sizes of cifs buffer pools in | 43 | do not get marked delete on close. Display sizes of cifs buffer pools in |
7 | cifs stats. Fix oops in unmount when cifsd thread being killed by | 44 | cifs 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. | |||
32 | 6) make modules (or "make" if CIFS VFS not to be built as a module) | 32 | 6) make modules (or "make" if CIFS VFS not to be built as a module) |
33 | 33 | ||
34 | For Linux 2.6: | 34 | For Linux 2.6: |
35 | 1) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper | 35 | 1) Download the kernel (e.g. from http://www.kernel.org) |
36 | at bk://linux.bkbits.net/linux-2.5) and change directory into the top | 36 | and change directory into the top of the kernel directory tree |
37 | of the kernel directory tree (e.g. /usr/src/linux-2.5.73) | 37 | (e.g. /usr/src/linux-2.5.73) |
38 | 2) make menuconfig (or make xconfig) | 38 | 2) make menuconfig (or make xconfig) |
39 | 3) select cifs from within the network filesystem choices | 39 | 3) select cifs from within the network filesystem choices |
40 | 4) save and exit | 40 | 4) save and exit |
@@ -75,7 +75,7 @@ Allowing User Mounts | |||
75 | ==================== | 75 | ==================== |
76 | To permit users to mount and unmount over directories they own is possible | 76 | To permit users to mount and unmount over directories they own is possible |
77 | with the cifs vfs. A way to enable such mounting is to mark the mount.cifs | 77 | with the cifs vfs. A way to enable such mounting is to mark the mount.cifs |
78 | utility as suid (e.g. "chmod +s /sbin/mount/cifs). To enable users to | 78 | utility as suid (e.g. "chmod +s /sbin/mount.cifs). To enable users to |
79 | umount shares they mount requires | 79 | umount shares they mount requires |
80 | 1) mount.cifs version 1.4 or later | 80 | 1) mount.cifs version 1.4 or later |
81 | 2) an entry for the share in /etc/fstab indicating that a user may | 81 | 2) an entry for the share in /etc/fstab indicating that a user may |
@@ -97,6 +97,26 @@ mount.cifs with the following flag: | |||
97 | There is a corresponding manual page for cifs mounting in the Samba 3.0 and | 97 | There is a corresponding manual page for cifs mounting in the Samba 3.0 and |
98 | later source tree in docs/manpages/mount.cifs.8 | 98 | later source tree in docs/manpages/mount.cifs.8 |
99 | 99 | ||
100 | Allowing User Unmounts | ||
101 | ====================== | ||
102 | To permit users to ummount directories that they have user mounted (see above), | ||
103 | the utility umount.cifs may be used. It may be invoked directly, or if | ||
104 | umount.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 | ||
106 | mounts, unless umount is invoked with -i (which will avoid invoking a umount | ||
107 | helper). As with mount.cifs, to enable user unmounts umount.cifs must be marked | ||
108 | as suid (e.g. "chmod +s /sbin/umount.cifs") or equivalent (some distributions | ||
109 | allow adding entries to a file to the /etc/permissions file to achieve the | ||
110 | equivalent suid effect). For this utility to succeed the target path | ||
111 | must be a cifs mount, and the uid of the current user must match the uid | ||
112 | of the user who mounted the resource. | ||
113 | |||
114 | Also 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 | ||
116 | to the file /etc/fstab for each //server/share you wish to mount, but | ||
117 | this can become unwieldy when potential mount targets include many | ||
118 | or unpredictable UNC names. | ||
119 | |||
100 | Samba Considerations | 120 | Samba Considerations |
101 | ==================== | 121 | ==================== |
102 | To get the maximum benefit from the CIFS VFS, we recommend using a server that | 122 | To 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 | ||
380 | The mount.cifs mount helper also accepts a few mount options before -o | 413 | The mount.cifs mount helper also accepts a few mount options before -o |
381 | including: | 414 | including: |
@@ -392,7 +425,7 @@ Misc /proc/fs/cifs Flags and Debug Info | |||
392 | ======================================= | 425 | ======================================= |
393 | Informational pseudo-files: | 426 | Informational pseudo-files: |
394 | DebugData Displays information about active CIFS sessions | 427 | DebugData Displays information about active CIFS sessions |
395 | and shares. | 428 | and shares, as well as the cifs.ko version. |
396 | Stats Lists summary resource usage information as well as per | 429 | Stats 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 | |||
449 | Two other experimental features are under development and to test | 482 | Two other experimental features are under development and to test |
450 | require enabling CONFIG_CIFS_EXPERIMENTAL | 483 | require 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 | ||
468 | Also note that "cat /proc/fs/cifs/DebugData" will display information about | 501 | Also note that "cat /proc/fs/cifs/DebugData" will display information about |
469 | the active sessions and the shares that are mounted. Note: NTLMv2 enablement | 502 | the active sessions and the shares that are mounted. Note: NTLMv2 enablement |
470 | will not work since they its implementation is not quite complete yet. | 503 | will not work since its implementation is not quite complete yet. Do not alter |
471 | Do not alter these configuration values unless you are doing specific testing. | 504 | the ExtendedSecurity configuration value unless you are doing specific testing. |
472 | Enabling extended security works to Windows 2000 Workstations and XP but not to | 505 | Enabling extended security works to Windows 2000 Workstations and XP but not to |
473 | Windows 2000 server or Samba since it does not usually send "raw NTLMSSP" | 506 | Windows 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 @@ | |||
1 | version 1.22 July 30, 2004 | 1 | version 1.34 April 29, 2005 |
2 | 2 | ||
3 | A Partial List of Missing Features | 3 | A Partial List of Missing Features |
4 | ================================== | 4 | ================================== |
@@ -14,7 +14,7 @@ b) Better pam/winbind integration (e.g. to handle uid mapping | |||
14 | better) | 14 | better) |
15 | 15 | ||
16 | c) multi-user mounts - multiplexed sessionsetups over single vc | 16 | c) 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 | ||
19 | d) Kerberos/SPNEGO session setup support - (started) | 19 | d) Kerberos/SPNEGO session setup support - (started) |
20 | 20 | ||
@@ -67,12 +67,26 @@ q) implement support for security and trusted categories of xattrs | |||
67 | 67 | ||
68 | r) Implement O_DIRECT flag on open (already supported on mount) | 68 | r) Implement O_DIRECT flag on open (already supported on mount) |
69 | 69 | ||
70 | KNOWN BUGS (updated December 10, 2004) | 70 | s) Allow remapping of last remaining character (\) to +0xF000 which |
71 | (this character is valid for POSIX but not for Windows) | ||
72 | |||
73 | t) Create UID mapping facility so server UIDs can be mapped on a per | ||
74 | mount or a per server basis to client UIDs or nobody if no mapping | ||
75 | exists. This is helpful when Unix extensions are negotiated to | ||
76 | allow better permission checking when UIDs differ on the server | ||
77 | and client. Add new protocol request to the CIFS protocol | ||
78 | standard for asking the server for the corresponding name of a | ||
79 | particular uid. | ||
80 | |||
81 | KNOWN BUGS (updated April 29, 2005) | ||
71 | ==================================== | 82 | ==================================== |
83 | See http://bugzilla.samba.org - search on product "CifsVFS" for | ||
84 | current bug list. | ||
85 | |||
72 | 1) existing symbolic links (Windows reparse points) are recognized but | 86 | 1) existing symbolic links (Windows reparse points) are recognized but |
73 | can not be created remotely. They are implemented for Samba and those that | 87 | can not be created remotely. They are implemented for Samba and those that |
74 | support the CIFS Unix extensions but Samba has a bug currently handling | 88 | support the CIFS Unix extensions, although earlier versions of Samba |
75 | symlink text beginning with slash | 89 | overly restrict the pathnames. |
76 | 2) follow_link and readdir code does not follow dfs junctions | 90 | 2) follow_link and readdir code does not follow dfs junctions |
77 | but recognizes them | 91 | but recognizes them |
78 | 3) create of new files to FAT partitions on Windows servers can | 92 | 3) 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, | |||
98 | and when signing is disabled to request larger read sizes (larger than | 112 | and when signing is disabled to request larger read sizes (larger than |
99 | negotiated size) and send larger write sizes to modern servers. | 113 | negotiated size) and send larger write sizes to modern servers. |
100 | 114 | ||
101 | 4) More exhaustively test the recently added NT4 support against various | 115 | 4) More exhaustively test against less common servers. More testing |
102 | NT4 service pack levels, and fix cifs_setattr for setting file times and | 116 | against Windows 9x, Windows ME servers. |
103 | size 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 | ||
33 | void | 34 | void |
34 | cifs_dump_mem(char *label, void *data, int length) | 35 | cifs_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 | ||
27 | struct cifs_sb_info { | 28 | struct 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 | ||
53 | int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses, | 53 | int 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) | |||
169 | static int | 169 | static int |
170 | cifs_statfs(struct super_block *sb, struct kstatfs *buf) | 170 | cifs_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 | ||
211 | static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd) | 215 | static 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 | ||
596 | static void | 609 | static 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 | ||
827 | static int __init | 841 | static 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); |
92 | extern int cifs_removexattr(struct dentry *, const char *); | 92 | extern int cifs_removexattr(struct dentry *, const char *); |
93 | extern int cifs_setxattr(struct dentry *, const char *, const void *, | 93 | extern int cifs_setxattr(struct dentry *, const char *, const void *, |
94 | size_t, int); | 94 | size_t, int); |
95 | extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); | 95 | extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); |
96 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 96 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
97 | #define CIFS_VERSION "1.31" | 97 | extern 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 | ||
323 | struct oplock_q_entry { | 327 | struct 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 | |||
766 | typedef 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 | |||
765 | typedef struct smb_com_lock_rsp { | 775 | typedef 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 | |||
1257 | struct 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 | ||
1265 | struct 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 */ | ||
1530 | typedef struct { | 1560 | typedef 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 | ||
1974 | typedef struct { | 2004 | typedef 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 | |||
2033 | typedef 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, | |||
57 | extern int cifs_inet_pton(int, char * source, void *dst); | 57 | extern int cifs_inet_pton(int, char * source, void *dst); |
58 | extern int map_smb_to_linux_error(struct smb_hdr *smb); | 58 | extern int map_smb_to_linux_error(struct smb_hdr *smb); |
59 | extern void header_assemble(struct smb_hdr *, char /* command */ , | 59 | extern 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 | ); |
63 | extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *); | 63 | extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, |
64 | struct cifsTconInfo *); | ||
64 | extern void DeleteOplockQEntry(struct oplock_q_entry *); | 65 | extern void DeleteOplockQEntry(struct oplock_q_entry *); |
65 | extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ ); | 66 | extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ ); |
66 | extern u64 cifs_UnixTimeToNT(struct timespec); | 67 | extern u64 cifs_UnixTimeToNT(struct timespec); |
@@ -88,7 +89,7 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
88 | 89 | ||
89 | extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, | 90 | extern 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 | ||
93 | extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | 94 | extern 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, | |||
99 | extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, | 100 | extern 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 | ||
104 | extern int CIFSSMBUnixQPathInfo(const int xid, | 105 | extern 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 | ||
110 | extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, | 111 | extern 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 | ||
116 | extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | 117 | extern 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); |
119 | extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | 120 | extern 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); | ||
122 | extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, | 126 | extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, |
123 | struct kstatfs *FSData, | 127 | struct kstatfs *FSData); |
124 | const struct nls_table *nls_codepage); | ||
125 | extern int CIFSSMBQFSAttributeInfo(const int xid, | 128 | extern int CIFSSMBQFSAttributeInfo(const int xid, |
126 | struct cifsTconInfo *tcon, | 129 | struct cifsTconInfo *tcon); |
127 | const struct nls_table *nls_codepage); | 130 | extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon); |
128 | extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon, | 131 | extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon); |
129 | const struct nls_table *nls_codepage); | ||
130 | extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon, | ||
131 | const struct nls_table *nls_codepage); | ||
132 | extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, | 132 | extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, |
133 | struct kstatfs *FSData, const struct nls_table *nls_codepage); | 133 | struct kstatfs *FSData); |
134 | 134 | ||
135 | extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, | 135 | extern 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); | ||
138 | extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | 139 | extern 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 */ |
145 | extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, | 146 | extern 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); | ||
148 | extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, | 151 | extern 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); | ||
150 | extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon, | 154 | extern 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 | ||
154 | extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, | 160 | extern 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); | ||
157 | extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, | 164 | extern 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 | ||
160 | extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, | 168 | extern 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); | ||
163 | extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, | 172 | extern 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); | ||
166 | extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, | 176 | extern 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); | ||
168 | extern int CIFSCreateHardLink(const int xid, | 180 | extern 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); | ||
172 | extern int CIFSUnixCreateHardLink(const int xid, | 185 | extern 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); | ||
176 | extern int CIFSUnixCreateSymLink(const int xid, | 190 | extern 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); |
196 | extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, | 210 | extern 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); |
212 | extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | 226 | extern 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 */ |
231 | extern int cifs_convertUCSpath(char *target, const __u16 *source, int maxlen, | ||
232 | const struct nls_table * codepage); | ||
233 | extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen, | ||
234 | const struct nls_table * cp, int mapChars); | ||
216 | 235 | ||
217 | extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | 236 | extern 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 | ||
231 | extern int cifs_reconnect(struct TCP_Server_Info *server); | 250 | extern int cifs_reconnect(struct TCP_Server_Info *server); |
232 | 251 | ||
233 | extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *); | 252 | extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *); |
234 | extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, | 253 | extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, |
235 | __u32 expected_sequence_number); | 254 | __u32 expected_sequence_number); |
236 | extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); | 255 | extern 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); | ||
245 | extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | 265 | extern 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); |
248 | extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, | 268 | extern 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); | ||
251 | extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon, | 272 | extern 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); |
255 | extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, | 276 | extern 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); |
259 | extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, | 280 | extern 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); |
263 | extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, | 284 | extern 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); |
267 | int cifs_ioctl (struct inode * inode, struct file * filep, | 288 | extern 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 | ||
540 | int | 552 | int |
541 | CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, | 553 | CIFSSMBDelFile(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 | ||
591 | int | 602 | int |
592 | CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, | 603 | CIFSSMBRmDir(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 | ||
640 | int | 650 | int |
641 | CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, | 651 | CIFSSMBMkDir(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) | |||
1108 | int | 1118 | int |
1109 | CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, | 1119 | CIFSSMBRename(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 | ||
1184 | int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, | 1192 | int 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, | |||
1263 | int | 1274 | int |
1264 | CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, | 1275 | CIFSSMBCopy(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: | |||
1425 | int | 1434 | int |
1426 | CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon, | 1435 | CIFSUnixCreateHardLink(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: | |||
1512 | int | 1519 | int |
1513 | CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon, | 1520 | CIFSCreateHardLink(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 */ |
1796 | static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const int acl_type,const int size_of_data_area) | 1802 | static 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 | |||
1912 | CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, | 1919 | CIFSSMBGetPosixACL(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: | |||
1997 | int | 2004 | int |
1998 | CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, | 2005 | CIFSSMBSetPosixACL(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 */ |
2084 | int | ||
2085 | CIFSGetExtAttr(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 | |||
2098 | GetExtAttrRetry: | ||
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 | } | ||
2158 | GetExtAttrOut: | ||
2159 | cifs_buf_release(pSMB); | ||
2160 | if (rc == -EAGAIN) | ||
2161 | goto GetExtAttrRetry; | ||
2162 | return rc; | ||
2163 | } | ||
2164 | |||
2165 | |||
2166 | #endif /* CONFIG_POSIX */ | ||
2076 | 2167 | ||
2077 | int | 2168 | int |
2078 | CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, | 2169 | CIFSSMBQPathInfo(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 | |||
2160 | CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, | 2250 | CIFSSMBUnixQPathInfo(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 | ||
2341 | findFirstRetry: | 2430 | findFirstRetry: |
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 | |||
2608 | CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | 2705 | CIFSGetSrvInodeNumber(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 | ||
2873 | int | 2968 | int |
2874 | CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, | 2969 | CIFSSMBQFSInfo(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 | ||
2957 | int | 3051 | int |
2958 | CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon, | 3052 | CIFSSMBQFSAttributeInfo(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 | ||
3026 | int | 3119 | int |
3027 | CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon, | 3120 | CIFSSMBQFSDeviceInfo(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 | ||
3096 | int | 3188 | int |
3097 | CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon, | 3189 | CIFSSMBQFSUnixInfo(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 | ||
3167 | int | 3258 | int |
3168 | CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, | 3259 | CIFSSMBQFSPosixInfo(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 | ||
3259 | int | 3350 | int |
3260 | CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName, | 3351 | CIFSSMBSetEOF(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 | |||
3512 | int | 3607 | int |
3513 | CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName, | 3608 | CIFSSMBSetTimes(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 | ||
3645 | int | 3739 | int |
3646 | CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon, | 3740 | CIFSSMBUnixSetPerms(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 | |||
3789 | CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, | 3883 | CIFSSMBQAllEAs(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: | |||
3934 | ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon, | 4027 | ssize_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: | |||
4082 | int | 4174 | int |
4083 | CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName, | 4175 | CIFSSMBSetEA(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 | */ | ||
203 | static 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 | |||
245 | static 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 | |||
193 | static int | 311 | static int |
194 | cifs_demultiplex_thread(struct TCP_Server_Info *server) | 312 | cifs_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; | ||
579 | multi_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 | ||
472 | static void * | ||
473 | cifs_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 | |||
482 | static int | 718 | static int |
483 | cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | 719 | cifs_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 | ||
919 | int | 1172 | int |
920 | connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | 1173 | connect_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, | |||
940 | int | 1194 | int |
941 | get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | 1195 | get_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 | 2064 | sesssetup_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) |
105 | char * | ||
106 | build_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 | |||
117 | cifs_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 | 112 | BB 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 | 277 | cifs_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 | ||
456 | int | ||
457 | cifs_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 | |||
487 | static int | 406 | static int |
488 | cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | 407 | cifs_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 | ||
30 | int cifs_ioctl (struct inode * inode, struct file * filep, | 34 | int 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 | ||
32 | extern mempool_t *cifs_sm_req_poolp; | 33 | extern mempool_t *cifs_sm_req_poolp; |
33 | extern mempool_t *cifs_req_poolp; | 34 | extern 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 */ | ||
539 | int | ||
540 | cifs_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 | } | ||
589 | cUCS_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 */ | ||
598 | int | ||
599 | cifsConvertToUCS(__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 | |||
658 | ctoUCS_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 | ||
107 | static void fill_in_inode(struct inode *tmp_inode, | 107 | static 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 | ||
199 | static void unix_fill_in_inode(struct inode *tmp_inode, | 218 | static 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 | ||
365 | ffirst_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 |
78 | class.*/ | 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 | ||
183 | int | 186 | int |
184 | smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer, | 187 | smb_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 | } |
88 | remove_ea_exit: | 89 | remove_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); |