diff options
Diffstat (limited to 'ANDROID_3.4.5/fs/cifs')
50 files changed, 0 insertions, 38575 deletions
diff --git a/ANDROID_3.4.5/fs/cifs/AUTHORS b/ANDROID_3.4.5/fs/cifs/AUTHORS deleted file mode 100644 index ea940b1d..00000000 --- a/ANDROID_3.4.5/fs/cifs/AUTHORS +++ /dev/null @@ -1,55 +0,0 @@ -Original Author -=============== -Steve French (sfrench@samba.org) - -The author wishes to express his appreciation and thanks to: -Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS -improvements. Thanks to IBM for allowing me time and test resources to pursue -this project, to Jim McDonough from IBM (and the Samba Team) for his help, to -the IBM Linux JFS team for explaining many esoteric Linux filesystem features. -Jeremy Allison of the Samba team has done invaluable work in adding the server -side of the original CIFS Unix extensions and reviewing and implementing -portions of the newer CIFS POSIX extensions into the Samba 3 file server. Thank -Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client) -for proving years ago that very good smb/cifs clients could be done on Unix-like -operating systems. Volker Lendecke, Andrew Tridgell, Urban Widmark, John -Newbigin and others for their work on the Linux smbfs module. Thanks to -the other members of the Storage Network Industry Association CIFS Technical -Workgroup for their work specifying this highly complex protocol and finally -thanks to the Samba team for their technical advice and encouragement. - -Patch Contributors ------------------- -Zwane Mwaikambo -Andi Kleen -Amrut Joshi -Shobhit Dayal -Sergey Vlasov -Richard Hughes -Yury Umanets -Mark Hamzy (for some of the early cifs IPv6 work) -Domen Puncer -Jesper Juhl (in particular for lots of whitespace/formatting cleanup) -Vince Negri and Dave Stahl (for finding an important caching bug) -Adrian Bunk (kcalloc cleanups) -Miklos Szeredi -Kazeon team for various fixes especially for 2.4 version. -Asser Ferno (Change Notify support) -Shaggy (Dave Kleikamp) for innumerable small fs suggestions and some good cleanup -Gunter Kukkukk (testing and suggestions for support of old servers) -Igor Mammedov (DFS support) -Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code) - -Test case and Bug Report contributors -------------------------------------- -Thanks to those in the community who have submitted detailed bug reports -and debug of problems they have found: Jochen Dolze, David Blaine, -Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori, -Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen, -Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special -mention to the Stanford Checker (SWAT) which pointed out many minor -bugs in error paths. Valuable suggestions also have come from Al Viro -and Dave Miller. - -And thanks to the IBM LTC and Power test teams and SuSE testers for -finding multiple bugs during excellent stress test runs. diff --git a/ANDROID_3.4.5/fs/cifs/CHANGES b/ANDROID_3.4.5/fs/cifs/CHANGES deleted file mode 100644 index bc0025cd..00000000 --- a/ANDROID_3.4.5/fs/cifs/CHANGES +++ /dev/null @@ -1,1065 +0,0 @@ -Version 1.62 ------------- -Add sockopt=TCP_NODELAY mount option. EA (xattr) routines hardened -to more strictly handle corrupt frames. - -Version 1.61 ------------- -Fix append problem to Samba servers (files opened with O_APPEND could -have duplicated data). Fix oops in cifs_lookup. Workaround problem -mounting to OS/400 Netserve. Fix oops in cifs_get_tcp_session. -Disable use of server inode numbers when server only -partially supports them (e.g. for one server querying inode numbers on -FindFirst fails but QPathInfo queries works). Fix oops with dfs in -cifs_put_smb_ses. Fix mmap to work on directio mounts (needed -for OpenOffice when on forcedirectio mount e.g.) - -Version 1.60 -------------- -Fix memory leak in reconnect. Fix oops in DFS mount error path. -Set s_maxbytes to smaller (the max that vfs can handle) so that -sendfile will now work over cifs mounts again. Add noforcegid -and noforceuid mount parameters. Fix small mem leak when using -ntlmv2. Fix 2nd mount to same server but with different port to -be allowed (rather than reusing the 1st port) - only when the -user explicitly overrides the port on the 2nd mount. - -Version 1.59 ------------- -Client uses server inode numbers (which are persistent) rather than -client generated ones by default (mount option "serverino" turned -on by default if server supports it). Add forceuid and forcegid -mount options (so that when negotiating unix extensions specifying -which uid mounted does not immediately force the server's reported -uids to be overridden). Add support for scope mount parm. Improve -hard link detection to use same inode for both. Do not set -read-only dos attribute on directories (for chmod) since Windows -explorer special cases this attribute bit for directories for -a different purpose. - -Version 1.58 ------------- -Guard against buffer overruns in various UCS-2 to UTF-8 string conversions -when the UTF-8 string is composed of unusually long (more than 4 byte) converted -characters. Add support for mounting root of a share which redirects immediately -to DFS target. Convert string conversion functions from Unicode to more -accurately mark string length before allocating memory (which may help the -rare cases where a UTF-8 string is much larger than the UCS2 string that -we converted from). Fix endianness of the vcnum field used during -session setup to distinguish multiple mounts to same server from different -userids. Raw NTLMSSP fixed (it requires /proc/fs/cifs/experimental -flag to be set to 2, and mount must enable krb5 to turn on extended security). -Performance of file create to Samba improved (posix create on lookup -removes 1 of 2 network requests sent on file create) - -Version 1.57 ------------- -Improve support for multiple security contexts to the same server. We -used to use the same "vcnumber" for all connections which could cause -the server to treat subsequent connections, especially those that -are authenticated as guest, as reconnections, invalidating the earlier -user's smb session. This fix allows cifs to mount multiple times to the -same server with different userids without risking invalidating earlier -established security contexts. fsync now sends SMB Flush operation -to better ensure that we wait for server to write all of the data to -server disk (not just write it over the network). Add new mount -parameter to allow user to disable sending the (slow) SMB flush on -fsync if desired (fsync still flushes all cached write data to the server). -Posix file open support added (turned off after one attempt if server -fails to support it properly, as with Samba server versions prior to 3.3.2) -Fix "redzone overwritten" bug in cifs_put_tcon (CIFSTcon may allocate too -little memory for the "nativeFileSystem" field returned by the server -during mount). Endian convert inode numbers if necessary (makes it easier -to compare inode numbers on network files from big endian systems). - -Version 1.56 ------------- -Add "forcemandatorylock" mount option to allow user to use mandatory -rather than posix (advisory) byte range locks, even though server would -support posix byte range locks. Fix query of root inode when prefixpath -specified and user does not have access to query information about the -top of the share. Fix problem in 2.6.28 resolving DFS paths to -Samba servers (worked to Windows). Fix rmdir so that pending search -(readdir) requests do not get invalid results which include the now -removed directory. Fix oops in cifs_dfs_ref.c when prefixpath is not reachable -when using DFS. Add better file create support to servers which support -the CIFS POSIX protocol extensions (this adds support for new flags -on create, and improves semantics for write of locked ranges). - -Version 1.55 ------------- -Various fixes to make delete of open files behavior more predictable -(when delete of an open file fails we mark the file as "delete-on-close" -in a way that more servers accept, but only if we can first rename the -file to a temporary name). Add experimental support for more safely -handling fcntl(F_SETLEASE). Convert cifs to using blocking tcp -sends, and also let tcp autotune the socket send and receive buffers. -This reduces the number of EAGAIN errors returned by TCP/IP in -high stress workloads (and the number of retries on socket writes -when sending large SMBWriteX requests). Fix case in which a portion of -data can in some cases not get written to the file on the server before the -file is closed. Fix DFS parsing to properly handle path consumed field, -and to handle certain codepage conversions better. Fix mount and -umount race that can cause oops in mount or umount or reconnect. - -Version 1.54 ------------- -Fix premature write failure on congested networks (we would give up -on EAGAIN from the socket too quickly on large writes). -Cifs_mkdir and cifs_create now respect the setgid bit on parent dir. -Fix endian problems in acl (mode from/to cifs acl) on bigendian -architectures. Fix problems with preserving timestamps on copying open -files (e.g. "cp -a") to Windows servers. For mkdir and create honor setgid bit -on parent directory when server supports Unix Extensions but not POSIX -create. Update cifs.upcall version to handle new Kerberos sec flags -(this requires update of cifs.upcall program from Samba). Fix memory leak -on dns_upcall (resolving DFS referralls). Fix plain text password -authentication (requires setting SecurityFlags to 0x30030 to enable -lanman and plain text though). Fix writes to be at correct offset when -file is open with O_APPEND and file is on a directio (forcediretio) mount. -Fix bug in rewinding readdir directory searches. Add nodfs mount option. - -Version 1.53 ------------- -DFS support added (Microsoft Distributed File System client support needed -for referrals which enable a hierarchical name space among servers). -Disable temporary caching of mode bits to servers which do not support -storing of mode (e.g. Windows servers, when client mounts without cifsacl -mount option) and add new "dynperm" mount option to enable temporary caching -of mode (enable old behavior). Fix hang on mount caused when server crashes -tcp session during negotiate protocol. - -Version 1.52 ------------- -Fix oops on second mount to server when null auth is used. -Enable experimental Kerberos support. Return writebehind errors on flush -and sync so that events like out of disk space get reported properly on -cached files. Fix setxattr failure to certain Samba versions. Fix mount -of second share to disconnected server session (autoreconnect on this). -Add ability to modify cifs acls for handling chmod (when mounted with -cifsacl flag). Fix prefixpath path separator so we can handle mounts -with prefixpaths longer than one directory (one path component) when -mounted to Windows servers. Fix slow file open when cifsacl -enabled. Fix memory leak in FindNext when the SMB call returns -EBADF. - - -Version 1.51 ------------- -Fix memory leak in statfs when mounted to very old servers (e.g. -Windows 9x). Add new feature "POSIX open" which allows servers -which support the current POSIX Extensions to provide better semantics -(e.g. delete for open files opened with posix open). Take into -account umask on posix mkdir not just older style mkdir. Add -ability to mount to IPC$ share (which allows CIFS named pipes to be -opened, read and written as if they were files). When 1st tree -connect fails (e.g. due to signing negotiation failure) fix -leak that causes cifsd not to stop and rmmod to fail to cleanup -cifs_request_buffers pool. Fix problem with POSIX Open/Mkdir on -bigendian architectures. Fix possible memory corruption when -EAGAIN returned on kern_recvmsg. Return better error if server -requires packet signing but client has disabled it. When mounted -with cifsacl mount option - mode bits are approximated based -on the contents of the ACL of the file or directory. When cifs -mount helper is missing convert make sure that UNC name -has backslash (not forward slash) between ip address of server -and the share name. - -Version 1.50 ------------- -Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is -done with "serverino" mount option). Add support for POSIX Unlink -(helps with certain sharing violation cases when server such as -Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix" -mount option to allow disabling the CIFS Unix Extensions for just -that mount. Fix hang on spinlock in find_writable_file (race when -reopening file after session crash). Byte range unlock request to -windows server could unlock more bytes (on server copy of file) -than intended if start of unlock request is well before start of -a previous byte range lock that we issued. - -Version 1.49 ------------- -IPv6 support. Enable ipv6 addresses to be passed on mount (put the ipv6 -address after the "ip=" mount option, at least until mount.cifs is fixed to -handle DNS host to ipv6 name translation). Accept override of uid or gid -on mount even when Unix Extensions are negotiated (it used to be ignored -when Unix Extensions were ignored). This allows users to override the -default uid and gid for files when they are certain that the uids or -gids on the server do not match those of the client. Make "sec=none" -mount override username (so that null user connection is attempted) -to match what documentation said. Support for very large reads, over 127K, -available to some newer servers (such as Samba 3.0.26 and later but -note that it also requires setting CIFSMaxBufSize at module install -time to a larger value which may hurt performance in some cases). -Make sign option force signing (or fail if server does not support it). - -Version 1.48 ------------- -Fix mtime bouncing around from local idea of last write times to remote time. -Fix hang (in i_size_read) when simultaneous size update of same remote file -on smp system corrupts sequence number. Do not reread unnecessarily partial page -(which we are about to overwrite anyway) when writing out file opened rw. -When DOS attribute of file on non-Unix server's file changes on the server side -from read-only back to read-write, reflect this change in default file mode -(we had been leaving a file's mode read-only until the inode were reloaded). -Allow setting of attribute back to ATTR_NORMAL (removing readonly dos attribute -when archive dos attribute not set and we are changing mode back to writeable -on server which does not support the Unix Extensions). Remove read only dos -attribute on chmod when adding any write permission (ie on any of -user/group/other (not all of user/group/other ie 0222) when -mounted to windows. Add support for POSIX MkDir (slight performance -enhancement and eliminates the network race between the mkdir and set -path info of the mode). - - -Version 1.47 ------------- -Fix oops in list_del during mount caused by unaligned string. -Fix file corruption which could occur on some large file -copies caused by writepages page i/o completion bug. -Seek to SEEK_END forces check for update of file size for non-cached -files. Allow file size to be updated on remote extend of locally open, -non-cached file. Fix reconnect to newer Samba servers (or other servers -which support the CIFS Unix/POSIX extensions) so that we again tell the -server the Unix/POSIX cifs capabilities which we support (SetFSInfo). -Add experimental support for new POSIX Open/Mkdir (which returns -stat information on the open, and allows setting the mode). - -Version 1.46 ------------- -Support deep tree mounts. Better support OS/2, Win9x (DOS) time stamps. -Allow null user to be specified on mount ("username="). Do not return -EINVAL on readdir when filldir fails due to overwritten blocksize -(fixes FC problem). Return error in rename 2nd attempt retry (ie report -if rename by handle also fails, after rename by path fails, we were -not reporting whether the retry worked or not). Fix NTLMv2 to -work to Windows servers (mount with option "sec=ntlmv2"). - -Version 1.45 ------------- -Do not time out lockw calls when using posix extensions. Do not -time out requests if server still responding reasonably fast -on requests on other threads. Improve POSIX locking emulation, -(lock cancel now works, and unlock of merged range works even -to Windows servers now). Fix oops on mount to lanman servers -(win9x, os/2 etc.) when null password. Do not send listxattr -(SMB to query all EAs) if nouser_xattr specified. Fix SE Linux -problem (instantiate inodes/dentries in right order for readdir). - -Version 1.44 ------------- -Rewritten sessionsetup support, including support for legacy SMB -session setup needed for OS/2 and older servers such as Windows 95 and 98. -Fix oops on ls to OS/2 servers. Add support for level 1 FindFirst -so we can do search (ls etc.) to OS/2. Do not send NTCreateX -or recent levels of FindFirst unless server says it supports NT SMBs -(instead use legacy equivalents from LANMAN dialect). Fix to allow -NTLMv2 authentication support (now can use stronger password hashing -on mount if corresponding /proc/fs/cifs/SecurityFlags is set (0x4004). -Allow override of global cifs security flags on mount via "sec=" option(s). - -Version 1.43 ------------- -POSIX locking to servers which support CIFS POSIX Extensions -(disabled by default controlled by proc/fs/cifs/Experimental). -Handle conversion of long share names (especially Asian languages) -to Unicode during mount. Fix memory leak in sess struct on reconnect. -Fix rare oops after acpi suspend. Fix O_TRUNC opens to overwrite on -cifs open which helps rare case when setpathinfo fails or server does -not support it. - -Version 1.42 ------------- -Fix slow oplock break when mounted to different servers at the same time and -the tids match and we try to find matching fid on wrong server. Fix read -looping when signing required by server (2.6.16 kernel only). Fix readdir -vs. rename race which could cause each to hang. Return . and .. even -if server does not. Allow searches to skip first three entries and -begin at any location. Fix oops in find_writeable_file. - -Version 1.41 ------------- -Fix NTLMv2 security (can be enabled in /proc/fs/cifs) so customers can -configure stronger authentication. Fix sfu symlinks so they can -be followed (not just recognized). Fix wraparound of bcc on -read responses when buffer size over 64K and also fix wrap of -max smb buffer size when CIFSMaxBufSize over 64K. Fix oops in -cifs_user_read and cifs_readpages (when EAGAIN on send of smb -on socket is returned over and over). Add POSIX (advisory) byte range -locking support (requires server with newest CIFS UNIX Extensions -to the protocol implemented). Slow down negprot slightly in port 139 -RFC1001 case to give session_init time on buggy servers. - -Version 1.40 ------------- -Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance -of readpages by eliminating one extra memcpy. Allow update of file size -from remote server even if file is open for write as long as mount is -directio. Recognize share mode security and send NTLM encrypted password -on tree connect if share mode negotiated. - -Version 1.39 ------------- -Defer close of a file handle slightly if pending writes depend on that handle -(this reduces the EBADF bad file handle errors that can be logged under heavy -stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2 -Fix SFU style symlinks and mknod needed for servers which do not support the -CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative -dentries so files that the client sees as deleted but that later get created -on the server will be recognized. Add client side permission check on setattr. -Timeout stuck requests better (where server has never responded or sent corrupt -responses) - -Version 1.38 ------------- -Fix tcp socket retransmission timeouts (e.g. on ENOSPACE from the socket) -to be smaller at first (but increasing) so large write performance performance -over GigE is better. Do not hang thread on illegal byte range lock response -from Windows (Windows can send an RFC1001 size which does not match smb size) by -allowing an SMBs TCP length to be up to a few bytes longer than it should be. -wsize and rsize can now be larger than negotiated buffer size if server -supports large readx/writex, even when directio mount flag not specified. -Write size will in many cases now be 16K instead of 4K which greatly helps -file copy performance on lightly loaded networks. Fix oops in dnotify -when experimental config flag enabled. Make cifsFYI more granular. - -Version 1.37 ------------- -Fix readdir caching when unlink removes file in current search buffer, -and this is followed by a rewind search to just before the deleted entry. -Do not attempt to set ctime unless atime and/or mtime change requested -(most servers throw it away anyway). Fix length check of received smbs -to be more accurate. Fix big endian problem with mapchars mount option, -and with a field returned by statfs. - -Version 1.36 ------------- -Add support for mounting to older pre-CIFS servers such as Windows9x and ME. -For these older servers, add option for passing netbios name of server in -on mount (servernetbiosname). Add suspend support for power management, to -avoid cifsd thread preventing software suspend from working. -Add mount option for disabling the default behavior of sending byte range lock -requests to the server (necessary for certain applications which break with -mandatory lock behavior such as Evolution), and also mount option for -requesting case insensitive matching for path based requests (requesting -case sensitive is the default). - -Version 1.35 ------------- -Add writepage performance improvements. Fix path name conversions -for long filenames on mounts which were done with "mapchars" mount option -specified. Ensure multiplex ids do not collide. Fix case in which -rmmod can oops if done soon after last unmount. Fix truncated -search (readdir) output when resume filename was a long filename. -Fix filename conversion when mapchars mount option was specified and -filename was a long filename. - -Version 1.34 ------------- -Fix error mapping of the TOO_MANY_LINKS (hardlinks) case. -Do not oops if root user kills cifs oplock kernel thread or -kills the cifsd thread (NB: killing the cifs kernel threads is not -recommended, unmount and rmmod cifs will kill them when they are -no longer needed). Fix readdir to ASCII servers (ie older servers -which do not support Unicode) and also require asterisk. -Fix out of memory case in which data could be written one page -off in the page cache. - -Version 1.33 ------------- -Fix caching problem, in which readdir of directory containing a file -which was cached could cause the file's time stamp to be updated -without invalidating the readahead data (so we could get stale -file data on the client for that file even as the server copy changed). -Cleanup response processing so cifsd can not loop when abnormally -terminated. - - -Version 1.32 ------------- -Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one -transact response for an SMB request and search entry split across two frames. -Add support for lsattr (getting ext2/ext3/reiserfs attr flags from the server) -as new protocol extensions. Do not send Get/Set calls for POSIX ACLs -unless server explicitly claims to support them in CIFS Unix extensions -POSIX ACL capability bit. Fix packet signing when multiuser mounting with -different users from the same client to the same server. Fix oops in -cifs_close. Add mount option for remapping reserved characters in -filenames (also allow recognizing files with created by SFU which have any -of these seven reserved characters, except backslash, to be recognized). -Fix invalid transact2 message (we were sometimes trying to interpret -oplock breaks as SMB responses). Add ioctl for checking that the -current uid matches the uid of the mounter (needed by umount.cifs). -Reduce the number of large buffer allocations in cifs response processing -(significantly reduces memory pressure under heavy stress with multiple -processes accessing the same server at the same time). - -Version 1.31 ------------- -Fix updates of DOS attributes and time fields so that files on NT4 servers -do not get marked delete on close. Display sizes of cifs buffer pools in -cifs stats. Fix oops in unmount when cifsd thread being killed by -shutdown. Add generic readv/writev and aio support. Report inode numbers -consistently in readdir and lookup (when serverino mount option is -specified use the inode number that the server reports - for both lookup -and readdir, otherwise by default the locally generated inode number is used -for inodes created in either path since servers are not always able to -provide unique inode numbers when exporting multiple volumes from under one -sharename). - -Version 1.30 ------------- -Allow new nouser_xattr mount parm to disable xattr support for user namespace. -Do not flag user_xattr mount parm in dmesg. Retry failures setting file time -(mostly affects NT4 servers) by retry with handle based network operation. -Add new POSIX Query FS Info for returning statfs info more accurately. -Handle passwords with multiple commas in them. - -Version 1.29 ------------- -Fix default mode in sysfs of cifs module parms. Remove old readdir routine. -Fix capabilities flags for large readx so as to allow reads larger than 64K. - -Version 1.28 ------------- -Add module init parm for large SMB buffer size (to allow it to be changed -from its default of 16K) which is especially useful for large file copy -when mounting with the directio mount option. Fix oops after -returning from mount when experimental ExtendedSecurity enabled and -SpnegoNegotiated returning invalid error. Fix case to retry better when -peek returns from 1 to 3 bytes on socket which should have more data. -Fixed path based calls (such as cifs lookup) to handle path names -longer than 530 (now can handle PATH_MAX). Fix pass through authentication -from Samba server to DC (Samba required dummy LM password). - -Version 1.27 ------------- -Turn off DNOTIFY (directory change notification support) by default -(unless built with the experimental flag) to fix hang with KDE -file browser. Fix DNOTIFY flag mappings. Fix hang (in wait_event -waiting on an SMB response) in SendReceive when session dies but -reconnects quickly from another task. Add module init parms for -minimum number of large and small network buffers in the buffer pools, -and for the maximum number of simultaneous requests. - -Version 1.26 ------------- -Add setfacl support to allow setting of ACLs remotely to Samba 3.10 and later -and other POSIX CIFS compliant servers. Fix error mapping for getfacl -to EOPNOTSUPP when server does not support posix acls on the wire. Fix -improperly zeroed buffer in CIFS Unix extensions set times call. - -Version 1.25 ------------- -Fix internationalization problem in cifs readdir with filenames that map to -longer UTF-8 strings than the string on the wire was in Unicode. Add workaround -for readdir to netapp servers. Fix search rewind (seek into readdir to return -non-consecutive entries). Do not do readdir when server negotiates -buffer size to small to fit filename. Add support for reading POSIX ACLs from -the server (add also acl and noacl mount options). - -Version 1.24 ------------- -Optionally allow using server side inode numbers, rather than client generated -ones by specifying mount option "serverino" - this is required for some apps -to work which double check hardlinked files and have persistent inode numbers. - -Version 1.23 ------------- -Multiple bigendian fixes. On little endian systems (for reconnect after -network failure) fix tcp session reconnect code so we do not try first -to reconnect on reverse of port 445. Treat reparse points (NTFS junctions) -as directories rather than symlinks because we can do follow link on them. - -Version 1.22 ------------- -Add config option to enable XATTR (extended attribute) support, mapping -xattr names in the "user." namespace space to SMB/CIFS EAs. Lots of -minor fixes pointed out by the Stanford SWAT checker (mostly missing -or out of order NULL pointer checks in little used error paths). - -Version 1.21 ------------- -Add new mount parm to control whether mode check (generic_permission) is done -on the client. If Unix extensions are enabled and the uids on the client -and server do not match, client permission checks are meaningless on -server uids that do not exist on the client (this does not affect the -normal ACL check which occurs on the server). Fix default uid -on mknod to match create and mkdir. Add optional mount parm to allow -override of the default uid behavior (in which the server sets the uid -and gid of newly created files). Normally for network filesystem mounts -user want the server to set the uid/gid on newly created files (rather than -using uid of the client processes you would in a local filesystem). - -Version 1.20 ------------- -Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps -info into /proc/fs/cifs/DebugData. Fix oops in rare oops in readdir -(in build_wildcard_path_from_dentry). Fix mknod to pass type field -(block/char/fifo) properly. Remove spurious mount warning log entry when -credentials passed as mount argument. Set major/minor device number in -inode for block and char devices when unix extensions enabled. - -Version 1.19 ------------- -Fix /proc/fs/cifs/Stats and DebugData display to handle larger -amounts of return data. Properly limit requests to MAX_REQ (50 -is the usual maximum active multiplex SMB/CIFS requests per server). -Do not kill cifsd (and thus hurt the other SMB session) when more than one -session to the same server (but with different userids) exists and one -of the two user's smb sessions is being removed while leaving the other. -Do not loop reconnecting in cifsd demultiplex thread when admin -kills the thread without going through unmount. - -Version 1.18 ------------- -Do not rename hardlinked files (since that should be a noop). Flush -cached write behind data when reopening a file after session abend, -except when already in write. Grab per socket sem during reconnect -to avoid oops in sendmsg if overlapping with reconnect. Do not -reset cached inode file size on readdir for files open for write on -client. - - -Version 1.17 ------------- -Update number of blocks in file so du command is happier (in Linux a fake -blocksize of 512 is required for calculating number of blocks in inode). -Fix prepare write of partial pages to read in data from server if possible. -Fix race on tcpStatus field between unmount and reconnection code, causing -cifsd process sometimes to hang around forever. Improve out of memory -checks in cifs_filldir - -Version 1.16 ------------- -Fix incorrect file size in file handle based setattr on big endian hardware. -Fix oops in build_path_from_dentry when out of memory. Add checks for invalid -and closing file structs in writepage/partialpagewrite. Add statistics -for each mounted share (new menuconfig option). Fix endianness problem in -volume information displayed in /proc/fs/cifs/DebugData (only affects -affects big endian architectures). Prevent renames while constructing -path names for open, mkdir and rmdir. - -Version 1.15 ------------- -Change to mempools for alloc smb request buffers and multiplex structs -to better handle low memory problems (and potential deadlocks). - -Version 1.14 ------------- -Fix incomplete listings of large directories on Samba servers when Unix -extensions enabled. Fix oops when smb_buffer can not be allocated. Fix -rename deadlock when writing out dirty pages at same time. - -Version 1.13 ------------- -Fix open of files in which O_CREATE can cause the mode to change in -some cases. Fix case in which retry of write overlaps file close. -Fix PPC64 build error. Reduce excessive stack usage in smb password -hashing. Fix overwrite of Linux user's view of file mode to Windows servers. - -Version 1.12 ------------- -Fixes for large file copy, signal handling, socket retry, buffer -allocation and low memory situations. - -Version 1.11 ------------- -Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize) -also now allowing support for specifying client netbiosname. NT4 support added. - -Version 1.10 ------------- -Fix reconnection (and certain failed mounts) to properly wake up the -blocked users thread so it does not seem hung (in some cases was blocked -until the cifs receive timeout expired). Fix spurious error logging -to kernel log when application with open network files killed. - -Version 1.09 ------------- -Fix /proc/fs module unload warning message (that could be logged -to the kernel log). Fix intermittent failure in connectathon -test7 (hardlink count not immediately refreshed in case in which -inode metadata can be incorrectly kept cached when time near zero) - -Version 1.08 ------------- -Allow file_mode and dir_mode (specified at mount time) to be enforced -locally (the server already enforced its own ACLs too) for servers -that do not report the correct mode (do not support the -CIFS Unix Extensions). - -Version 1.07 ------------- -Fix some small memory leaks in some unmount error paths. Fix major leak -of cache pages in readpages causing multiple read oriented stress -testcases (including fsx, and even large file copy) to fail over time. - -Version 1.06 ------------- -Send NTCreateX with ATTR_POSIX if Linux/Unix extensions negotiated with server. -This allows files that differ only in case and improves performance of file -creation and file open to such servers. Fix semaphore conflict which causes -slow delete of open file to Samba (which unfortunately can cause an oplock -break to self while vfs_unlink held i_sem) which can hang for 20 seconds. - -Version 1.05 ------------- -fixes to cifs_readpages for fsx test case - -Version 1.04 ------------- -Fix caching data integrity bug when extending file size especially when no -oplock on file. Fix spurious logging of valid already parsed mount options -that are parsed outside of the cifs vfs such as nosuid. - - -Version 1.03 ------------- -Connect to server when port number override not specified, and tcp port -unitialized. Reset search to restart at correct file when kernel routine -filldir returns error during large directory searches (readdir). - -Version 1.02 ------------- -Fix caching problem when files opened by multiple clients in which -page cache could contain stale data, and write through did -not occur often enough while file was still open when read ahead -(read oplock) not allowed. Treat "sep=" when first mount option -as an override of comma as the default separator between mount -options. - -Version 1.01 ------------- -Allow passwords longer than 16 bytes. Allow null password string. - -Version 1.00 ------------- -Gracefully clean up failed mounts when attempting to mount to servers such as -Windows 98 that terminate tcp sessions during protocol negotiation. Handle -embedded commas in mount parsing of passwords. - -Version 0.99 ------------- -Invalidate local inode cached pages on oplock break and when last file -instance is closed so that the client does not continue using stale local -copy rather than later modified server copy of file. Do not reconnect -when server drops the tcp session prematurely before negotiate -protocol response. Fix oops in reopen_file when dentry freed. Allow -the support for CIFS Unix Extensions to be disabled via proc interface. - -Version 0.98 ------------- -Fix hang in commit_write during reconnection of open files under heavy load. -Fix unload_nls oops in a mount failure path. Serialize writes to same socket -which also fixes any possible races when cifs signatures are enabled in SMBs -being sent out of signature sequence number order. - -Version 0.97 ------------- -Fix byte range locking bug (endian problem) causing bad offset and -length. - -Version 0.96 ------------- -Fix oops (in send_sig) caused by CIFS unmount code trying to -wake up the demultiplex thread after it had exited. Do not log -error on harmless oplock release of closed handle. - -Version 0.95 ------------- -Fix unsafe global variable usage and password hash failure on gcc 3.3.1 -Fix problem reconnecting secondary mounts to same server after session -failure. Fix invalid dentry - race in mkdir when directory gets created -by another client between the lookup and mkdir. - -Version 0.94 ------------- -Fix to list processing in reopen_files. Fix reconnection when server hung -but tcpip session still alive. Set proper timeout on socket read. - -Version 0.93 ------------- -Add missing mount options including iocharset. SMP fixes in write and open. -Fix errors in reconnecting after TCP session failure. Fix module unloading -of default nls codepage - -Version 0.92 ------------- -Active smb transactions should never go negative (fix double FreeXid). Fix -list processing in file routines. Check return code on kmalloc in open. -Fix spinlock usage for SMP. - -Version 0.91 ------------- -Fix oops in reopen_files when invalid dentry. drop dentry on server rename -and on revalidate errors. Fix cases where pid is now tgid. Fix return code -on create hard link when server does not support them. - -Version 0.90 ------------- -Fix scheduling while atomic error in getting inode info on newly created file. -Fix truncate of existing files opened with O_CREAT but not O_TRUNC set. - -Version 0.89 ------------- -Fix oops on write to dead tcp session. Remove error log write for case when file open -O_CREAT but not O_EXCL - -Version 0.88 ------------- -Fix non-POSIX behavior on rename of open file and delete of open file by taking -advantage of trans2 SetFileInfo rename facility if available on target server. -Retry on ENOSPC and EAGAIN socket errors. - -Version 0.87 ------------- -Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix -allocation size miscalculation. After oplock token lost do not read through -cache. - -Version 0.86 ------------- -Fix oops on empty file readahead. Fix for file size handling for locally cached files. - -Version 0.85 ------------- -Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files -during auto reconnection to server after server recovered from failure. - -Version 0.84 ------------- -Finish support for Linux 2.5 open/create changes, which removes the -redundant NTCreate/QPathInfo/close that was sent during file create. -Enable oplock by default. Enable packet signing by default (needed to -access many recent Windows servers) - -Version 0.83 ------------- -Fix oops when mounting to long server names caused by inverted parms to kmalloc. -Fix MultiuserMount (/proc/fs/cifs configuration setting) so that when enabled -we will choose a cifs user session (smb uid) that better matches the local -uid if a) the mount uid does not match the current uid and b) we have another -session to the same server (ip address) for a different mount which -matches the current local uid. - -Version 0.82 ------------- -Add support for mknod of block or character devices. Fix oplock -code (distributed caching) to properly send response to oplock -break from server. - -Version 0.81 ------------- -Finish up CIFS packet digital signing for the default -NTLM security case. This should help Windows 2003 -network interoperability since it is common for -packet signing to be required now. Fix statfs (stat -f) -which recently started returning errors due to -invalid value (-1 instead of 0) being set in the -struct kstatfs f_ffiles field. - -Version 0.80 ------------ -Fix oops on stopping oplock thread when removing cifs when -built as module. - -Version 0.79 ------------- -Fix mount options for ro (readonly), uid, gid and file and directory mode. - -Version 0.78 ------------- -Fix errors displayed on failed mounts to be more understandable. -Fixed various incorrect or misleading smb to posix error code mappings. - -Version 0.77 ------------- -Fix display of NTFS DFS junctions to display as symlinks. -They are the network equivalent. Fix oops in -cifs_partialpagewrite caused by missing spinlock protection -of openfile linked list. Allow writebehind caching errors to -be returned to the application at file close. - -Version 0.76 ------------- -Clean up options displayed in /proc/mounts by show_options to -be more consistent with other filesystems. - -Version 0.75 ------------- -Fix delete of readonly file to Windows servers. Reflect -presence or absence of read only dos attribute in mode -bits for servers that do not support CIFS Unix extensions. -Fix shortened results on readdir of large directories to -servers supporting CIFS Unix extensions (caused by -incorrect resume key). - -Version 0.74 ------------- -Fix truncate bug (set file size) that could cause hangs e.g. running fsx - -Version 0.73 ------------- -unload nls if mount fails. - -Version 0.72 ------------- -Add resume key support to search (readdir) code to workaround -Windows bug. Add /proc/fs/cifs/LookupCacheEnable which -allows disabling caching of attribute information for -lookups. - -Version 0.71 ------------- -Add more oplock handling (distributed caching code). Remove -dead code. Remove excessive stack space utilization from -symlink routines. - -Version 0.70 ------------- -Fix oops in get dfs referral (triggered when null path sent in to -mount). Add support for overriding rsize at mount time. - -Version 0.69 ------------- -Fix buffer overrun in readdir which caused intermittent kernel oopses. -Fix writepage code to release kmap on write data. Allow "-ip=" new -mount option to be passed in on parameter distinct from the first part -(server name portion of) the UNC name. Allow override of the -tcp port of the target server via new mount option "-port=" - -Version 0.68 ------------- -Fix search handle leak on rewind. Fix setuid and gid so that they are -reflected in the local inode immediately. Cleanup of whitespace -to make 2.4 and 2.5 versions more consistent. - - -Version 0.67 ------------- -Fix signal sending so that captive thread (cifsd) exits on umount -(which was causing the warning in kmem_cache_free of the request buffers -at rmmod time). This had broken as a sideeffect of the recent global -kernel change to daemonize. Fix memory leak in readdir code which -showed up in "ls -R" (and applications that did search rewinding). - -Version 0.66 ------------- -Reconnect tids and fids after session reconnection (still do not -reconnect byte range locks though). Fix problem caching -lookup information for directory inodes, improving performance, -especially in deep directory trees. Fix various build warnings. - -Version 0.65 ------------- -Finish fixes to commit write for caching/readahead consistency. fsx -now works to Samba servers. Fix oops caused when readahead -was interrupted by a signal. - -Version 0.64 ------------- -Fix data corruption (in partial page after truncate) that caused fsx to -fail to Windows servers. Cleaned up some extraneous error logging in -common error paths. Add generic sendfile support. - -Version 0.63 ------------- -Fix memory leak in AllocMidQEntry. -Finish reconnection logic, so connection with server can be dropped -(or server rebooted) and the cifs client will reconnect. - -Version 0.62 ------------- -Fix temporary socket leak when bad userid or password specified -(or other SMBSessSetup failure). Increase maximum buffer size to slightly -over 16K to allow negotiation of up to Samba and Windows server default read -sizes. Add support for readpages - -Version 0.61 ------------- -Fix oops when username not passed in on mount. Extensive fixes and improvements -to error logging (strip redundant newlines, change debug macros to ensure newline -passed in and to be more consistent). Fix writepage wrong file handle problem, -a readonly file handle could be incorrectly used to attempt to write out -file updates through the page cache to multiply open files. This could cause -the iozone benchmark to fail on the fwrite test. Fix bug mounting two different -shares to the same Windows server when using different usernames -(doing this to Samba servers worked but Windows was rejecting it) - now it is -possible to use different userids when connecting to the same server from a -Linux client. Fix oops when treeDisconnect called during unmount on -previously freed socket. - -Version 0.60 ------------- -Fix oops in readpages caused by not setting address space operations in inode in -rare code path. - -Version 0.59 ------------- -Includes support for deleting of open files and renaming over existing files (per POSIX -requirement). Add readlink support for Windows junction points (directory symlinks). - -Version 0.58 ------------- -Changed read and write to go through pagecache. Added additional address space operations. -Memory mapped operations now working. - -Version 0.57 ------------- -Added writepage code for additional memory mapping support. Fixed leak in xids causing -the simultaneous operations counter (/proc/fs/cifs/SimultaneousOps) to increase on -every stat call. Additional formatting cleanup. - -Version 0.56 ------------- -Fix bigendian bug in order of time conversion. Merge 2.5 to 2.4 version. Formatting cleanup. - -Version 0.55 ------------- -Fixes from Zwane Mwaikambo for adding missing return code checking in a few places. -Also included a modified version of his fix to protect global list manipulation of -the smb session and tree connection and mid related global variables. - -Version 0.54 ------------- -Fix problem with captive thread hanging around at unmount time. Adjust to 2.5.42-pre -changes to superblock layout. Remove wasteful allocation of smb buffers (now the send -buffer is reused for responses). Add more oplock handling. Additional minor cleanup. - -Version 0.53 ------------- -More stylistic updates to better match kernel style. Add additional statistics -for filesystem which can be viewed via /proc/fs/cifs. Add more pieces of NTLMv2 -and CIFS Packet Signing enablement. - -Version 0.52 ------------- -Replace call to sleep_on with safer wait_on_event. -Make stylistic changes to better match kernel style recommendations. -Remove most typedef usage (except for the PDUs themselves). - -Version 0.51 ------------- -Update mount so the -unc mount option is no longer required (the ip address can be specified -in a UNC style device name. Implementation of readpage/writepage started. - -Version 0.50 ------------- -Fix intermittent problem with incorrect smb header checking on badly -fragmented tcp responses - -Version 0.49 ------------- -Fixes to setting of allocation size and file size. - -Version 0.48 ------------- -Various 2.5.38 fixes. Now works on 2.5.38 - -Version 0.47 ------------- -Prepare for 2.5 kernel merge. Remove ifdefs. - -Version 0.46 ------------- -Socket buffer management fixes. Fix dual free. - -Version 0.45 ------------- -Various big endian fixes for hardlinks and symlinks and also for dfs. - -Version 0.44 ------------- -Various big endian fixes for servers with Unix extensions such as Samba - -Version 0.43 ------------- -Various FindNext fixes for incorrect filenames on large directory searches on big endian -clients. basic posix file i/o tests now work on big endian machines, not just le - -Version 0.42 ------------- -SessionSetup and NegotiateProtocol now work from Big Endian machines. -Various Big Endian fixes found during testing on the Linux on 390. Various fixes for compatibility with older -versions of 2.4 kernel (now builds and works again on kernels at least as early as 2.4.7). - -Version 0.41 ------------- -Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked -files now return the correct number of links on fstat as they are repeatedly linked and unlinked. - -Version 0.40 ------------- -Implemented "Raw" (i.e. not encapsulated in SPNEGO) NTLMSSP (i.e. the Security Provider Interface used to negotiate -session advanced session authentication). Raw NTLMSSP is preferred by Windows 2000 Professional and Windows XP. -Began implementing support for SPNEGO encapsulation of NTLMSSP based session authentication blobs -(which is the mechanism preferred by Windows 2000 server in the absence of Kerberos). - -Version 0.38 ------------- -Introduced optional mount helper utility mount.cifs and made coreq changes to cifs vfs to enable -it. Fixed a few bugs in the DFS code (e.g. bcc two bytes too short and incorrect uid in PDU). - -Version 0.37 ------------- -Rewrote much of connection and mount/unmount logic to handle bugs with -multiple uses to same share, multiple users to same server etc. - -Version 0.36 ------------- -Fixed major problem with dentry corruption (missing call to dput) - -Version 0.35 ------------- -Rewrite of readdir code to fix bug. Various fixes for bigendian machines. -Begin adding oplock support. Multiusermount and oplockEnabled flags added to /proc/fs/cifs -although corresponding function not fully implemented in the vfs yet - -Version 0.34 ------------- -Fixed dentry caching bug, misc. cleanup - -Version 0.33 ------------- -Fixed 2.5 support to handle build and configure changes as well as misc. 2.5 changes. Now can build -on current 2.5 beta version (2.5.24) of the Linux kernel as well as on 2.4 Linux kernels. -Support for STATUS codes (newer 32 bit NT error codes) added. DFS support begun to be added. - -Version 0.32 ------------- -Unix extensions (symlink, readlink, hardlink, chmod and some chgrp and chown) implemented -and tested against Samba 2.2.5 - - -Version 0.31 ------------- -1) Fixed lockrange to be correct (it was one byte too short) - -2) Fixed GETLK (i.e. the fcntl call to test a range of bytes in a file to see if locked) to correctly -show range as locked when there is a conflict with an existing lock. - -3) default file perms are now 2767 (indicating support for mandatory locks) instead of 777 for directories -in most cases. Eventually will offer optional ability to query server for the correct perms. - -3) Fixed eventual trap when mounting twice to different shares on the same server when the first succeeded -but the second one was invalid and failed (the second one was incorrectly disconnecting the tcp and smb -session) - -4) Fixed error logging of valid mount options - -5) Removed logging of password field. - -6) Moved negotiate, treeDisconnect and uloggoffX (only tConx and SessSetup remain in connect.c) to cifssmb.c -and cleaned them up and made them more consistent with other cifs functions. - -7) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways -(with or without Unix extensions) but FindNext and QueryPathInfo with the Unix extensions are not completed, -nor is the symlink support using the Unix extensions - -8) Started adding the readlink and follow_link code - -Version 0.3 ------------ -Initial drop - diff --git a/ANDROID_3.4.5/fs/cifs/Kconfig b/ANDROID_3.4.5/fs/cifs/Kconfig deleted file mode 100644 index 2b243af7..00000000 --- a/ANDROID_3.4.5/fs/cifs/Kconfig +++ /dev/null @@ -1,160 +0,0 @@ -config CIFS - tristate "CIFS support (advanced network filesystem, SMBFS successor)" - depends on INET - select NLS - select CRYPTO - select CRYPTO_MD4 - select CRYPTO_MD5 - select CRYPTO_HMAC - select CRYPTO_ARC4 - select CRYPTO_ECB - select CRYPTO_DES - help - This is the client VFS module for the Common Internet File System - (CIFS) protocol which is the successor to the Server Message Block - (SMB) protocol, the native file sharing mechanism for most early - PC operating systems. The CIFS protocol is fully supported by - file servers such as Windows 2000 (including Windows 2003, NT 4 - and Windows XP) as well by Samba (which provides excellent CIFS - server support for Linux and many other operating systems). Limited - support for OS/2 and Windows ME and similar servers is provided as - well. - - The cifs module provides an advanced network file system - client for mounting to CIFS compliant servers. It includes - support for DFS (hierarchical name space), secure per-user - session establishment via Kerberos or NTLM or NTLMv2, - safe distributed caching (oplock), optional packet - signing, Unicode and other internationalization improvements. - If you need to mount to Samba or Windows from this machine, say Y. - -config CIFS_STATS - bool "CIFS statistics" - depends on CIFS - help - Enabling this option will cause statistics for each server share - mounted by the cifs client to be displayed in /proc/fs/cifs/Stats - -config CIFS_STATS2 - bool "Extended statistics" - depends on CIFS_STATS - help - Enabling this option will allow more detailed statistics on SMB - request timing to be displayed in /proc/fs/cifs/DebugData and also - allow optional logging of slow responses to dmesg (depending on the - value of /proc/fs/cifs/cifsFYI, see fs/cifs/README for more details). - These additional statistics may have a minor effect on performance - and memory utilization. - - Unless you are a developer or are doing network performance analysis - or tuning, say N. - -config CIFS_WEAK_PW_HASH - bool "Support legacy servers which use weaker LANMAN security" - depends on CIFS - help - Modern CIFS servers including Samba and most Windows versions - (since 1997) support stronger NTLM (and even NTLMv2 and Kerberos) - security mechanisms. These hash the password more securely - than the mechanisms used in the older LANMAN version of the - SMB protocol but LANMAN based authentication is needed to - establish sessions with some old SMB servers. - - Enabling this option allows the cifs module to mount to older - LANMAN based servers such as OS/2 and Windows 95, but such - mounts may be less secure than mounts using NTLM or more recent - security mechanisms if you are on a public network. Unless you - have a need to access old SMB servers (and are on a private - network) you probably want to say N. Even if this support - is enabled in the kernel build, LANMAN authentication will not be - used automatically. At runtime LANMAN mounts are disabled but - can be set to required (or optional) either in - /proc/fs/cifs (see fs/cifs/README for more detail) or via an - option on the mount command. This support is disabled by - default in order to reduce the possibility of a downgrade - attack. - - If unsure, say N. - -config CIFS_UPCALL - bool "Kerberos/SPNEGO advanced session setup" - depends on CIFS && KEYS - select DNS_RESOLVER - help - Enables an upcall mechanism for CIFS which accesses userspace helper - utilities to provide SPNEGO packaged (RFC 4178) Kerberos tickets - which are needed to mount to certain secure servers (for which more - secure Kerberos authentication is required). If unsure, say N. - -config CIFS_XATTR - bool "CIFS extended attributes" - depends on CIFS - help - Extended attributes are name:value pairs associated with inodes by - the kernel or by users (see the attr(5) manual page, or visit - <http://acl.bestbits.at/> for details). CIFS maps the name of - extended attributes beginning with the user namespace prefix - to SMB/CIFS EAs. EAs are stored on Windows servers without the - user namespace prefix, but their names are seen by Linux cifs clients - prefaced by the user namespace prefix. The system namespace - (used by some filesystems to store ACLs) is not supported at - this time. - - If unsure, say N. - -config CIFS_POSIX - bool "CIFS POSIX Extensions" - depends on CIFS_XATTR - help - Enabling this option will cause the cifs client to attempt to - negotiate a newer dialect with servers, such as Samba 3.0.5 - or later, that optionally can handle more POSIX like (rather - than Windows like) file behavior. It also enables - support for POSIX ACLs (getfacl and setfacl) to servers - (such as Samba 3.10 and later) which can negotiate - CIFS POSIX ACL support. If unsure, say N. - -config CIFS_DEBUG2 - bool "Enable additional CIFS debugging routines" - depends on CIFS - help - Enabling this option adds a few more debugging routines - to the cifs code which slightly increases the size of - the cifs module and can cause additional logging of debug - messages in some error paths, slowing performance. This - option can be turned off unless you are debugging - cifs problems. If unsure, say N. - -config CIFS_DFS_UPCALL - bool "DFS feature support" - depends on CIFS && KEYS - select DNS_RESOLVER - help - Distributed File System (DFS) support is used to access shares - transparently in an enterprise name space, even if the share - moves to a different server. This feature also enables - an upcall mechanism for CIFS which contacts userspace helper - utilities to provide server name resolution (host names to - IP addresses) which is needed for implicit mounts of DFS junction - points. If unsure, say N. - -config CIFS_FSCACHE - bool "Provide CIFS client caching support" - depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y - help - Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data - to be cached locally on disk through the general filesystem cache - manager. If unsure, say N. - -config CIFS_ACL - bool "Provide CIFS ACL support" - depends on CIFS_XATTR && KEYS - help - Allows to fetch CIFS/NTFS ACL from the server. The DACL blob - is handed over to the application/caller. - -config CIFS_NFSD_EXPORT - bool "Allow nfsd to export CIFS file system (EXPERIMENTAL)" - depends on CIFS && EXPERIMENTAL && BROKEN - help - Allows NFS server to export a CIFS mounted share (nfsd over cifs) diff --git a/ANDROID_3.4.5/fs/cifs/Makefile b/ANDROID_3.4.5/fs/cifs/Makefile deleted file mode 100644 index 005d524c..00000000 --- a/ANDROID_3.4.5/fs/cifs/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# -# Makefile for Linux CIFS VFS client -# -obj-$(CONFIG_CIFS) += cifs.o - -cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ - link.o misc.o netmisc.o smbencrypt.o transport.o asn1.o \ - cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ - readdir.o ioctl.o sess.o export.o - -cifs-$(CONFIG_CIFS_ACL) += cifsacl.o - -cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o - -cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o - -cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o diff --git a/ANDROID_3.4.5/fs/cifs/README b/ANDROID_3.4.5/fs/cifs/README deleted file mode 100644 index b7d782ba..00000000 --- a/ANDROID_3.4.5/fs/cifs/README +++ /dev/null @@ -1,758 +0,0 @@ -The CIFS VFS support for Linux supports many advanced network filesystem -features such as hierarchical dfs like namespace, hardlinks, locking and more. -It was designed to comply with the SNIA CIFS Technical Reference (which -supersedes the 1992 X/Open SMB Standard) as well as to perform best practice -practical interoperability with Windows 2000, Windows XP, Samba and equivalent -servers. This code was developed in participation with the Protocol Freedom -Information Foundation. - -Please see - http://protocolfreedom.org/ and - http://samba.org/samba/PFIF/ -for more details. - - -For questions or bug reports please contact: - sfrench@samba.org (sfrench@us.ibm.com) - -Build instructions: -================== -For Linux 2.4: -1) Get the kernel source (e.g.from http://www.kernel.org) -and download the cifs vfs source (see the project page -at http://us1.samba.org/samba/Linux_CIFS_client.html) -and change directory into the top of the kernel directory -then patch the kernel (e.g. "patch -p1 < cifs_24.patch") -to add the cifs vfs to your kernel configure options if -it has not already been added (e.g. current SuSE and UL -users do not need to apply the cifs_24.patch since the cifs vfs is -already in the kernel configure menu) and then -mkdir linux/fs/cifs and then copy the current cifs vfs files from -the cifs download to your kernel build directory e.g. - - cp <cifs_download_dir>/fs/cifs/* to <kernel_download_dir>/fs/cifs - -2) make menuconfig (or make xconfig) -3) select cifs from within the network filesystem choices -4) save and exit -5) make dep -6) make modules (or "make" if CIFS VFS not to be built as a module) - -For Linux 2.6: -1) Download the kernel (e.g. from http://www.kernel.org) -and change directory into the top of the kernel directory tree -(e.g. /usr/src/linux-2.5.73) -2) make menuconfig (or make xconfig) -3) select cifs from within the network filesystem choices -4) save and exit -5) make - - -Installation instructions: -========================= -If you have built the CIFS vfs as module (successfully) simply -type "make modules_install" (or if you prefer, manually copy the file to -the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.o). - -If you have built the CIFS vfs into the kernel itself, follow the instructions -for your distribution on how to install a new kernel (usually you -would simply type "make install"). - -If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on -the CIFS VFS web site) copy it to the same directory in which mount.smbfs and -similar files reside (usually /sbin). Although the helper software is not -required, mount.cifs is recommended. Eventually the Samba 3.0 utility program -"net" may also be helpful since it may someday provide easier mount syntax for -users who are used to Windows e.g. - net use <mount point> <UNC name or cifs URL> -Note that running the Winbind pam/nss module (logon service) on all of your -Linux clients is useful in mapping Uids and Gids consistently across the -domain to the proper network user. The mount.cifs mount helper can be -trivially built from Samba 3.0 or later source e.g. by executing: - - gcc samba/source/client/mount.cifs.c -o mount.cifs - -If cifs is built as a module, then the size and number of network buffers -and maximum number of simultaneous requests to one server can be configured. -Changing these from their defaults is not recommended. By executing modinfo - modinfo kernel/fs/cifs/cifs.ko -on kernel/fs/cifs/cifs.ko the list of configuration changes that can be made -at module initialization time (by running insmod cifs.ko) can be seen. - -Allowing User Mounts -==================== -To permit users to mount and unmount over directories they own is possible -with the cifs vfs. A way to enable such mounting is to mark the mount.cifs -utility as suid (e.g. "chmod +s /sbin/mount.cifs). To enable users to -umount shares they mount requires -1) mount.cifs version 1.4 or later -2) an entry for the share in /etc/fstab indicating that a user may -unmount it e.g. -//server/usersharename /mnt/username cifs user 0 0 - -Note that when the mount.cifs utility is run suid (allowing user mounts), -in order to reduce risks, the "nosuid" mount flag is passed in on mount to -disallow execution of an suid program mounted on the remote target. -When mount is executed as root, nosuid is not passed in by default, -and execution of suid programs on the remote target would be enabled -by default. This can be changed, as with nfs and other filesystems, -by simply specifying "nosuid" among the mount options. For user mounts -though to be able to pass the suid flag to mount requires rebuilding -mount.cifs with the following flag: - - gcc samba/source/client/mount.cifs.c -DCIFS_ALLOW_USR_SUID -o mount.cifs - -There is a corresponding manual page for cifs mounting in the Samba 3.0 and -later source tree in docs/manpages/mount.cifs.8 - -Allowing User Unmounts -====================== -To permit users to ummount directories that they have user mounted (see above), -the utility umount.cifs may be used. It may be invoked directly, or if -umount.cifs is placed in /sbin, umount can invoke the cifs umount helper -(at least for most versions of the umount utility) for umount of cifs -mounts, unless umount is invoked with -i (which will avoid invoking a umount -helper). As with mount.cifs, to enable user unmounts umount.cifs must be marked -as suid (e.g. "chmod +s /sbin/umount.cifs") or equivalent (some distributions -allow adding entries to a file to the /etc/permissions file to achieve the -equivalent suid effect). For this utility to succeed the target path -must be a cifs mount, and the uid of the current user must match the uid -of the user who mounted the resource. - -Also note that the customary way of allowing user mounts and unmounts is -(instead of using mount.cifs and unmount.cifs as suid) to add a line -to the file /etc/fstab for each //server/share you wish to mount, but -this can become unwieldy when potential mount targets include many -or unpredictable UNC names. - -Samba Considerations -==================== -To get the maximum benefit from the CIFS VFS, we recommend using a server that -supports the SNIA CIFS Unix Extensions standard (e.g. Samba 2.2.5 or later or -Samba 3.0) but the CIFS vfs works fine with a wide variety of CIFS servers. -Note that uid, gid and file permissions will display default values if you do -not have a server that supports the Unix extensions for CIFS (such as Samba -2.2.5 or later). To enable the Unix CIFS Extensions in the Samba server, add -the line: - - unix extensions = yes - -to your smb.conf file on the server. Note that the following smb.conf settings -are also useful (on the Samba server) when the majority of clients are Unix or -Linux: - - case sensitive = yes - delete readonly = yes - ea support = yes - -Note that server ea support is required for supporting xattrs from the Linux -cifs client, and that EA support is present in later versions of Samba (e.g. -3.0.6 and later (also EA support works in all versions of Windows, at least to -shares on NTFS filesystems). Extended Attribute (xattr) support is an optional -feature of most Linux filesystems which may require enabling via -make menuconfig. Client support for extended attributes (user xattr) can be -disabled on a per-mount basis by specifying "nouser_xattr" on mount. - -The CIFS client can get and set POSIX ACLs (getfacl, setfacl) to Samba servers -version 3.10 and later. Setting POSIX ACLs requires enabling both XATTR and -then POSIX support in the CIFS configuration options when building the cifs -module. POSIX ACL support can be disabled on a per mount basic by specifying -"noacl" on mount. - -Some administrators may want to change Samba's smb.conf "map archive" and -"create mask" parameters from the default. Unless the create mask is changed -newly created files can end up with an unnecessarily restrictive default mode, -which may not be what you want, although if the CIFS Unix extensions are -enabled on the server and client, subsequent setattr calls (e.g. chmod) can -fix the mode. Note that creating special devices (mknod) remotely -may require specifying a mkdev function to Samba if you are not using -Samba 3.0.6 or later. For more information on these see the manual pages -("man smb.conf") on the Samba server system. Note that the cifs vfs, -unlike the smbfs vfs, does not read the smb.conf on the client system -(the few optional settings are passed in on mount via -o parameters instead). -Note that Samba 2.2.7 or later includes a fix that allows the CIFS VFS to delete -open files (required for strict POSIX compliance). Windows Servers already -supported this feature. Samba server does not allow symlinks that refer to files -outside of the share, so in Samba versions prior to 3.0.6, most symlinks to -files with absolute paths (ie beginning with slash) such as: - ln -s /mnt/foo bar -would be forbidden. Samba 3.0.6 server or later includes the ability to create -such symlinks safely by converting unsafe symlinks (ie symlinks to server -files that are outside of the share) to a samba specific format on the server -that is ignored by local server applications and non-cifs clients and that will -not be traversed by the Samba server). This is opaque to the Linux client -application using the cifs vfs. Absolute symlinks will work to Samba 3.0.5 or -later, but only for remote clients using the CIFS Unix extensions, and will -be invisbile to Windows clients and typically will not affect local -applications running on the same server as Samba. - -Use instructions: -================ -Once the CIFS VFS support is built into the kernel or installed as a module -(cifs.o), you can use mount syntax like the following to access Samba or Windows -servers: - - mount -t cifs //9.53.216.11/e$ /mnt -o user=myname,pass=mypassword - -Before -o the option -v may be specified to make the mount.cifs -mount helper display the mount steps more verbosely. -After -o the following commonly used cifs vfs specific options -are supported: - - user=<username> - pass=<password> - domain=<domain name> - -Other cifs mount options are described below. Use of TCP names (in addition to -ip addresses) is available if the mount helper (mount.cifs) is installed. If -you do not trust the server to which are mounted, or if you do not have -cifs signing enabled (and the physical network is insecure), consider use -of the standard mount options "noexec" and "nosuid" to reduce the risk of -running an altered binary on your local system (downloaded from a hostile server -or altered by a hostile router). - -Although mounting using format corresponding to the CIFS URL specification is -not possible in mount.cifs yet, it is possible to use an alternate format -for the server and sharename (which is somewhat similar to NFS style mount -syntax) instead of the more widely used UNC format (i.e. \\server\share): - mount -t cifs tcp_name_of_server:share_name /mnt -o user=myname,pass=mypasswd - -When using the mount helper mount.cifs, passwords may be specified via alternate -mechanisms, instead of specifying it after -o using the normal "pass=" syntax -on the command line: -1) By including it in a credential file. Specify credentials=filename as one -of the mount options. Credential files contain two lines - username=someuser - password=your_password -2) By specifying the password in the PASSWD environment variable (similarly -the user name can be taken from the USER environment variable). -3) By specifying the password in a file by name via PASSWD_FILE -4) By specifying the password in a file by file descriptor via PASSWD_FD - -If no password is provided, mount.cifs will prompt for password entry - -Restrictions -============ -Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC -1001/1002 support for "Netbios-Over-TCP/IP." This is not likely to be a -problem as most servers support this. - -Valid filenames differ between Windows and Linux. Windows typically restricts -filenames which contain certain reserved characters (e.g.the character : -which is used to delimit the beginning of a stream name by Windows), while -Linux allows a slightly wider set of valid characters in filenames. Windows -servers can remap such characters when an explicit mapping is specified in -the Server's registry. Samba starting with version 3.10 will allow such -filenames (ie those which contain valid Linux characters, which normally -would be forbidden for Windows/CIFS semantics) as long as the server is -configured for Unix Extensions (and the client has not disabled -/proc/fs/cifs/LinuxExtensionsEnabled). - - -CIFS VFS Mount Options -====================== -A partial list of the supported mount options follows: - user The user name to use when trying to establish - the CIFS session. - password The user password. If the mount helper is - installed, the user will be prompted for password - if not supplied. - ip The ip address of the target server - unc The target server Universal Network Name (export) to - mount. - domain Set the SMB/CIFS workgroup name prepended to the - username during CIFS session establishment - forceuid Set the default uid for inodes to the uid - passed in on mount. For mounts to servers - which do support the CIFS Unix extensions, such as a - properly configured Samba server, the server provides - the uid, gid and mode so this parameter should not be - specified unless the server and clients uid and gid - numbering differ. If the server and client are in the - same domain (e.g. running winbind or nss_ldap) and - the server supports the Unix Extensions then the uid - and gid can be retrieved from the server (and uid - and gid would not have to be specifed on the mount. - For servers which do not support the CIFS Unix - extensions, the default uid (and gid) returned on lookup - of existing files will be the uid (gid) of the person - who executed the mount (root, except when mount.cifs - is configured setuid for user mounts) unless the "uid=" - (gid) mount option is specified. Also note that permission - checks (authorization checks) on accesses to a file occur - at the server, but there are cases in which an administrator - may want to restrict at the client as well. For those - servers which do not report a uid/gid owner - (such as Windows), permissions can also be checked at the - client, and a crude form of client side permission checking - can be enabled by specifying file_mode and dir_mode on - the client. (default) - forcegid (similar to above but for the groupid instead of uid) (default) - noforceuid Fill in file owner information (uid) by requesting it from - the server if possible. With this option, the value given in - the uid= option (on mount) will only be used if the server - can not support returning uids on inodes. - noforcegid (similar to above but for the group owner, gid, instead of uid) - uid Set the default uid for inodes, and indicate to the - cifs kernel driver which local user mounted. If the server - supports the unix extensions the default uid is - not used to fill in the owner fields of inodes (files) - unless the "forceuid" parameter is specified. - gid Set the default gid for inodes (similar to above). - file_mode If CIFS Unix extensions are not supported by the server - this overrides the default mode for file inodes. - fsc Enable local disk caching using FS-Cache (off by default). This - option could be useful to improve performance on a slow link, - heavily loaded server and/or network where reading from the - disk is faster than reading from the server (over the network). - This could also impact scalability positively as the - number of calls to the server are reduced. However, local - caching is not suitable for all workloads for e.g. read-once - type workloads. So, you need to consider carefully your - workload/scenario before using this option. Currently, local - disk caching is functional for CIFS files opened as read-only. - dir_mode If CIFS Unix extensions are not supported by the server - this overrides the default mode for directory inodes. - port attempt to contact the server on this tcp port, before - trying the usual ports (port 445, then 139). - iocharset Codepage used to convert local path names to and from - Unicode. Unicode is used by default for network path - names if the server supports it. If iocharset is - not specified then the nls_default specified - during the local client kernel build will be used. - If server does not support Unicode, this parameter is - unused. - rsize default read size (usually 16K). The client currently - can not use rsize larger than CIFSMaxBufSize. CIFSMaxBufSize - defaults to 16K and may be changed (from 8K to the maximum - kmalloc size allowed by your kernel) at module install time - for cifs.ko. Setting CIFSMaxBufSize to a very large value - will cause cifs to use more memory and may reduce performance - in some cases. To use rsize greater than 127K (the original - cifs protocol maximum) also requires that the server support - a new Unix Capability flag (for very large read) which some - newer servers (e.g. Samba 3.0.26 or later) do. rsize can be - set from a minimum of 2048 to a maximum of 130048 (127K or - CIFSMaxBufSize, whichever is smaller) - wsize default write size (default 57344) - maximum wsize currently allowed by CIFS is 57344 (fourteen - 4096 byte pages) - actimeo=n attribute cache timeout in seconds (default 1 second). - After this timeout, the cifs client requests fresh attribute - information from the server. This option allows to tune the - attribute cache timeout to suit the workload needs. Shorter - timeouts mean better the cache coherency, but increased number - of calls to the server. Longer timeouts mean reduced number - of calls to the server at the expense of less stricter cache - coherency checks (i.e. incorrect attribute cache for a short - period of time). - rw mount the network share read-write (note that the - server may still consider the share read-only) - ro mount network share read-only - version used to distinguish different versions of the - mount helper utility (not typically needed) - sep if first mount option (after the -o), overrides - the comma as the separator between the mount - parms. e.g. - -o user=myname,password=mypassword,domain=mydom - could be passed instead with period as the separator by - -o sep=.user=myname.password=mypassword.domain=mydom - this might be useful when comma is contained within username - or password or domain. This option is less important - when the cifs mount helper cifs.mount (version 1.1 or later) - is used. - nosuid Do not allow remote executables with the suid bit - program to be executed. This is only meaningful for mounts - to servers such as Samba which support the CIFS Unix Extensions. - If you do not trust the servers in your network (your mount - targets) it is recommended that you specify this option for - greater security. - exec Permit execution of binaries on the mount. - noexec Do not permit execution of binaries on the mount. - dev Recognize block devices on the remote mount. - nodev Do not recognize devices on the remote mount. - suid Allow remote files on this mountpoint with suid enabled to - be executed (default for mounts when executed as root, - nosuid is default for user mounts). - credentials Although ignored by the cifs kernel component, it is used by - the mount helper, mount.cifs. When mount.cifs is installed it - opens and reads the credential file specified in order - to obtain the userid and password arguments which are passed to - the cifs vfs. - guest Although ignored by the kernel component, the mount.cifs - mount helper will not prompt the user for a password - if guest is specified on the mount options. If no - password is specified a null password will be used. - perm Client does permission checks (vfs_permission check of uid - and gid of the file against the mode and desired operation), - Note that this is in addition to the normal ACL check on the - target machine done by the server software. - Client permission checking is enabled by default. - noperm Client does not do permission checks. This can expose - files on this mount to access by other users on the local - client system. It is typically only needed when the server - supports the CIFS Unix Extensions but the UIDs/GIDs on the - client and server system do not match closely enough to allow - access by the user doing the mount, but it may be useful with - non CIFS Unix Extension mounts for cases in which the default - mode is specified on the mount but is not to be enforced on the - client (e.g. perhaps when MultiUserMount is enabled) - Note that this does not affect the normal ACL check on the - target machine done by the server software (of the server - ACL against the user name provided at mount time). - serverino Use server's inode numbers instead of generating automatically - incrementing inode numbers on the client. Although this will - make it easier to spot hardlinked files (as they will have - the same inode numbers) and inode numbers may be persistent, - note that the server does not guarantee that the inode numbers - are unique if multiple server side mounts are exported under a - single share (since inode numbers on the servers might not - be unique if multiple filesystems are mounted under the same - shared higher level directory). Note that some older - (e.g. pre-Windows 2000) do not support returning UniqueIDs - or the CIFS Unix Extensions equivalent and for those - this mount option will have no effect. Exporting cifs mounts - under nfsd requires this mount option on the cifs mount. - This is now the default if server supports the - required network operation. - noserverino Client generates inode numbers (rather than using the actual one - from the server). These inode numbers will vary after - unmount or reboot which can confuse some applications, - but not all server filesystems support unique inode - numbers. - setuids If the CIFS Unix extensions are negotiated with the server - the client will attempt to set the effective uid and gid of - the local process on newly created files, directories, and - devices (create, mkdir, mknod). If the CIFS Unix Extensions - are not negotiated, for newly created files and directories - instead of using the default uid and gid specified on - the mount, cache the new file's uid and gid locally which means - that the uid for the file can change when the inode is - reloaded (or the user remounts the share). - nosetuids The client will not attempt to set the uid and gid on - on newly created files, directories, and devices (create, - mkdir, mknod) which will result in the server setting the - uid and gid to the default (usually the server uid of the - user who mounted the share). Letting the server (rather than - the client) set the uid and gid is the default. If the CIFS - Unix Extensions are not negotiated then the uid and gid for - new files will appear to be the uid (gid) of the mounter or the - uid (gid) parameter specified on the mount. - netbiosname When mounting to servers via port 139, specifies the RFC1001 - source name to use to represent the client netbios machine - name when doing the RFC1001 netbios session initialize. - direct Do not do inode data caching on files opened on this mount. - This precludes mmapping files on this mount. In some cases - with fast networks and little or no caching benefits on the - client (e.g. when the application is doing large sequential - reads bigger than page size without rereading the same data) - this can provide better performance than the default - behavior which caches reads (readahead) and writes - (writebehind) through the local Linux client pagecache - if oplock (caching token) is granted and held. Note that - direct allows write operations larger than page size - to be sent to the server. - strictcache Use for switching on strict cache mode. In this mode the - client read from the cache all the time it has Oplock Level II, - otherwise - read from the server. All written data are stored - in the cache, but if the client doesn't have Exclusive Oplock, - it writes the data to the server. - rwpidforward Forward pid of a process who opened a file to any read or write - operation on that file. This prevent applications like WINE - from failing on read and write if we use mandatory brlock style. - acl Allow setfacl and getfacl to manage posix ACLs if server - supports them. (default) - noacl Do not allow setfacl and getfacl calls on this mount - user_xattr Allow getting and setting user xattrs (those attributes whose - name begins with "user." or "os2.") as OS/2 EAs (extended - attributes) to the server. This allows support of the - setfattr and getfattr utilities. (default) - nouser_xattr Do not allow getfattr/setfattr to get/set/list xattrs - mapchars Translate six of the seven reserved characters (not backslash) - *?<>|: - to the remap range (above 0xF000), which also - allows the CIFS client to recognize files created with - such characters by Windows's POSIX emulation. This can - also be useful when mounting to most versions of Samba - (which also forbids creating and opening files - whose names contain any of these seven characters). - This has no effect if the server does not support - Unicode on the wire. - nomapchars Do not translate any of these seven characters (default). - nocase Request case insensitive path name matching (case - sensitive is the default if the server suports it). - (mount option "ignorecase" is identical to "nocase") - posixpaths If CIFS Unix extensions are supported, attempt to - negotiate posix path name support which allows certain - characters forbidden in typical CIFS filenames, without - requiring remapping. (default) - noposixpaths If CIFS Unix extensions are supported, do not request - posix path name support (this may cause servers to - reject creatingfile with certain reserved characters). - nounix Disable the CIFS Unix Extensions for this mount (tree - connection). This is rarely needed, but it may be useful - in order to turn off multiple settings all at once (ie - posix acls, posix locks, posix paths, symlink support - and retrieving uids/gids/mode from the server) or to - work around a bug in server which implement the Unix - Extensions. - nobrl Do not send byte range lock requests to the server. - This is necessary for certain applications that break - with cifs style mandatory byte range locks (and most - cifs servers do not yet support requesting advisory - byte range locks). - forcemandatorylock Even if the server supports posix (advisory) byte range - locking, send only mandatory lock requests. For some - (presumably rare) applications, originally coded for - DOS/Windows, which require Windows style mandatory byte range - locking, they may be able to take advantage of this option, - forcing the cifs client to only send mandatory locks - even if the cifs server would support posix advisory locks. - "forcemand" is accepted as a shorter form of this mount - option. - nostrictsync If this mount option is set, when an application does an - fsync call then the cifs client does not send an SMB Flush - to the server (to force the server to write all dirty data - for this file immediately to disk), although cifs still sends - all dirty (cached) file data to the server and waits for the - server to respond to the write. Since SMB Flush can be - very slow, and some servers may be reliable enough (to risk - delaying slightly flushing the data to disk on the server), - turning on this option may be useful to improve performance for - applications that fsync too much, at a small risk of server - crash. If this mount option is not set, by default cifs will - send an SMB flush request (and wait for a response) on every - fsync call. - nodfs Disable DFS (global name space support) even if the - server claims to support it. This can help work around - a problem with parsing of DFS paths with Samba server - versions 3.0.24 and 3.0.25. - remount remount the share (often used to change from ro to rw mounts - or vice versa) - cifsacl Report mode bits (e.g. on stat) based on the Windows ACL for - the file. (EXPERIMENTAL) - servern Specify the server 's netbios name (RFC1001 name) to use - when attempting to setup a session to the server. - This is needed for mounting to some older servers (such - as OS/2 or Windows 98 and Windows ME) since they do not - support a default server name. A server name can be up - to 15 characters long and is usually uppercased. - sfu When the CIFS Unix Extensions are not negotiated, attempt to - create device files and fifos in a format compatible with - Services for Unix (SFU). In addition retrieve bits 10-12 - of the mode via the SETFILEBITS extended attribute (as - SFU does). In the future the bottom 9 bits of the - mode also will be emulated using queries of the security - descriptor (ACL). - mfsymlinks Enable support for Minshall+French symlinks - (see http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks) - This option is ignored when specified together with the - 'sfu' option. Minshall+French symlinks are used even if - the server supports the CIFS Unix Extensions. - sign Must use packet signing (helps avoid unwanted data modification - by intermediate systems in the route). Note that signing - does not work with lanman or plaintext authentication. - seal Must seal (encrypt) all data on this mounted share before - sending on the network. Requires support for Unix Extensions. - Note that this differs from the sign mount option in that it - causes encryption of data sent over this mounted share but other - shares mounted to the same server are unaffected. - locallease This option is rarely needed. Fcntl F_SETLEASE is - used by some applications such as Samba and NFSv4 server to - check to see whether a file is cacheable. CIFS has no way - to explicitly request a lease, but can check whether a file - is cacheable (oplocked). Unfortunately, even if a file - is not oplocked, it could still be cacheable (ie cifs client - could grant fcntl leases if no other local processes are using - the file) for cases for example such as when the server does not - support oplocks and the user is sure that the only updates to - the file will be from this client. Specifying this mount option - will allow the cifs client to check for leases (only) locally - for files which are not oplocked instead of denying leases - in that case. (EXPERIMENTAL) - sec Security mode. Allowed values are: - none attempt to connection as a null user (no name) - krb5 Use Kerberos version 5 authentication - krb5i Use Kerberos authentication and packet signing - ntlm Use NTLM password hashing (default) - ntlmi Use NTLM password hashing with signing (if - /proc/fs/cifs/PacketSigningEnabled on or if - server requires signing also can be the default) - ntlmv2 Use NTLMv2 password hashing - ntlmv2i Use NTLMv2 password hashing with packet signing - lanman (if configured in kernel config) use older - lanman hash -hard Retry file operations if server is not responding -soft Limit retries to unresponsive servers (usually only - one retry) before returning an error. (default) - -The mount.cifs mount helper also accepts a few mount options before -o -including: - - -S take password from stdin (equivalent to setting the environment - variable "PASSWD_FD=0" - -V print mount.cifs version - -? display simple usage information - -With most 2.6 kernel versions of modutils, the version of the cifs kernel -module can be displayed via modinfo. - -Misc /proc/fs/cifs Flags and Debug Info -======================================= -Informational pseudo-files: -DebugData Displays information about active CIFS sessions and - shares, features enabled as well as the cifs.ko - version. -Stats Lists summary resource usage information as well as per - share statistics, if CONFIG_CIFS_STATS in enabled - in the kernel configuration. - -Configuration pseudo-files: -MultiuserMount If set to one, more than one CIFS session to - the same server ip address can be established - if more than one uid accesses the same mount - point and if the uids user/password mapping - information is available. (default is 0) -PacketSigningEnabled If set to one, cifs packet signing is enabled - and will be used if the server requires - it. If set to two, cifs packet signing is - required even if the server considers packet - signing optional. (default 1) -SecurityFlags Flags which control security negotiation and - also packet signing. Authentication (may/must) - flags (e.g. for NTLM and/or NTLMv2) may be combined with - the signing flags. Specifying two different password - hashing mechanisms (as "must use") on the other hand - does not make much sense. Default flags are - 0x07007 - (NTLM, NTLMv2 and packet signing allowed). The maximum - allowable flags if you want to allow mounts to servers - using weaker password hashes is 0x37037 (lanman, - plaintext, ntlm, ntlmv2, signing allowed). Some - SecurityFlags require the corresponding menuconfig - options to be enabled (lanman and plaintext require - CONFIG_CIFS_WEAK_PW_HASH for example). Enabling - plaintext authentication currently requires also - enabling lanman authentication in the security flags - because the cifs module only supports sending - laintext passwords using the older lanman dialect - form of the session setup SMB. (e.g. for authentication - using plain text passwords, set the SecurityFlags - to 0x30030): - - may use packet signing 0x00001 - must use packet signing 0x01001 - may use NTLM (most common password hash) 0x00002 - must use NTLM 0x02002 - may use NTLMv2 0x00004 - must use NTLMv2 0x04004 - may use Kerberos security 0x00008 - must use Kerberos 0x08008 - may use lanman (weak) password hash 0x00010 - must use lanman password hash 0x10010 - may use plaintext passwords 0x00020 - must use plaintext passwords 0x20020 - (reserved for future packet encryption) 0x00040 - -cifsFYI If set to non-zero value, additional debug information - will be logged to the system error log. This field - contains three flags controlling different classes of - debugging entries. The maximum value it can be set - to is 7 which enables all debugging points (default 0). - Some debugging statements are not compiled into the - cifs kernel unless CONFIG_CIFS_DEBUG2 is enabled in the - kernel configuration. cifsFYI may be set to one or - nore of the following flags (7 sets them all): - - log cifs informational messages 0x01 - log return codes from cifs entry points 0x02 - log slow responses (ie which take longer than 1 second) - CONFIG_CIFS_STATS2 must be enabled in .config 0x04 - - -traceSMB If set to one, debug information is logged to the - system error log with the start of smb requests - and responses (default 0) -LookupCacheEnable If set to one, inode information is kept cached - for one second improving performance of lookups - (default 1) -OplockEnabled If set to one, safe distributed caching enabled. - (default 1) -LinuxExtensionsEnabled If set to one then the client will attempt to - use the CIFS "UNIX" extensions which are optional - protocol enhancements that allow CIFS servers - to return accurate UID/GID information as well - as support symbolic links. If you use servers - such as Samba that support the CIFS Unix - extensions but do not want to use symbolic link - support and want to map the uid and gid fields - to values supplied at mount (rather than the - actual values, then set this to zero. (default 1) - -These experimental features and tracing can be enabled by changing flags in -/proc/fs/cifs (after the cifs module has been installed or built into the -kernel, e.g. insmod cifs). To enable a feature set it to 1 e.g. to enable -tracing to the kernel message log type: - - echo 7 > /proc/fs/cifs/cifsFYI - -cifsFYI functions as a bit mask. Setting it to 1 enables additional kernel -logging of various informational messages. 2 enables logging of non-zero -SMB return codes while 4 enables logging of requests that take longer -than one second to complete (except for byte range lock requests). -Setting it to 4 requires defining CONFIG_CIFS_STATS2 manually in the -source code (typically by setting it in the beginning of cifsglob.h), -and setting it to seven enables all three. Finally, tracing -the start of smb requests and responses can be enabled via: - - echo 1 > /proc/fs/cifs/traceSMB - -Per share (per client mount) statistics are available in /proc/fs/cifs/Stats -if the kernel was configured with cifs statistics enabled. The statistics -represent the number of successful (ie non-zero return code from the server) -SMB responses to some of the more common commands (open, delete, mkdir etc.). -Also recorded is the total bytes read and bytes written to the server for -that share. Note that due to client caching effects this can be less than the -number of bytes read and written by the application running on the client. -The statistics for the number of total SMBs and oplock breaks are different in -that they represent all for that share, not just those for which the server -returned success. - -Also note that "cat /proc/fs/cifs/DebugData" will display information about -the active sessions and the shares that are mounted. - -Enabling Kerberos (extended security) works but requires version 1.2 or later -of the helper program cifs.upcall to be present and to be configured in the -/etc/request-key.conf file. The cifs.upcall helper program is from the Samba -project(http://www.samba.org). NTLM and NTLMv2 and LANMAN support do not -require this helper. Note that NTLMv2 security (which does not require the -cifs.upcall helper program), instead of using Kerberos, is sufficient for -some use cases. - -DFS support allows transparent redirection to shares in an MS-DFS name space. -In addition, DFS support for target shares which are specified as UNC -names which begin with host names (rather than IP addresses) requires -a user space helper (such as cifs.upcall) to be present in order to -translate host names to ip address, and the user space helper must also -be configured in the file /etc/request-key.conf. Samba, Windows servers and -many NAS appliances support DFS as a way of constructing a global name -space to ease network configuration and improve reliability. - -To use cifs Kerberos and DFS support, the Linux keyutils package should be -installed and something like the following lines should be added to the -/etc/request-key.conf file: - -create cifs.spnego * * /usr/local/sbin/cifs.upcall %k -create dns_resolver * * /usr/local/sbin/cifs.upcall %k - -CIFS kernel module parameters -============================= -These module parameters can be specified or modified either during the time of -module loading or during the runtime by using the interface - /proc/module/cifs/parameters/<param> - -i.e. echo "value" > /sys/module/cifs/parameters/<param> - -1. enable_oplocks - Enable or disable oplocks. Oplocks are enabled by default. - [Y/y/1]. To disable use any of [N/n/0]. - diff --git a/ANDROID_3.4.5/fs/cifs/TODO b/ANDROID_3.4.5/fs/cifs/TODO deleted file mode 100644 index 355abcdc..00000000 --- a/ANDROID_3.4.5/fs/cifs/TODO +++ /dev/null @@ -1,129 +0,0 @@ -Version 1.53 May 20, 2008 - -A Partial List of Missing Features -================================== - -Contributions are welcome. There are plenty of opportunities -for visible, important contributions to this module. Here -is a partial list of the known problems and missing features: - -a) Support for SecurityDescriptors(Windows/CIFS ACLs) for chmod/chgrp/chown -so that these operations can be supported to Windows servers - -b) Mapping POSIX ACLs (and eventually NFSv4 ACLs) to CIFS -SecurityDescriptors - -c) Better pam/winbind integration (e.g. to handle uid mapping -better) - -d) Cleanup now unneeded SessSetup code in -fs/cifs/connect.c and add back in NTLMSSP code if any servers -need it - -e) fix NTLMv2 signing when two mounts with different users to same -server. - -f) Directory entry caching relies on a 1 second timer, rather than -using FindNotify or equivalent. - (started) - -g) quota support (needs minor kernel change since quota calls -to make it to network filesystems or deviceless filesystems) - -h) investigate sync behavior (including syncpage) and check -for proper behavior of intr/nointr - -i) improve support for very old servers (OS/2 and Win9x for example) -Including support for changing the time remotely (utimes command). - -j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the -extra copy in/out of the socket buffers in some cases. - -k) Better optimize open (and pathbased setfilesize) to reduce the -oplock breaks coming from windows srv. Piggyback identical file -opens on top of each other by incrementing reference count rather -than resending (helps reduce server resource utilization and avoid -spurious oplock breaks). - -l) Improve performance of readpages by sending more than one read -at a time when 8 pages or more are requested. In conjuntion -add support for async_cifs_readpages. - -m) Add support for storing symlink info to Windows servers -in the Extended Attribute format their SFU clients would recognize. - -n) Finish fcntl D_NOTIFY support so kde and gnome file list windows -will autorefresh (partially complete by Asser). Needs minor kernel -vfs change to support removing D_NOTIFY on a file. - -o) Add GUI tool to configure /proc/fs/cifs settings and for display of -the CIFS statistics (started) - -p) implement support for security and trusted categories of xattrs -(requires minor protocol extension) to enable better support for SELINUX - -q) Implement O_DIRECT flag on open (already supported on mount) - -r) Create UID mapping facility so server UIDs can be mapped on a per -mount or a per server basis to client UIDs or nobody if no mapping -exists. This is helpful when Unix extensions are negotiated to -allow better permission checking when UIDs differ on the server -and client. Add new protocol request to the CIFS protocol -standard for asking the server for the corresponding name of a -particular uid. - -s) Add support for CIFS Unix and also the newer POSIX extensions to the -server side for Samba 4. - -t) In support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers) -need to add ability to set time to server (utimes command) - -u) DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too) - -v) mount check for unmatched uids - -w) Add support for new vfs entry point for fallocate - -x) Fix Samba 3 server to handle Linux kernel aio so dbench with lots of -processes can proceed better in parallel (on the server) - -y) Fix Samba 3 to handle reads/writes over 127K (and remove the cifs mount -restriction of wsize max being 127K) - -KNOWN BUGS (updated April 24, 2007) -==================================== -See http://bugzilla.samba.org - search on product "CifsVFS" for -current bug list. - -1) existing symbolic links (Windows reparse points) are recognized but -can not be created remotely. They are implemented for Samba and those that -support the CIFS Unix extensions, although earlier versions of Samba -overly restrict the pathnames. -2) follow_link and readdir code does not follow dfs junctions -but recognizes them -3) create of new files to FAT partitions on Windows servers can -succeed but still return access denied (appears to be Windows -server not cifs client problem) and has not been reproduced recently. -NTFS partitions do not have this problem. -4) Unix/POSIX capabilities are reset after reconnection, and affect -a few fields in the tree connection but we do do not know which -superblocks to apply these changes to. We should probably walk -the list of superblocks to set these. Also need to check the -flags on the second mount to the same share, and see if we -can do the same trick that NFS does to remount duplicate shares. - -Misc testing to do -================== -1) check out max path names and max path name components against various server -types. Try nested symlinks (8 deep). Return max path name in stat -f information - -2) Modify file portion of ltp so it can run against a mounted network -share and run it against cifs vfs in automated fashion. - -3) Additional performance testing and optimization using iozone and similar - -there are some easy changes that can be done to parallelize sequential writes, -and when signing is disabled to request larger read sizes (larger than -negotiated size) and send larger write sizes to modern servers. - -4) More exhaustively test against less common servers. More testing -against Windows 9x, Windows ME servers. - diff --git a/ANDROID_3.4.5/fs/cifs/asn1.c b/ANDROID_3.4.5/fs/cifs/asn1.c deleted file mode 100644 index cfd1ce34..00000000 --- a/ANDROID_3.4.5/fs/cifs/asn1.c +++ /dev/null @@ -1,666 +0,0 @@ -/* - * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in - * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich - * - * Copyright (c) 2000 RP Internet (www.rpi.net.au). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifs_debug.h" -#include "cifsproto.h" - -/***************************************************************************** - * - * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse) - * - *****************************************************************************/ - -/* Class */ -#define ASN1_UNI 0 /* Universal */ -#define ASN1_APL 1 /* Application */ -#define ASN1_CTX 2 /* Context */ -#define ASN1_PRV 3 /* Private */ - -/* Tag */ -#define ASN1_EOC 0 /* End Of Contents or N/A */ -#define ASN1_BOL 1 /* Boolean */ -#define ASN1_INT 2 /* Integer */ -#define ASN1_BTS 3 /* Bit String */ -#define ASN1_OTS 4 /* Octet String */ -#define ASN1_NUL 5 /* Null */ -#define ASN1_OJI 6 /* Object Identifier */ -#define ASN1_OJD 7 /* Object Description */ -#define ASN1_EXT 8 /* External */ -#define ASN1_ENUM 10 /* Enumerated */ -#define ASN1_SEQ 16 /* Sequence */ -#define ASN1_SET 17 /* Set */ -#define ASN1_NUMSTR 18 /* Numerical String */ -#define ASN1_PRNSTR 19 /* Printable String */ -#define ASN1_TEXSTR 20 /* Teletext String */ -#define ASN1_VIDSTR 21 /* Video String */ -#define ASN1_IA5STR 22 /* IA5 String */ -#define ASN1_UNITIM 23 /* Universal Time */ -#define ASN1_GENTIM 24 /* General Time */ -#define ASN1_GRASTR 25 /* Graphical String */ -#define ASN1_VISSTR 26 /* Visible String */ -#define ASN1_GENSTR 27 /* General String */ - -/* Primitive / Constructed methods*/ -#define ASN1_PRI 0 /* Primitive */ -#define ASN1_CON 1 /* Constructed */ - -/* - * Error codes. - */ -#define ASN1_ERR_NOERROR 0 -#define ASN1_ERR_DEC_EMPTY 2 -#define ASN1_ERR_DEC_EOC_MISMATCH 3 -#define ASN1_ERR_DEC_LENGTH_MISMATCH 4 -#define ASN1_ERR_DEC_BADVALUE 5 - -#define SPNEGO_OID_LEN 7 -#define NTLMSSP_OID_LEN 10 -#define KRB5_OID_LEN 7 -#define KRB5U2U_OID_LEN 8 -#define MSKRB5_OID_LEN 7 -static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 }; -static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 }; -static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 }; -static unsigned long KRB5U2U_OID[8] = { 1, 2, 840, 113554, 1, 2, 2, 3 }; -static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 }; - -/* - * ASN.1 context. - */ -struct asn1_ctx { - int error; /* Error condition */ - unsigned char *pointer; /* Octet just to be decoded */ - unsigned char *begin; /* First octet */ - unsigned char *end; /* Octet after last octet */ -}; - -/* - * Octet string (not null terminated) - */ -struct asn1_octstr { - unsigned char *data; - unsigned int len; -}; - -static void -asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len) -{ - ctx->begin = buf; - ctx->end = buf + len; - ctx->pointer = buf; - ctx->error = ASN1_ERR_NOERROR; -} - -static unsigned char -asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch) -{ - if (ctx->pointer >= ctx->end) { - ctx->error = ASN1_ERR_DEC_EMPTY; - return 0; - } - *ch = *(ctx->pointer)++; - return 1; -} - -#if 0 /* will be needed later by spnego decoding/encoding of ntlmssp */ -static unsigned char -asn1_enum_decode(struct asn1_ctx *ctx, __le32 *val) -{ - unsigned char ch; - - if (ctx->pointer >= ctx->end) { - ctx->error = ASN1_ERR_DEC_EMPTY; - return 0; - } - - ch = *(ctx->pointer)++; /* ch has 0xa, ptr points to length octet */ - if ((ch) == ASN1_ENUM) /* if ch value is ENUM, 0xa */ - *val = *(++(ctx->pointer)); /* value has enum value */ - else - return 0; - - ctx->pointer++; - return 1; -} -#endif - -static unsigned char -asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag) -{ - unsigned char ch; - - *tag = 0; - - do { - if (!asn1_octet_decode(ctx, &ch)) - return 0; - *tag <<= 7; - *tag |= ch & 0x7F; - } while ((ch & 0x80) == 0x80); - return 1; -} - -static unsigned char -asn1_id_decode(struct asn1_ctx *ctx, - unsigned int *cls, unsigned int *con, unsigned int *tag) -{ - unsigned char ch; - - if (!asn1_octet_decode(ctx, &ch)) - return 0; - - *cls = (ch & 0xC0) >> 6; - *con = (ch & 0x20) >> 5; - *tag = (ch & 0x1F); - - if (*tag == 0x1F) { - if (!asn1_tag_decode(ctx, tag)) - return 0; - } - return 1; -} - -static unsigned char -asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len) -{ - unsigned char ch, cnt; - - if (!asn1_octet_decode(ctx, &ch)) - return 0; - - if (ch == 0x80) - *def = 0; - else { - *def = 1; - - if (ch < 0x80) - *len = ch; - else { - cnt = (unsigned char) (ch & 0x7F); - *len = 0; - - while (cnt > 0) { - if (!asn1_octet_decode(ctx, &ch)) - return 0; - *len <<= 8; - *len |= ch; - cnt--; - } - } - } - - /* don't trust len bigger than ctx buffer */ - if (*len > ctx->end - ctx->pointer) - return 0; - - return 1; -} - -static unsigned char -asn1_header_decode(struct asn1_ctx *ctx, - unsigned char **eoc, - unsigned int *cls, unsigned int *con, unsigned int *tag) -{ - unsigned int def = 0; - unsigned int len = 0; - - if (!asn1_id_decode(ctx, cls, con, tag)) - return 0; - - if (!asn1_length_decode(ctx, &def, &len)) - return 0; - - /* primitive shall be definite, indefinite shall be constructed */ - if (*con == ASN1_PRI && !def) - return 0; - - if (def) - *eoc = ctx->pointer + len; - else - *eoc = NULL; - return 1; -} - -static unsigned char -asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc) -{ - unsigned char ch; - - if (eoc == NULL) { - if (!asn1_octet_decode(ctx, &ch)) - return 0; - - if (ch != 0x00) { - ctx->error = ASN1_ERR_DEC_EOC_MISMATCH; - return 0; - } - - if (!asn1_octet_decode(ctx, &ch)) - return 0; - - if (ch != 0x00) { - ctx->error = ASN1_ERR_DEC_EOC_MISMATCH; - return 0; - } - return 1; - } else { - if (ctx->pointer != eoc) { - ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH; - return 0; - } - return 1; - } -} - -/* static unsigned char asn1_null_decode(struct asn1_ctx *ctx, - unsigned char *eoc) -{ - ctx->pointer = eoc; - return 1; -} - -static unsigned char asn1_long_decode(struct asn1_ctx *ctx, - unsigned char *eoc, long *integer) -{ - unsigned char ch; - unsigned int len; - - if (!asn1_octet_decode(ctx, &ch)) - return 0; - - *integer = (signed char) ch; - len = 1; - - while (ctx->pointer < eoc) { - if (++len > sizeof(long)) { - ctx->error = ASN1_ERR_DEC_BADVALUE; - return 0; - } - - if (!asn1_octet_decode(ctx, &ch)) - return 0; - - *integer <<= 8; - *integer |= ch; - } - return 1; -} - -static unsigned char asn1_uint_decode(struct asn1_ctx *ctx, - unsigned char *eoc, - unsigned int *integer) -{ - unsigned char ch; - unsigned int len; - - if (!asn1_octet_decode(ctx, &ch)) - return 0; - - *integer = ch; - if (ch == 0) - len = 0; - else - len = 1; - - while (ctx->pointer < eoc) { - if (++len > sizeof(unsigned int)) { - ctx->error = ASN1_ERR_DEC_BADVALUE; - return 0; - } - - if (!asn1_octet_decode(ctx, &ch)) - return 0; - - *integer <<= 8; - *integer |= ch; - } - return 1; -} - -static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx, - unsigned char *eoc, - unsigned long *integer) -{ - unsigned char ch; - unsigned int len; - - if (!asn1_octet_decode(ctx, &ch)) - return 0; - - *integer = ch; - if (ch == 0) - len = 0; - else - len = 1; - - while (ctx->pointer < eoc) { - if (++len > sizeof(unsigned long)) { - ctx->error = ASN1_ERR_DEC_BADVALUE; - return 0; - } - - if (!asn1_octet_decode(ctx, &ch)) - return 0; - - *integer <<= 8; - *integer |= ch; - } - return 1; -} - -static unsigned char -asn1_octets_decode(struct asn1_ctx *ctx, - unsigned char *eoc, - unsigned char **octets, unsigned int *len) -{ - unsigned char *ptr; - - *len = 0; - - *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC); - if (*octets == NULL) { - return 0; - } - - ptr = *octets; - while (ctx->pointer < eoc) { - if (!asn1_octet_decode(ctx, (unsigned char *) ptr++)) { - kfree(*octets); - *octets = NULL; - return 0; - } - (*len)++; - } - return 1; -} */ - -static unsigned char -asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid) -{ - unsigned char ch; - - *subid = 0; - - do { - if (!asn1_octet_decode(ctx, &ch)) - return 0; - - *subid <<= 7; - *subid |= ch & 0x7F; - } while ((ch & 0x80) == 0x80); - return 1; -} - -static int -asn1_oid_decode(struct asn1_ctx *ctx, - unsigned char *eoc, unsigned long **oid, unsigned int *len) -{ - unsigned long subid; - unsigned int size; - unsigned long *optr; - - size = eoc - ctx->pointer + 1; - - /* first subid actually encodes first two subids */ - if (size < 2 || size > UINT_MAX/sizeof(unsigned long)) - return 0; - - *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); - if (*oid == NULL) - return 0; - - optr = *oid; - - if (!asn1_subid_decode(ctx, &subid)) { - kfree(*oid); - *oid = NULL; - return 0; - } - - if (subid < 40) { - optr[0] = 0; - optr[1] = subid; - } else if (subid < 80) { - optr[0] = 1; - optr[1] = subid - 40; - } else { - optr[0] = 2; - optr[1] = subid - 80; - } - - *len = 2; - optr += 2; - - while (ctx->pointer < eoc) { - if (++(*len) > size) { - ctx->error = ASN1_ERR_DEC_BADVALUE; - kfree(*oid); - *oid = NULL; - return 0; - } - - if (!asn1_subid_decode(ctx, optr++)) { - kfree(*oid); - *oid = NULL; - return 0; - } - } - return 1; -} - -static int -compare_oid(unsigned long *oid1, unsigned int oid1len, - unsigned long *oid2, unsigned int oid2len) -{ - unsigned int i; - - if (oid1len != oid2len) - return 0; - else { - for (i = 0; i < oid1len; i++) { - if (oid1[i] != oid2[i]) - return 0; - } - return 1; - } -} - - /* BB check for endian conversion issues here */ - -int -decode_negTokenInit(unsigned char *security_blob, int length, - struct TCP_Server_Info *server) -{ - struct asn1_ctx ctx; - unsigned char *end; - unsigned char *sequence_end; - unsigned long *oid = NULL; - unsigned int cls, con, tag, oidlen, rc; - - /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */ - - asn1_open(&ctx, security_blob, length); - - /* GSSAPI header */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, "Error decoding negTokenInit header"); - return 0; - } else if ((cls != ASN1_APL) || (con != ASN1_CON) - || (tag != ASN1_EOC)) { - cFYI(1, "cls = %d con = %d tag = %d", cls, con, tag); - return 0; - } - - /* Check for SPNEGO OID -- remember to free obj->oid */ - rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); - if (rc) { - if ((tag == ASN1_OJI) && (con == ASN1_PRI) && - (cls == ASN1_UNI)) { - rc = asn1_oid_decode(&ctx, end, &oid, &oidlen); - if (rc) { - rc = compare_oid(oid, oidlen, SPNEGO_OID, - SPNEGO_OID_LEN); - kfree(oid); - } - } else - rc = 0; - } - - /* SPNEGO OID not present or garbled -- bail out */ - if (!rc) { - cFYI(1, "Error decoding negTokenInit header"); - return 0; - } - - /* SPNEGO */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, "Error decoding negTokenInit"); - return 0; - } else if ((cls != ASN1_CTX) || (con != ASN1_CON) - || (tag != ASN1_EOC)) { - cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 0", - cls, con, tag, end, *end); - return 0; - } - - /* negTokenInit */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, "Error decoding negTokenInit"); - return 0; - } else if ((cls != ASN1_UNI) || (con != ASN1_CON) - || (tag != ASN1_SEQ)) { - cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 1", - cls, con, tag, end, *end); - return 0; - } - - /* sequence */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, "Error decoding 2nd part of negTokenInit"); - return 0; - } else if ((cls != ASN1_CTX) || (con != ASN1_CON) - || (tag != ASN1_EOC)) { - cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 0", - cls, con, tag, end, *end); - return 0; - } - - /* sequence of */ - if (asn1_header_decode - (&ctx, &sequence_end, &cls, &con, &tag) == 0) { - cFYI(1, "Error decoding 2nd part of negTokenInit"); - return 0; - } else if ((cls != ASN1_UNI) || (con != ASN1_CON) - || (tag != ASN1_SEQ)) { - cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 1", - cls, con, tag, end, *end); - return 0; - } - - /* list of security mechanisms */ - while (!asn1_eoc_decode(&ctx, sequence_end)) { - rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); - if (!rc) { - cFYI(1, "Error decoding negTokenInit hdr exit2"); - return 0; - } - if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { - if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) { - - cFYI(1, "OID len = %d oid = 0x%lx 0x%lx " - "0x%lx 0x%lx", oidlen, *oid, - *(oid + 1), *(oid + 2), *(oid + 3)); - - if (compare_oid(oid, oidlen, MSKRB5_OID, - MSKRB5_OID_LEN)) - server->sec_mskerberos = true; - else if (compare_oid(oid, oidlen, KRB5U2U_OID, - KRB5U2U_OID_LEN)) - server->sec_kerberosu2u = true; - else if (compare_oid(oid, oidlen, KRB5_OID, - KRB5_OID_LEN)) - server->sec_kerberos = true; - else if (compare_oid(oid, oidlen, NTLMSSP_OID, - NTLMSSP_OID_LEN)) - server->sec_ntlmssp = true; - - kfree(oid); - } - } else { - cFYI(1, "Should be an oid what is going on?"); - } - } - - /* mechlistMIC */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - /* Check if we have reached the end of the blob, but with - no mechListMic (e.g. NTLMSSP instead of KRB5) */ - if (ctx.error == ASN1_ERR_DEC_EMPTY) - goto decode_negtoken_exit; - cFYI(1, "Error decoding last part negTokenInit exit3"); - return 0; - } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { - /* tag = 3 indicating mechListMIC */ - cFYI(1, "Exit 4 cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end); - return 0; - } - - /* sequence */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, "Error decoding last part negTokenInit exit5"); - return 0; - } else if ((cls != ASN1_UNI) || (con != ASN1_CON) - || (tag != ASN1_SEQ)) { - cFYI(1, "cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end); - } - - /* sequence of */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, "Error decoding last part negTokenInit exit 7"); - return 0; - } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { - cFYI(1, "Exit 8 cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end); - return 0; - } - - /* general string */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, "Error decoding last part negTokenInit exit9"); - return 0; - } else if ((cls != ASN1_UNI) || (con != ASN1_PRI) - || (tag != ASN1_GENSTR)) { - cFYI(1, "Exit10 cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end); - return 0; - } - cFYI(1, "Need to call asn1_octets_decode() function for %s", - ctx.pointer); /* is this UTF-8 or ASCII? */ -decode_negtoken_exit: - return 1; -} diff --git a/ANDROID_3.4.5/fs/cifs/cache.c b/ANDROID_3.4.5/fs/cifs/cache.c deleted file mode 100644 index 545509c3..00000000 --- a/ANDROID_3.4.5/fs/cifs/cache.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * fs/cifs/cache.c - CIFS filesystem cache index structure definitions - * - * Copyright (c) 2010 Novell, Inc. - * Authors(s): Suresh Jayaraman (sjayaraman@suse.de> - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "fscache.h" -#include "cifs_debug.h" - -/* - * CIFS filesystem definition for FS-Cache - */ -struct fscache_netfs cifs_fscache_netfs = { - .name = "cifs", - .version = 0, -}; - -/* - * Register CIFS for caching with FS-Cache - */ -int cifs_fscache_register(void) -{ - return fscache_register_netfs(&cifs_fscache_netfs); -} - -/* - * Unregister CIFS for caching - */ -void cifs_fscache_unregister(void) -{ - fscache_unregister_netfs(&cifs_fscache_netfs); -} - -/* - * Key layout of CIFS server cache index object - */ -struct cifs_server_key { - uint16_t family; /* address family */ - __be16 port; /* IP port */ - union { - struct in_addr ipv4_addr; - struct in6_addr ipv6_addr; - } addr[0]; -}; - -/* - * Server object keyed by {IPaddress,port,family} tuple - */ -static uint16_t cifs_server_get_key(const void *cookie_netfs_data, - void *buffer, uint16_t maxbuf) -{ - const struct TCP_Server_Info *server = cookie_netfs_data; - const struct sockaddr *sa = (struct sockaddr *) &server->dstaddr; - const struct sockaddr_in *addr = (struct sockaddr_in *) sa; - const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) sa; - struct cifs_server_key *key = buffer; - uint16_t key_len = sizeof(struct cifs_server_key); - - memset(key, 0, key_len); - - /* - * Should not be a problem as sin_family/sin6_family overlays - * sa_family field - */ - switch (sa->sa_family) { - case AF_INET: - key->family = sa->sa_family; - key->port = addr->sin_port; - key->addr[0].ipv4_addr = addr->sin_addr; - key_len += sizeof(key->addr[0].ipv4_addr); - break; - - case AF_INET6: - key->family = sa->sa_family; - key->port = addr6->sin6_port; - key->addr[0].ipv6_addr = addr6->sin6_addr; - key_len += sizeof(key->addr[0].ipv6_addr); - break; - - default: - cERROR(1, "Unknown network family '%d'", sa->sa_family); - key_len = 0; - break; - } - - return key_len; -} - -/* - * Server object for FS-Cache - */ -const struct fscache_cookie_def cifs_fscache_server_index_def = { - .name = "CIFS.server", - .type = FSCACHE_COOKIE_TYPE_INDEX, - .get_key = cifs_server_get_key, -}; - -/* - * Auxiliary data attached to CIFS superblock within the cache - */ -struct cifs_fscache_super_auxdata { - u64 resource_id; /* unique server resource id */ -}; - -static char *extract_sharename(const char *treename) -{ - const char *src; - char *delim, *dst; - int len; - - /* skip double chars at the beginning */ - src = treename + 2; - - /* share name is always preceded by '\\' now */ - delim = strchr(src, '\\'); - if (!delim) - return ERR_PTR(-EINVAL); - delim++; - len = strlen(delim); - - /* caller has to free the memory */ - dst = kstrndup(delim, len, GFP_KERNEL); - if (!dst) - return ERR_PTR(-ENOMEM); - - return dst; -} - -/* - * Superblock object currently keyed by share name - */ -static uint16_t cifs_super_get_key(const void *cookie_netfs_data, void *buffer, - uint16_t maxbuf) -{ - const struct cifs_tcon *tcon = cookie_netfs_data; - char *sharename; - uint16_t len; - - sharename = extract_sharename(tcon->treeName); - if (IS_ERR(sharename)) { - cFYI(1, "%s: couldn't extract sharename\n", __func__); - sharename = NULL; - return 0; - } - - len = strlen(sharename); - if (len > maxbuf) - return 0; - - memcpy(buffer, sharename, len); - - kfree(sharename); - - return len; -} - -static uint16_t -cifs_fscache_super_get_aux(const void *cookie_netfs_data, void *buffer, - uint16_t maxbuf) -{ - struct cifs_fscache_super_auxdata auxdata; - const struct cifs_tcon *tcon = cookie_netfs_data; - - memset(&auxdata, 0, sizeof(auxdata)); - auxdata.resource_id = tcon->resource_id; - - if (maxbuf > sizeof(auxdata)) - maxbuf = sizeof(auxdata); - - memcpy(buffer, &auxdata, maxbuf); - - return maxbuf; -} - -static enum -fscache_checkaux cifs_fscache_super_check_aux(void *cookie_netfs_data, - const void *data, - uint16_t datalen) -{ - struct cifs_fscache_super_auxdata auxdata; - const struct cifs_tcon *tcon = cookie_netfs_data; - - if (datalen != sizeof(auxdata)) - return FSCACHE_CHECKAUX_OBSOLETE; - - memset(&auxdata, 0, sizeof(auxdata)); - auxdata.resource_id = tcon->resource_id; - - if (memcmp(data, &auxdata, datalen) != 0) - return FSCACHE_CHECKAUX_OBSOLETE; - - return FSCACHE_CHECKAUX_OKAY; -} - -/* - * Superblock object for FS-Cache - */ -const struct fscache_cookie_def cifs_fscache_super_index_def = { - .name = "CIFS.super", - .type = FSCACHE_COOKIE_TYPE_INDEX, - .get_key = cifs_super_get_key, - .get_aux = cifs_fscache_super_get_aux, - .check_aux = cifs_fscache_super_check_aux, -}; - -/* - * Auxiliary data attached to CIFS inode within the cache - */ -struct cifs_fscache_inode_auxdata { - struct timespec last_write_time; - struct timespec last_change_time; - u64 eof; -}; - -static uint16_t cifs_fscache_inode_get_key(const void *cookie_netfs_data, - void *buffer, uint16_t maxbuf) -{ - const struct cifsInodeInfo *cifsi = cookie_netfs_data; - uint16_t keylen; - - /* use the UniqueId as the key */ - keylen = sizeof(cifsi->uniqueid); - if (keylen > maxbuf) - keylen = 0; - else - memcpy(buffer, &cifsi->uniqueid, keylen); - - return keylen; -} - -static void -cifs_fscache_inode_get_attr(const void *cookie_netfs_data, uint64_t *size) -{ - const struct cifsInodeInfo *cifsi = cookie_netfs_data; - - *size = cifsi->vfs_inode.i_size; -} - -static uint16_t -cifs_fscache_inode_get_aux(const void *cookie_netfs_data, void *buffer, - uint16_t maxbuf) -{ - struct cifs_fscache_inode_auxdata auxdata; - const struct cifsInodeInfo *cifsi = cookie_netfs_data; - - memset(&auxdata, 0, sizeof(auxdata)); - auxdata.eof = cifsi->server_eof; - auxdata.last_write_time = cifsi->vfs_inode.i_mtime; - auxdata.last_change_time = cifsi->vfs_inode.i_ctime; - - if (maxbuf > sizeof(auxdata)) - maxbuf = sizeof(auxdata); - - memcpy(buffer, &auxdata, maxbuf); - - return maxbuf; -} - -static enum -fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data, - const void *data, - uint16_t datalen) -{ - struct cifs_fscache_inode_auxdata auxdata; - struct cifsInodeInfo *cifsi = cookie_netfs_data; - - if (datalen != sizeof(auxdata)) - return FSCACHE_CHECKAUX_OBSOLETE; - - memset(&auxdata, 0, sizeof(auxdata)); - auxdata.eof = cifsi->server_eof; - auxdata.last_write_time = cifsi->vfs_inode.i_mtime; - auxdata.last_change_time = cifsi->vfs_inode.i_ctime; - - if (memcmp(data, &auxdata, datalen) != 0) - return FSCACHE_CHECKAUX_OBSOLETE; - - return FSCACHE_CHECKAUX_OKAY; -} - -static void cifs_fscache_inode_now_uncached(void *cookie_netfs_data) -{ - struct cifsInodeInfo *cifsi = cookie_netfs_data; - struct pagevec pvec; - pgoff_t first; - int loop, nr_pages; - - pagevec_init(&pvec, 0); - first = 0; - - cFYI(1, "%s: cifs inode 0x%p now uncached", __func__, cifsi); - - for (;;) { - nr_pages = pagevec_lookup(&pvec, - cifsi->vfs_inode.i_mapping, first, - PAGEVEC_SIZE - pagevec_count(&pvec)); - if (!nr_pages) - break; - - for (loop = 0; loop < nr_pages; loop++) - ClearPageFsCache(pvec.pages[loop]); - - first = pvec.pages[nr_pages - 1]->index + 1; - - pvec.nr = nr_pages; - pagevec_release(&pvec); - cond_resched(); - } -} - -const struct fscache_cookie_def cifs_fscache_inode_object_def = { - .name = "CIFS.uniqueid", - .type = FSCACHE_COOKIE_TYPE_DATAFILE, - .get_key = cifs_fscache_inode_get_key, - .get_attr = cifs_fscache_inode_get_attr, - .get_aux = cifs_fscache_inode_get_aux, - .check_aux = cifs_fscache_inode_check_aux, - .now_uncached = cifs_fscache_inode_now_uncached, -}; diff --git a/ANDROID_3.4.5/fs/cifs/cifs_debug.c b/ANDROID_3.4.5/fs/cifs/cifs_debug.c deleted file mode 100644 index 27046462..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifs_debug.c +++ /dev/null @@ -1,751 +0,0 @@ -/* - * fs/cifs_debug.c - * - * Copyright (C) International Business Machines Corp., 2000,2005 - * - * Modified by Steve French (sfrench@us.ibm.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/fs.h> -#include <linux/string.h> -#include <linux/ctype.h> -#include <linux/module.h> -#include <linux/proc_fs.h> -#include <asm/uaccess.h> -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifs_debug.h" -#include "cifsfs.h" - -void -cifs_dump_mem(char *label, void *data, int length) -{ - int i, j; - int *intptr = data; - char *charptr = data; - char buf[10], line[80]; - - printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n", - label, length, data); - for (i = 0; i < length; i += 16) { - line[0] = 0; - for (j = 0; (j < 4) && (i + j * 4 < length); j++) { - sprintf(buf, " %08x", intptr[i / 4 + j]); - strcat(line, buf); - } - buf[0] = ' '; - buf[2] = 0; - for (j = 0; (j < 16) && (i + j < length); j++) { - buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.'; - strcat(line, buf); - } - printk(KERN_DEBUG "%s\n", line); - } -} - -#ifdef CONFIG_CIFS_DEBUG2 -void cifs_dump_detail(void *buf) -{ - struct smb_hdr *smb = (struct smb_hdr *)buf; - - cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", - smb->Command, smb->Status.CifsError, - smb->Flags, smb->Flags2, smb->Mid, smb->Pid); - cERROR(1, "smb buf %p len %d", smb, smbCalcSize(smb)); -} - -void cifs_dump_mids(struct TCP_Server_Info *server) -{ - struct list_head *tmp; - struct mid_q_entry *mid_entry; - - if (server == NULL) - return; - - cERROR(1, "Dump pending requests:"); - spin_lock(&GlobalMid_Lock); - list_for_each(tmp, &server->pending_mid_q) { - mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - cERROR(1, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu", - mid_entry->mid_state, - le16_to_cpu(mid_entry->command), - mid_entry->pid, - mid_entry->callback_data, - mid_entry->mid); -#ifdef CONFIG_CIFS_STATS2 - cERROR(1, "IsLarge: %d buf: %p time rcv: %ld now: %ld", - mid_entry->large_buf, - mid_entry->resp_buf, - mid_entry->when_received, - jiffies); -#endif /* STATS2 */ - cERROR(1, "IsMult: %d IsEnd: %d", mid_entry->multiRsp, - mid_entry->multiEnd); - if (mid_entry->resp_buf) { - cifs_dump_detail(mid_entry->resp_buf); - cifs_dump_mem("existing buf: ", - mid_entry->resp_buf, 62); - } - } - spin_unlock(&GlobalMid_Lock); -} -#endif /* CONFIG_CIFS_DEBUG2 */ - -#ifdef CONFIG_PROC_FS -static int cifs_debug_data_proc_show(struct seq_file *m, void *v) -{ - struct list_head *tmp1, *tmp2, *tmp3; - struct mid_q_entry *mid_entry; - struct TCP_Server_Info *server; - struct cifs_ses *ses; - struct cifs_tcon *tcon; - int i, j; - __u32 dev_type; - - seq_puts(m, - "Display Internal CIFS Data Structures for Debugging\n" - "---------------------------------------------------\n"); - seq_printf(m, "CIFS Version %s\n", CIFS_VERSION); - seq_printf(m, "Features:"); -#ifdef CONFIG_CIFS_DFS_UPCALL - seq_printf(m, " dfs"); -#endif -#ifdef CONFIG_CIFS_FSCACHE - seq_printf(m, " fscache"); -#endif -#ifdef CONFIG_CIFS_WEAK_PW_HASH - seq_printf(m, " lanman"); -#endif -#ifdef CONFIG_CIFS_POSIX - seq_printf(m, " posix"); -#endif -#ifdef CONFIG_CIFS_UPCALL - seq_printf(m, " spnego"); -#endif -#ifdef CONFIG_CIFS_XATTR - seq_printf(m, " xattr"); -#endif -#ifdef CONFIG_CIFS_ACL - seq_printf(m, " acl"); -#endif - seq_putc(m, '\n'); - seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid); - seq_printf(m, "Servers:"); - - i = 0; - spin_lock(&cifs_tcp_ses_lock); - list_for_each(tmp1, &cifs_tcp_ses_list) { - server = list_entry(tmp1, struct TCP_Server_Info, - tcp_ses_list); - i++; - list_for_each(tmp2, &server->smb_ses_list) { - ses = list_entry(tmp2, struct cifs_ses, - smb_ses_list); - if ((ses->serverDomain == NULL) || - (ses->serverOS == NULL) || - (ses->serverNOS == NULL)) { - seq_printf(m, "\n%d) entry for %s not fully " - "displayed\n\t", i, ses->serverName); - } else { - seq_printf(m, - "\n%d) Name: %s Domain: %s Uses: %d OS:" - " %s\n\tNOS: %s\tCapability: 0x%x\n\tSMB" - " session status: %d\t", - i, ses->serverName, ses->serverDomain, - ses->ses_count, ses->serverOS, ses->serverNOS, - ses->capabilities, ses->status); - } - seq_printf(m, "TCP status: %d\n\tLocal Users To " - "Server: %d SecMode: 0x%x Req On Wire: %d", - server->tcpStatus, server->srv_count, - server->sec_mode, in_flight(server)); - -#ifdef CONFIG_CIFS_STATS2 - seq_printf(m, " In Send: %d In MaxReq Wait: %d", - atomic_read(&server->in_send), - atomic_read(&server->num_waiters)); -#endif - - seq_puts(m, "\n\tShares:"); - j = 0; - list_for_each(tmp3, &ses->tcon_list) { - tcon = list_entry(tmp3, struct cifs_tcon, - tcon_list); - ++j; - dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); - seq_printf(m, "\n\t%d) %s Mounts: %d ", j, - tcon->treeName, tcon->tc_count); - if (tcon->nativeFileSystem) { - seq_printf(m, "Type: %s ", - tcon->nativeFileSystem); - } - seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x" - "\nPathComponentMax: %d Status: 0x%d", - le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics), - le32_to_cpu(tcon->fsAttrInfo.Attributes), - le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), - tcon->tidStatus); - if (dev_type == FILE_DEVICE_DISK) - seq_puts(m, " type: DISK "); - else if (dev_type == FILE_DEVICE_CD_ROM) - seq_puts(m, " type: CDROM "); - else - seq_printf(m, " type: %d ", dev_type); - - if (tcon->need_reconnect) - seq_puts(m, "\tDISCONNECTED "); - seq_putc(m, '\n'); - } - - seq_puts(m, "\n\tMIDs:\n"); - - spin_lock(&GlobalMid_Lock); - list_for_each(tmp3, &server->pending_mid_q) { - mid_entry = list_entry(tmp3, struct mid_q_entry, - qhead); - seq_printf(m, "\tState: %d com: %d pid:" - " %d cbdata: %p mid %llu\n", - mid_entry->mid_state, - le16_to_cpu(mid_entry->command), - mid_entry->pid, - mid_entry->callback_data, - mid_entry->mid); - } - spin_unlock(&GlobalMid_Lock); - } - } - spin_unlock(&cifs_tcp_ses_lock); - seq_putc(m, '\n'); - - /* BB add code to dump additional info such as TCP session info now */ - return 0; -} - -static int cifs_debug_data_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, cifs_debug_data_proc_show, NULL); -} - -static const struct file_operations cifs_debug_data_proc_fops = { - .owner = THIS_MODULE, - .open = cifs_debug_data_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -#ifdef CONFIG_CIFS_STATS -static ssize_t cifs_stats_proc_write(struct file *file, - const char __user *buffer, size_t count, loff_t *ppos) -{ - char c; - int rc; - struct list_head *tmp1, *tmp2, *tmp3; - struct TCP_Server_Info *server; - struct cifs_ses *ses; - struct cifs_tcon *tcon; - - rc = get_user(c, buffer); - if (rc) - return rc; - - if (c == '1' || c == 'y' || c == 'Y' || c == '0') { -#ifdef CONFIG_CIFS_STATS2 - atomic_set(&totBufAllocCount, 0); - atomic_set(&totSmBufAllocCount, 0); -#endif /* CONFIG_CIFS_STATS2 */ - spin_lock(&cifs_tcp_ses_lock); - list_for_each(tmp1, &cifs_tcp_ses_list) { - server = list_entry(tmp1, struct TCP_Server_Info, - tcp_ses_list); - list_for_each(tmp2, &server->smb_ses_list) { - ses = list_entry(tmp2, struct cifs_ses, - smb_ses_list); - list_for_each(tmp3, &ses->tcon_list) { - tcon = list_entry(tmp3, - struct cifs_tcon, - tcon_list); - atomic_set(&tcon->num_smbs_sent, 0); - atomic_set(&tcon->num_writes, 0); - atomic_set(&tcon->num_reads, 0); - atomic_set(&tcon->num_oplock_brks, 0); - atomic_set(&tcon->num_opens, 0); - atomic_set(&tcon->num_posixopens, 0); - atomic_set(&tcon->num_posixmkdirs, 0); - atomic_set(&tcon->num_closes, 0); - atomic_set(&tcon->num_deletes, 0); - atomic_set(&tcon->num_mkdirs, 0); - atomic_set(&tcon->num_rmdirs, 0); - atomic_set(&tcon->num_renames, 0); - atomic_set(&tcon->num_t2renames, 0); - atomic_set(&tcon->num_ffirst, 0); - atomic_set(&tcon->num_fnext, 0); - atomic_set(&tcon->num_fclose, 0); - atomic_set(&tcon->num_hardlinks, 0); - atomic_set(&tcon->num_symlinks, 0); - atomic_set(&tcon->num_locks, 0); - } - } - } - spin_unlock(&cifs_tcp_ses_lock); - } - - return count; -} - -static int cifs_stats_proc_show(struct seq_file *m, void *v) -{ - int i; - struct list_head *tmp1, *tmp2, *tmp3; - struct TCP_Server_Info *server; - struct cifs_ses *ses; - struct cifs_tcon *tcon; - - seq_printf(m, - "Resources in use\nCIFS Session: %d\n", - sesInfoAllocCount.counter); - seq_printf(m, "Share (unique mount targets): %d\n", - tconInfoAllocCount.counter); - seq_printf(m, "SMB Request/Response Buffer: %d Pool size: %d\n", - bufAllocCount.counter, - cifs_min_rcv + tcpSesAllocCount.counter); - seq_printf(m, "SMB Small Req/Resp Buffer: %d Pool size: %d\n", - smBufAllocCount.counter, cifs_min_small); -#ifdef CONFIG_CIFS_STATS2 - seq_printf(m, "Total Large %d Small %d Allocations\n", - atomic_read(&totBufAllocCount), - atomic_read(&totSmBufAllocCount)); -#endif /* CONFIG_CIFS_STATS2 */ - - seq_printf(m, "Operations (MIDs): %d\n", atomic_read(&midCount)); - seq_printf(m, - "\n%d session %d share reconnects\n", - tcpSesReconnectCount.counter, tconInfoReconnectCount.counter); - - seq_printf(m, - "Total vfs operations: %d maximum at one time: %d\n", - GlobalCurrentXid, GlobalMaxActiveXid); - - i = 0; - spin_lock(&cifs_tcp_ses_lock); - list_for_each(tmp1, &cifs_tcp_ses_list) { - server = list_entry(tmp1, struct TCP_Server_Info, - tcp_ses_list); - list_for_each(tmp2, &server->smb_ses_list) { - ses = list_entry(tmp2, struct cifs_ses, - smb_ses_list); - list_for_each(tmp3, &ses->tcon_list) { - tcon = list_entry(tmp3, - struct cifs_tcon, - tcon_list); - i++; - seq_printf(m, "\n%d) %s", i, tcon->treeName); - if (tcon->need_reconnect) - seq_puts(m, "\tDISCONNECTED "); - seq_printf(m, "\nSMBs: %d Oplock Breaks: %d", - atomic_read(&tcon->num_smbs_sent), - atomic_read(&tcon->num_oplock_brks)); - seq_printf(m, "\nReads: %d Bytes: %lld", - atomic_read(&tcon->num_reads), - (long long)(tcon->bytes_read)); - seq_printf(m, "\nWrites: %d Bytes: %lld", - atomic_read(&tcon->num_writes), - (long long)(tcon->bytes_written)); - seq_printf(m, "\nFlushes: %d", - atomic_read(&tcon->num_flushes)); - seq_printf(m, "\nLocks: %d HardLinks: %d " - "Symlinks: %d", - atomic_read(&tcon->num_locks), - atomic_read(&tcon->num_hardlinks), - atomic_read(&tcon->num_symlinks)); - seq_printf(m, "\nOpens: %d Closes: %d " - "Deletes: %d", - atomic_read(&tcon->num_opens), - atomic_read(&tcon->num_closes), - atomic_read(&tcon->num_deletes)); - seq_printf(m, "\nPosix Opens: %d " - "Posix Mkdirs: %d", - atomic_read(&tcon->num_posixopens), - atomic_read(&tcon->num_posixmkdirs)); - seq_printf(m, "\nMkdirs: %d Rmdirs: %d", - atomic_read(&tcon->num_mkdirs), - atomic_read(&tcon->num_rmdirs)); - seq_printf(m, "\nRenames: %d T2 Renames %d", - atomic_read(&tcon->num_renames), - atomic_read(&tcon->num_t2renames)); - seq_printf(m, "\nFindFirst: %d FNext %d " - "FClose %d", - atomic_read(&tcon->num_ffirst), - atomic_read(&tcon->num_fnext), - atomic_read(&tcon->num_fclose)); - } - } - } - spin_unlock(&cifs_tcp_ses_lock); - - seq_putc(m, '\n'); - return 0; -} - -static int cifs_stats_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, cifs_stats_proc_show, NULL); -} - -static const struct file_operations cifs_stats_proc_fops = { - .owner = THIS_MODULE, - .open = cifs_stats_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = cifs_stats_proc_write, -}; -#endif /* STATS */ - -static struct proc_dir_entry *proc_fs_cifs; -static const struct file_operations cifsFYI_proc_fops; -static const struct file_operations cifs_lookup_cache_proc_fops; -static const struct file_operations traceSMB_proc_fops; -static const struct file_operations cifs_multiuser_mount_proc_fops; -static const struct file_operations cifs_security_flags_proc_fops; -static const struct file_operations cifs_linux_ext_proc_fops; - -void -cifs_proc_init(void) -{ - proc_fs_cifs = proc_mkdir("fs/cifs", NULL); - if (proc_fs_cifs == NULL) - return; - - proc_create("DebugData", 0, proc_fs_cifs, &cifs_debug_data_proc_fops); - -#ifdef CONFIG_CIFS_STATS - proc_create("Stats", 0, proc_fs_cifs, &cifs_stats_proc_fops); -#endif /* STATS */ - proc_create("cifsFYI", 0, proc_fs_cifs, &cifsFYI_proc_fops); - proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops); - proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs, - &cifs_linux_ext_proc_fops); - proc_create("MultiuserMount", 0, proc_fs_cifs, - &cifs_multiuser_mount_proc_fops); - proc_create("SecurityFlags", 0, proc_fs_cifs, - &cifs_security_flags_proc_fops); - proc_create("LookupCacheEnabled", 0, proc_fs_cifs, - &cifs_lookup_cache_proc_fops); -} - -void -cifs_proc_clean(void) -{ - if (proc_fs_cifs == NULL) - return; - - remove_proc_entry("DebugData", proc_fs_cifs); - remove_proc_entry("cifsFYI", proc_fs_cifs); - remove_proc_entry("traceSMB", proc_fs_cifs); -#ifdef CONFIG_CIFS_STATS - remove_proc_entry("Stats", proc_fs_cifs); -#endif - remove_proc_entry("MultiuserMount", proc_fs_cifs); - remove_proc_entry("SecurityFlags", proc_fs_cifs); - remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs); - remove_proc_entry("LookupCacheEnabled", proc_fs_cifs); - remove_proc_entry("fs/cifs", NULL); -} - -static int cifsFYI_proc_show(struct seq_file *m, void *v) -{ - seq_printf(m, "%d\n", cifsFYI); - return 0; -} - -static int cifsFYI_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, cifsFYI_proc_show, NULL); -} - -static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) -{ - char c; - int rc; - - rc = get_user(c, buffer); - if (rc) - return rc; - if (c == '0' || c == 'n' || c == 'N') - cifsFYI = 0; - else if (c == '1' || c == 'y' || c == 'Y') - cifsFYI = 1; - else if ((c > '1') && (c <= '9')) - cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */ - - return count; -} - -static const struct file_operations cifsFYI_proc_fops = { - .owner = THIS_MODULE, - .open = cifsFYI_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = cifsFYI_proc_write, -}; - -static int cifs_linux_ext_proc_show(struct seq_file *m, void *v) -{ - seq_printf(m, "%d\n", linuxExtEnabled); - return 0; -} - -static int cifs_linux_ext_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, cifs_linux_ext_proc_show, NULL); -} - -static ssize_t cifs_linux_ext_proc_write(struct file *file, - const char __user *buffer, size_t count, loff_t *ppos) -{ - char c; - int rc; - - rc = get_user(c, buffer); - if (rc) - return rc; - if (c == '0' || c == 'n' || c == 'N') - linuxExtEnabled = 0; - else if (c == '1' || c == 'y' || c == 'Y') - linuxExtEnabled = 1; - - return count; -} - -static const struct file_operations cifs_linux_ext_proc_fops = { - .owner = THIS_MODULE, - .open = cifs_linux_ext_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = cifs_linux_ext_proc_write, -}; - -static int cifs_lookup_cache_proc_show(struct seq_file *m, void *v) -{ - seq_printf(m, "%d\n", lookupCacheEnabled); - return 0; -} - -static int cifs_lookup_cache_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, cifs_lookup_cache_proc_show, NULL); -} - -static ssize_t cifs_lookup_cache_proc_write(struct file *file, - const char __user *buffer, size_t count, loff_t *ppos) -{ - char c; - int rc; - - rc = get_user(c, buffer); - if (rc) - return rc; - if (c == '0' || c == 'n' || c == 'N') - lookupCacheEnabled = 0; - else if (c == '1' || c == 'y' || c == 'Y') - lookupCacheEnabled = 1; - - return count; -} - -static const struct file_operations cifs_lookup_cache_proc_fops = { - .owner = THIS_MODULE, - .open = cifs_lookup_cache_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = cifs_lookup_cache_proc_write, -}; - -static int traceSMB_proc_show(struct seq_file *m, void *v) -{ - seq_printf(m, "%d\n", traceSMB); - return 0; -} - -static int traceSMB_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, traceSMB_proc_show, NULL); -} - -static ssize_t traceSMB_proc_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) -{ - char c; - int rc; - - rc = get_user(c, buffer); - if (rc) - return rc; - if (c == '0' || c == 'n' || c == 'N') - traceSMB = 0; - else if (c == '1' || c == 'y' || c == 'Y') - traceSMB = 1; - - return count; -} - -static const struct file_operations traceSMB_proc_fops = { - .owner = THIS_MODULE, - .open = traceSMB_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = traceSMB_proc_write, -}; - -static int cifs_multiuser_mount_proc_show(struct seq_file *m, void *v) -{ - seq_printf(m, "%d\n", multiuser_mount); - return 0; -} - -static int cifs_multiuser_mount_proc_open(struct inode *inode, struct file *fh) -{ - return single_open(fh, cifs_multiuser_mount_proc_show, NULL); -} - -static ssize_t cifs_multiuser_mount_proc_write(struct file *file, - const char __user *buffer, size_t count, loff_t *ppos) -{ - char c; - int rc; - static bool warned; - - rc = get_user(c, buffer); - if (rc) - return rc; - if (c == '0' || c == 'n' || c == 'N') - multiuser_mount = 0; - else if (c == '1' || c == 'y' || c == 'Y') { - multiuser_mount = 1; - if (!warned) { - warned = true; - printk(KERN_WARNING "CIFS VFS: The legacy multiuser " - "mount code is scheduled to be deprecated in " - "3.5. Please switch to using the multiuser " - "mount option."); - } - } - - return count; -} - -static const struct file_operations cifs_multiuser_mount_proc_fops = { - .owner = THIS_MODULE, - .open = cifs_multiuser_mount_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = cifs_multiuser_mount_proc_write, -}; - -static int cifs_security_flags_proc_show(struct seq_file *m, void *v) -{ - seq_printf(m, "0x%x\n", global_secflags); - return 0; -} - -static int cifs_security_flags_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, cifs_security_flags_proc_show, NULL); -} - -static ssize_t cifs_security_flags_proc_write(struct file *file, - const char __user *buffer, size_t count, loff_t *ppos) -{ - unsigned int flags; - char flags_string[12]; - char c; - - if ((count < 1) || (count > 11)) - return -EINVAL; - - memset(flags_string, 0, 12); - - if (copy_from_user(flags_string, buffer, count)) - return -EFAULT; - - if (count < 3) { - /* single char or single char followed by null */ - c = flags_string[0]; - if (c == '0' || c == 'n' || c == 'N') { - global_secflags = CIFSSEC_DEF; /* default */ - return count; - } else if (c == '1' || c == 'y' || c == 'Y') { - global_secflags = CIFSSEC_MAX; - return count; - } else if (!isdigit(c)) { - cERROR(1, "invalid flag %c", c); - return -EINVAL; - } - } - /* else we have a number */ - - flags = simple_strtoul(flags_string, NULL, 0); - - cFYI(1, "sec flags 0x%x", flags); - - if (flags <= 0) { - cERROR(1, "invalid security flags %s", flags_string); - return -EINVAL; - } - - if (flags & ~CIFSSEC_MASK) { - cERROR(1, "attempt to set unsupported security flags 0x%x", - flags & ~CIFSSEC_MASK); - return -EINVAL; - } - /* flags look ok - update the global security flags for cifs module */ - global_secflags = flags; - if (global_secflags & CIFSSEC_MUST_SIGN) { - /* requiring signing implies signing is allowed */ - global_secflags |= CIFSSEC_MAY_SIGN; - cFYI(1, "packet signing now required"); - } else if ((global_secflags & CIFSSEC_MAY_SIGN) == 0) { - cFYI(1, "packet signing disabled"); - } - /* BB should we turn on MAY flags for other MUST options? */ - return count; -} - -static const struct file_operations cifs_security_flags_proc_fops = { - .owner = THIS_MODULE, - .open = cifs_security_flags_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = cifs_security_flags_proc_write, -}; -#else -inline void cifs_proc_init(void) -{ -} - -inline void cifs_proc_clean(void) -{ -} -#endif /* PROC_FS */ diff --git a/ANDROID_3.4.5/fs/cifs/cifs_debug.h b/ANDROID_3.4.5/fs/cifs/cifs_debug.h deleted file mode 100644 index 566e0ae8..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifs_debug.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * - * Copyright (c) International Business Machines Corp., 2000,2002 - * Modified by Steve French (sfrench@us.ibm.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ -#define CIFS_DEBUG /* BB temporary */ - -#ifndef _H_CIFS_DEBUG -#define _H_CIFS_DEBUG - -void cifs_dump_mem(char *label, void *data, int length); -#ifdef CONFIG_CIFS_DEBUG2 -#define DBG2 2 -void cifs_dump_detail(void *); -void cifs_dump_mids(struct TCP_Server_Info *); -#else -#define DBG2 0 -#endif -extern int traceSMB; /* flag which enables the function below */ -void dump_smb(void *, int); -#define CIFS_INFO 0x01 -#define CIFS_RC 0x02 -#define CIFS_TIMER 0x04 - -/* - * debug ON - * -------- - */ -#ifdef CIFS_DEBUG - -/* information message: e.g., configuration, major event */ -extern int cifsFYI; -#define cifsfyi(fmt, arg...) \ -do { \ - if (cifsFYI & CIFS_INFO) \ - printk(KERN_DEBUG "%s: " fmt "\n", __FILE__, ##arg); \ -} while (0) - -#define cFYI(set, fmt, arg...) \ -do { \ - if (set) \ - cifsfyi(fmt, ##arg); \ -} while (0) - -#define cifswarn(fmt, arg...) \ - printk(KERN_WARNING fmt "\n", ##arg) - -/* debug event message: */ -extern int cifsERROR; - -#define cEVENT(fmt, arg...) \ -do { \ - if (cifsERROR) \ - printk(KERN_EVENT "%s: " fmt "\n", __FILE__, ##arg); \ -} while (0) - -/* error event message: e.g., i/o error */ -#define cifserror(fmt, arg...) \ -do { \ - if (cifsERROR) \ - printk(KERN_ERR "CIFS VFS: " fmt "\n", ##arg); \ -} while (0) - -#define cERROR(set, fmt, arg...) \ -do { \ - if (set) \ - cifserror(fmt, ##arg); \ -} while (0) - -/* - * debug OFF - * --------- - */ -#else /* _CIFS_DEBUG */ -#define cERROR(set, fmt, arg...) -#define cEVENT(fmt, arg...) -#define cFYI(set, fmt, arg...) -#define cifserror(fmt, arg...) -#endif /* _CIFS_DEBUG */ - -#endif /* _H_CIFS_DEBUG */ diff --git a/ANDROID_3.4.5/fs/cifs/cifs_dfs_ref.c b/ANDROID_3.4.5/fs/cifs/cifs_dfs_ref.c deleted file mode 100644 index 6873bb63..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifs_dfs_ref.c +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Contains the CIFS DFS referral mounting routines used for handling - * traversal via DFS junction point - * - * Copyright (c) 2007 Igor Mammedov - * Copyright (C) International Business Machines Corp., 2008 - * Author(s): Igor Mammedov (niallain@gmail.com) - * Steve French (sfrench@us.ibm.com) - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <linux/dcache.h> -#include <linux/mount.h> -#include <linux/namei.h> -#include <linux/slab.h> -#include <linux/vfs.h> -#include <linux/fs.h> -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifsfs.h" -#include "dns_resolve.h" -#include "cifs_debug.h" - -static LIST_HEAD(cifs_dfs_automount_list); - -static void cifs_dfs_expire_automounts(struct work_struct *work); -static DECLARE_DELAYED_WORK(cifs_dfs_automount_task, - cifs_dfs_expire_automounts); -static int cifs_dfs_mountpoint_expiry_timeout = 500 * HZ; - -static void cifs_dfs_expire_automounts(struct work_struct *work) -{ - struct list_head *list = &cifs_dfs_automount_list; - - mark_mounts_for_expiry(list); - if (!list_empty(list)) - schedule_delayed_work(&cifs_dfs_automount_task, - cifs_dfs_mountpoint_expiry_timeout); -} - -void cifs_dfs_release_automount_timer(void) -{ - BUG_ON(!list_empty(&cifs_dfs_automount_list)); - cancel_delayed_work_sync(&cifs_dfs_automount_task); -} - -/** - * cifs_get_share_name - extracts share name from UNC - * @node_name: pointer to UNC string - * - * Extracts sharename form full UNC. - * i.e. strips from UNC trailing path that is not part of share - * name and fixup missing '\' in the beginning of DFS node refferal - * if necessary. - * Returns pointer to share name on success or ERR_PTR on error. - * Caller is responsible for freeing returned string. - */ -static char *cifs_get_share_name(const char *node_name) -{ - int len; - char *UNC; - char *pSep; - - len = strlen(node_name); - UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */, - GFP_KERNEL); - if (!UNC) - return ERR_PTR(-ENOMEM); - - /* get share name and server name */ - if (node_name[1] != '\\') { - UNC[0] = '\\'; - strncpy(UNC+1, node_name, len); - len++; - UNC[len] = 0; - } else { - strncpy(UNC, node_name, len); - UNC[len] = 0; - } - - /* find server name end */ - pSep = memchr(UNC+2, '\\', len-2); - if (!pSep) { - cERROR(1, "%s: no server name end in node name: %s", - __func__, node_name); - kfree(UNC); - return ERR_PTR(-EINVAL); - } - - /* find sharename end */ - pSep++; - pSep = memchr(UNC+(pSep-UNC), '\\', len-(pSep-UNC)); - if (pSep) { - /* trim path up to sharename end - * now we have share name in UNC */ - *pSep = 0; - } - - return UNC; -} - - -/** - * cifs_compose_mount_options - creates mount options for refferral - * @sb_mountdata: parent/root DFS mount options (template) - * @fullpath: full path in UNC format - * @ref: server's referral - * @devname: pointer for saving device name - * - * creates mount options for submount based on template options sb_mountdata - * and replacing unc,ip,prefixpath options with ones we've got form ref_unc. - * - * Returns: pointer to new mount options or ERR_PTR. - * Caller is responcible for freeing retunrned value if it is not error. - */ -char *cifs_compose_mount_options(const char *sb_mountdata, - const char *fullpath, - const struct dfs_info3_param *ref, - char **devname) -{ - int rc; - char *mountdata = NULL; - int md_len; - char *tkn_e; - char *srvIP = NULL; - char sep = ','; - int off, noff; - - if (sb_mountdata == NULL) - return ERR_PTR(-EINVAL); - - *devname = cifs_get_share_name(ref->node_name); - if (IS_ERR(*devname)) { - rc = PTR_ERR(*devname); - *devname = NULL; - goto compose_mount_options_err; - } - - rc = dns_resolve_server_name_to_ip(*devname, &srvIP); - if (rc < 0) { - cFYI(1, "%s: Failed to resolve server part of %s to IP: %d", - __func__, *devname, rc); - goto compose_mount_options_err; - } - - /* md_len = strlen(...) + 12 for 'sep+prefixpath=' - * assuming that we have 'unc=' and 'ip=' in - * the original sb_mountdata - */ - md_len = strlen(sb_mountdata) + rc + strlen(ref->node_name) + 12; - mountdata = kzalloc(md_len+1, GFP_KERNEL); - if (mountdata == NULL) { - rc = -ENOMEM; - goto compose_mount_options_err; - } - - /* copy all options except of unc,ip,prefixpath */ - off = 0; - if (strncmp(sb_mountdata, "sep=", 4) == 0) { - sep = sb_mountdata[4]; - strncpy(mountdata, sb_mountdata, 5); - off += 5; - } - - do { - tkn_e = strchr(sb_mountdata + off, sep); - if (tkn_e == NULL) - noff = strlen(sb_mountdata + off); - else - noff = tkn_e - (sb_mountdata + off) + 1; - - if (strnicmp(sb_mountdata + off, "unc=", 4) == 0) { - off += noff; - continue; - } - if (strnicmp(sb_mountdata + off, "ip=", 3) == 0) { - off += noff; - continue; - } - if (strnicmp(sb_mountdata + off, "prefixpath=", 11) == 0) { - off += noff; - continue; - } - strncat(mountdata, sb_mountdata + off, noff); - off += noff; - } while (tkn_e); - strcat(mountdata, sb_mountdata + off); - mountdata[md_len] = '\0'; - - /* copy new IP and ref share name */ - if (mountdata[strlen(mountdata) - 1] != sep) - strncat(mountdata, &sep, 1); - strcat(mountdata, "ip="); - strcat(mountdata, srvIP); - strncat(mountdata, &sep, 1); - strcat(mountdata, "unc="); - strcat(mountdata, *devname); - - /* find & copy prefixpath */ - tkn_e = strchr(ref->node_name + 2, '\\'); - if (tkn_e == NULL) { - /* invalid unc, missing share name*/ - rc = -EINVAL; - goto compose_mount_options_err; - } - - tkn_e = strchr(tkn_e + 1, '\\'); - if (tkn_e || (strlen(fullpath) - ref->path_consumed)) { - strncat(mountdata, &sep, 1); - strcat(mountdata, "prefixpath="); - if (tkn_e) - strcat(mountdata, tkn_e + 1); - strcat(mountdata, fullpath + ref->path_consumed); - } - - /*cFYI(1, "%s: parent mountdata: %s", __func__,sb_mountdata);*/ - /*cFYI(1, "%s: submount mountdata: %s", __func__, mountdata );*/ - -compose_mount_options_out: - kfree(srvIP); - return mountdata; - -compose_mount_options_err: - kfree(mountdata); - mountdata = ERR_PTR(rc); - goto compose_mount_options_out; -} - -/** - * cifs_dfs_do_refmount - mounts specified path using provided refferal - * @cifs_sb: parent/root superblock - * @fullpath: full path in UNC format - * @ref: server's referral - */ -static struct vfsmount *cifs_dfs_do_refmount(struct cifs_sb_info *cifs_sb, - const char *fullpath, const struct dfs_info3_param *ref) -{ - struct vfsmount *mnt; - char *mountdata; - char *devname = NULL; - - /* strip first '\' from fullpath */ - mountdata = cifs_compose_mount_options(cifs_sb->mountdata, - fullpath + 1, ref, &devname); - - if (IS_ERR(mountdata)) - return (struct vfsmount *)mountdata; - - mnt = vfs_kern_mount(&cifs_fs_type, 0, devname, mountdata); - kfree(mountdata); - kfree(devname); - return mnt; - -} - -static void dump_referral(const struct dfs_info3_param *ref) -{ - cFYI(1, "DFS: ref path: %s", ref->path_name); - cFYI(1, "DFS: node path: %s", ref->node_name); - cFYI(1, "DFS: fl: %hd, srv_type: %hd", ref->flags, ref->server_type); - cFYI(1, "DFS: ref_flags: %hd, path_consumed: %hd", ref->ref_flag, - ref->path_consumed); -} - -/* - * Create a vfsmount that we can automount - */ -static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt) -{ - struct dfs_info3_param *referrals = NULL; - unsigned int num_referrals = 0; - struct cifs_sb_info *cifs_sb; - struct cifs_ses *ses; - char *full_path; - int xid, i; - int rc; - struct vfsmount *mnt; - struct tcon_link *tlink; - - cFYI(1, "in %s", __func__); - BUG_ON(IS_ROOT(mntpt)); - - /* - * The MSDFS spec states that paths in DFS referral requests and - * responses must be prefixed by a single '\' character instead of - * the double backslashes usually used in the UNC. This function - * gives us the latter, so we must adjust the result. - */ - mnt = ERR_PTR(-ENOMEM); - full_path = build_path_from_dentry(mntpt); - if (full_path == NULL) - goto cdda_exit; - - cifs_sb = CIFS_SB(mntpt->d_inode->i_sb); - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) { - mnt = ERR_CAST(tlink); - goto free_full_path; - } - ses = tlink_tcon(tlink)->ses; - - xid = GetXid(); - rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls, - &num_referrals, &referrals, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - FreeXid(xid); - - cifs_put_tlink(tlink); - - mnt = ERR_PTR(-ENOENT); - for (i = 0; i < num_referrals; i++) { - int len; - dump_referral(referrals + i); - /* connect to a node */ - len = strlen(referrals[i].node_name); - if (len < 2) { - cERROR(1, "%s: Net Address path too short: %s", - __func__, referrals[i].node_name); - mnt = ERR_PTR(-EINVAL); - break; - } - mnt = cifs_dfs_do_refmount(cifs_sb, - full_path, referrals + i); - cFYI(1, "%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__, - referrals[i].node_name, mnt); - if (!IS_ERR(mnt)) - goto success; - } - - /* no valid submounts were found; return error from get_dfs_path() by - * preference */ - if (rc != 0) - mnt = ERR_PTR(rc); - -success: - free_dfs_info_array(referrals, num_referrals); -free_full_path: - kfree(full_path); -cdda_exit: - cFYI(1, "leaving %s" , __func__); - return mnt; -} - -/* - * Attempt to automount the referral - */ -struct vfsmount *cifs_dfs_d_automount(struct path *path) -{ - struct vfsmount *newmnt; - - cFYI(1, "in %s", __func__); - - newmnt = cifs_dfs_do_automount(path->dentry); - if (IS_ERR(newmnt)) { - cFYI(1, "leaving %s [automount failed]" , __func__); - return newmnt; - } - - mntget(newmnt); /* prevent immediate expiration */ - mnt_set_expiry(newmnt, &cifs_dfs_automount_list); - schedule_delayed_work(&cifs_dfs_automount_task, - cifs_dfs_mountpoint_expiry_timeout); - cFYI(1, "leaving %s [ok]" , __func__); - return newmnt; -} - -const struct inode_operations cifs_dfs_referral_inode_operations = { -}; diff --git a/ANDROID_3.4.5/fs/cifs/cifs_fs_sb.h b/ANDROID_3.4.5/fs/cifs/cifs_fs_sb.h deleted file mode 100644 index c865bfdf..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifs_fs_sb.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * fs/cifs/cifs_fs_sb.h - * - * Copyright (c) International Business Machines Corp., 2002,2004 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - */ -#include <linux/rbtree.h> - -#ifndef _CIFS_FS_SB_H -#define _CIFS_FS_SB_H - -#include <linux/backing-dev.h> - -#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */ -#define CIFS_MOUNT_SET_UID 2 /* set current's euid in create etc. */ -#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */ -#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ -#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ -#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */ -#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible*/ -#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */ -#define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */ -#define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */ -#define CIFS_MOUNT_OVERR_UID 0x400 /* override uid returned from server */ -#define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */ -#define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */ -#define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */ -#define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/ -#define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */ -#define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */ -#define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ -#define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ -#define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */ -#define CIFS_MOUNT_POSIXACL 0x100000 /* mirror of MS_POSIXACL in mnt_cifs_flags */ -#define CIFS_MOUNT_CIFS_BACKUPUID 0x200000 /* backup intent bit for a user */ -#define CIFS_MOUNT_CIFS_BACKUPGID 0x400000 /* backup intent bit for a group */ - -struct cifs_sb_info { - struct rb_root tlink_tree; - spinlock_t tlink_tree_lock; - struct tcon_link *master_tlink; - struct nls_table *local_nls; - unsigned int rsize; - unsigned int wsize; - unsigned long actimeo; /* attribute cache timeout (jiffies) */ - atomic_t active; - uid_t mnt_uid; - gid_t mnt_gid; - uid_t mnt_backupuid; - gid_t mnt_backupgid; - umode_t mnt_file_mode; - umode_t mnt_dir_mode; - unsigned int mnt_cifs_flags; - char *mountdata; /* options received at mount time or via DFS refs */ - struct backing_dev_info bdi; - struct delayed_work prune_tlinks; -}; -#endif /* _CIFS_FS_SB_H */ diff --git a/ANDROID_3.4.5/fs/cifs/cifs_spnego.c b/ANDROID_3.4.5/fs/cifs/cifs_spnego.c deleted file mode 100644 index e622863b..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifs_spnego.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * fs/cifs/cifs_spnego.c -- SPNEGO upcall management for CIFS - * - * Copyright (c) 2007 Red Hat, Inc. - * Author(s): Jeff Layton (jlayton@redhat.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/list.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <keys/user-type.h> -#include <linux/key-type.h> -#include <linux/inet.h> -#include "cifsglob.h" -#include "cifs_spnego.h" -#include "cifs_debug.h" - -/* create a new cifs key */ -static int -cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen) -{ - char *payload; - int ret; - - ret = -ENOMEM; - payload = kmalloc(datalen, GFP_KERNEL); - if (!payload) - goto error; - - /* attach the data */ - memcpy(payload, data, datalen); - key->payload.data = payload; - ret = 0; - -error: - return ret; -} - -static void -cifs_spnego_key_destroy(struct key *key) -{ - kfree(key->payload.data); -} - - -/* - * keytype for CIFS spnego keys - */ -struct key_type cifs_spnego_key_type = { - .name = "cifs.spnego", - .instantiate = cifs_spnego_key_instantiate, - .match = user_match, - .destroy = cifs_spnego_key_destroy, - .describe = user_describe, -}; - -/* length of longest version string e.g. strlen("ver=0xFF") */ -#define MAX_VER_STR_LEN 8 - -/* length of longest security mechanism name, eg in future could have - * strlen(";sec=ntlmsspi") */ -#define MAX_MECH_STR_LEN 13 - -/* strlen of "host=" */ -#define HOST_KEY_LEN 5 - -/* strlen of ";ip4=" or ";ip6=" */ -#define IP_KEY_LEN 5 - -/* strlen of ";uid=0x" */ -#define UID_KEY_LEN 7 - -/* strlen of ";creduid=0x" */ -#define CREDUID_KEY_LEN 11 - -/* strlen of ";user=" */ -#define USER_KEY_LEN 6 - -/* strlen of ";pid=0x" */ -#define PID_KEY_LEN 7 - -/* get a key struct with a SPNEGO security blob, suitable for session setup */ -struct key * -cifs_get_spnego_key(struct cifs_ses *sesInfo) -{ - struct TCP_Server_Info *server = sesInfo->server; - struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr; - struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr; - char *description, *dp; - size_t desc_len; - struct key *spnego_key; - const char *hostname = server->hostname; - - /* length of fields (with semicolons): ver=0xyz ip4=ipaddress - host=hostname sec=mechanism uid=0xFF user=username */ - desc_len = MAX_VER_STR_LEN + - HOST_KEY_LEN + strlen(hostname) + - IP_KEY_LEN + INET6_ADDRSTRLEN + - MAX_MECH_STR_LEN + - UID_KEY_LEN + (sizeof(uid_t) * 2) + - CREDUID_KEY_LEN + (sizeof(uid_t) * 2) + - PID_KEY_LEN + (sizeof(pid_t) * 2) + 1; - - if (sesInfo->user_name) - desc_len += USER_KEY_LEN + strlen(sesInfo->user_name); - - spnego_key = ERR_PTR(-ENOMEM); - description = kzalloc(desc_len, GFP_KERNEL); - if (description == NULL) - goto out; - - dp = description; - /* start with version and hostname portion of UNC string */ - spnego_key = ERR_PTR(-EINVAL); - sprintf(dp, "ver=0x%x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION, - hostname); - dp = description + strlen(description); - - /* add the server address */ - if (server->dstaddr.ss_family == AF_INET) - sprintf(dp, "ip4=%pI4", &sa->sin_addr); - else if (server->dstaddr.ss_family == AF_INET6) - sprintf(dp, "ip6=%pI6", &sa6->sin6_addr); - else - goto out; - - dp = description + strlen(description); - - /* for now, only sec=krb5 and sec=mskrb5 are valid */ - if (server->sec_kerberos) - sprintf(dp, ";sec=krb5"); - else if (server->sec_mskerberos) - sprintf(dp, ";sec=mskrb5"); - else - goto out; - - dp = description + strlen(description); - sprintf(dp, ";uid=0x%x", sesInfo->linux_uid); - - dp = description + strlen(description); - sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid); - - if (sesInfo->user_name) { - dp = description + strlen(description); - sprintf(dp, ";user=%s", sesInfo->user_name); - } - - dp = description + strlen(description); - sprintf(dp, ";pid=0x%x", current->pid); - - cFYI(1, "key description = %s", description); - spnego_key = request_key(&cifs_spnego_key_type, description, ""); - -#ifdef CONFIG_CIFS_DEBUG2 - if (cifsFYI && !IS_ERR(spnego_key)) { - struct cifs_spnego_msg *msg = spnego_key->payload.data; - cifs_dump_mem("SPNEGO reply blob:", msg->data, min(1024U, - msg->secblob_len + msg->sesskey_len)); - } -#endif /* CONFIG_CIFS_DEBUG2 */ - -out: - kfree(description); - return spnego_key; -} diff --git a/ANDROID_3.4.5/fs/cifs/cifs_spnego.h b/ANDROID_3.4.5/fs/cifs/cifs_spnego.h deleted file mode 100644 index 31bef9ee..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifs_spnego.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * fs/cifs/cifs_spnego.h -- SPNEGO upcall management for CIFS - * - * Copyright (c) 2007 Red Hat, Inc. - * Author(s): Jeff Layton (jlayton@redhat.com) - * Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _CIFS_SPNEGO_H -#define _CIFS_SPNEGO_H - -#define CIFS_SPNEGO_UPCALL_VERSION 2 - -/* - * The version field should always be set to CIFS_SPNEGO_UPCALL_VERSION. - * The flags field is for future use. The request-key callout should set - * sesskey_len and secblob_len, and then concatenate the SessKey+SecBlob - * and stuff it in the data field. - */ -struct cifs_spnego_msg { - uint32_t version; - uint32_t flags; - uint32_t sesskey_len; - uint32_t secblob_len; - uint8_t data[1]; -}; - -#ifdef __KERNEL__ -extern struct key_type cifs_spnego_key_type; -extern struct key *cifs_get_spnego_key(struct cifs_ses *sesInfo); -#endif /* KERNEL */ - -#endif /* _CIFS_SPNEGO_H */ diff --git a/ANDROID_3.4.5/fs/cifs/cifs_unicode.c b/ANDROID_3.4.5/fs/cifs/cifs_unicode.c deleted file mode 100644 index fbb9da95..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifs_unicode.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * fs/cifs/cifs_unicode.c - * - * Copyright (c) International Business Machines Corp., 2000,2009 - * Modified by Steve French (sfrench@us.ibm.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/fs.h> -#include <linux/slab.h> -#include "cifs_unicode.h" -#include "cifs_uniupr.h" -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifs_debug.h" - -/* - * cifs_utf16_bytes - how long will a string be after conversion? - * @utf16 - pointer to input string - * @maxbytes - don't go past this many bytes of input string - * @codepage - destination codepage - * - * Walk a utf16le string and return the number of bytes that the string will - * be after being converted to the given charset, not including any null - * termination required. Don't walk past maxbytes in the source buffer. - */ -int -cifs_utf16_bytes(const __le16 *from, int maxbytes, - const struct nls_table *codepage) -{ - int i; - int charlen, outlen = 0; - int maxwords = maxbytes / 2; - char tmp[NLS_MAX_CHARSET_SIZE]; - __u16 ftmp; - - for (i = 0; i < maxwords; i++) { - ftmp = get_unaligned_le16(&from[i]); - if (ftmp == 0) - break; - - charlen = codepage->uni2char(ftmp, tmp, NLS_MAX_CHARSET_SIZE); - if (charlen > 0) - outlen += charlen; - else - outlen++; - } - - return outlen; -} - -/* - * cifs_mapchar - convert a host-endian char to proper char in codepage - * @target - where converted character should be copied - * @src_char - 2 byte host-endian source character - * @cp - codepage to which character should be converted - * @mapchar - should character be mapped according to mapchars mount option? - * - * This function handles the conversion of a single character. It is the - * responsibility of the caller to ensure that the target buffer is large - * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). - */ -static int -cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, - bool mapchar) -{ - int len = 1; - - if (!mapchar) - goto cp_convert; - - /* - * BB: Cannot handle remapping UNI_SLASH until all the calls to - * build_path_from_dentry are modified, as they use slash as - * separator. - */ - switch (src_char) { - case UNI_COLON: - *target = ':'; - break; - case UNI_ASTERISK: - *target = '*'; - break; - case UNI_QUESTION: - *target = '?'; - break; - case UNI_PIPE: - *target = '|'; - break; - case UNI_GRTRTHAN: - *target = '>'; - break; - case UNI_LESSTHAN: - *target = '<'; - break; - default: - goto cp_convert; - } - -out: - return len; - -cp_convert: - len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE); - if (len <= 0) { - *target = '?'; - len = 1; - } - goto out; -} - -/* - * cifs_from_utf16 - convert utf16le string to local charset - * @to - destination buffer - * @from - source buffer - * @tolen - destination buffer size (in bytes) - * @fromlen - source buffer size (in bytes) - * @codepage - codepage to which characters should be converted - * @mapchar - should characters be remapped according to the mapchars option? - * - * Convert a little-endian utf16le string (as sent by the server) to a string - * in the provided codepage. The tolen and fromlen parameters are to ensure - * that the code doesn't walk off of the end of the buffer (which is always - * a danger if the alignment of the source buffer is off). The destination - * string is always properly null terminated and fits in the destination - * buffer. Returns the length of the destination string in bytes (including - * null terminator). - * - * Note that some windows versions actually send multiword UTF-16 characters - * instead of straight UTF16-2. The linux nls routines however aren't able to - * deal with those characters properly. In the event that we get some of - * those characters, they won't be translated properly. - */ -int -cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, - const struct nls_table *codepage, bool mapchar) -{ - int i, charlen, safelen; - int outlen = 0; - int nullsize = nls_nullsize(codepage); - int fromwords = fromlen / 2; - char tmp[NLS_MAX_CHARSET_SIZE]; - __u16 ftmp; - - /* - * because the chars can be of varying widths, we need to take care - * not to overflow the destination buffer when we get close to the - * end of it. Until we get to this offset, we don't need to check - * for overflow however. - */ - safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); - - for (i = 0; i < fromwords; i++) { - ftmp = get_unaligned_le16(&from[i]); - if (ftmp == 0) - break; - - /* - * check to see if converting this character might make the - * conversion bleed into the null terminator - */ - if (outlen >= safelen) { - charlen = cifs_mapchar(tmp, ftmp, codepage, mapchar); - if ((outlen + charlen) > (tolen - nullsize)) - break; - } - - /* put converted char into 'to' buffer */ - charlen = cifs_mapchar(&to[outlen], ftmp, codepage, mapchar); - outlen += charlen; - } - - /* properly null-terminate string */ - for (i = 0; i < nullsize; i++) - to[outlen++] = 0; - - return outlen; -} - -/* - * NAME: cifs_strtoUTF16() - * - * FUNCTION: Convert character string to unicode string - * - */ -int -cifs_strtoUTF16(__le16 *to, const char *from, int len, - const struct nls_table *codepage) -{ - int charlen; - int i; - wchar_t wchar_to; /* needed to quiet sparse */ - - for (i = 0; len && *from; i++, from += charlen, len -= charlen) { - charlen = codepage->char2uni(from, len, &wchar_to); - if (charlen < 1) { - cERROR(1, "strtoUTF16: char2uni of 0x%x returned %d", - *from, charlen); - /* A question mark */ - wchar_to = 0x003f; - charlen = 1; - } - put_unaligned_le16(wchar_to, &to[i]); - } - - put_unaligned_le16(0, &to[i]); - return i; -} - -/* - * cifs_strndup_from_utf16 - copy a string from wire format to the local - * codepage - * @src - source string - * @maxlen - don't walk past this many bytes in the source string - * @is_unicode - is this a unicode string? - * @codepage - destination codepage - * - * Take a string given by the server, convert it to the local codepage and - * put it in a new buffer. Returns a pointer to the new string or NULL on - * error. - */ -char * -cifs_strndup_from_utf16(const char *src, const int maxlen, - const bool is_unicode, const struct nls_table *codepage) -{ - int len; - char *dst; - - if (is_unicode) { - len = cifs_utf16_bytes((__le16 *) src, maxlen, codepage); - len += nls_nullsize(codepage); - dst = kmalloc(len, GFP_KERNEL); - if (!dst) - return NULL; - cifs_from_utf16(dst, (__le16 *) src, len, maxlen, codepage, - false); - } else { - len = strnlen(src, maxlen); - len++; - dst = kmalloc(len, GFP_KERNEL); - if (!dst) - return NULL; - strlcpy(dst, src, len); - } - - return dst; -} - -/* - * Convert 16 bit Unicode pathname to wire format from string in current code - * page. Conversion may involve remapping up the six characters that are - * only legal in POSIX-like OS (if they are present in the string). Path - * names are little endian 16 bit Unicode on the wire - */ -int -cifsConvertToUTF16(__le16 *target, const char *source, int srclen, - const struct nls_table *cp, int mapChars) -{ - int i, j, charlen; - char src_char; - __le16 dst_char; - wchar_t tmp; - - if (!mapChars) - return cifs_strtoUTF16(target, source, PATH_MAX, cp); - - for (i = 0, j = 0; i < srclen; j++) { - src_char = source[i]; - charlen = 1; - switch (src_char) { - case 0: - put_unaligned(0, &target[j]); - goto ctoUTF16_out; - case ':': - dst_char = cpu_to_le16(UNI_COLON); - break; - case '*': - dst_char = cpu_to_le16(UNI_ASTERISK); - break; - case '?': - dst_char = cpu_to_le16(UNI_QUESTION); - break; - case '<': - dst_char = cpu_to_le16(UNI_LESSTHAN); - break; - case '>': - dst_char = cpu_to_le16(UNI_GRTRTHAN); - break; - case '|': - dst_char = cpu_to_le16(UNI_PIPE); - break; - /* - * FIXME: We can not handle remapping backslash (UNI_SLASH) - * until all the calls to build_path_from_dentry are modified, - * as they use backslash as separator. - */ - default: - charlen = cp->char2uni(source + i, srclen - i, &tmp); - dst_char = cpu_to_le16(tmp); - - /* - * if no match, use question mark, which at least in - * some cases serves as wild card - */ - if (charlen < 1) { - dst_char = cpu_to_le16(0x003f); - charlen = 1; - } - } - /* - * character may take more than one byte in the source string, - * but will take exactly two bytes in the target string - */ - i += charlen; - put_unaligned(dst_char, &target[j]); - } - -ctoUTF16_out: - return i; -} - diff --git a/ANDROID_3.4.5/fs/cifs/cifs_unicode.h b/ANDROID_3.4.5/fs/cifs/cifs_unicode.h deleted file mode 100644 index a513a546..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifs_unicode.h +++ /dev/null @@ -1,383 +0,0 @@ -/* - * cifs_unicode: Unicode kernel case support - * - * Function: - * Convert a unicode character to upper or lower case using - * compressed tables. - * - * Copyright (c) International Business Machines Corp., 2000,2009 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Notes: - * These APIs are based on the C library functions. The semantics - * should match the C functions but with expanded size operands. - * - * The upper/lower functions are based on a table created by mkupr. - * This is a compressed table of upper and lower case conversion. - * - */ -#ifndef _CIFS_UNICODE_H -#define _CIFS_UNICODE_H - -#include <asm/byteorder.h> -#include <linux/types.h> -#include <linux/nls.h> - -#define UNIUPR_NOLOWER /* Example to not expand lower case tables */ - -/* - * Windows maps these to the user defined 16 bit Unicode range since they are - * reserved symbols (along with \ and /), otherwise illegal to store - * in filenames in NTFS - */ -#define UNI_ASTERISK (__u16) ('*' + 0xF000) -#define UNI_QUESTION (__u16) ('?' + 0xF000) -#define UNI_COLON (__u16) (':' + 0xF000) -#define UNI_GRTRTHAN (__u16) ('>' + 0xF000) -#define UNI_LESSTHAN (__u16) ('<' + 0xF000) -#define UNI_PIPE (__u16) ('|' + 0xF000) -#define UNI_SLASH (__u16) ('\\' + 0xF000) - -/* Just define what we want from uniupr.h. We don't want to define the tables - * in each source file. - */ -#ifndef UNICASERANGE_DEFINED -struct UniCaseRange { - wchar_t start; - wchar_t end; - signed char *table; -}; -#endif /* UNICASERANGE_DEFINED */ - -#ifndef UNIUPR_NOUPPER -extern signed char CifsUniUpperTable[512]; -extern const struct UniCaseRange CifsUniUpperRange[]; -#endif /* UNIUPR_NOUPPER */ - -#ifndef UNIUPR_NOLOWER -extern signed char CifsUniLowerTable[512]; -extern const struct UniCaseRange CifsUniLowerRange[]; -#endif /* UNIUPR_NOLOWER */ - -#ifdef __KERNEL__ -int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, - const struct nls_table *codepage, bool mapchar); -int cifs_utf16_bytes(const __le16 *from, int maxbytes, - const struct nls_table *codepage); -int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *); -char *cifs_strndup_from_utf16(const char *src, const int maxlen, - const bool is_unicode, - const struct nls_table *codepage); -extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen, - const struct nls_table *cp, int mapChars); - -#endif - -/* - * UniStrcat: Concatenate the second string to the first - * - * Returns: - * Address of the first string - */ -static inline wchar_t * -UniStrcat(wchar_t *ucs1, const wchar_t *ucs2) -{ - wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */ - - while (*ucs1++) ; /* To end of first string */ - ucs1--; /* Return to the null */ - while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */ - return anchor; -} - -/* - * UniStrchr: Find a character in a string - * - * Returns: - * Address of first occurrence of character in string - * or NULL if the character is not in the string - */ -static inline wchar_t * -UniStrchr(const wchar_t *ucs, wchar_t uc) -{ - while ((*ucs != uc) && *ucs) - ucs++; - - if (*ucs == uc) - return (wchar_t *) ucs; - return NULL; -} - -/* - * UniStrcmp: Compare two strings - * - * Returns: - * < 0: First string is less than second - * = 0: Strings are equal - * > 0: First string is greater than second - */ -static inline int -UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2) -{ - while ((*ucs1 == *ucs2) && *ucs1) { - ucs1++; - ucs2++; - } - return (int) *ucs1 - (int) *ucs2; -} - -/* - * UniStrcpy: Copy a string - */ -static inline wchar_t * -UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2) -{ - wchar_t *anchor = ucs1; /* save the start of result string */ - - while ((*ucs1++ = *ucs2++)) ; - return anchor; -} - -/* - * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes) - */ -static inline size_t -UniStrlen(const wchar_t *ucs1) -{ - int i = 0; - - while (*ucs1++) - i++; - return i; -} - -/* - * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a - * string (length limited) - */ -static inline size_t -UniStrnlen(const wchar_t *ucs1, int maxlen) -{ - int i = 0; - - while (*ucs1++) { - i++; - if (i >= maxlen) - break; - } - return i; -} - -/* - * UniStrncat: Concatenate length limited string - */ -static inline wchar_t * -UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n) -{ - wchar_t *anchor = ucs1; /* save pointer to string 1 */ - - while (*ucs1++) ; - ucs1--; /* point to null terminator of s1 */ - while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */ - ucs1++; - ucs2++; - } - *ucs1 = 0; /* Null terminate the result */ - return (anchor); -} - -/* - * UniStrncmp: Compare length limited string - */ -static inline int -UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n) -{ - if (!n) - return 0; /* Null strings are equal */ - while ((*ucs1 == *ucs2) && *ucs1 && --n) { - ucs1++; - ucs2++; - } - return (int) *ucs1 - (int) *ucs2; -} - -/* - * UniStrncmp_le: Compare length limited string - native to little-endian - */ -static inline int -UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n) -{ - if (!n) - return 0; /* Null strings are equal */ - while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) { - ucs1++; - ucs2++; - } - return (int) *ucs1 - (int) __le16_to_cpu(*ucs2); -} - -/* - * UniStrncpy: Copy length limited string with pad - */ -static inline wchar_t * -UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n) -{ - wchar_t *anchor = ucs1; - - while (n-- && *ucs2) /* Copy the strings */ - *ucs1++ = *ucs2++; - - n++; - while (n--) /* Pad with nulls */ - *ucs1++ = 0; - return anchor; -} - -/* - * UniStrncpy_le: Copy length limited string with pad to little-endian - */ -static inline wchar_t * -UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n) -{ - wchar_t *anchor = ucs1; - - while (n-- && *ucs2) /* Copy the strings */ - *ucs1++ = __le16_to_cpu(*ucs2++); - - n++; - while (n--) /* Pad with nulls */ - *ucs1++ = 0; - return anchor; -} - -/* - * UniStrstr: Find a string in a string - * - * Returns: - * Address of first match found - * NULL if no matching string is found - */ -static inline wchar_t * -UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2) -{ - const wchar_t *anchor1 = ucs1; - const wchar_t *anchor2 = ucs2; - - while (*ucs1) { - if (*ucs1 == *ucs2) { - /* Partial match found */ - ucs1++; - ucs2++; - } else { - if (!*ucs2) /* Match found */ - return (wchar_t *) anchor1; - ucs1 = ++anchor1; /* No match */ - ucs2 = anchor2; - } - } - - if (!*ucs2) /* Both end together */ - return (wchar_t *) anchor1; /* Match found */ - return NULL; /* No match */ -} - -#ifndef UNIUPR_NOUPPER -/* - * UniToupper: Convert a unicode character to upper case - */ -static inline wchar_t -UniToupper(register wchar_t uc) -{ - register const struct UniCaseRange *rp; - - if (uc < sizeof(CifsUniUpperTable)) { - /* Latin characters */ - return uc + CifsUniUpperTable[uc]; /* Use base tables */ - } else { - rp = CifsUniUpperRange; /* Use range tables */ - while (rp->start) { - if (uc < rp->start) /* Before start of range */ - return uc; /* Uppercase = input */ - if (uc <= rp->end) /* In range */ - return uc + rp->table[uc - rp->start]; - rp++; /* Try next range */ - } - } - return uc; /* Past last range */ -} - -/* - * UniStrupr: Upper case a unicode string - */ -static inline wchar_t * -UniStrupr(register wchar_t *upin) -{ - register wchar_t *up; - - up = upin; - while (*up) { /* For all characters */ - *up = UniToupper(*up); - up++; - } - return upin; /* Return input pointer */ -} -#endif /* UNIUPR_NOUPPER */ - -#ifndef UNIUPR_NOLOWER -/* - * UniTolower: Convert a unicode character to lower case - */ -static inline wchar_t -UniTolower(register wchar_t uc) -{ - register const struct UniCaseRange *rp; - - if (uc < sizeof(CifsUniLowerTable)) { - /* Latin characters */ - return uc + CifsUniLowerTable[uc]; /* Use base tables */ - } else { - rp = CifsUniLowerRange; /* Use range tables */ - while (rp->start) { - if (uc < rp->start) /* Before start of range */ - return uc; /* Uppercase = input */ - if (uc <= rp->end) /* In range */ - return uc + rp->table[uc - rp->start]; - rp++; /* Try next range */ - } - } - return uc; /* Past last range */ -} - -/* - * UniStrlwr: Lower case a unicode string - */ -static inline wchar_t * -UniStrlwr(register wchar_t *upin) -{ - register wchar_t *up; - - up = upin; - while (*up) { /* For all characters */ - *up = UniTolower(*up); - up++; - } - return upin; /* Return input pointer */ -} - -#endif - -#endif /* _CIFS_UNICODE_H */ diff --git a/ANDROID_3.4.5/fs/cifs/cifs_uniupr.h b/ANDROID_3.4.5/fs/cifs/cifs_uniupr.h deleted file mode 100644 index 0ac7c5a8..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifs_uniupr.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2000,2002 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * uniupr.h - Unicode compressed case ranges - * -*/ - -#ifndef UNIUPR_NOUPPER -/* - * Latin upper case - */ -signed char CifsUniUpperTable[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */ - 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 060-06f */ - -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, 0, 0, 0, 0, 0, /* 070-07f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */ - -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 0e0-0ef */ - -32, -32, -32, -32, -32, -32, -32, 0, -32, -32, -32, -32, -32, -32, -32, 121, /* 0f0-0ff */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */ - 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */ - -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */ - 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */ - 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */ - 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */ - -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */ - 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */ - -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */ - 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */ -}; - -/* Upper case range - Greek */ -static signed char UniCaseRangeU03a0[47] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */ - 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 3b0-3bf */ - -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64, - -63, -63, -}; - -/* Upper case range - Cyrillic */ -static signed char UniCaseRangeU0430[48] = { - -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 430-43f */ - -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 440-44f */ - 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, 0, -80, -80, /* 450-45f */ -}; - -/* Upper case range - Extended cyrillic */ -static signed char UniCaseRangeU0490[61] = { - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */ - 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, -}; - -/* Upper case range - Extended latin and greek */ -static signed char UniCaseRangeU1e00[509] = { - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */ - 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */ - 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */ - 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */ - 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */ - 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */ - 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */ - 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */ - 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */ - 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */ - 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112, 126, 126, 0, 0, /* 1f70-1f7f */ - 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */ - 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */ - 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */ - 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */ - 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */ - 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */ - 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */ - 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - -/* Upper case range - Wide latin */ -static signed char UniCaseRangeUff40[27] = { - 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* ff40-ff4f */ - -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -}; - -/* - * Upper Case Range - */ -const struct UniCaseRange CifsUniUpperRange[] = { - {0x03a0, 0x03ce, UniCaseRangeU03a0}, - {0x0430, 0x045f, UniCaseRangeU0430}, - {0x0490, 0x04cc, UniCaseRangeU0490}, - {0x1e00, 0x1ffc, UniCaseRangeU1e00}, - {0xff40, 0xff5a, UniCaseRangeUff40}, - {0} -}; -#endif - -#ifndef UNIUPR_NOLOWER -/* - * Latin lower case - */ -signed char CifsUniLowerTable[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */ - 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 040-04f */ - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, /* 050-05f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */ - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 0c0-0cf */ - 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, /* 0d0-0df */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */ - 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */ - 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */ - 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0, 0, /* 170-17f */ - 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79, 0, /* 180-18f */ - 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */ - 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */ - 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */ - 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */ - 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */ - 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */ -}; - -/* Lower case range - Greek */ -static signed char UniCaseRangeL0380[44] = { - 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */ - 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 390-39f */ - 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, -}; - -/* Lower case range - Cyrillic */ -static signed char UniCaseRangeL0400[48] = { - 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, 80, 80, /* 400-40f */ - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 410-41f */ - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 420-42f */ -}; - -/* Lower case range - Extended cyrillic */ -static signed char UniCaseRangeL0490[60] = { - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */ - 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, -}; - -/* Lower case range - Extended latin and greek */ -static signed char UniCaseRangeL1e00[504] = { - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */ - 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */ - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */ - 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */ - 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */ - 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */ - 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */ - 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */ - 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */ - 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */ - 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */ - 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */ - 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */ - 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0, 0, 0, /* 1fc0-1fcf */ - 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */ - 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0, 0, 0, /* 1fe0-1fef */ - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -/* Lower case range - Wide latin */ -static signed char UniCaseRangeLff20[27] = { - 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* ff20-ff2f */ - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, -}; - -/* - * Lower Case Range - */ -const struct UniCaseRange CifsUniLowerRange[] = { - {0x0380, 0x03ab, UniCaseRangeL0380}, - {0x0400, 0x042f, UniCaseRangeL0400}, - {0x0490, 0x04cb, UniCaseRangeL0490}, - {0x1e00, 0x1ff7, UniCaseRangeL1e00}, - {0xff20, 0xff3a, UniCaseRangeLff20}, - {0} -}; -#endif diff --git a/ANDROID_3.4.5/fs/cifs/cifsacl.c b/ANDROID_3.4.5/fs/cifs/cifsacl.c deleted file mode 100644 index 3cc1b251..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifsacl.c +++ /dev/null @@ -1,1354 +0,0 @@ -/* - * fs/cifs/cifsacl.c - * - * Copyright (C) International Business Machines Corp., 2007,2008 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * Contains the routines for mapping CIFS/NTFS ACLs - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/fs.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/keyctl.h> -#include <linux/key-type.h> -#include <keys/user-type.h> -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsacl.h" -#include "cifsproto.h" -#include "cifs_debug.h" - -/* security id for everyone/world system group */ -static const struct cifs_sid sid_everyone = { - 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; -/* security id for Authenticated Users system group */ -static const struct cifs_sid sid_authusers = { - 1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11)} }; -/* group users */ -static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; - -const struct cred *root_cred; - -static void -shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem, - int *nr_del) -{ - struct rb_node *node; - struct rb_node *tmp; - struct cifs_sid_id *psidid; - - node = rb_first(root); - while (node) { - tmp = node; - node = rb_next(tmp); - psidid = rb_entry(tmp, struct cifs_sid_id, rbnode); - if (nr_to_scan == 0 || *nr_del == nr_to_scan) - ++(*nr_rem); - else { - if (time_after(jiffies, psidid->time + SID_MAP_EXPIRE) - && psidid->refcount == 0) { - rb_erase(tmp, root); - ++(*nr_del); - } else - ++(*nr_rem); - } - } -} - -/* - * Run idmap cache shrinker. - */ -static int -cifs_idmap_shrinker(struct shrinker *shrink, struct shrink_control *sc) -{ - int nr_to_scan = sc->nr_to_scan; - int nr_del = 0; - int nr_rem = 0; - struct rb_root *root; - - root = &uidtree; - spin_lock(&siduidlock); - shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); - spin_unlock(&siduidlock); - - root = &gidtree; - spin_lock(&sidgidlock); - shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); - spin_unlock(&sidgidlock); - - root = &siduidtree; - spin_lock(&uidsidlock); - shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); - spin_unlock(&uidsidlock); - - root = &sidgidtree; - spin_lock(&gidsidlock); - shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); - spin_unlock(&gidsidlock); - - return nr_rem; -} - -static void -sid_rb_insert(struct rb_root *root, unsigned long cid, - struct cifs_sid_id **psidid, char *typestr) -{ - char *strptr; - struct rb_node *node = root->rb_node; - struct rb_node *parent = NULL; - struct rb_node **linkto = &(root->rb_node); - struct cifs_sid_id *lsidid; - - while (node) { - lsidid = rb_entry(node, struct cifs_sid_id, rbnode); - parent = node; - if (cid > lsidid->id) { - linkto = &(node->rb_left); - node = node->rb_left; - } - if (cid < lsidid->id) { - linkto = &(node->rb_right); - node = node->rb_right; - } - } - - (*psidid)->id = cid; - (*psidid)->time = jiffies - (SID_MAP_RETRY + 1); - (*psidid)->refcount = 0; - - sprintf((*psidid)->sidstr, "%s", typestr); - strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr); - sprintf(strptr, "%ld", cid); - - clear_bit(SID_ID_PENDING, &(*psidid)->state); - clear_bit(SID_ID_MAPPED, &(*psidid)->state); - - rb_link_node(&(*psidid)->rbnode, parent, linkto); - rb_insert_color(&(*psidid)->rbnode, root); -} - -static struct cifs_sid_id * -sid_rb_search(struct rb_root *root, unsigned long cid) -{ - struct rb_node *node = root->rb_node; - struct cifs_sid_id *lsidid; - - while (node) { - lsidid = rb_entry(node, struct cifs_sid_id, rbnode); - if (cid > lsidid->id) - node = node->rb_left; - else if (cid < lsidid->id) - node = node->rb_right; - else /* node found */ - return lsidid; - } - - return NULL; -} - -static struct shrinker cifs_shrinker = { - .shrink = cifs_idmap_shrinker, - .seeks = DEFAULT_SEEKS, -}; - -static int -cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) -{ - char *payload; - - payload = kmalloc(datalen, GFP_KERNEL); - if (!payload) - return -ENOMEM; - - memcpy(payload, data, datalen); - key->payload.data = payload; - key->datalen = datalen; - return 0; -} - -static inline void -cifs_idmap_key_destroy(struct key *key) -{ - kfree(key->payload.data); -} - -struct key_type cifs_idmap_key_type = { - .name = "cifs.idmap", - .instantiate = cifs_idmap_key_instantiate, - .destroy = cifs_idmap_key_destroy, - .describe = user_describe, - .match = user_match, -}; - -static void -sid_to_str(struct cifs_sid *sidptr, char *sidstr) -{ - int i; - unsigned long saval; - char *strptr; - - strptr = sidstr; - - sprintf(strptr, "%s", "S"); - strptr = sidstr + strlen(sidstr); - - sprintf(strptr, "-%d", sidptr->revision); - strptr = sidstr + strlen(sidstr); - - for (i = 0; i < 6; ++i) { - if (sidptr->authority[i]) { - sprintf(strptr, "-%d", sidptr->authority[i]); - strptr = sidstr + strlen(sidstr); - } - } - - for (i = 0; i < sidptr->num_subauth; ++i) { - saval = le32_to_cpu(sidptr->sub_auth[i]); - sprintf(strptr, "-%ld", saval); - strptr = sidstr + strlen(sidstr); - } -} - -static void -id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, - struct cifs_sid_id **psidid, char *typestr) -{ - int rc; - char *strptr; - struct rb_node *node = root->rb_node; - struct rb_node *parent = NULL; - struct rb_node **linkto = &(root->rb_node); - struct cifs_sid_id *lsidid; - - while (node) { - lsidid = rb_entry(node, struct cifs_sid_id, rbnode); - parent = node; - rc = compare_sids(sidptr, &((lsidid)->sid)); - if (rc > 0) { - linkto = &(node->rb_left); - node = node->rb_left; - } else if (rc < 0) { - linkto = &(node->rb_right); - node = node->rb_right; - } - } - - memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid)); - (*psidid)->time = jiffies - (SID_MAP_RETRY + 1); - (*psidid)->refcount = 0; - - sprintf((*psidid)->sidstr, "%s", typestr); - strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr); - sid_to_str(&(*psidid)->sid, strptr); - - clear_bit(SID_ID_PENDING, &(*psidid)->state); - clear_bit(SID_ID_MAPPED, &(*psidid)->state); - - rb_link_node(&(*psidid)->rbnode, parent, linkto); - rb_insert_color(&(*psidid)->rbnode, root); -} - -static struct cifs_sid_id * -id_rb_search(struct rb_root *root, struct cifs_sid *sidptr) -{ - int rc; - struct rb_node *node = root->rb_node; - struct cifs_sid_id *lsidid; - - while (node) { - lsidid = rb_entry(node, struct cifs_sid_id, rbnode); - rc = compare_sids(sidptr, &((lsidid)->sid)); - if (rc > 0) { - node = node->rb_left; - } else if (rc < 0) { - node = node->rb_right; - } else /* node found */ - return lsidid; - } - - return NULL; -} - -static int -sidid_pending_wait(void *unused) -{ - schedule(); - return signal_pending(current) ? -ERESTARTSYS : 0; -} - -static int -id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) -{ - int rc = 0; - struct key *sidkey; - const struct cred *saved_cred; - struct cifs_sid *lsid; - struct cifs_sid_id *psidid, *npsidid; - struct rb_root *cidtree; - spinlock_t *cidlock; - - if (sidtype == SIDOWNER) { - cidlock = &siduidlock; - cidtree = &uidtree; - } else if (sidtype == SIDGROUP) { - cidlock = &sidgidlock; - cidtree = &gidtree; - } else - return -EINVAL; - - spin_lock(cidlock); - psidid = sid_rb_search(cidtree, cid); - - if (!psidid) { /* node does not exist, allocate one & attempt adding */ - spin_unlock(cidlock); - npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL); - if (!npsidid) - return -ENOMEM; - - npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL); - if (!npsidid->sidstr) { - kfree(npsidid); - return -ENOMEM; - } - - spin_lock(cidlock); - psidid = sid_rb_search(cidtree, cid); - if (psidid) { /* node happened to get inserted meanwhile */ - ++psidid->refcount; - spin_unlock(cidlock); - kfree(npsidid->sidstr); - kfree(npsidid); - } else { - psidid = npsidid; - sid_rb_insert(cidtree, cid, &psidid, - sidtype == SIDOWNER ? "oi:" : "gi:"); - ++psidid->refcount; - spin_unlock(cidlock); - } - } else { - ++psidid->refcount; - spin_unlock(cidlock); - } - - /* - * If we are here, it is safe to access psidid and its fields - * since a reference was taken earlier while holding the spinlock. - * A reference on the node is put without holding the spinlock - * and it is OK to do so in this case, shrinker will not erase - * this node until all references are put and we do not access - * any fields of the node after a reference is put . - */ - if (test_bit(SID_ID_MAPPED, &psidid->state)) { - memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); - psidid->time = jiffies; /* update ts for accessing */ - goto id_sid_out; - } - - if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) { - rc = -EINVAL; - goto id_sid_out; - } - - if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) { - saved_cred = override_creds(root_cred); - sidkey = request_key(&cifs_idmap_key_type, psidid->sidstr, ""); - if (IS_ERR(sidkey)) { - rc = -EINVAL; - cFYI(1, "%s: Can't map and id to a SID", __func__); - } else { - lsid = (struct cifs_sid *)sidkey->payload.data; - memcpy(&psidid->sid, lsid, - sidkey->datalen < sizeof(struct cifs_sid) ? - sidkey->datalen : sizeof(struct cifs_sid)); - memcpy(ssid, &psidid->sid, - sidkey->datalen < sizeof(struct cifs_sid) ? - sidkey->datalen : sizeof(struct cifs_sid)); - set_bit(SID_ID_MAPPED, &psidid->state); - key_put(sidkey); - kfree(psidid->sidstr); - } - psidid->time = jiffies; /* update ts for accessing */ - revert_creds(saved_cred); - clear_bit(SID_ID_PENDING, &psidid->state); - wake_up_bit(&psidid->state, SID_ID_PENDING); - } else { - rc = wait_on_bit(&psidid->state, SID_ID_PENDING, - sidid_pending_wait, TASK_INTERRUPTIBLE); - if (rc) { - cFYI(1, "%s: sidid_pending_wait interrupted %d", - __func__, rc); - --psidid->refcount; - return rc; - } - if (test_bit(SID_ID_MAPPED, &psidid->state)) - memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); - else - rc = -EINVAL; - } -id_sid_out: - --psidid->refcount; - return rc; -} - -static int -sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, - struct cifs_fattr *fattr, uint sidtype) -{ - int rc; - unsigned long cid; - struct key *idkey; - const struct cred *saved_cred; - struct cifs_sid_id *psidid, *npsidid; - struct rb_root *cidtree; - spinlock_t *cidlock; - - if (sidtype == SIDOWNER) { - cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */ - cidlock = &siduidlock; - cidtree = &uidtree; - } else if (sidtype == SIDGROUP) { - cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */ - cidlock = &sidgidlock; - cidtree = &gidtree; - } else - return -ENOENT; - - spin_lock(cidlock); - psidid = id_rb_search(cidtree, psid); - - if (!psidid) { /* node does not exist, allocate one & attempt adding */ - spin_unlock(cidlock); - npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL); - if (!npsidid) - return -ENOMEM; - - npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL); - if (!npsidid->sidstr) { - kfree(npsidid); - return -ENOMEM; - } - - spin_lock(cidlock); - psidid = id_rb_search(cidtree, psid); - if (psidid) { /* node happened to get inserted meanwhile */ - ++psidid->refcount; - spin_unlock(cidlock); - kfree(npsidid->sidstr); - kfree(npsidid); - } else { - psidid = npsidid; - id_rb_insert(cidtree, psid, &psidid, - sidtype == SIDOWNER ? "os:" : "gs:"); - ++psidid->refcount; - spin_unlock(cidlock); - } - } else { - ++psidid->refcount; - spin_unlock(cidlock); - } - - /* - * If we are here, it is safe to access psidid and its fields - * since a reference was taken earlier while holding the spinlock. - * A reference on the node is put without holding the spinlock - * and it is OK to do so in this case, shrinker will not erase - * this node until all references are put and we do not access - * any fields of the node after a reference is put . - */ - if (test_bit(SID_ID_MAPPED, &psidid->state)) { - cid = psidid->id; - psidid->time = jiffies; /* update ts for accessing */ - goto sid_to_id_out; - } - - if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) - goto sid_to_id_out; - - if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) { - saved_cred = override_creds(root_cred); - idkey = request_key(&cifs_idmap_key_type, psidid->sidstr, ""); - if (IS_ERR(idkey)) - cFYI(1, "%s: Can't map SID to an id", __func__); - else { - cid = *(unsigned long *)idkey->payload.value; - psidid->id = cid; - set_bit(SID_ID_MAPPED, &psidid->state); - key_put(idkey); - kfree(psidid->sidstr); - } - revert_creds(saved_cred); - psidid->time = jiffies; /* update ts for accessing */ - clear_bit(SID_ID_PENDING, &psidid->state); - wake_up_bit(&psidid->state, SID_ID_PENDING); - } else { - rc = wait_on_bit(&psidid->state, SID_ID_PENDING, - sidid_pending_wait, TASK_INTERRUPTIBLE); - if (rc) { - cFYI(1, "%s: sidid_pending_wait interrupted %d", - __func__, rc); - --psidid->refcount; /* decremented without spinlock */ - return rc; - } - if (test_bit(SID_ID_MAPPED, &psidid->state)) - cid = psidid->id; - } - -sid_to_id_out: - --psidid->refcount; /* decremented without spinlock */ - if (sidtype == SIDOWNER) - fattr->cf_uid = cid; - else - fattr->cf_gid = cid; - - return 0; -} - -int -init_cifs_idmap(void) -{ - struct cred *cred; - struct key *keyring; - int ret; - - cFYI(1, "Registering the %s key type\n", cifs_idmap_key_type.name); - - /* create an override credential set with a special thread keyring in - * which requests are cached - * - * this is used to prevent malicious redirections from being installed - * with add_key(). - */ - cred = prepare_kernel_cred(NULL); - if (!cred) - return -ENOMEM; - - keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred, - (KEY_POS_ALL & ~KEY_POS_SETATTR) | - KEY_USR_VIEW | KEY_USR_READ, - KEY_ALLOC_NOT_IN_QUOTA); - if (IS_ERR(keyring)) { - ret = PTR_ERR(keyring); - goto failed_put_cred; - } - - ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL); - if (ret < 0) - goto failed_put_key; - - ret = register_key_type(&cifs_idmap_key_type); - if (ret < 0) - goto failed_put_key; - - /* instruct request_key() to use this special keyring as a cache for - * the results it looks up */ - set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); - cred->thread_keyring = keyring; - cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; - root_cred = cred; - - spin_lock_init(&siduidlock); - uidtree = RB_ROOT; - spin_lock_init(&sidgidlock); - gidtree = RB_ROOT; - - spin_lock_init(&uidsidlock); - siduidtree = RB_ROOT; - spin_lock_init(&gidsidlock); - sidgidtree = RB_ROOT; - register_shrinker(&cifs_shrinker); - - cFYI(1, "cifs idmap keyring: %d\n", key_serial(keyring)); - return 0; - -failed_put_key: - key_put(keyring); -failed_put_cred: - put_cred(cred); - return ret; -} - -void -exit_cifs_idmap(void) -{ - key_revoke(root_cred->thread_keyring); - unregister_key_type(&cifs_idmap_key_type); - put_cred(root_cred); - unregister_shrinker(&cifs_shrinker); - cFYI(1, "Unregistered %s key type\n", cifs_idmap_key_type.name); -} - -void -cifs_destroy_idmaptrees(void) -{ - struct rb_root *root; - struct rb_node *node; - - root = &uidtree; - spin_lock(&siduidlock); - while ((node = rb_first(root))) - rb_erase(node, root); - spin_unlock(&siduidlock); - - root = &gidtree; - spin_lock(&sidgidlock); - while ((node = rb_first(root))) - rb_erase(node, root); - spin_unlock(&sidgidlock); - - root = &siduidtree; - spin_lock(&uidsidlock); - while ((node = rb_first(root))) - rb_erase(node, root); - spin_unlock(&uidsidlock); - - root = &sidgidtree; - spin_lock(&gidsidlock); - while ((node = rb_first(root))) - rb_erase(node, root); - spin_unlock(&gidsidlock); -} - -/* if the two SIDs (roughly equivalent to a UUID for a user or group) are - the same returns 1, if they do not match returns 0 */ -int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) -{ - int i; - int num_subauth, num_sat, num_saw; - - if ((!ctsid) || (!cwsid)) - return 1; - - /* compare the revision */ - if (ctsid->revision != cwsid->revision) { - if (ctsid->revision > cwsid->revision) - return 1; - else - return -1; - } - - /* compare all of the six auth values */ - for (i = 0; i < 6; ++i) { - if (ctsid->authority[i] != cwsid->authority[i]) { - if (ctsid->authority[i] > cwsid->authority[i]) - return 1; - else - return -1; - } - } - - /* compare all of the subauth values if any */ - num_sat = ctsid->num_subauth; - num_saw = cwsid->num_subauth; - num_subauth = num_sat < num_saw ? num_sat : num_saw; - if (num_subauth) { - for (i = 0; i < num_subauth; ++i) { - if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) { - if (le32_to_cpu(ctsid->sub_auth[i]) > - le32_to_cpu(cwsid->sub_auth[i])) - return 1; - else - return -1; - } - } - } - - return 0; /* sids compare/match */ -} - - -/* copy ntsd, owner sid, and group sid from a security descriptor to another */ -static void copy_sec_desc(const struct cifs_ntsd *pntsd, - struct cifs_ntsd *pnntsd, __u32 sidsoffset) -{ - int i; - - struct cifs_sid *owner_sid_ptr, *group_sid_ptr; - struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr; - - /* copy security descriptor control portion */ - pnntsd->revision = pntsd->revision; - pnntsd->type = pntsd->type; - pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd)); - pnntsd->sacloffset = 0; - pnntsd->osidoffset = cpu_to_le32(sidsoffset); - pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid)); - - /* copy owner sid */ - owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + - le32_to_cpu(pntsd->osidoffset)); - nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset); - - nowner_sid_ptr->revision = owner_sid_ptr->revision; - nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth; - for (i = 0; i < 6; i++) - nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i]; - for (i = 0; i < 5; i++) - nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i]; - - /* copy group sid */ - group_sid_ptr = (struct cifs_sid *)((char *)pntsd + - le32_to_cpu(pntsd->gsidoffset)); - ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset + - sizeof(struct cifs_sid)); - - ngroup_sid_ptr->revision = group_sid_ptr->revision; - ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth; - for (i = 0; i < 6; i++) - ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i]; - for (i = 0; i < 5; i++) - ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i]; - - return; -} - - -/* - change posix mode to reflect permissions - pmode is the existing mode (we only want to overwrite part of this - bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007 -*/ -static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode, - umode_t *pbits_to_set) -{ - __u32 flags = le32_to_cpu(ace_flags); - /* the order of ACEs is important. The canonical order is to begin with - DENY entries followed by ALLOW, otherwise an allow entry could be - encountered first, making the subsequent deny entry like "dead code" - which would be superflous since Windows stops when a match is made - for the operation you are trying to perform for your user */ - - /* For deny ACEs we change the mask so that subsequent allow access - control entries do not turn on the bits we are denying */ - if (type == ACCESS_DENIED) { - if (flags & GENERIC_ALL) - *pbits_to_set &= ~S_IRWXUGO; - - if ((flags & GENERIC_WRITE) || - ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) - *pbits_to_set &= ~S_IWUGO; - if ((flags & GENERIC_READ) || - ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) - *pbits_to_set &= ~S_IRUGO; - if ((flags & GENERIC_EXECUTE) || - ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) - *pbits_to_set &= ~S_IXUGO; - return; - } else if (type != ACCESS_ALLOWED) { - cERROR(1, "unknown access control type %d", type); - return; - } - /* else ACCESS_ALLOWED type */ - - if (flags & GENERIC_ALL) { - *pmode |= (S_IRWXUGO & (*pbits_to_set)); - cFYI(DBG2, "all perms"); - return; - } - if ((flags & GENERIC_WRITE) || - ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) - *pmode |= (S_IWUGO & (*pbits_to_set)); - if ((flags & GENERIC_READ) || - ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) - *pmode |= (S_IRUGO & (*pbits_to_set)); - if ((flags & GENERIC_EXECUTE) || - ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) - *pmode |= (S_IXUGO & (*pbits_to_set)); - - cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode); - return; -} - -/* - Generate access flags to reflect permissions mode is the existing mode. - This function is called for every ACE in the DACL whose SID matches - with either owner or group or everyone. -*/ - -static void mode_to_access_flags(umode_t mode, umode_t bits_to_use, - __u32 *pace_flags) -{ - /* reset access mask */ - *pace_flags = 0x0; - - /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */ - mode &= bits_to_use; - - /* check for R/W/X UGO since we do not know whose flags - is this but we have cleared all the bits sans RWX for - either user or group or other as per bits_to_use */ - if (mode & S_IRUGO) - *pace_flags |= SET_FILE_READ_RIGHTS; - if (mode & S_IWUGO) - *pace_flags |= SET_FILE_WRITE_RIGHTS; - if (mode & S_IXUGO) - *pace_flags |= SET_FILE_EXEC_RIGHTS; - - cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags); - return; -} - -static __u16 fill_ace_for_sid(struct cifs_ace *pntace, - const struct cifs_sid *psid, __u64 nmode, umode_t bits) -{ - int i; - __u16 size = 0; - __u32 access_req = 0; - - pntace->type = ACCESS_ALLOWED; - pntace->flags = 0x0; - mode_to_access_flags(nmode, bits, &access_req); - if (!access_req) - access_req = SET_MINIMUM_RIGHTS; - pntace->access_req = cpu_to_le32(access_req); - - pntace->sid.revision = psid->revision; - pntace->sid.num_subauth = psid->num_subauth; - for (i = 0; i < 6; i++) - pntace->sid.authority[i] = psid->authority[i]; - for (i = 0; i < psid->num_subauth; i++) - pntace->sid.sub_auth[i] = psid->sub_auth[i]; - - size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4); - pntace->size = cpu_to_le16(size); - - return size; -} - - -#ifdef CONFIG_CIFS_DEBUG2 -static void dump_ace(struct cifs_ace *pace, char *end_of_acl) -{ - int num_subauth; - - /* validate that we do not go past end of acl */ - - if (le16_to_cpu(pace->size) < 16) { - cERROR(1, "ACE too small %d", le16_to_cpu(pace->size)); - return; - } - - if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) { - cERROR(1, "ACL too small to parse ACE"); - return; - } - - num_subauth = pace->sid.num_subauth; - if (num_subauth) { - int i; - cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d", - pace->sid.revision, pace->sid.num_subauth, pace->type, - pace->flags, le16_to_cpu(pace->size)); - for (i = 0; i < num_subauth; ++i) { - cFYI(1, "ACE sub_auth[%d]: 0x%x", i, - le32_to_cpu(pace->sid.sub_auth[i])); - } - - /* BB add length check to make sure that we do not have huge - num auths and therefore go off the end */ - } - - return; -} -#endif - - -static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, - struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, - struct cifs_fattr *fattr) -{ - int i; - int num_aces = 0; - int acl_size; - char *acl_base; - struct cifs_ace **ppace; - - /* BB need to add parm so we can store the SID BB */ - - if (!pdacl) { - /* no DACL in the security descriptor, set - all the permissions for user/group/other */ - fattr->cf_mode |= S_IRWXUGO; - return; - } - - /* validate that we do not go past end of acl */ - if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) { - cERROR(1, "ACL too small to parse DACL"); - return; - } - - cFYI(DBG2, "DACL revision %d size %d num aces %d", - le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size), - le32_to_cpu(pdacl->num_aces)); - - /* reset rwx permissions for user/group/other. - Also, if num_aces is 0 i.e. DACL has no ACEs, - user/group/other have no permissions */ - fattr->cf_mode &= ~(S_IRWXUGO); - - acl_base = (char *)pdacl; - acl_size = sizeof(struct cifs_acl); - - num_aces = le32_to_cpu(pdacl->num_aces); - if (num_aces > 0) { - umode_t user_mask = S_IRWXU; - umode_t group_mask = S_IRWXG; - umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO; - - if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *)) - return; - ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), - GFP_KERNEL); - if (!ppace) { - cERROR(1, "DACL memory allocation error"); - return; - } - - for (i = 0; i < num_aces; ++i) { - ppace[i] = (struct cifs_ace *) (acl_base + acl_size); -#ifdef CONFIG_CIFS_DEBUG2 - dump_ace(ppace[i], end_of_acl); -#endif - if (compare_sids(&(ppace[i]->sid), pownersid) == 0) - access_flags_to_mode(ppace[i]->access_req, - ppace[i]->type, - &fattr->cf_mode, - &user_mask); - if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) - access_flags_to_mode(ppace[i]->access_req, - ppace[i]->type, - &fattr->cf_mode, - &group_mask); - if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) - access_flags_to_mode(ppace[i]->access_req, - ppace[i]->type, - &fattr->cf_mode, - &other_mask); - if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0) - access_flags_to_mode(ppace[i]->access_req, - ppace[i]->type, - &fattr->cf_mode, - &other_mask); - - -/* memcpy((void *)(&(cifscred->aces[i])), - (void *)ppace[i], - sizeof(struct cifs_ace)); */ - - acl_base = (char *)ppace[i]; - acl_size = le16_to_cpu(ppace[i]->size); - } - - kfree(ppace); - } - - return; -} - - -static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, - struct cifs_sid *pgrpsid, __u64 nmode) -{ - u16 size = 0; - struct cifs_acl *pnndacl; - - pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl)); - - size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size), - pownersid, nmode, S_IRWXU); - size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), - pgrpsid, nmode, S_IRWXG); - size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), - &sid_everyone, nmode, S_IRWXO); - - pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl)); - pndacl->num_aces = cpu_to_le32(3); - - return 0; -} - - -static int parse_sid(struct cifs_sid *psid, char *end_of_acl) -{ - /* BB need to add parm so we can store the SID BB */ - - /* validate that we do not go past end of ACL - sid must be at least 8 - bytes long (assuming no sub-auths - e.g. the null SID */ - if (end_of_acl < (char *)psid + 8) { - cERROR(1, "ACL too small to parse SID %p", psid); - return -EINVAL; - } - - if (psid->num_subauth) { -#ifdef CONFIG_CIFS_DEBUG2 - int i; - cFYI(1, "SID revision %d num_auth %d", - psid->revision, psid->num_subauth); - - for (i = 0; i < psid->num_subauth; i++) { - cFYI(1, "SID sub_auth[%d]: 0x%x ", i, - le32_to_cpu(psid->sub_auth[i])); - } - - /* BB add length check to make sure that we do not have huge - num auths and therefore go off the end */ - cFYI(1, "RID 0x%x", - le32_to_cpu(psid->sub_auth[psid->num_subauth-1])); -#endif - } - - return 0; -} - - -/* Convert CIFS ACL to POSIX form */ -static int parse_sec_desc(struct cifs_sb_info *cifs_sb, - struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr) -{ - int rc = 0; - struct cifs_sid *owner_sid_ptr, *group_sid_ptr; - struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ - char *end_of_acl = ((char *)pntsd) + acl_len; - __u32 dacloffset; - - if (pntsd == NULL) - return -EIO; - - owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + - le32_to_cpu(pntsd->osidoffset)); - group_sid_ptr = (struct cifs_sid *)((char *)pntsd + - le32_to_cpu(pntsd->gsidoffset)); - dacloffset = le32_to_cpu(pntsd->dacloffset); - dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset); - cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x " - "sacloffset 0x%x dacloffset 0x%x", - pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset), - le32_to_cpu(pntsd->gsidoffset), - le32_to_cpu(pntsd->sacloffset), dacloffset); -/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */ - rc = parse_sid(owner_sid_ptr, end_of_acl); - if (rc) { - cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc); - return rc; - } - rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER); - if (rc) { - cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc); - return rc; - } - - rc = parse_sid(group_sid_ptr, end_of_acl); - if (rc) { - cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc); - return rc; - } - rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP); - if (rc) { - cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc); - return rc; - } - - if (dacloffset) - parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, - group_sid_ptr, fattr); - else - cFYI(1, "no ACL"); /* BB grant all or default perms? */ - - return rc; -} - -/* Convert permission bits from mode to equivalent CIFS ACL */ -static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, - __u32 secdesclen, __u64 nmode, uid_t uid, gid_t gid, int *aclflag) -{ - int rc = 0; - __u32 dacloffset; - __u32 ndacloffset; - __u32 sidsoffset; - struct cifs_sid *owner_sid_ptr, *group_sid_ptr; - struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr; - struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */ - struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */ - - if (nmode != NO_CHANGE_64) { /* chmod */ - owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + - le32_to_cpu(pntsd->osidoffset)); - group_sid_ptr = (struct cifs_sid *)((char *)pntsd + - le32_to_cpu(pntsd->gsidoffset)); - dacloffset = le32_to_cpu(pntsd->dacloffset); - dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset); - ndacloffset = sizeof(struct cifs_ntsd); - ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset); - ndacl_ptr->revision = dacl_ptr->revision; - ndacl_ptr->size = 0; - ndacl_ptr->num_aces = 0; - - rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, - nmode); - sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size); - /* copy sec desc control portion & owner and group sids */ - copy_sec_desc(pntsd, pnntsd, sidsoffset); - *aclflag = CIFS_ACL_DACL; - } else { - memcpy(pnntsd, pntsd, secdesclen); - if (uid != NO_CHANGE_32) { /* chown */ - owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + - le32_to_cpu(pnntsd->osidoffset)); - nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid), - GFP_KERNEL); - if (!nowner_sid_ptr) - return -ENOMEM; - rc = id_to_sid(uid, SIDOWNER, nowner_sid_ptr); - if (rc) { - cFYI(1, "%s: Mapping error %d for owner id %d", - __func__, rc, uid); - kfree(nowner_sid_ptr); - return rc; - } - memcpy(owner_sid_ptr, nowner_sid_ptr, - sizeof(struct cifs_sid)); - kfree(nowner_sid_ptr); - *aclflag = CIFS_ACL_OWNER; - } - if (gid != NO_CHANGE_32) { /* chgrp */ - group_sid_ptr = (struct cifs_sid *)((char *)pnntsd + - le32_to_cpu(pnntsd->gsidoffset)); - ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid), - GFP_KERNEL); - if (!ngroup_sid_ptr) - return -ENOMEM; - rc = id_to_sid(gid, SIDGROUP, ngroup_sid_ptr); - if (rc) { - cFYI(1, "%s: Mapping error %d for group id %d", - __func__, rc, gid); - kfree(ngroup_sid_ptr); - return rc; - } - memcpy(group_sid_ptr, ngroup_sid_ptr, - sizeof(struct cifs_sid)); - kfree(ngroup_sid_ptr); - *aclflag = CIFS_ACL_GROUP; - } - } - - return rc; -} - -static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, - __u16 fid, u32 *pacllen) -{ - struct cifs_ntsd *pntsd = NULL; - int xid, rc; - struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); - - if (IS_ERR(tlink)) - return ERR_CAST(tlink); - - xid = GetXid(); - rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen); - FreeXid(xid); - - cifs_put_tlink(tlink); - - cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen); - if (rc) - return ERR_PTR(rc); - return pntsd; -} - -static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, - const char *path, u32 *pacllen) -{ - struct cifs_ntsd *pntsd = NULL; - int oplock = 0; - int xid, rc, create_options = 0; - __u16 fid; - struct cifs_tcon *tcon; - struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); - - if (IS_ERR(tlink)) - return ERR_CAST(tlink); - - tcon = tlink_tcon(tlink); - xid = GetXid(); - - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - - rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, - create_options, &fid, &oplock, NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (!rc) { - rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); - CIFSSMBClose(xid, tcon, fid); - } - - cifs_put_tlink(tlink); - FreeXid(xid); - - cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen); - if (rc) - return ERR_PTR(rc); - return pntsd; -} - -/* Retrieve an ACL from the server */ -struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, - struct inode *inode, const char *path, - u32 *pacllen) -{ - struct cifs_ntsd *pntsd = NULL; - struct cifsFileInfo *open_file = NULL; - - if (inode) - open_file = find_readable_file(CIFS_I(inode), true); - if (!open_file) - return get_cifs_acl_by_path(cifs_sb, path, pacllen); - - pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen); - cifsFileInfo_put(open_file); - return pntsd; -} - - /* Set an ACL on the server */ -int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, - struct inode *inode, const char *path, int aclflag) -{ - int oplock = 0; - int xid, rc, access_flags, create_options = 0; - __u16 fid; - struct cifs_tcon *tcon; - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); - - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - - tcon = tlink_tcon(tlink); - xid = GetXid(); - - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - - if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP) - access_flags = WRITE_OWNER; - else - access_flags = WRITE_DAC; - - rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags, - create_options, &fid, &oplock, NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc) { - cERROR(1, "Unable to open file to set ACL"); - goto out; - } - - rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag); - cFYI(DBG2, "SetCIFSACL rc = %d", rc); - - CIFSSMBClose(xid, tcon, fid); -out: - FreeXid(xid); - cifs_put_tlink(tlink); - return rc; -} - -/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ -int -cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, - struct inode *inode, const char *path, const __u16 *pfid) -{ - struct cifs_ntsd *pntsd = NULL; - u32 acllen = 0; - int rc = 0; - - cFYI(DBG2, "converting ACL to mode for %s", path); - - if (pfid) - pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen); - else - pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen); - - /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ - if (IS_ERR(pntsd)) { - rc = PTR_ERR(pntsd); - cERROR(1, "%s: error %d getting sec desc", __func__, rc); - } else { - rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr); - kfree(pntsd); - if (rc) - cERROR(1, "parse sec desc failed rc = %d", rc); - } - - return rc; -} - -/* Convert mode bits to an ACL so we can update the ACL on the server */ -int -id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, - uid_t uid, gid_t gid) -{ - int rc = 0; - int aclflag = CIFS_ACL_DACL; /* default flag to set */ - __u32 secdesclen = 0; - struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */ - struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */ - - cFYI(DBG2, "set ACL from mode for %s", path); - - /* Get the security descriptor */ - pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen); - - /* Add three ACEs for owner, group, everyone getting rid of - other ACEs as chmod disables ACEs and set the security descriptor */ - - if (IS_ERR(pntsd)) { - rc = PTR_ERR(pntsd); - cERROR(1, "%s: error %d getting sec desc", __func__, rc); - } else { - /* allocate memory for the smb header, - set security descriptor request security descriptor - parameters, and secuirty descriptor itself */ - - secdesclen = secdesclen < DEFSECDESCLEN ? - DEFSECDESCLEN : secdesclen; - pnntsd = kmalloc(secdesclen, GFP_KERNEL); - if (!pnntsd) { - cERROR(1, "Unable to allocate security descriptor"); - kfree(pntsd); - return -ENOMEM; - } - - rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid, - &aclflag); - - cFYI(DBG2, "build_sec_desc rc: %d", rc); - - if (!rc) { - /* Set the security descriptor */ - rc = set_cifs_acl(pnntsd, secdesclen, inode, - path, aclflag); - cFYI(DBG2, "set_cifs_acl rc: %d", rc); - } - - kfree(pnntsd); - kfree(pntsd); - } - - return rc; -} diff --git a/ANDROID_3.4.5/fs/cifs/cifsacl.h b/ANDROID_3.4.5/fs/cifs/cifsacl.h deleted file mode 100644 index 5c902c7c..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifsacl.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * fs/cifs/cifsacl.h - * - * Copyright (c) International Business Machines Corp., 2007 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _CIFSACL_H -#define _CIFSACL_H - - -#define NUM_AUTHS 6 /* number of authority fields */ -#define NUM_SUBAUTHS 5 /* number of sub authority fields */ -#define NUM_WK_SIDS 7 /* number of well known sids */ -#define SIDNAMELENGTH 20 /* long enough for the ones we care about */ -#define DEFSECDESCLEN 192 /* sec desc len contaiting a dacl with three aces */ - -#define READ_BIT 0x4 -#define WRITE_BIT 0x2 -#define EXEC_BIT 0x1 - -#define UBITSHIFT 6 -#define GBITSHIFT 3 - -#define ACCESS_ALLOWED 0 -#define ACCESS_DENIED 1 - -#define SIDOWNER 1 -#define SIDGROUP 2 -#define SIDLEN 150 /* S- 1 revision- 6 authorities- max 5 sub authorities */ - -#define SID_ID_MAPPED 0 -#define SID_ID_PENDING 1 -#define SID_MAP_EXPIRE (3600 * HZ) /* map entry expires after one hour */ -#define SID_MAP_RETRY (300 * HZ) /* wait 5 minutes for next attempt to map */ - -struct cifs_ntsd { - __le16 revision; /* revision level */ - __le16 type; - __le32 osidoffset; - __le32 gsidoffset; - __le32 sacloffset; - __le32 dacloffset; -} __attribute__((packed)); - -struct cifs_sid { - __u8 revision; /* revision level */ - __u8 num_subauth; - __u8 authority[6]; - __le32 sub_auth[5]; /* sub_auth[num_subauth] */ -} __attribute__((packed)); - -struct cifs_acl { - __le16 revision; /* revision level */ - __le16 size; - __le32 num_aces; -} __attribute__((packed)); - -struct cifs_ace { - __u8 type; - __u8 flags; - __le16 size; - __le32 access_req; - struct cifs_sid sid; /* ie UUID of user or group who gets these perms */ -} __attribute__((packed)); - -struct cifs_wksid { - struct cifs_sid cifssid; - char sidname[SIDNAMELENGTH]; -} __attribute__((packed)); - -struct cifs_sid_id { - unsigned int refcount; /* increment with spinlock, decrement without */ - unsigned long id; - unsigned long time; - unsigned long state; - char *sidstr; - struct rb_node rbnode; - struct cifs_sid sid; -}; - -#ifdef __KERNEL__ -extern struct key_type cifs_idmap_key_type; -extern const struct cred *root_cred; -#endif /* KERNEL */ - -extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *); - -#endif /* _CIFSACL_H */ diff --git a/ANDROID_3.4.5/fs/cifs/cifsencrypt.c b/ANDROID_3.4.5/fs/cifs/cifsencrypt.c deleted file mode 100644 index 63c460e5..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifsencrypt.c +++ /dev/null @@ -1,754 +0,0 @@ -/* - * fs/cifs/cifsencrypt.c - * - * Copyright (C) International Business Machines Corp., 2005,2006 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/fs.h> -#include <linux/slab.h> -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifs_debug.h" -#include "cifs_unicode.h" -#include "cifsproto.h" -#include "ntlmssp.h" -#include <linux/ctype.h> -#include <linux/random.h> - -/* - * Calculate and return the CIFS signature based on the mac key and SMB PDU. - * The 16 byte signature must be allocated by the caller. Note we only use the - * 1st eight bytes and that the smb header signature field on input contains - * the sequence number before this function is called. Also, this function - * should be called with the server->srv_mutex held. - */ -static int cifs_calc_signature(const struct kvec *iov, int n_vec, - struct TCP_Server_Info *server, char *signature) -{ - int i; - int rc; - - if (iov == NULL || signature == NULL || server == NULL) - return -EINVAL; - - if (!server->secmech.sdescmd5) { - cERROR(1, "%s: Can't generate signature\n", __func__); - return -1; - } - - rc = crypto_shash_init(&server->secmech.sdescmd5->shash); - if (rc) { - cERROR(1, "%s: Could not init md5\n", __func__); - return rc; - } - - rc = crypto_shash_update(&server->secmech.sdescmd5->shash, - server->session_key.response, server->session_key.len); - if (rc) { - cERROR(1, "%s: Could not update with response\n", __func__); - return rc; - } - - for (i = 0; i < n_vec; i++) { - if (iov[i].iov_len == 0) - continue; - if (iov[i].iov_base == NULL) { - cERROR(1, "null iovec entry"); - return -EIO; - } - /* The first entry includes a length field (which does not get - signed that occupies the first 4 bytes before the header */ - if (i == 0) { - if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ - break; /* nothing to sign or corrupt header */ - rc = - crypto_shash_update(&server->secmech.sdescmd5->shash, - iov[i].iov_base + 4, iov[i].iov_len - 4); - } else { - rc = - crypto_shash_update(&server->secmech.sdescmd5->shash, - iov[i].iov_base, iov[i].iov_len); - } - if (rc) { - cERROR(1, "%s: Could not update with payload\n", - __func__); - return rc; - } - } - - rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature); - if (rc) - cERROR(1, "%s: Could not generate md5 hash\n", __func__); - - return rc; -} - -/* must be called with server->srv_mutex held */ -int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, - __u32 *pexpected_response_sequence_number) -{ - int rc = 0; - char smb_signature[20]; - struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base; - - if ((cifs_pdu == NULL) || (server == NULL)) - return -EINVAL; - - if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) || - server->tcpStatus == CifsNeedNegotiate) - return rc; - - if (!server->session_estab) { - memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8); - return rc; - } - - cifs_pdu->Signature.Sequence.SequenceNumber = - cpu_to_le32(server->sequence_number); - cifs_pdu->Signature.Sequence.Reserved = 0; - - *pexpected_response_sequence_number = server->sequence_number++; - server->sequence_number++; - - rc = cifs_calc_signature(iov, n_vec, server, smb_signature); - if (rc) - memset(cifs_pdu->Signature.SecuritySignature, 0, 8); - else - memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8); - - return rc; -} - -/* must be called with server->srv_mutex held */ -int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, - __u32 *pexpected_response_sequence_number) -{ - struct kvec iov; - - iov.iov_base = cifs_pdu; - iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4; - - return cifs_sign_smb2(&iov, 1, server, - pexpected_response_sequence_number); -} - -int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov, - struct TCP_Server_Info *server, - __u32 expected_sequence_number) -{ - unsigned int rc; - char server_response_sig[8]; - char what_we_think_sig_should_be[20]; - struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base; - - if (cifs_pdu == NULL || server == NULL) - return -EINVAL; - - if (!server->session_estab) - return 0; - - if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) { - struct smb_com_lock_req *pSMB = - (struct smb_com_lock_req *)cifs_pdu; - if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE) - return 0; - } - - /* BB what if signatures are supposed to be on for session but - server does not send one? BB */ - - /* Do not need to verify session setups with signature "BSRSPYL " */ - if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0) - cFYI(1, "dummy signature received for smb command 0x%x", - cifs_pdu->Command); - - /* save off the origiginal signature so we can modify the smb and check - its signature against what the server sent */ - memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8); - - cifs_pdu->Signature.Sequence.SequenceNumber = - cpu_to_le32(expected_sequence_number); - cifs_pdu->Signature.Sequence.Reserved = 0; - - mutex_lock(&server->srv_mutex); - rc = cifs_calc_signature(iov, nr_iov, server, - what_we_think_sig_should_be); - mutex_unlock(&server->srv_mutex); - - if (rc) - return rc; - -/* cifs_dump_mem("what we think it should be: ", - what_we_think_sig_should_be, 16); */ - - if (memcmp(server_response_sig, what_we_think_sig_should_be, 8)) - return -EACCES; - else - return 0; - -} - -/* first calculate 24 bytes ntlm response and then 16 byte session key */ -int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp) -{ - int rc = 0; - unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE; - char temp_key[CIFS_SESS_KEY_SIZE]; - - if (!ses) - return -EINVAL; - - ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL); - if (!ses->auth_key.response) { - cERROR(1, "NTLM can't allocate (%u bytes) memory", temp_len); - return -ENOMEM; - } - ses->auth_key.len = temp_len; - - rc = SMBNTencrypt(ses->password, ses->server->cryptkey, - ses->auth_key.response + CIFS_SESS_KEY_SIZE, nls_cp); - if (rc) { - cFYI(1, "%s Can't generate NTLM response, error: %d", - __func__, rc); - return rc; - } - - rc = E_md4hash(ses->password, temp_key, nls_cp); - if (rc) { - cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); - return rc; - } - - rc = mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE); - if (rc) - cFYI(1, "%s Can't generate NTLM session key, error: %d", - __func__, rc); - - return rc; -} - -#ifdef CONFIG_CIFS_WEAK_PW_HASH -int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, - char *lnm_session_key) -{ - int i; - int rc; - char password_with_pad[CIFS_ENCPWD_SIZE]; - - memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); - if (password) - strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE); - - if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) { - memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE); - memcpy(lnm_session_key, password_with_pad, - CIFS_ENCPWD_SIZE); - return 0; - } - - /* calculate old style session key */ - /* calling toupper is less broken than repeatedly - calling nls_toupper would be since that will never - work for UTF8, but neither handles multibyte code pages - but the only alternative would be converting to UCS-16 (Unicode) - (using a routine something like UniStrupr) then - uppercasing and then converting back from Unicode - which - would only worth doing it if we knew it were utf8. Basically - utf8 and other multibyte codepages each need their own strupper - function since a byte at a time will ont work. */ - - for (i = 0; i < CIFS_ENCPWD_SIZE; i++) - password_with_pad[i] = toupper(password_with_pad[i]); - - rc = SMBencrypt(password_with_pad, cryptkey, lnm_session_key); - - return rc; -} -#endif /* CIFS_WEAK_PW_HASH */ - -/* Build a proper attribute value/target info pairs blob. - * Fill in netbios and dns domain name and workstation name - * and client time (total five av pairs and + one end of fields indicator. - * Allocate domain name which gets freed when session struct is deallocated. - */ -static int -build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp) -{ - unsigned int dlen; - unsigned int size = 2 * sizeof(struct ntlmssp2_name); - char *defdmname = "WORKGROUP"; - unsigned char *blobptr; - struct ntlmssp2_name *attrptr; - - if (!ses->domainName) { - ses->domainName = kstrdup(defdmname, GFP_KERNEL); - if (!ses->domainName) - return -ENOMEM; - } - - dlen = strlen(ses->domainName); - - /* - * The length of this blob is two times the size of a - * structure (av pair) which holds name/size - * ( for NTLMSSP_AV_NB_DOMAIN_NAME followed by NTLMSSP_AV_EOL ) + - * unicode length of a netbios domain name - */ - ses->auth_key.len = size + 2 * dlen; - ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL); - if (!ses->auth_key.response) { - ses->auth_key.len = 0; - cERROR(1, "Challenge target info allocation failure"); - return -ENOMEM; - } - - blobptr = ses->auth_key.response; - attrptr = (struct ntlmssp2_name *) blobptr; - - /* - * As defined in MS-NTLM 3.3.2, just this av pair field - * is sufficient as part of the temp - */ - attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME); - attrptr->length = cpu_to_le16(2 * dlen); - blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name); - cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp); - - return 0; -} - -/* Server has provided av pairs/target info in the type 2 challenge - * packet and we have plucked it and stored within smb session. - * We parse that blob here to find netbios domain name to be used - * as part of ntlmv2 authentication (in Target String), if not already - * specified on the command line. - * If this function returns without any error but without fetching - * domain name, authentication may fail against some server but - * may not fail against other (those who are not very particular - * about target string i.e. for some, just user name might suffice. - */ -static int -find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp) -{ - unsigned int attrsize; - unsigned int type; - unsigned int onesize = sizeof(struct ntlmssp2_name); - unsigned char *blobptr; - unsigned char *blobend; - struct ntlmssp2_name *attrptr; - - if (!ses->auth_key.len || !ses->auth_key.response) - return 0; - - blobptr = ses->auth_key.response; - blobend = blobptr + ses->auth_key.len; - - while (blobptr + onesize < blobend) { - attrptr = (struct ntlmssp2_name *) blobptr; - type = le16_to_cpu(attrptr->type); - if (type == NTLMSSP_AV_EOL) - break; - blobptr += 2; /* advance attr type */ - attrsize = le16_to_cpu(attrptr->length); - blobptr += 2; /* advance attr size */ - if (blobptr + attrsize > blobend) - break; - if (type == NTLMSSP_AV_NB_DOMAIN_NAME) { - if (!attrsize) - break; - if (!ses->domainName) { - ses->domainName = - kmalloc(attrsize + 1, GFP_KERNEL); - if (!ses->domainName) - return -ENOMEM; - cifs_from_utf16(ses->domainName, - (__le16 *)blobptr, attrsize, attrsize, - nls_cp, false); - break; - } - } - blobptr += attrsize; /* advance attr value */ - } - - return 0; -} - -static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, - const struct nls_table *nls_cp) -{ - int rc = 0; - int len; - char nt_hash[CIFS_NTHASH_SIZE]; - wchar_t *user; - wchar_t *domain; - wchar_t *server; - - if (!ses->server->secmech.sdeschmacmd5) { - cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); - return -1; - } - - /* calculate md4 hash of password */ - E_md4hash(ses->password, nt_hash, nls_cp); - - rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash, - CIFS_NTHASH_SIZE); - if (rc) { - cERROR(1, "%s: Could not set NT Hash as a key", __func__); - return rc; - } - - rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); - if (rc) { - cERROR(1, "calc_ntlmv2_hash: could not init hmacmd5\n"); - return rc; - } - - /* convert ses->user_name to unicode and uppercase */ - len = ses->user_name ? strlen(ses->user_name) : 0; - user = kmalloc(2 + (len * 2), GFP_KERNEL); - if (user == NULL) { - cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n"); - rc = -ENOMEM; - return rc; - } - - if (len) { - len = cifs_strtoUTF16((__le16 *)user, ses->user_name, len, nls_cp); - UniStrupr(user); - } else { - memset(user, '\0', 2); - } - - rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, - (char *)user, 2 * len); - kfree(user); - if (rc) { - cERROR(1, "%s: Could not update with user\n", __func__); - return rc; - } - - /* convert ses->domainName to unicode and uppercase */ - if (ses->domainName) { - len = strlen(ses->domainName); - - domain = kmalloc(2 + (len * 2), GFP_KERNEL); - if (domain == NULL) { - cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure"); - rc = -ENOMEM; - return rc; - } - len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len, - nls_cp); - rc = - crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, - (char *)domain, 2 * len); - kfree(domain); - if (rc) { - cERROR(1, "%s: Could not update with domain\n", - __func__); - return rc; - } - } else if (ses->serverName) { - len = strlen(ses->serverName); - - server = kmalloc(2 + (len * 2), GFP_KERNEL); - if (server == NULL) { - cERROR(1, "calc_ntlmv2_hash: server mem alloc failure"); - rc = -ENOMEM; - return rc; - } - len = cifs_strtoUTF16((__le16 *)server, ses->serverName, len, - nls_cp); - rc = - crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, - (char *)server, 2 * len); - kfree(server); - if (rc) { - cERROR(1, "%s: Could not update with server\n", - __func__); - return rc; - } - } - - rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash, - ntlmv2_hash); - if (rc) - cERROR(1, "%s: Could not generate md5 hash\n", __func__); - - return rc; -} - -static int -CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash) -{ - int rc; - unsigned int offset = CIFS_SESS_KEY_SIZE + 8; - - if (!ses->server->secmech.sdeschmacmd5) { - cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); - return -1; - } - - rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, - ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); - if (rc) { - cERROR(1, "%s: Could not set NTLMV2 Hash as a key", __func__); - return rc; - } - - rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); - if (rc) { - cERROR(1, "CalcNTLMv2_response: could not init hmacmd5"); - return rc; - } - - if (ses->server->secType == RawNTLMSSP) - memcpy(ses->auth_key.response + offset, - ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); - else - memcpy(ses->auth_key.response + offset, - ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); - rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, - ses->auth_key.response + offset, ses->auth_key.len - offset); - if (rc) { - cERROR(1, "%s: Could not update with response\n", __func__); - return rc; - } - - rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash, - ses->auth_key.response + CIFS_SESS_KEY_SIZE); - if (rc) - cERROR(1, "%s: Could not generate md5 hash\n", __func__); - - return rc; -} - - -int -setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) -{ - int rc; - int baselen; - unsigned int tilen; - struct ntlmv2_resp *buf; - char ntlmv2_hash[16]; - unsigned char *tiblob = NULL; /* target info blob */ - - if (ses->server->secType == RawNTLMSSP) { - if (!ses->domainName) { - rc = find_domain_name(ses, nls_cp); - if (rc) { - cERROR(1, "error %d finding domain name", rc); - goto setup_ntlmv2_rsp_ret; - } - } - } else { - rc = build_avpair_blob(ses, nls_cp); - if (rc) { - cERROR(1, "error %d building av pair blob", rc); - goto setup_ntlmv2_rsp_ret; - } - } - - baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp); - tilen = ses->auth_key.len; - tiblob = ses->auth_key.response; - - ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL); - if (!ses->auth_key.response) { - rc = ENOMEM; - ses->auth_key.len = 0; - cERROR(1, "%s: Can't allocate auth blob", __func__); - goto setup_ntlmv2_rsp_ret; - } - ses->auth_key.len += baselen; - - buf = (struct ntlmv2_resp *) - (ses->auth_key.response + CIFS_SESS_KEY_SIZE); - buf->blob_signature = cpu_to_le32(0x00000101); - buf->reserved = 0; - buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); - buf->reserved2 = 0; - - memcpy(ses->auth_key.response + baselen, tiblob, tilen); - - /* calculate ntlmv2_hash */ - rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp); - if (rc) { - cERROR(1, "could not get v2 hash rc %d", rc); - goto setup_ntlmv2_rsp_ret; - } - - /* calculate first part of the client response (CR1) */ - rc = CalcNTLMv2_response(ses, ntlmv2_hash); - if (rc) { - cERROR(1, "Could not calculate CR1 rc: %d", rc); - goto setup_ntlmv2_rsp_ret; - } - - /* now calculate the session key for NTLMv2 */ - rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, - ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); - if (rc) { - cERROR(1, "%s: Could not set NTLMV2 Hash as a key", __func__); - goto setup_ntlmv2_rsp_ret; - } - - rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); - if (rc) { - cERROR(1, "%s: Could not init hmacmd5\n", __func__); - goto setup_ntlmv2_rsp_ret; - } - - rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, - ses->auth_key.response + CIFS_SESS_KEY_SIZE, - CIFS_HMAC_MD5_HASH_SIZE); - if (rc) { - cERROR(1, "%s: Could not update with response\n", __func__); - goto setup_ntlmv2_rsp_ret; - } - - rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash, - ses->auth_key.response); - if (rc) - cERROR(1, "%s: Could not generate md5 hash\n", __func__); - -setup_ntlmv2_rsp_ret: - kfree(tiblob); - - return rc; -} - -int -calc_seckey(struct cifs_ses *ses) -{ - int rc; - struct crypto_blkcipher *tfm_arc4; - struct scatterlist sgin, sgout; - struct blkcipher_desc desc; - unsigned char sec_key[CIFS_SESS_KEY_SIZE]; /* a nonce */ - - get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE); - - tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm_arc4)) { - rc = PTR_ERR(tfm_arc4); - cERROR(1, "could not allocate crypto API arc4\n"); - return rc; - } - - desc.tfm = tfm_arc4; - - rc = crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response, - CIFS_SESS_KEY_SIZE); - if (rc) { - cERROR(1, "%s: Could not set response as a key", __func__); - return rc; - } - - sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE); - sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); - - rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE); - if (rc) { - cERROR(1, "could not encrypt session key rc: %d\n", rc); - crypto_free_blkcipher(tfm_arc4); - return rc; - } - - /* make secondary_key/nonce as session key */ - memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE); - /* and make len as that of session key only */ - ses->auth_key.len = CIFS_SESS_KEY_SIZE; - - crypto_free_blkcipher(tfm_arc4); - - return rc; -} - -void -cifs_crypto_shash_release(struct TCP_Server_Info *server) -{ - if (server->secmech.md5) - crypto_free_shash(server->secmech.md5); - - if (server->secmech.hmacmd5) - crypto_free_shash(server->secmech.hmacmd5); - - kfree(server->secmech.sdeschmacmd5); - - kfree(server->secmech.sdescmd5); -} - -int -cifs_crypto_shash_allocate(struct TCP_Server_Info *server) -{ - int rc; - unsigned int size; - - server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); - if (IS_ERR(server->secmech.hmacmd5)) { - cERROR(1, "could not allocate crypto hmacmd5\n"); - return PTR_ERR(server->secmech.hmacmd5); - } - - server->secmech.md5 = crypto_alloc_shash("md5", 0, 0); - if (IS_ERR(server->secmech.md5)) { - cERROR(1, "could not allocate crypto md5\n"); - rc = PTR_ERR(server->secmech.md5); - goto crypto_allocate_md5_fail; - } - - size = sizeof(struct shash_desc) + - crypto_shash_descsize(server->secmech.hmacmd5); - server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); - if (!server->secmech.sdeschmacmd5) { - cERROR(1, "cifs_crypto_shash_allocate: can't alloc hmacmd5\n"); - rc = -ENOMEM; - goto crypto_allocate_hmacmd5_sdesc_fail; - } - server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5; - server->secmech.sdeschmacmd5->shash.flags = 0x0; - - - size = sizeof(struct shash_desc) + - crypto_shash_descsize(server->secmech.md5); - server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL); - if (!server->secmech.sdescmd5) { - cERROR(1, "cifs_crypto_shash_allocate: can't alloc md5\n"); - rc = -ENOMEM; - goto crypto_allocate_md5_sdesc_fail; - } - server->secmech.sdescmd5->shash.tfm = server->secmech.md5; - server->secmech.sdescmd5->shash.flags = 0x0; - - return 0; - -crypto_allocate_md5_sdesc_fail: - kfree(server->secmech.sdeschmacmd5); - -crypto_allocate_hmacmd5_sdesc_fail: - crypto_free_shash(server->secmech.md5); - -crypto_allocate_md5_fail: - crypto_free_shash(server->secmech.hmacmd5); - - return rc; -} diff --git a/ANDROID_3.4.5/fs/cifs/cifsfs.c b/ANDROID_3.4.5/fs/cifs/cifsfs.c deleted file mode 100644 index 541ef81f..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifsfs.c +++ /dev/null @@ -1,1211 +0,0 @@ -/* - * fs/cifs/cifsfs.c - * - * Copyright (C) International Business Machines Corp., 2002,2008 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * Common Internet FileSystem (CIFS) client - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Note that BB means BUGBUG (ie something to fix eventually) */ - -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/mount.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/seq_file.h> -#include <linux/vfs.h> -#include <linux/mempool.h> -#include <linux/delay.h> -#include <linux/kthread.h> -#include <linux/freezer.h> -#include <linux/namei.h> -#include <net/ipv6.h> -#include "cifsfs.h" -#include "cifspdu.h" -#define DECLARE_GLOBALS_HERE -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifs_debug.h" -#include "cifs_fs_sb.h" -#include <linux/mm.h> -#include <linux/key-type.h> -#include "cifs_spnego.h" -#include "fscache.h" -#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */ - -int cifsFYI = 0; -int cifsERROR = 1; -int traceSMB = 0; -bool enable_oplocks = true; -unsigned int linuxExtEnabled = 1; -unsigned int lookupCacheEnabled = 1; -unsigned int multiuser_mount = 0; -unsigned int global_secflags = CIFSSEC_DEF; -/* unsigned int ntlmv2_support = 0; */ -unsigned int sign_CIFS_PDUs = 1; -static const struct super_operations cifs_super_ops; -unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; -module_param(CIFSMaxBufSize, int, 0); -MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header). " - "Default: 16384 Range: 8192 to 130048"); -unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL; -module_param(cifs_min_rcv, int, 0); -MODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: " - "1 to 64"); -unsigned int cifs_min_small = 30; -module_param(cifs_min_small, int, 0); -MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 " - "Range: 2 to 256"); -unsigned int cifs_max_pending = CIFS_MAX_REQ; -module_param(cifs_max_pending, int, 0444); -MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. " - "Default: 32767 Range: 2 to 32767."); -module_param(enable_oplocks, bool, 0644); -MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks (bool). Default:" - "y/Y/1"); - -extern mempool_t *cifs_sm_req_poolp; -extern mempool_t *cifs_req_poolp; -extern mempool_t *cifs_mid_poolp; - -struct workqueue_struct *cifsiod_wq; - -static int -cifs_read_super(struct super_block *sb) -{ - struct inode *inode; - struct cifs_sb_info *cifs_sb; - int rc = 0; - - cifs_sb = CIFS_SB(sb); - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL) - sb->s_flags |= MS_POSIXACL; - - if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES) - sb->s_maxbytes = MAX_LFS_FILESIZE; - else - sb->s_maxbytes = MAX_NON_LFS; - - /* BB FIXME fix time_gran to be larger for LANMAN sessions */ - sb->s_time_gran = 100; - - sb->s_magic = CIFS_MAGIC_NUMBER; - sb->s_op = &cifs_super_ops; - sb->s_bdi = &cifs_sb->bdi; - sb->s_blocksize = CIFS_MAX_MSGSIZE; - sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ - inode = cifs_root_iget(sb); - - if (IS_ERR(inode)) { - rc = PTR_ERR(inode); - goto out_no_root; - } - - sb->s_root = d_make_root(inode); - if (!sb->s_root) { - rc = -ENOMEM; - goto out_no_root; - } - - /* do that *after* d_alloc_root() - we want NULL ->d_op for root here */ - if (cifs_sb_master_tcon(cifs_sb)->nocase) - sb->s_d_op = &cifs_ci_dentry_ops; - else - sb->s_d_op = &cifs_dentry_ops; - -#ifdef CONFIG_CIFS_NFSD_EXPORT - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { - cFYI(1, "export ops supported"); - sb->s_export_op = &cifs_export_ops; - } -#endif /* CONFIG_CIFS_NFSD_EXPORT */ - - return 0; - -out_no_root: - cERROR(1, "cifs_read_super: get root inode failed"); - return rc; -} - -static void cifs_kill_sb(struct super_block *sb) -{ - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - kill_anon_super(sb); - cifs_umount(cifs_sb); -} - -static int -cifs_statfs(struct dentry *dentry, struct kstatfs *buf) -{ - struct super_block *sb = dentry->d_sb; - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); - int rc = -EOPNOTSUPP; - int xid; - - xid = GetXid(); - - buf->f_type = CIFS_MAGIC_NUMBER; - - /* - * PATH_MAX may be too long - it would presumably be total path, - * but note that some servers (includinng Samba 3) have a shorter - * maximum path. - * - * Instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO. - */ - buf->f_namelen = PATH_MAX; - buf->f_files = 0; /* undefined */ - buf->f_ffree = 0; /* unlimited */ - - /* - * We could add a second check for a QFS Unix capability bit - */ - if ((tcon->ses->capabilities & CAP_UNIX) && - (CIFS_POSIX_EXTENSIONS & le64_to_cpu(tcon->fsUnixInfo.Capability))) - rc = CIFSSMBQFSPosixInfo(xid, tcon, buf); - - /* - * Only need to call the old QFSInfo if failed on newer one, - * e.g. by OS/2. - **/ - if (rc && (tcon->ses->capabilities & CAP_NT_SMBS)) - rc = CIFSSMBQFSInfo(xid, tcon, buf); - - /* - * Some old Windows servers also do not support level 103, retry with - * older level one if old server failed the previous call or we - * bypassed it because we detected that this was an older LANMAN sess - */ - if (rc) - rc = SMBOldQFSInfo(xid, tcon, buf); - - FreeXid(xid); - return 0; -} - -static int cifs_permission(struct inode *inode, int mask) -{ - struct cifs_sb_info *cifs_sb; - - cifs_sb = CIFS_SB(inode->i_sb); - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { - if ((mask & MAY_EXEC) && !execute_ok(inode)) - return -EACCES; - else - return 0; - } else /* file mode might have been restricted at mount time - on the client (above and beyond ACL on servers) for - servers which do not support setting and viewing mode bits, - so allowing client to check permissions is useful */ - return generic_permission(inode, mask); -} - -static struct kmem_cache *cifs_inode_cachep; -static struct kmem_cache *cifs_req_cachep; -static struct kmem_cache *cifs_mid_cachep; -static struct kmem_cache *cifs_sm_req_cachep; -mempool_t *cifs_sm_req_poolp; -mempool_t *cifs_req_poolp; -mempool_t *cifs_mid_poolp; - -static struct inode * -cifs_alloc_inode(struct super_block *sb) -{ - struct cifsInodeInfo *cifs_inode; - cifs_inode = kmem_cache_alloc(cifs_inode_cachep, GFP_KERNEL); - if (!cifs_inode) - return NULL; - cifs_inode->cifsAttrs = 0x20; /* default */ - cifs_inode->time = 0; - /* Until the file is open and we have gotten oplock - info back from the server, can not assume caching of - file data or metadata */ - cifs_set_oplock_level(cifs_inode, 0); - cifs_inode->delete_pending = false; - cifs_inode->invalid_mapping = false; - cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ - cifs_inode->server_eof = 0; - cifs_inode->uniqueid = 0; - cifs_inode->createtime = 0; - - /* Can not set i_flags here - they get immediately overwritten - to zero by the VFS */ -/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/ - INIT_LIST_HEAD(&cifs_inode->openFileList); - return &cifs_inode->vfs_inode; -} - -static void cifs_i_callback(struct rcu_head *head) -{ - struct inode *inode = container_of(head, struct inode, i_rcu); - INIT_LIST_HEAD(&inode->i_dentry); - kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); -} - -static void -cifs_destroy_inode(struct inode *inode) -{ - call_rcu(&inode->i_rcu, cifs_i_callback); -} - -static void -cifs_evict_inode(struct inode *inode) -{ - truncate_inode_pages(&inode->i_data, 0); - end_writeback(inode); - cifs_fscache_release_inode_cookie(inode); -} - -static void -cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) -{ - struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr; - struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr; - - seq_printf(s, ",addr="); - - switch (server->dstaddr.ss_family) { - case AF_INET: - seq_printf(s, "%pI4", &sa->sin_addr.s_addr); - break; - case AF_INET6: - seq_printf(s, "%pI6", &sa6->sin6_addr.s6_addr); - if (sa6->sin6_scope_id) - seq_printf(s, "%%%u", sa6->sin6_scope_id); - break; - default: - seq_printf(s, "(unknown)"); - } -} - -static void -cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server) -{ - seq_printf(s, ",sec="); - - switch (server->secType) { - case LANMAN: - seq_printf(s, "lanman"); - break; - case NTLMv2: - seq_printf(s, "ntlmv2"); - break; - case NTLM: - seq_printf(s, "ntlm"); - break; - case Kerberos: - seq_printf(s, "krb5"); - break; - case RawNTLMSSP: - seq_printf(s, "ntlmssp"); - break; - default: - /* shouldn't ever happen */ - seq_printf(s, "unknown"); - break; - } - - if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) - seq_printf(s, "i"); -} - -/* - * cifs_show_options() is for displaying mount options in /proc/mounts. - * Not all settable options are displayed but most of the important - * ones are. - */ -static int -cifs_show_options(struct seq_file *s, struct dentry *root) -{ - struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb); - struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); - struct sockaddr *srcaddr; - srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; - - cifs_show_security(s, tcon->ses->server); - - seq_printf(s, ",unc=%s", tcon->treeName); - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) - seq_printf(s, ",multiuser"); - else if (tcon->ses->user_name) - seq_printf(s, ",username=%s", tcon->ses->user_name); - - if (tcon->ses->domainName) - seq_printf(s, ",domain=%s", tcon->ses->domainName); - - if (srcaddr->sa_family != AF_UNSPEC) { - struct sockaddr_in *saddr4; - struct sockaddr_in6 *saddr6; - saddr4 = (struct sockaddr_in *)srcaddr; - saddr6 = (struct sockaddr_in6 *)srcaddr; - if (srcaddr->sa_family == AF_INET6) - seq_printf(s, ",srcaddr=%pI6c", - &saddr6->sin6_addr); - else if (srcaddr->sa_family == AF_INET) - seq_printf(s, ",srcaddr=%pI4", - &saddr4->sin_addr.s_addr); - else - seq_printf(s, ",srcaddr=BAD-AF:%i", - (int)(srcaddr->sa_family)); - } - - seq_printf(s, ",uid=%u", cifs_sb->mnt_uid); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) - seq_printf(s, ",forceuid"); - else - seq_printf(s, ",noforceuid"); - - seq_printf(s, ",gid=%u", cifs_sb->mnt_gid); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) - seq_printf(s, ",forcegid"); - else - seq_printf(s, ",noforcegid"); - - cifs_show_address(s, tcon->ses->server); - - if (!tcon->unix_ext) - seq_printf(s, ",file_mode=0%ho,dir_mode=0%ho", - cifs_sb->mnt_file_mode, - cifs_sb->mnt_dir_mode); - if (tcon->seal) - seq_printf(s, ",seal"); - if (tcon->nocase) - seq_printf(s, ",nocase"); - if (tcon->retry) - seq_printf(s, ",hard"); - if (tcon->unix_ext) - seq_printf(s, ",unix"); - else - seq_printf(s, ",nounix"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) - seq_printf(s, ",posixpaths"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) - seq_printf(s, ",setuids"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) - seq_printf(s, ",serverino"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) - seq_printf(s, ",rwpidforward"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) - seq_printf(s, ",forcemand"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) - seq_printf(s, ",directio"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - seq_printf(s, ",nouser_xattr"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) - seq_printf(s, ",mapchars"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) - seq_printf(s, ",sfu"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - seq_printf(s, ",nobrl"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) - seq_printf(s, ",cifsacl"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) - seq_printf(s, ",dynperm"); - if (root->d_sb->s_flags & MS_POSIXACL) - seq_printf(s, ",acl"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) - seq_printf(s, ",mfsymlinks"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) - seq_printf(s, ",fsc"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC) - seq_printf(s, ",nostrictsync"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) - seq_printf(s, ",noperm"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) - seq_printf(s, ",strictcache"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) - seq_printf(s, ",backupuid=%u", cifs_sb->mnt_backupuid); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) - seq_printf(s, ",backupgid=%u", cifs_sb->mnt_backupgid); - - seq_printf(s, ",rsize=%u", cifs_sb->rsize); - seq_printf(s, ",wsize=%u", cifs_sb->wsize); - /* convert actimeo and display it in seconds */ - seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); - - return 0; -} - -static void cifs_umount_begin(struct super_block *sb) -{ - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - struct cifs_tcon *tcon; - - if (cifs_sb == NULL) - return; - - tcon = cifs_sb_master_tcon(cifs_sb); - - spin_lock(&cifs_tcp_ses_lock); - if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) { - /* we have other mounts to same share or we have - already tried to force umount this and woken up - all waiting network requests, nothing to do */ - spin_unlock(&cifs_tcp_ses_lock); - return; - } else if (tcon->tc_count == 1) - tcon->tidStatus = CifsExiting; - spin_unlock(&cifs_tcp_ses_lock); - - /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */ - /* cancel_notify_requests(tcon); */ - if (tcon->ses && tcon->ses->server) { - cFYI(1, "wake up tasks now - umount begin not complete"); - wake_up_all(&tcon->ses->server->request_q); - wake_up_all(&tcon->ses->server->response_q); - msleep(1); /* yield */ - /* we have to kick the requests once more */ - wake_up_all(&tcon->ses->server->response_q); - msleep(1); - } - - return; -} - -#ifdef CONFIG_CIFS_STATS2 -static int cifs_show_stats(struct seq_file *s, struct dentry *root) -{ - /* BB FIXME */ - return 0; -} -#endif - -static int cifs_remount(struct super_block *sb, int *flags, char *data) -{ - *flags |= MS_NODIRATIME; - return 0; -} - -static int cifs_drop_inode(struct inode *inode) -{ - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - - /* no serverino => unconditional eviction */ - return !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) || - generic_drop_inode(inode); -} - -static const struct super_operations cifs_super_ops = { - .statfs = cifs_statfs, - .alloc_inode = cifs_alloc_inode, - .destroy_inode = cifs_destroy_inode, - .drop_inode = cifs_drop_inode, - .evict_inode = cifs_evict_inode, -/* .delete_inode = cifs_delete_inode, */ /* Do not need above - function unless later we add lazy close of inodes or unless the - kernel forgets to call us with the same number of releases (closes) - as opens */ - .show_options = cifs_show_options, - .umount_begin = cifs_umount_begin, - .remount_fs = cifs_remount, -#ifdef CONFIG_CIFS_STATS2 - .show_stats = cifs_show_stats, -#endif -}; - -/* - * Get root dentry from superblock according to prefix path mount option. - * Return dentry with refcount + 1 on success and NULL otherwise. - */ -static struct dentry * -cifs_get_root(struct smb_vol *vol, struct super_block *sb) -{ - struct dentry *dentry; - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - char *full_path = NULL; - char *s, *p; - char sep; - - full_path = cifs_build_path_to_root(vol, cifs_sb, - cifs_sb_master_tcon(cifs_sb)); - if (full_path == NULL) - return ERR_PTR(-ENOMEM); - - cFYI(1, "Get root dentry for %s", full_path); - - sep = CIFS_DIR_SEP(cifs_sb); - dentry = dget(sb->s_root); - p = s = full_path; - - do { - struct inode *dir = dentry->d_inode; - struct dentry *child; - - if (!dir) { - dput(dentry); - dentry = ERR_PTR(-ENOENT); - break; - } - - /* skip separators */ - while (*s == sep) - s++; - if (!*s) - break; - p = s++; - /* next separator */ - while (*s && *s != sep) - s++; - - mutex_lock(&dir->i_mutex); - child = lookup_one_len(p, dentry, s - p); - mutex_unlock(&dir->i_mutex); - dput(dentry); - dentry = child; - } while (!IS_ERR(dentry)); - kfree(full_path); - return dentry; -} - -static int cifs_set_super(struct super_block *sb, void *data) -{ - struct cifs_mnt_data *mnt_data = data; - sb->s_fs_info = mnt_data->cifs_sb; - return set_anon_super(sb, NULL); -} - -static struct dentry * -cifs_do_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) -{ - int rc; - struct super_block *sb; - struct cifs_sb_info *cifs_sb; - struct smb_vol *volume_info; - struct cifs_mnt_data mnt_data; - struct dentry *root; - - cFYI(1, "Devname: %s flags: %d ", dev_name, flags); - - volume_info = cifs_get_volume_info((char *)data, dev_name); - if (IS_ERR(volume_info)) - return ERR_CAST(volume_info); - - cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); - if (cifs_sb == NULL) { - root = ERR_PTR(-ENOMEM); - goto out_nls; - } - - cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); - if (cifs_sb->mountdata == NULL) { - root = ERR_PTR(-ENOMEM); - goto out_cifs_sb; - } - - cifs_setup_cifs_sb(volume_info, cifs_sb); - - rc = cifs_mount(cifs_sb, volume_info); - if (rc) { - if (!(flags & MS_SILENT)) - cERROR(1, "cifs_mount failed w/return code = %d", rc); - root = ERR_PTR(rc); - goto out_mountdata; - } - - mnt_data.vol = volume_info; - mnt_data.cifs_sb = cifs_sb; - mnt_data.flags = flags; - - sb = sget(fs_type, cifs_match_super, cifs_set_super, &mnt_data); - if (IS_ERR(sb)) { - root = ERR_CAST(sb); - cifs_umount(cifs_sb); - goto out; - } - - if (sb->s_root) { - cFYI(1, "Use existing superblock"); - cifs_umount(cifs_sb); - } else { - sb->s_flags = flags; - /* BB should we make this contingent on mount parm? */ - sb->s_flags |= MS_NODIRATIME | MS_NOATIME; - - rc = cifs_read_super(sb); - if (rc) { - root = ERR_PTR(rc); - goto out_super; - } - - sb->s_flags |= MS_ACTIVE; - } - - root = cifs_get_root(volume_info, sb); - if (IS_ERR(root)) - goto out_super; - - cFYI(1, "dentry root is: %p", root); - goto out; - -out_super: - deactivate_locked_super(sb); -out: - cifs_cleanup_volume_info(volume_info); - return root; - -out_mountdata: - kfree(cifs_sb->mountdata); -out_cifs_sb: - kfree(cifs_sb); -out_nls: - unload_nls(volume_info->local_nls); - goto out; -} - -static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) -{ - struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; - ssize_t written; - int rc; - - written = generic_file_aio_write(iocb, iov, nr_segs, pos); - - if (CIFS_I(inode)->clientCanCacheAll) - return written; - - rc = filemap_fdatawrite(inode->i_mapping); - if (rc) - cFYI(1, "cifs_file_aio_write: %d rc on %p inode", rc, inode); - - return written; -} - -static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) -{ - /* - * origin == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate - * the cached file length - */ - if (origin != SEEK_SET && origin != SEEK_CUR) { - int rc; - struct inode *inode = file->f_path.dentry->d_inode; - - /* - * We need to be sure that all dirty pages are written and the - * server has the newest file length. - */ - if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping && - inode->i_mapping->nrpages != 0) { - rc = filemap_fdatawait(inode->i_mapping); - if (rc) { - mapping_set_error(inode->i_mapping, rc); - return rc; - } - } - /* - * Some applications poll for the file length in this strange - * way so we must seek to end on non-oplocked files by - * setting the revalidate time to zero. - */ - CIFS_I(inode)->time = 0; - - rc = cifs_revalidate_file_attr(file); - if (rc < 0) - return (loff_t)rc; - } - return generic_file_llseek(file, offset, origin); -} - -static int cifs_setlease(struct file *file, long arg, struct file_lock **lease) -{ - /* note that this is called by vfs setlease with lock_flocks held - to protect *lease from going away */ - struct inode *inode = file->f_path.dentry->d_inode; - struct cifsFileInfo *cfile = file->private_data; - - if (!(S_ISREG(inode->i_mode))) - return -EINVAL; - - /* check if file is oplocked */ - if (((arg == F_RDLCK) && - (CIFS_I(inode)->clientCanCacheRead)) || - ((arg == F_WRLCK) && - (CIFS_I(inode)->clientCanCacheAll))) - return generic_setlease(file, arg, lease); - else if (tlink_tcon(cfile->tlink)->local_lease && - !CIFS_I(inode)->clientCanCacheRead) - /* If the server claims to support oplock on this - file, then we still need to check oplock even - if the local_lease mount option is set, but there - are servers which do not support oplock for which - this mount option may be useful if the user - knows that the file won't be changed on the server - by anyone else */ - return generic_setlease(file, arg, lease); - else - return -EAGAIN; -} - -struct file_system_type cifs_fs_type = { - .owner = THIS_MODULE, - .name = "cifs", - .mount = cifs_do_mount, - .kill_sb = cifs_kill_sb, - /* .fs_flags */ -}; -const struct inode_operations cifs_dir_inode_ops = { - .create = cifs_create, - .lookup = cifs_lookup, - .getattr = cifs_getattr, - .unlink = cifs_unlink, - .link = cifs_hardlink, - .mkdir = cifs_mkdir, - .rmdir = cifs_rmdir, - .rename = cifs_rename, - .permission = cifs_permission, -/* revalidate:cifs_revalidate, */ - .setattr = cifs_setattr, - .symlink = cifs_symlink, - .mknod = cifs_mknod, -#ifdef CONFIG_CIFS_XATTR - .setxattr = cifs_setxattr, - .getxattr = cifs_getxattr, - .listxattr = cifs_listxattr, - .removexattr = cifs_removexattr, -#endif -}; - -const struct inode_operations cifs_file_inode_ops = { -/* revalidate:cifs_revalidate, */ - .setattr = cifs_setattr, - .getattr = cifs_getattr, /* do we need this anymore? */ - .rename = cifs_rename, - .permission = cifs_permission, -#ifdef CONFIG_CIFS_XATTR - .setxattr = cifs_setxattr, - .getxattr = cifs_getxattr, - .listxattr = cifs_listxattr, - .removexattr = cifs_removexattr, -#endif -}; - -const struct inode_operations cifs_symlink_inode_ops = { - .readlink = generic_readlink, - .follow_link = cifs_follow_link, - .put_link = cifs_put_link, - .permission = cifs_permission, - /* BB add the following two eventually */ - /* revalidate: cifs_revalidate, - setattr: cifs_notify_change, *//* BB do we need notify change */ -#ifdef CONFIG_CIFS_XATTR - .setxattr = cifs_setxattr, - .getxattr = cifs_getxattr, - .listxattr = cifs_listxattr, - .removexattr = cifs_removexattr, -#endif -}; - -const struct file_operations cifs_file_ops = { - .read = do_sync_read, - .write = do_sync_write, - .aio_read = generic_file_aio_read, - .aio_write = cifs_file_aio_write, - .open = cifs_open, - .release = cifs_close, - .lock = cifs_lock, - .fsync = cifs_fsync, - .flush = cifs_flush, - .mmap = cifs_file_mmap, - .splice_read = generic_file_splice_read, - .llseek = cifs_llseek, -#ifdef CONFIG_CIFS_POSIX - .unlocked_ioctl = cifs_ioctl, -#endif /* CONFIG_CIFS_POSIX */ - .setlease = cifs_setlease, -}; - -const struct file_operations cifs_file_strict_ops = { - .read = do_sync_read, - .write = do_sync_write, - .aio_read = cifs_strict_readv, - .aio_write = cifs_strict_writev, - .open = cifs_open, - .release = cifs_close, - .lock = cifs_lock, - .fsync = cifs_strict_fsync, - .flush = cifs_flush, - .mmap = cifs_file_strict_mmap, - .splice_read = generic_file_splice_read, - .llseek = cifs_llseek, -#ifdef CONFIG_CIFS_POSIX - .unlocked_ioctl = cifs_ioctl, -#endif /* CONFIG_CIFS_POSIX */ - .setlease = cifs_setlease, -}; - -const struct file_operations cifs_file_direct_ops = { - /* BB reevaluate whether they can be done with directio, no cache */ - .read = do_sync_read, - .write = do_sync_write, - .aio_read = cifs_user_readv, - .aio_write = cifs_user_writev, - .open = cifs_open, - .release = cifs_close, - .lock = cifs_lock, - .fsync = cifs_fsync, - .flush = cifs_flush, - .mmap = cifs_file_mmap, - .splice_read = generic_file_splice_read, -#ifdef CONFIG_CIFS_POSIX - .unlocked_ioctl = cifs_ioctl, -#endif /* CONFIG_CIFS_POSIX */ - .llseek = cifs_llseek, - .setlease = cifs_setlease, -}; - -const struct file_operations cifs_file_nobrl_ops = { - .read = do_sync_read, - .write = do_sync_write, - .aio_read = generic_file_aio_read, - .aio_write = cifs_file_aio_write, - .open = cifs_open, - .release = cifs_close, - .fsync = cifs_fsync, - .flush = cifs_flush, - .mmap = cifs_file_mmap, - .splice_read = generic_file_splice_read, - .llseek = cifs_llseek, -#ifdef CONFIG_CIFS_POSIX - .unlocked_ioctl = cifs_ioctl, -#endif /* CONFIG_CIFS_POSIX */ - .setlease = cifs_setlease, -}; - -const struct file_operations cifs_file_strict_nobrl_ops = { - .read = do_sync_read, - .write = do_sync_write, - .aio_read = cifs_strict_readv, - .aio_write = cifs_strict_writev, - .open = cifs_open, - .release = cifs_close, - .fsync = cifs_strict_fsync, - .flush = cifs_flush, - .mmap = cifs_file_strict_mmap, - .splice_read = generic_file_splice_read, - .llseek = cifs_llseek, -#ifdef CONFIG_CIFS_POSIX - .unlocked_ioctl = cifs_ioctl, -#endif /* CONFIG_CIFS_POSIX */ - .setlease = cifs_setlease, -}; - -const struct file_operations cifs_file_direct_nobrl_ops = { - /* BB reevaluate whether they can be done with directio, no cache */ - .read = do_sync_read, - .write = do_sync_write, - .aio_read = cifs_user_readv, - .aio_write = cifs_user_writev, - .open = cifs_open, - .release = cifs_close, - .fsync = cifs_fsync, - .flush = cifs_flush, - .mmap = cifs_file_mmap, - .splice_read = generic_file_splice_read, -#ifdef CONFIG_CIFS_POSIX - .unlocked_ioctl = cifs_ioctl, -#endif /* CONFIG_CIFS_POSIX */ - .llseek = cifs_llseek, - .setlease = cifs_setlease, -}; - -const struct file_operations cifs_dir_ops = { - .readdir = cifs_readdir, - .release = cifs_closedir, - .read = generic_read_dir, - .unlocked_ioctl = cifs_ioctl, - .llseek = generic_file_llseek, -}; - -static void -cifs_init_once(void *inode) -{ - struct cifsInodeInfo *cifsi = inode; - - inode_init_once(&cifsi->vfs_inode); - INIT_LIST_HEAD(&cifsi->llist); - mutex_init(&cifsi->lock_mutex); -} - -static int -cifs_init_inodecache(void) -{ - cifs_inode_cachep = kmem_cache_create("cifs_inode_cache", - sizeof(struct cifsInodeInfo), - 0, (SLAB_RECLAIM_ACCOUNT| - SLAB_MEM_SPREAD), - cifs_init_once); - if (cifs_inode_cachep == NULL) - return -ENOMEM; - - return 0; -} - -static void -cifs_destroy_inodecache(void) -{ - kmem_cache_destroy(cifs_inode_cachep); -} - -static int -cifs_init_request_bufs(void) -{ - if (CIFSMaxBufSize < 8192) { - /* Buffer size can not be smaller than 2 * PATH_MAX since maximum - Unicode path name has to fit in any SMB/CIFS path based frames */ - CIFSMaxBufSize = 8192; - } else if (CIFSMaxBufSize > 1024*127) { - CIFSMaxBufSize = 1024 * 127; - } else { - CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/ - } -/* cERROR(1, "CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize); */ - cifs_req_cachep = kmem_cache_create("cifs_request", - CIFSMaxBufSize + - MAX_CIFS_HDR_SIZE, 0, - SLAB_HWCACHE_ALIGN, NULL); - if (cifs_req_cachep == NULL) - return -ENOMEM; - - if (cifs_min_rcv < 1) - cifs_min_rcv = 1; - else if (cifs_min_rcv > 64) { - cifs_min_rcv = 64; - cERROR(1, "cifs_min_rcv set to maximum (64)"); - } - - cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv, - cifs_req_cachep); - - if (cifs_req_poolp == NULL) { - kmem_cache_destroy(cifs_req_cachep); - return -ENOMEM; - } - /* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and - almost all handle based requests (but not write response, nor is it - sufficient for path based requests). A smaller size would have - been more efficient (compacting multiple slab items on one 4k page) - for the case in which debug was on, but this larger size allows - more SMBs to use small buffer alloc and is still much more - efficient to alloc 1 per page off the slab compared to 17K (5page) - alloc of large cifs buffers even when page debugging is on */ - cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq", - MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN, - NULL); - if (cifs_sm_req_cachep == NULL) { - mempool_destroy(cifs_req_poolp); - kmem_cache_destroy(cifs_req_cachep); - return -ENOMEM; - } - - if (cifs_min_small < 2) - cifs_min_small = 2; - else if (cifs_min_small > 256) { - cifs_min_small = 256; - cFYI(1, "cifs_min_small set to maximum (256)"); - } - - cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small, - cifs_sm_req_cachep); - - if (cifs_sm_req_poolp == NULL) { - mempool_destroy(cifs_req_poolp); - kmem_cache_destroy(cifs_req_cachep); - kmem_cache_destroy(cifs_sm_req_cachep); - return -ENOMEM; - } - - return 0; -} - -static void -cifs_destroy_request_bufs(void) -{ - mempool_destroy(cifs_req_poolp); - kmem_cache_destroy(cifs_req_cachep); - mempool_destroy(cifs_sm_req_poolp); - kmem_cache_destroy(cifs_sm_req_cachep); -} - -static int -cifs_init_mids(void) -{ - cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids", - sizeof(struct mid_q_entry), 0, - SLAB_HWCACHE_ALIGN, NULL); - if (cifs_mid_cachep == NULL) - return -ENOMEM; - - /* 3 is a reasonable minimum number of simultaneous operations */ - cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep); - if (cifs_mid_poolp == NULL) { - kmem_cache_destroy(cifs_mid_cachep); - return -ENOMEM; - } - - return 0; -} - -static void -cifs_destroy_mids(void) -{ - mempool_destroy(cifs_mid_poolp); - kmem_cache_destroy(cifs_mid_cachep); -} - -static int __init -init_cifs(void) -{ - int rc = 0; - cifs_proc_init(); - INIT_LIST_HEAD(&cifs_tcp_ses_list); -#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */ - INIT_LIST_HEAD(&GlobalDnotifyReqList); - INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); -#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ -/* - * Initialize Global counters - */ - atomic_set(&sesInfoAllocCount, 0); - atomic_set(&tconInfoAllocCount, 0); - atomic_set(&tcpSesAllocCount, 0); - atomic_set(&tcpSesReconnectCount, 0); - atomic_set(&tconInfoReconnectCount, 0); - - atomic_set(&bufAllocCount, 0); - atomic_set(&smBufAllocCount, 0); -#ifdef CONFIG_CIFS_STATS2 - atomic_set(&totBufAllocCount, 0); - atomic_set(&totSmBufAllocCount, 0); -#endif /* CONFIG_CIFS_STATS2 */ - - atomic_set(&midCount, 0); - GlobalCurrentXid = 0; - GlobalTotalActiveXid = 0; - GlobalMaxActiveXid = 0; - spin_lock_init(&cifs_tcp_ses_lock); - spin_lock_init(&cifs_file_list_lock); - spin_lock_init(&GlobalMid_Lock); - - if (cifs_max_pending < 2) { - cifs_max_pending = 2; - cFYI(1, "cifs_max_pending set to min of 2"); - } else if (cifs_max_pending > CIFS_MAX_REQ) { - cifs_max_pending = CIFS_MAX_REQ; - cFYI(1, "cifs_max_pending set to max of %u", CIFS_MAX_REQ); - } - - cifsiod_wq = alloc_workqueue("cifsiod", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); - if (!cifsiod_wq) { - rc = -ENOMEM; - goto out_clean_proc; - } - - rc = cifs_fscache_register(); - if (rc) - goto out_destroy_wq; - - rc = cifs_init_inodecache(); - if (rc) - goto out_unreg_fscache; - - rc = cifs_init_mids(); - if (rc) - goto out_destroy_inodecache; - - rc = cifs_init_request_bufs(); - if (rc) - goto out_destroy_mids; - -#ifdef CONFIG_CIFS_UPCALL - rc = register_key_type(&cifs_spnego_key_type); - if (rc) - goto out_destroy_request_bufs; -#endif /* CONFIG_CIFS_UPCALL */ - -#ifdef CONFIG_CIFS_ACL - rc = init_cifs_idmap(); - if (rc) - goto out_register_key_type; -#endif /* CONFIG_CIFS_ACL */ - - rc = register_filesystem(&cifs_fs_type); - if (rc) - goto out_init_cifs_idmap; - - return 0; - -out_init_cifs_idmap: -#ifdef CONFIG_CIFS_ACL - exit_cifs_idmap(); -out_register_key_type: -#endif -#ifdef CONFIG_CIFS_UPCALL - unregister_key_type(&cifs_spnego_key_type); -out_destroy_request_bufs: -#endif - cifs_destroy_request_bufs(); -out_destroy_mids: - cifs_destroy_mids(); -out_destroy_inodecache: - cifs_destroy_inodecache(); -out_unreg_fscache: - cifs_fscache_unregister(); -out_destroy_wq: - destroy_workqueue(cifsiod_wq); -out_clean_proc: - cifs_proc_clean(); - return rc; -} - -static void __exit -exit_cifs(void) -{ - cFYI(DBG2, "exit_cifs"); - unregister_filesystem(&cifs_fs_type); - cifs_dfs_release_automount_timer(); -#ifdef CONFIG_CIFS_ACL - cifs_destroy_idmaptrees(); - exit_cifs_idmap(); -#endif -#ifdef CONFIG_CIFS_UPCALL - unregister_key_type(&cifs_spnego_key_type); -#endif - cifs_destroy_request_bufs(); - cifs_destroy_mids(); - cifs_destroy_inodecache(); - cifs_fscache_unregister(); - destroy_workqueue(cifsiod_wq); - cifs_proc_clean(); -} - -MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); -MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */ -MODULE_DESCRIPTION - ("VFS to access servers complying with the SNIA CIFS Specification " - "e.g. Samba and Windows"); -MODULE_VERSION(CIFS_VERSION); -module_init(init_cifs) -module_exit(exit_cifs) diff --git a/ANDROID_3.4.5/fs/cifs/cifsfs.h b/ANDROID_3.4.5/fs/cifs/cifsfs.h deleted file mode 100644 index 65365358..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifsfs.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * fs/cifs/cifsfs.h - * - * Copyright (c) International Business Machines Corp., 2002, 2007 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _CIFSFS_H -#define _CIFSFS_H - -#define ROOT_I 2 - -/* - * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down - * so that it will fit. - */ -static inline ino_t -cifs_uniqueid_to_ino_t(u64 fileid) -{ - ino_t ino = (ino_t) fileid; - if (sizeof(ino_t) < sizeof(u64)) - ino ^= fileid >> (sizeof(u64)-sizeof(ino_t)) * 8; - return ino; -} - -extern struct file_system_type cifs_fs_type; -extern const struct address_space_operations cifs_addr_ops; -extern const struct address_space_operations cifs_addr_ops_smallbuf; - -/* Functions related to inodes */ -extern const struct inode_operations cifs_dir_inode_ops; -extern struct inode *cifs_root_iget(struct super_block *); -extern int cifs_create(struct inode *, struct dentry *, umode_t, - struct nameidata *); -extern struct dentry *cifs_lookup(struct inode *, struct dentry *, - struct nameidata *); -extern int cifs_unlink(struct inode *dir, struct dentry *dentry); -extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *); -extern int cifs_mknod(struct inode *, struct dentry *, umode_t, dev_t); -extern int cifs_mkdir(struct inode *, struct dentry *, umode_t); -extern int cifs_rmdir(struct inode *, struct dentry *); -extern int cifs_rename(struct inode *, struct dentry *, struct inode *, - struct dentry *); -extern int cifs_revalidate_file_attr(struct file *filp); -extern int cifs_revalidate_dentry_attr(struct dentry *); -extern int cifs_revalidate_file(struct file *filp); -extern int cifs_revalidate_dentry(struct dentry *); -extern int cifs_invalidate_mapping(struct inode *inode); -extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); -extern int cifs_setattr(struct dentry *, struct iattr *); - -extern const struct inode_operations cifs_file_inode_ops; -extern const struct inode_operations cifs_symlink_inode_ops; -extern const struct inode_operations cifs_dfs_referral_inode_operations; - - -/* Functions related to files and directories */ -extern const struct file_operations cifs_file_ops; -extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */ -extern const struct file_operations cifs_file_strict_ops; /* if strictio mnt */ -extern const struct file_operations cifs_file_nobrl_ops; /* no brlocks */ -extern const struct file_operations cifs_file_direct_nobrl_ops; -extern const struct file_operations cifs_file_strict_nobrl_ops; -extern int cifs_open(struct inode *inode, struct file *file); -extern int cifs_close(struct inode *inode, struct file *file); -extern int cifs_closedir(struct inode *inode, struct file *file); -extern ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos); -extern ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos); -extern ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos); -extern ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos); -extern int cifs_lock(struct file *, int, struct file_lock *); -extern int cifs_fsync(struct file *, loff_t, loff_t, int); -extern int cifs_strict_fsync(struct file *, loff_t, loff_t, int); -extern int cifs_flush(struct file *, fl_owner_t id); -extern int cifs_file_mmap(struct file * , struct vm_area_struct *); -extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *); -extern const struct file_operations cifs_dir_ops; -extern int cifs_dir_open(struct inode *inode, struct file *file); -extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); - -/* Functions related to dir entries */ -extern const struct dentry_operations cifs_dentry_ops; -extern const struct dentry_operations cifs_ci_dentry_ops; - -#ifdef CONFIG_CIFS_DFS_UPCALL -extern struct vfsmount *cifs_dfs_d_automount(struct path *path); -#else -#define cifs_dfs_d_automount NULL -#endif - -/* Functions related to symlinks */ -extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd); -extern void cifs_put_link(struct dentry *direntry, - struct nameidata *nd, void *); -extern int cifs_readlink(struct dentry *direntry, char __user *buffer, - int buflen); -extern int cifs_symlink(struct inode *inode, struct dentry *direntry, - const char *symname); -extern int cifs_removexattr(struct dentry *, const char *); -extern int cifs_setxattr(struct dentry *, const char *, const void *, - size_t, int); -extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); -extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); -extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); - -#ifdef CONFIG_CIFS_NFSD_EXPORT -extern const struct export_operations cifs_export_ops; -#endif /* CONFIG_CIFS_NFSD_EXPORT */ - -#define CIFS_VERSION "1.78" -#endif /* _CIFSFS_H */ diff --git a/ANDROID_3.4.5/fs/cifs/cifsglob.h b/ANDROID_3.4.5/fs/cifs/cifsglob.h deleted file mode 100644 index 73fea285..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifsglob.h +++ /dev/null @@ -1,1078 +0,0 @@ -/* - * fs/cifs/cifsglob.h - * - * Copyright (C) International Business Machines Corp., 2002,2008 - * Author(s): Steve French (sfrench@us.ibm.com) - * Jeremy Allison (jra@samba.org) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - */ -#ifndef _CIFS_GLOB_H -#define _CIFS_GLOB_H - -#include <linux/in.h> -#include <linux/in6.h> -#include <linux/slab.h> -#include <linux/workqueue.h> -#include "cifs_fs_sb.h" -#include "cifsacl.h" -#include <crypto/internal/hash.h> -#include <linux/scatterlist.h> - -/* - * The sizes of various internal tables and strings - */ -#define MAX_UID_INFO 16 -#define MAX_SES_INFO 2 -#define MAX_TCON_INFO 4 - -#define MAX_TREE_SIZE (2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1) -#define MAX_SERVER_SIZE 15 -#define MAX_SHARE_SIZE 80 -#define MAX_USERNAME_SIZE 256 /* reasonable maximum for current servers */ -#define MAX_PASSWORD_SIZE 512 /* max for windows seems to be 256 wide chars */ - -#define CIFS_MIN_RCV_POOL 4 - -#define MAX_REOPEN_ATT 5 /* these many maximum attempts to reopen a file */ -/* - * default attribute cache timeout (jiffies) - */ -#define CIFS_DEF_ACTIMEO (1 * HZ) - -/* - * max attribute cache timeout (jiffies) - 2^30 - */ -#define CIFS_MAX_ACTIMEO (1 << 30) - -/* - * MAX_REQ is the maximum number of requests that WE will send - * on one socket concurrently. - */ -#define CIFS_MAX_REQ 32767 - -#define RFC1001_NAME_LEN 15 -#define RFC1001_NAME_LEN_WITH_NULL (RFC1001_NAME_LEN + 1) - -/* currently length of NIP6_FMT */ -#define SERVER_NAME_LENGTH 40 -#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1) - -/* used to define string lengths for reversing unicode strings */ -/* (256+1)*2 = 514 */ -/* (max path length + 1 for null) * 2 for unicode */ -#define MAX_NAME 514 - -#include "cifspdu.h" - -#ifndef XATTR_DOS_ATTRIB -#define XATTR_DOS_ATTRIB "user.DOSATTRIB" -#endif - -/* - * CIFS vfs client Status information (based on what we know.) - */ - -/* associated with each tcp and smb session */ -enum statusEnum { - CifsNew = 0, - CifsGood, - CifsExiting, - CifsNeedReconnect, - CifsNeedNegotiate -}; - -enum securityEnum { - LANMAN = 0, /* Legacy LANMAN auth */ - NTLM, /* Legacy NTLM012 auth with NTLM hash */ - NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ - RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */ -/* NTLMSSP, */ /* can use rawNTLMSSP instead of NTLMSSP via SPNEGO */ - Kerberos, /* Kerberos via SPNEGO */ -}; - -enum protocolEnum { - TCP = 0, - SCTP - /* Netbios frames protocol not supported at this time */ -}; - -struct session_key { - unsigned int len; - char *response; -}; - -/* crypto security descriptor definition */ -struct sdesc { - struct shash_desc shash; - char ctx[]; -}; - -/* crypto hashing related structure/fields, not specific to a sec mech */ -struct cifs_secmech { - struct crypto_shash *hmacmd5; /* hmac-md5 hash function */ - struct crypto_shash *md5; /* md5 hash function */ - struct sdesc *sdeschmacmd5; /* ctxt to generate ntlmv2 hash, CR1 */ - struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */ -}; - -/* per smb session structure/fields */ -struct ntlmssp_auth { - __u32 client_flags; /* sent by client in type 1 ntlmsssp exchange */ - __u32 server_flags; /* sent by server in type 2 ntlmssp exchange */ - unsigned char ciphertext[CIFS_CPHTXT_SIZE]; /* sent to server */ - char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlmssp */ -}; - -struct cifs_cred { - int uid; - int gid; - int mode; - int cecount; - struct cifs_sid osid; - struct cifs_sid gsid; - struct cifs_ntace *ntaces; - struct cifs_ace *aces; -}; - -/* - ***************************************************************** - * Except the CIFS PDUs themselves all the - * globally interesting structs should go here - ***************************************************************** - */ - -struct smb_vol { - char *username; - char *password; - char *domainname; - char *UNC; - char *UNCip; - char *iocharset; /* local code page for mapping to and from Unicode */ - char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */ - char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */ - uid_t cred_uid; - uid_t linux_uid; - gid_t linux_gid; - uid_t backupuid; - gid_t backupgid; - umode_t file_mode; - umode_t dir_mode; - unsigned secFlg; - bool retry:1; - bool intr:1; - bool setuids:1; - bool override_uid:1; - bool override_gid:1; - bool dynperm:1; - bool noperm:1; - bool no_psx_acl:1; /* set if posix acl support should be disabled */ - bool cifs_acl:1; - bool backupuid_specified; /* mount option backupuid is specified */ - bool backupgid_specified; /* mount option backupgid is specified */ - bool no_xattr:1; /* set if xattr (EA) support should be disabled*/ - bool server_ino:1; /* use inode numbers from server ie UniqueId */ - bool direct_io:1; - bool strict_io:1; /* strict cache behavior */ - bool remap:1; /* set to remap seven reserved chars in filenames */ - bool posix_paths:1; /* unset to not ask for posix pathnames. */ - bool no_linux_ext:1; - bool sfu_emul:1; - bool nullauth:1; /* attempt to authenticate with null user */ - bool nocase:1; /* request case insensitive filenames */ - bool nobrl:1; /* disable sending byte range locks to srv */ - bool mand_lock:1; /* send mandatory not posix byte range lock reqs */ - bool seal:1; /* request transport encryption on share */ - bool nodfs:1; /* Do not request DFS, even if available */ - bool local_lease:1; /* check leases only on local system, not remote */ - bool noblocksnd:1; - bool noautotune:1; - bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ - bool fsc:1; /* enable fscache */ - bool mfsymlinks:1; /* use Minshall+French Symlinks */ - bool multiuser:1; - bool rwpidforward:1; /* pid forward for read/write operations */ - unsigned int rsize; - unsigned int wsize; - bool sockopt_tcp_nodelay:1; - unsigned short int port; - unsigned long actimeo; /* attribute cache timeout (jiffies) */ - char *prepath; - struct sockaddr_storage srcaddr; /* allow binding to a local IP */ - struct nls_table *local_nls; -}; - -#define CIFS_MOUNT_MASK (CIFS_MOUNT_NO_PERM | CIFS_MOUNT_SET_UID | \ - CIFS_MOUNT_SERVER_INUM | CIFS_MOUNT_DIRECT_IO | \ - CIFS_MOUNT_NO_XATTR | CIFS_MOUNT_MAP_SPECIAL_CHR | \ - CIFS_MOUNT_UNX_EMUL | CIFS_MOUNT_NO_BRL | \ - CIFS_MOUNT_CIFS_ACL | CIFS_MOUNT_OVERR_UID | \ - CIFS_MOUNT_OVERR_GID | CIFS_MOUNT_DYNPERM | \ - CIFS_MOUNT_NOPOSIXBRL | CIFS_MOUNT_NOSSYNC | \ - CIFS_MOUNT_FSCACHE | CIFS_MOUNT_MF_SYMLINKS | \ - CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO | \ - CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID) - -#define CIFS_MS_MASK (MS_RDONLY | MS_MANDLOCK | MS_NOEXEC | MS_NOSUID | \ - MS_NODEV | MS_SYNCHRONOUS) - -struct cifs_mnt_data { - struct cifs_sb_info *cifs_sb; - struct smb_vol *vol; - int flags; -}; - -static inline unsigned int -get_rfc1002_length(void *buf) -{ - return be32_to_cpu(*((__be32 *)buf)); -} - -struct TCP_Server_Info { - struct list_head tcp_ses_list; - struct list_head smb_ses_list; - int srv_count; /* reference counter */ - /* 15 character server name + 0x20 16th byte indicating type = srv */ - char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; - enum statusEnum tcpStatus; /* what we think the status is */ - char *hostname; /* hostname portion of UNC string */ - struct socket *ssocket; - struct sockaddr_storage dstaddr; - struct sockaddr_storage srcaddr; /* locally bind to this IP */ -#ifdef CONFIG_NET_NS - struct net *net; -#endif - wait_queue_head_t response_q; - wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/ - struct list_head pending_mid_q; - bool noblocksnd; /* use blocking sendmsg */ - bool noautotune; /* do not autotune send buf sizes */ - bool tcp_nodelay; - int credits; /* send no more requests at once */ - unsigned int in_flight; /* number of requests on the wire to server */ - spinlock_t req_lock; /* protect the two values above */ - struct mutex srv_mutex; - struct task_struct *tsk; - char server_GUID[16]; - char sec_mode; - bool session_estab; /* mark when very first sess is established */ - u16 dialect; /* dialect index that server chose */ - enum securityEnum secType; - bool oplocks:1; /* enable oplocks */ - unsigned int maxReq; /* Clients should submit no more */ - /* than maxReq distinct unanswered SMBs to the server when using */ - /* multiplexed reads or writes */ - unsigned int maxBuf; /* maxBuf specifies the maximum */ - /* message size the server can send or receive for non-raw SMBs */ - /* maxBuf is returned by SMB NegotiateProtocol so maxBuf is only 0 */ - /* when socket is setup (and during reconnect) before NegProt sent */ - unsigned int max_rw; /* maxRw specifies the maximum */ - /* message size the server can send or receive for */ - /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ - unsigned int max_vcs; /* maximum number of smb sessions, at least - those that can be specified uniquely with - vcnumbers */ - int capabilities; /* allow selective disabling of caps by smb sess */ - int timeAdj; /* Adjust for difference in server time zone in sec */ - __u64 CurrentMid; /* multiplex id - rotating counter */ - char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */ - /* 16th byte of RFC1001 workstation name is always null */ - char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; - __u32 sequence_number; /* for signing, protected by srv_mutex */ - struct session_key session_key; - unsigned long lstrp; /* when we got last response from this server */ - struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */ - /* extended security flavors that server supports */ - bool sec_ntlmssp; /* supports NTLMSSP */ - bool sec_kerberosu2u; /* supports U2U Kerberos */ - bool sec_kerberos; /* supports plain Kerberos */ - bool sec_mskerberos; /* supports legacy MS Kerberos */ - bool large_buf; /* is current buffer large? */ - struct delayed_work echo; /* echo ping workqueue job */ - struct kvec *iov; /* reusable kvec array for receives */ - unsigned int nr_iov; /* number of kvecs in array */ - char *smallbuf; /* pointer to current "small" buffer */ - char *bigbuf; /* pointer to current "big" buffer */ - unsigned int total_read; /* total amount of data read in this pass */ -#ifdef CONFIG_CIFS_FSCACHE - struct fscache_cookie *fscache; /* client index cache cookie */ -#endif -#ifdef CONFIG_CIFS_STATS2 - atomic_t in_send; /* requests trying to send */ - atomic_t num_waiters; /* blocked waiting to get in sendrecv */ -#endif -}; - -static inline unsigned int -in_flight(struct TCP_Server_Info *server) -{ - unsigned int num; - spin_lock(&server->req_lock); - num = server->in_flight; - spin_unlock(&server->req_lock); - return num; -} - -static inline int* -get_credits_field(struct TCP_Server_Info *server) -{ - /* - * This will change to switch statement when we reserve slots for echos - * and oplock breaks. - */ - return &server->credits; -} - -static inline bool -has_credits(struct TCP_Server_Info *server, int *credits) -{ - int num; - spin_lock(&server->req_lock); - num = *credits; - spin_unlock(&server->req_lock); - return num > 0; -} - -static inline size_t -header_size(void) -{ - return sizeof(struct smb_hdr); -} - -static inline size_t -max_header_size(void) -{ - return MAX_CIFS_HDR_SIZE; -} - -/* - * Macros to allow the TCP_Server_Info->net field and related code to drop out - * when CONFIG_NET_NS isn't set. - */ - -#ifdef CONFIG_NET_NS - -static inline struct net *cifs_net_ns(struct TCP_Server_Info *srv) -{ - return srv->net; -} - -static inline void cifs_set_net_ns(struct TCP_Server_Info *srv, struct net *net) -{ - srv->net = net; -} - -#else - -static inline struct net *cifs_net_ns(struct TCP_Server_Info *srv) -{ - return &init_net; -} - -static inline void cifs_set_net_ns(struct TCP_Server_Info *srv, struct net *net) -{ -} - -#endif - -/* - * Session structure. One of these for each uid session with a particular host - */ -struct cifs_ses { - struct list_head smb_ses_list; - struct list_head tcon_list; - struct mutex session_mutex; - struct TCP_Server_Info *server; /* pointer to server info */ - int ses_count; /* reference counter */ - enum statusEnum status; - unsigned overrideSecFlg; /* if non-zero override global sec flags */ - __u16 ipc_tid; /* special tid for connection to IPC share */ - __u16 flags; - __u16 vcnum; - char *serverOS; /* name of operating system underlying server */ - char *serverNOS; /* name of network operating system of server */ - char *serverDomain; /* security realm of server */ - int Suid; /* remote smb uid */ - uid_t linux_uid; /* overriding owner of files on the mount */ - uid_t cred_uid; /* owner of credentials */ - int capabilities; - char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for - TCP names - will ipv6 and sctp addresses fit? */ - char *user_name; /* must not be null except during init of sess - and after mount option parsing we fill it */ - char *domainName; - char *password; - struct session_key auth_key; - struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */ - bool need_reconnect:1; /* connection reset, uid now invalid */ -}; -/* no more than one of the following three session flags may be set */ -#define CIFS_SES_NT4 1 -#define CIFS_SES_OS2 2 -#define CIFS_SES_W9X 4 -/* following flag is set for old servers such as OS2 (and Win95?) - which do not negotiate NTLM or POSIX dialects, but instead - negotiate one of the older LANMAN dialects */ -#define CIFS_SES_LANMAN 8 -/* - * there is one of these for each connection to a resource on a particular - * session - */ -struct cifs_tcon { - struct list_head tcon_list; - int tc_count; - struct list_head openFileList; - struct cifs_ses *ses; /* pointer to session associated with */ - char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */ - char *nativeFileSystem; - char *password; /* for share-level security */ - __u16 tid; /* The 2 byte tree id */ - __u16 Flags; /* optional support bits */ - enum statusEnum tidStatus; -#ifdef CONFIG_CIFS_STATS - atomic_t num_smbs_sent; - atomic_t num_writes; - atomic_t num_reads; - atomic_t num_flushes; - atomic_t num_oplock_brks; - atomic_t num_opens; - atomic_t num_closes; - atomic_t num_deletes; - atomic_t num_mkdirs; - atomic_t num_posixopens; - atomic_t num_posixmkdirs; - atomic_t num_rmdirs; - atomic_t num_renames; - atomic_t num_t2renames; - atomic_t num_ffirst; - atomic_t num_fnext; - atomic_t num_fclose; - atomic_t num_hardlinks; - atomic_t num_symlinks; - atomic_t num_locks; - atomic_t num_acl_get; - atomic_t num_acl_set; -#ifdef CONFIG_CIFS_STATS2 - unsigned long long time_writes; - unsigned long long time_reads; - unsigned long long time_opens; - unsigned long long time_deletes; - unsigned long long time_closes; - unsigned long long time_mkdirs; - unsigned long long time_rmdirs; - unsigned long long time_renames; - unsigned long long time_t2renames; - unsigned long long time_ffirst; - unsigned long long time_fnext; - unsigned long long time_fclose; -#endif /* CONFIG_CIFS_STATS2 */ - __u64 bytes_read; - __u64 bytes_written; - spinlock_t stat_lock; -#endif /* CONFIG_CIFS_STATS */ - FILE_SYSTEM_DEVICE_INFO fsDevInfo; - FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */ - FILE_SYSTEM_UNIX_INFO fsUnixInfo; - bool ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */ - bool retry:1; - bool nocase:1; - bool seal:1; /* transport encryption for this mounted share */ - bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol - for this mount even if server would support */ - bool local_lease:1; /* check leases (only) on local system not remote */ - bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ - bool need_reconnect:1; /* connection reset, tid now invalid */ -#ifdef CONFIG_CIFS_FSCACHE - u64 resource_id; /* server resource id */ - struct fscache_cookie *fscache; /* cookie for share */ -#endif - /* BB add field for back pointer to sb struct(s)? */ -}; - -/* - * This is a refcounted and timestamped container for a tcon pointer. The - * container holds a tcon reference. It is considered safe to free one of - * these when the tl_count goes to 0. The tl_time is the time of the last - * "get" on the container. - */ -struct tcon_link { - struct rb_node tl_rbnode; - uid_t tl_uid; - unsigned long tl_flags; -#define TCON_LINK_MASTER 0 -#define TCON_LINK_PENDING 1 -#define TCON_LINK_IN_TREE 2 - unsigned long tl_time; - atomic_t tl_count; - struct cifs_tcon *tl_tcon; -}; - -extern struct tcon_link *cifs_sb_tlink(struct cifs_sb_info *cifs_sb); - -static inline struct cifs_tcon * -tlink_tcon(struct tcon_link *tlink) -{ - return tlink->tl_tcon; -} - -extern void cifs_put_tlink(struct tcon_link *tlink); - -static inline struct tcon_link * -cifs_get_tlink(struct tcon_link *tlink) -{ - if (tlink && !IS_ERR(tlink)) - atomic_inc(&tlink->tl_count); - return tlink; -} - -/* This function is always expected to succeed */ -extern struct cifs_tcon *cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb); - -/* - * This info hangs off the cifsFileInfo structure, pointed to by llist. - * This is used to track byte stream locks on the file - */ -struct cifsLockInfo { - struct list_head llist; /* pointer to next cifsLockInfo */ - struct list_head blist; /* pointer to locks blocked on this */ - wait_queue_head_t block_q; - __u64 offset; - __u64 length; - __u32 pid; - __u8 type; - __u16 netfid; -}; - -/* - * One of these for each open instance of a file - */ -struct cifs_search_info { - loff_t index_of_last_entry; - __u16 entries_in_buffer; - __u16 info_level; - __u32 resume_key; - char *ntwrk_buf_start; - char *srch_entries_start; - char *last_entry; - const char *presume_name; - unsigned int resume_name_len; - bool endOfSearch:1; - bool emptyDir:1; - bool unicode:1; - bool smallBuf:1; /* so we know which buf_release function to call */ -}; - -struct cifsFileInfo { - struct list_head tlist; /* pointer to next fid owned by tcon */ - struct list_head flist; /* next fid (file instance) for this inode */ - unsigned int uid; /* allows finding which FileInfo structure */ - __u32 pid; /* process id who opened file */ - __u16 netfid; /* file id from remote */ - /* BB add lock scope info here if needed */ ; - /* lock scope id (0 if none) */ - struct dentry *dentry; - unsigned int f_flags; - struct tcon_link *tlink; - bool invalidHandle:1; /* file closed via session abend */ - bool oplock_break_cancelled:1; - int count; /* refcount protected by cifs_file_list_lock */ - struct mutex fh_mutex; /* prevents reopen race after dead ses*/ - struct cifs_search_info srch_inf; - struct work_struct oplock_break; /* work for oplock breaks */ -}; - -struct cifs_io_parms { - __u16 netfid; - __u32 pid; - __u64 offset; - unsigned int length; - struct cifs_tcon *tcon; -}; - -/* - * Take a reference on the file private data. Must be called with - * cifs_file_list_lock held. - */ -static inline -struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file) -{ - ++cifs_file->count; - return cifs_file; -} - -void cifsFileInfo_put(struct cifsFileInfo *cifs_file); - -/* - * One of these for each file inode - */ - -struct cifsInodeInfo { - struct list_head llist; /* brlocks for this inode */ - bool can_cache_brlcks; - struct mutex lock_mutex; /* protect two fields above */ - /* BB add in lists for dirty pages i.e. write caching info for oplock */ - struct list_head openFileList; - __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ - bool clientCanCacheRead; /* read oplock */ - bool clientCanCacheAll; /* read and writebehind oplock */ - bool delete_pending; /* DELETE_ON_CLOSE is set */ - bool invalid_mapping; /* pagecache is invalid */ - unsigned long time; /* jiffies of last update of inode */ - u64 server_eof; /* current file size on server -- protected by i_lock */ - u64 uniqueid; /* server inode number */ - u64 createtime; /* creation time on server */ -#ifdef CONFIG_CIFS_FSCACHE - struct fscache_cookie *fscache; -#endif - struct inode vfs_inode; -}; - -static inline struct cifsInodeInfo * -CIFS_I(struct inode *inode) -{ - return container_of(inode, struct cifsInodeInfo, vfs_inode); -} - -static inline struct cifs_sb_info * -CIFS_SB(struct super_block *sb) -{ - return sb->s_fs_info; -} - -static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb) -{ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) - return '/'; - else - return '\\'; -} - -static inline void -convert_delimiter(char *path, char delim) -{ - int i; - char old_delim; - - if (path == NULL) - return; - - if (delim == '/') - old_delim = '\\'; - else - old_delim = '/'; - - for (i = 0; path[i] != '\0'; i++) { - if (path[i] == old_delim) - path[i] = delim; - } -} - -#ifdef CONFIG_CIFS_STATS -#define cifs_stats_inc atomic_inc - -static inline void cifs_stats_bytes_written(struct cifs_tcon *tcon, - unsigned int bytes) -{ - if (bytes) { - spin_lock(&tcon->stat_lock); - tcon->bytes_written += bytes; - spin_unlock(&tcon->stat_lock); - } -} - -static inline void cifs_stats_bytes_read(struct cifs_tcon *tcon, - unsigned int bytes) -{ - spin_lock(&tcon->stat_lock); - tcon->bytes_read += bytes; - spin_unlock(&tcon->stat_lock); -} -#else - -#define cifs_stats_inc(field) do {} while (0) -#define cifs_stats_bytes_written(tcon, bytes) do {} while (0) -#define cifs_stats_bytes_read(tcon, bytes) do {} while (0) - -#endif - -struct mid_q_entry; - -/* - * This is the prototype for the mid receive function. This function is for - * receiving the rest of the SMB frame, starting with the WordCount (which is - * just after the MID in struct smb_hdr). Note: - * - * - This will be called by cifsd, with no locks held. - * - The mid will still be on the pending_mid_q. - * - mid->resp_buf will point to the current buffer. - * - * Returns zero on a successful receive, or an error. The receive state in - * the TCP_Server_Info will also be updated. - */ -typedef int (mid_receive_t)(struct TCP_Server_Info *server, - struct mid_q_entry *mid); - -/* - * This is the prototype for the mid callback function. This is called once the - * mid has been received off of the socket. When creating one, take special - * care to avoid deadlocks. Things to bear in mind: - * - * - it will be called by cifsd, with no locks held - * - the mid will be removed from any lists - */ -typedef void (mid_callback_t)(struct mid_q_entry *mid); - -/* one of these for every pending CIFS request to the server */ -struct mid_q_entry { - struct list_head qhead; /* mids waiting on reply from this server */ - __u64 mid; /* multiplex id */ - __u32 pid; /* process id */ - __u32 sequence_number; /* for CIFS signing */ - unsigned long when_alloc; /* when mid was created */ -#ifdef CONFIG_CIFS_STATS2 - unsigned long when_sent; /* time when smb send finished */ - unsigned long when_received; /* when demux complete (taken off wire) */ -#endif - mid_receive_t *receive; /* call receive callback */ - mid_callback_t *callback; /* call completion callback */ - void *callback_data; /* general purpose pointer for callback */ - void *resp_buf; /* pointer to received SMB header */ - int mid_state; /* wish this were enum but can not pass to wait_event */ - __le16 command; /* smb command code */ - bool large_buf:1; /* if valid response, is pointer to large buf */ - bool multiRsp:1; /* multiple trans2 responses for one request */ - bool multiEnd:1; /* both received */ -}; - -/* Make code in transport.c a little cleaner by moving - update of optional stats into function below */ -#ifdef CONFIG_CIFS_STATS2 - -static inline void cifs_in_send_inc(struct TCP_Server_Info *server) -{ - atomic_inc(&server->in_send); -} - -static inline void cifs_in_send_dec(struct TCP_Server_Info *server) -{ - atomic_dec(&server->in_send); -} - -static inline void cifs_num_waiters_inc(struct TCP_Server_Info *server) -{ - atomic_inc(&server->num_waiters); -} - -static inline void cifs_num_waiters_dec(struct TCP_Server_Info *server) -{ - atomic_dec(&server->num_waiters); -} - -static inline void cifs_save_when_sent(struct mid_q_entry *mid) -{ - mid->when_sent = jiffies; -} -#else -static inline void cifs_in_send_inc(struct TCP_Server_Info *server) -{ -} -static inline void cifs_in_send_dec(struct TCP_Server_Info *server) -{ -} - -static inline void cifs_num_waiters_inc(struct TCP_Server_Info *server) -{ -} - -static inline void cifs_num_waiters_dec(struct TCP_Server_Info *server) -{ -} - -static inline void cifs_save_when_sent(struct mid_q_entry *mid) -{ -} -#endif - -/* for pending dnotify requests */ -struct dir_notify_req { - struct list_head lhead; - __le16 Pid; - __le16 PidHigh; - __u16 Mid; - __u16 Tid; - __u16 Uid; - __u16 netfid; - __u32 filter; /* CompletionFilter (for multishot) */ - int multishot; - struct file *pfile; -}; - -struct dfs_info3_param { - int flags; /* DFSREF_REFERRAL_SERVER, DFSREF_STORAGE_SERVER*/ - int path_consumed; - int server_type; - int ref_flag; - char *path_name; - char *node_name; -}; - -/* - * common struct for holding inode info when searching for or updating an - * inode with new info - */ - -#define CIFS_FATTR_DFS_REFERRAL 0x1 -#define CIFS_FATTR_DELETE_PENDING 0x2 -#define CIFS_FATTR_NEED_REVAL 0x4 -#define CIFS_FATTR_INO_COLLISION 0x8 - -struct cifs_fattr { - u32 cf_flags; - u32 cf_cifsattrs; - u64 cf_uniqueid; - u64 cf_eof; - u64 cf_bytes; - u64 cf_createtime; - uid_t cf_uid; - gid_t cf_gid; - umode_t cf_mode; - dev_t cf_rdev; - unsigned int cf_nlink; - unsigned int cf_dtype; - struct timespec cf_atime; - struct timespec cf_mtime; - struct timespec cf_ctime; -}; - -static inline void free_dfs_info_param(struct dfs_info3_param *param) -{ - if (param) { - kfree(param->path_name); - kfree(param->node_name); - kfree(param); - } -} - -static inline void free_dfs_info_array(struct dfs_info3_param *param, - int number_of_items) -{ - int i; - if ((number_of_items == 0) || (param == NULL)) - return; - for (i = 0; i < number_of_items; i++) { - kfree(param[i].path_name); - kfree(param[i].node_name); - } - kfree(param); -} - -#define MID_FREE 0 -#define MID_REQUEST_ALLOCATED 1 -#define MID_REQUEST_SUBMITTED 2 -#define MID_RESPONSE_RECEIVED 4 -#define MID_RETRY_NEEDED 8 /* session closed while this request out */ -#define MID_RESPONSE_MALFORMED 0x10 -#define MID_SHUTDOWN 0x20 - -/* Types of response buffer returned from SendReceive2 */ -#define CIFS_NO_BUFFER 0 /* Response buffer not returned */ -#define CIFS_SMALL_BUFFER 1 -#define CIFS_LARGE_BUFFER 2 -#define CIFS_IOVEC 4 /* array of response buffers */ - -/* Type of Request to SendReceive2 */ -#define CIFS_BLOCKING_OP 1 /* operation can block */ -#define CIFS_ASYNC_OP 2 /* do not wait for response */ -#define CIFS_TIMEOUT_MASK 0x003 /* only one of above set in req */ -#define CIFS_LOG_ERROR 0x010 /* log NT STATUS if non-zero */ -#define CIFS_LARGE_BUF_OP 0x020 /* large request buffer */ -#define CIFS_NO_RESP 0x040 /* no response buffer required */ - -/* Security Flags: indicate type of session setup needed */ -#define CIFSSEC_MAY_SIGN 0x00001 -#define CIFSSEC_MAY_NTLM 0x00002 -#define CIFSSEC_MAY_NTLMV2 0x00004 -#define CIFSSEC_MAY_KRB5 0x00008 -#ifdef CONFIG_CIFS_WEAK_PW_HASH -#define CIFSSEC_MAY_LANMAN 0x00010 -#define CIFSSEC_MAY_PLNTXT 0x00020 -#else -#define CIFSSEC_MAY_LANMAN 0 -#define CIFSSEC_MAY_PLNTXT 0 -#endif /* weak passwords */ -#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */ -#define CIFSSEC_MAY_NTLMSSP 0x00080 /* raw ntlmssp with ntlmv2 */ - -#define CIFSSEC_MUST_SIGN 0x01001 -/* note that only one of the following can be set so the -result of setting MUST flags more than once will be to -require use of the stronger protocol */ -#define CIFSSEC_MUST_NTLM 0x02002 -#define CIFSSEC_MUST_NTLMV2 0x04004 -#define CIFSSEC_MUST_KRB5 0x08008 -#ifdef CONFIG_CIFS_WEAK_PW_HASH -#define CIFSSEC_MUST_LANMAN 0x10010 -#define CIFSSEC_MUST_PLNTXT 0x20020 -#ifdef CONFIG_CIFS_UPCALL -#define CIFSSEC_MASK 0xBF0BF /* allows weak security but also krb5 */ -#else -#define CIFSSEC_MASK 0xB70B7 /* current flags supported if weak */ -#endif /* UPCALL */ -#else /* do not allow weak pw hash */ -#define CIFSSEC_MUST_LANMAN 0 -#define CIFSSEC_MUST_PLNTXT 0 -#ifdef CONFIG_CIFS_UPCALL -#define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */ -#else -#define CIFSSEC_MASK 0x87087 /* flags supported if no weak allowed */ -#endif /* UPCALL */ -#endif /* WEAK_PW_HASH */ -#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ -#define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */ - -#define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2) -#define CIFSSEC_MAX (CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2) -#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP) -/* - ***************************************************************** - * All constants go here - ***************************************************************** - */ - -#define UID_HASH (16) - -/* - * Note that ONE module should define _DECLARE_GLOBALS_HERE to cause the - * following to be declared. - */ - -/**************************************************************************** - * Locking notes. All updates to global variables and lists should be - * protected by spinlocks or semaphores. - * - * Spinlocks - * --------- - * GlobalMid_Lock protects: - * list operations on pending_mid_q and oplockQ - * updates to XID counters, multiplex id and SMB sequence numbers - * cifs_file_list_lock protects: - * list operations on tcp and SMB session lists and tCon lists - * f_owner.lock protects certain per file struct operations - * mapping->page_lock protects certain per page operations - * - * Semaphores - * ---------- - * sesSem operations on smb session - * tconSem operations on tree connection - * fh_sem file handle reconnection operations - * - ****************************************************************************/ - -#ifdef DECLARE_GLOBALS_HERE -#define GLOBAL_EXTERN -#else -#define GLOBAL_EXTERN extern -#endif - -/* - * the list of TCP_Server_Info structures, ie each of the sockets - * connecting our client to a distinct server (ip address), is - * chained together by cifs_tcp_ses_list. The list of all our SMB - * sessions (and from that the tree connections) can be found - * by iterating over cifs_tcp_ses_list - */ -GLOBAL_EXTERN struct list_head cifs_tcp_ses_list; - -/* - * This lock protects the cifs_tcp_ses_list, the list of smb sessions per - * tcp session, and the list of tcon's per smb session. It also protects - * the reference counters for the server, smb session, and tcon. Finally, - * changes to the tcon->tidStatus should be done while holding this lock. - */ -GLOBAL_EXTERN spinlock_t cifs_tcp_ses_lock; - -/* - * This lock protects the cifs_file->llist and cifs_file->flist - * list operations, and updates to some flags (cifs_file->invalidHandle) - * It will be moved to either use the tcon->stat_lock or equivalent later. - * If cifs_tcp_ses_lock and the lock below are both needed to be held, then - * the cifs_tcp_ses_lock must be grabbed first and released last. - */ -GLOBAL_EXTERN spinlock_t cifs_file_list_lock; - -#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */ -/* Outstanding dir notify requests */ -GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; -/* DirNotify response queue */ -GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q; -#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ - -/* - * Global transaction id (XID) information - */ -GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */ -GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */ -GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */ -GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above & list operations */ - /* on midQ entries */ -/* - * Global counters, updated atomically - */ -GLOBAL_EXTERN atomic_t sesInfoAllocCount; -GLOBAL_EXTERN atomic_t tconInfoAllocCount; -GLOBAL_EXTERN atomic_t tcpSesAllocCount; -GLOBAL_EXTERN atomic_t tcpSesReconnectCount; -GLOBAL_EXTERN atomic_t tconInfoReconnectCount; - -/* Various Debug counters */ -GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */ -#ifdef CONFIG_CIFS_STATS2 -GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */ -GLOBAL_EXTERN atomic_t totSmBufAllocCount; -#endif -GLOBAL_EXTERN atomic_t smBufAllocCount; -GLOBAL_EXTERN atomic_t midCount; - -/* Misc globals */ -GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions - to be established on existing mount if we - have the uid/password or Kerberos credential - or equivalent for current user */ -/* enable or disable oplocks */ -GLOBAL_EXTERN bool enable_oplocks; -GLOBAL_EXTERN unsigned int lookupCacheEnabled; -GLOBAL_EXTERN unsigned int global_secflags; /* if on, session setup sent - with more secure ntlmssp2 challenge/resp */ -GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ -GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ -GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */ -GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ -GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ -GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ - -#ifdef CONFIG_CIFS_ACL -GLOBAL_EXTERN struct rb_root uidtree; -GLOBAL_EXTERN struct rb_root gidtree; -GLOBAL_EXTERN spinlock_t siduidlock; -GLOBAL_EXTERN spinlock_t sidgidlock; -GLOBAL_EXTERN struct rb_root siduidtree; -GLOBAL_EXTERN struct rb_root sidgidtree; -GLOBAL_EXTERN spinlock_t uidsidlock; -GLOBAL_EXTERN spinlock_t gidsidlock; -#endif /* CONFIG_CIFS_ACL */ - -void cifs_oplock_break(struct work_struct *work); - -extern const struct slow_work_ops cifs_oplock_break_ops; -extern struct workqueue_struct *cifsiod_wq; - -#endif /* _CIFS_GLOB_H */ diff --git a/ANDROID_3.4.5/fs/cifs/cifspdu.h b/ANDROID_3.4.5/fs/cifs/cifspdu.h deleted file mode 100644 index 3fb03e2c..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifspdu.h +++ /dev/null @@ -1,2669 +0,0 @@ -/* - * fs/cifs/cifspdu.h - * - * Copyright (c) International Business Machines Corp., 2002,2009 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _CIFSPDU_H -#define _CIFSPDU_H - -#include <net/sock.h> -#include <asm/unaligned.h> -#include "smbfsctl.h" - -#ifdef CONFIG_CIFS_WEAK_PW_HASH -#define LANMAN_PROT 0 -#define LANMAN2_PROT 1 -#define CIFS_PROT 2 -#else -#define CIFS_PROT 0 -#endif -#define POSIX_PROT (CIFS_PROT+1) -#define BAD_PROT 0xFFFF - -/* SMB command codes: - * Note some commands have minimal (wct=0,bcc=0), or uninteresting, responses - * (ie which include no useful data other than the SMB error code itself). - * This can allow us to avoid response buffer allocations and copy in some cases - */ -#define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */ -#define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */ -#define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */ -#define SMB_COM_FLUSH 0x05 /* triv req/rsp */ -#define SMB_COM_DELETE 0x06 /* trivial response */ -#define SMB_COM_RENAME 0x07 /* trivial response */ -#define SMB_COM_QUERY_INFORMATION 0x08 /* aka getattr */ -#define SMB_COM_SETATTR 0x09 /* trivial response */ -#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */ -#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/ -#define SMB_COM_ECHO 0x2B /* echo request */ -#define SMB_COM_OPEN_ANDX 0x2D /* Legacy open for old servers */ -#define SMB_COM_READ_ANDX 0x2E -#define SMB_COM_WRITE_ANDX 0x2F -#define SMB_COM_TRANSACTION2 0x32 -#define SMB_COM_TRANSACTION2_SECONDARY 0x33 -#define SMB_COM_FIND_CLOSE2 0x34 /* trivial response */ -#define SMB_COM_TREE_DISCONNECT 0x71 /* trivial response */ -#define SMB_COM_NEGOTIATE 0x72 -#define SMB_COM_SESSION_SETUP_ANDX 0x73 -#define SMB_COM_LOGOFF_ANDX 0x74 /* trivial response */ -#define SMB_COM_TREE_CONNECT_ANDX 0x75 -#define SMB_COM_NT_TRANSACT 0xA0 -#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1 -#define SMB_COM_NT_CREATE_ANDX 0xA2 -#define SMB_COM_NT_CANCEL 0xA4 /* no response */ -#define SMB_COM_NT_RENAME 0xA5 /* trivial response */ - -/* Transact2 subcommand codes */ -#define TRANS2_OPEN 0x00 -#define TRANS2_FIND_FIRST 0x01 -#define TRANS2_FIND_NEXT 0x02 -#define TRANS2_QUERY_FS_INFORMATION 0x03 -#define TRANS2_SET_FS_INFORMATION 0x04 -#define TRANS2_QUERY_PATH_INFORMATION 0x05 -#define TRANS2_SET_PATH_INFORMATION 0x06 -#define TRANS2_QUERY_FILE_INFORMATION 0x07 -#define TRANS2_SET_FILE_INFORMATION 0x08 -#define TRANS2_GET_DFS_REFERRAL 0x10 -#define TRANS2_REPORT_DFS_INCOSISTENCY 0x11 - -/* SMB Transact (Named Pipe) subcommand codes */ -#define TRANS_SET_NMPIPE_STATE 0x0001 -#define TRANS_RAW_READ_NMPIPE 0x0011 -#define TRANS_QUERY_NMPIPE_STATE 0x0021 -#define TRANS_QUERY_NMPIPE_INFO 0x0022 -#define TRANS_PEEK_NMPIPE 0x0023 -#define TRANS_TRANSACT_NMPIPE 0x0026 -#define TRANS_RAW_WRITE_NMPIPE 0x0031 -#define TRANS_READ_NMPIPE 0x0036 -#define TRANS_WRITE_NMPIPE 0x0037 -#define TRANS_WAIT_NMPIPE 0x0053 -#define TRANS_CALL_NMPIPE 0x0054 - -/* NT Transact subcommand codes */ -#define NT_TRANSACT_CREATE 0x01 -#define NT_TRANSACT_IOCTL 0x02 -#define NT_TRANSACT_SET_SECURITY_DESC 0x03 -#define NT_TRANSACT_NOTIFY_CHANGE 0x04 -#define NT_TRANSACT_RENAME 0x05 -#define NT_TRANSACT_QUERY_SECURITY_DESC 0x06 -#define NT_TRANSACT_GET_USER_QUOTA 0x07 -#define NT_TRANSACT_SET_USER_QUOTA 0x08 - -#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */ -/* future chained NTCreateXReadX bigger, but for time being NTCreateX biggest */ -/* among the requests (NTCreateX response is bigger with wct of 34) */ -#define MAX_CIFS_HDR_SIZE 0x58 /* 4 len + 32 hdr + (2*24 wct) + 2 bct + 2 pad */ -#define CIFS_SMALL_PATH 120 /* allows for (448-88)/3 */ - -/* internal cifs vfs structures */ -/***************************************************************** - * All constants go here - ***************************************************************** - */ - -/* - * Starting value for maximum SMB size negotiation - */ -#define CIFS_MAX_MSGSIZE (4*4096) - -/* - * Size of encrypted user password in bytes - */ -#define CIFS_ENCPWD_SIZE (16) - -/* - * Size of the crypto key returned on the negotiate SMB in bytes - */ -#define CIFS_CRYPTO_KEY_SIZE (8) - -/* - * Size of the ntlm client response - */ -#define CIFS_AUTH_RESP_SIZE (24) - -/* - * Size of the session key (crypto key encrypted with the password - */ -#define CIFS_SESS_KEY_SIZE (16) - -#define CIFS_CLIENT_CHALLENGE_SIZE (8) -#define CIFS_SERVER_CHALLENGE_SIZE (8) -#define CIFS_HMAC_MD5_HASH_SIZE (16) -#define CIFS_CPHTXT_SIZE (16) -#define CIFS_NTHASH_SIZE (16) - -/* - * Maximum user name length - */ -#define CIFS_UNLEN (20) - -/* - * Flags on SMB open - */ -#define SMBOPEN_WRITE_THROUGH 0x4000 -#define SMBOPEN_DENY_ALL 0x0010 -#define SMBOPEN_DENY_WRITE 0x0020 -#define SMBOPEN_DENY_READ 0x0030 -#define SMBOPEN_DENY_NONE 0x0040 -#define SMBOPEN_READ 0x0000 -#define SMBOPEN_WRITE 0x0001 -#define SMBOPEN_READWRITE 0x0002 -#define SMBOPEN_EXECUTE 0x0003 - -#define SMBOPEN_OCREATE 0x0010 -#define SMBOPEN_OTRUNC 0x0002 -#define SMBOPEN_OAPPEND 0x0001 - -/* - * SMB flag definitions - */ -#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock smb */ -#define SMBFLG_RCV_POSTED 0x02 /* obsolete */ -#define SMBFLG_RSVD 0x04 -#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off - implies case sensitive file handling request) */ -#define SMBFLG_CANONICAL_PATH_FORMAT 0x10 /* obsolete */ -#define SMBFLG_OLD_OPLOCK 0x20 /* obsolete */ -#define SMBFLG_OLD_OPLOCK_NOTIFY 0x40 /* obsolete */ -#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */ - -/* - * SMB flag2 definitions - */ -#define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1) /* can send long (non-8.3) - path names in response */ -#define SMBFLG2_KNOWS_EAS cpu_to_le16(2) -#define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4) -#define SMBFLG2_COMPRESSED (8) -#define SMBFLG2_SECURITY_SIGNATURE_REQUIRED (0x10) -#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40) -#define SMBFLG2_REPARSE_PATH (0x400) -#define SMBFLG2_EXT_SEC cpu_to_le16(0x800) -#define SMBFLG2_DFS cpu_to_le16(0x1000) -#define SMBFLG2_PAGING_IO cpu_to_le16(0x2000) -#define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000) -#define SMBFLG2_UNICODE cpu_to_le16(0x8000) - -/* - * These are the file access permission bits defined in CIFS for the - * NTCreateAndX as well as the level 0x107 - * TRANS2_QUERY_PATH_INFORMATION API. The level 0x107, SMB_QUERY_FILE_ALL_INFO - * responds with the AccessFlags. - * The AccessFlags specifies the access permissions a caller has to the - * file and can have any suitable combination of the following values: - */ - -#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */ -#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */ -#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */ -#define FILE_READ_EA 0x00000008 /* Extended attributes associated */ - /* with the file can be read */ -#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */ - /* with the file can be written */ -#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */ - /* the file using system paging I/O */ -#define FILE_DELETE_CHILD 0x00000040 -#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */ - /* file can be read */ -#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */ - /* file can be written */ -#define DELETE 0x00010000 /* The file can be deleted */ -#define READ_CONTROL 0x00020000 /* The access control list and */ - /* ownership associated with the */ - /* file can be read */ -#define WRITE_DAC 0x00040000 /* The access control list and */ - /* ownership associated with the */ - /* file can be written. */ -#define WRITE_OWNER 0x00080000 /* Ownership information associated */ - /* with the file can be written */ -#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */ - /* synchronize with the completion */ - /* of an input/output request */ -#define GENERIC_ALL 0x10000000 -#define GENERIC_EXECUTE 0x20000000 -#define GENERIC_WRITE 0x40000000 -#define GENERIC_READ 0x80000000 - /* In summary - Relevant file */ - /* access flags from CIFS are */ - /* file_read_data, file_write_data */ - /* file_execute, file_read_attributes*/ - /* write_dac, and delete. */ - -#define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES) -#define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \ - | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES) -#define FILE_EXEC_RIGHTS (FILE_EXECUTE) - -#define SET_FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_WRITE_EA \ - | FILE_READ_ATTRIBUTES \ - | FILE_WRITE_ATTRIBUTES \ - | DELETE | READ_CONTROL | WRITE_DAC \ - | WRITE_OWNER | SYNCHRONIZE) -#define SET_FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \ - | FILE_READ_EA | FILE_WRITE_EA \ - | FILE_DELETE_CHILD | FILE_READ_ATTRIBUTES \ - | FILE_WRITE_ATTRIBUTES \ - | DELETE | READ_CONTROL | WRITE_DAC \ - | WRITE_OWNER | SYNCHRONIZE) -#define SET_FILE_EXEC_RIGHTS (FILE_READ_EA | FILE_WRITE_EA | FILE_EXECUTE \ - | FILE_READ_ATTRIBUTES \ - | FILE_WRITE_ATTRIBUTES \ - | DELETE | READ_CONTROL | WRITE_DAC \ - | WRITE_OWNER | SYNCHRONIZE) - -#define SET_MINIMUM_RIGHTS (FILE_READ_EA | FILE_READ_ATTRIBUTES \ - | READ_CONTROL | SYNCHRONIZE) - - -/* - * Invalid readdir handle - */ -#define CIFS_NO_HANDLE 0xFFFF - -#define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL -#define NO_CHANGE_32 0xFFFFFFFFUL - -/* IPC$ in ASCII */ -#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24" - -/* IPC$ in Unicode */ -#define CIFS_IPC_UNICODE_RESOURCE "\x00\x49\x00\x50\x00\x43\x00\x24\x00\x00" - -/* Unicode Null terminate 2 bytes of 0 */ -#define UNICODE_NULL "\x00\x00" -#define ASCII_NULL 0x00 - -/* - * Server type values (returned on EnumServer API - */ -#define CIFS_SV_TYPE_DC 0x00000008 -#define CIFS_SV_TYPE_BACKDC 0x00000010 - -/* - * Alias type flags (From EnumAlias API call - */ -#define CIFS_ALIAS_TYPE_FILE 0x0001 -#define CIFS_SHARE_TYPE_FILE 0x0000 - -/* - * File Attribute flags - */ -#define ATTR_READONLY 0x0001 -#define ATTR_HIDDEN 0x0002 -#define ATTR_SYSTEM 0x0004 -#define ATTR_VOLUME 0x0008 -#define ATTR_DIRECTORY 0x0010 -#define ATTR_ARCHIVE 0x0020 -#define ATTR_DEVICE 0x0040 -#define ATTR_NORMAL 0x0080 -#define ATTR_TEMPORARY 0x0100 -#define ATTR_SPARSE 0x0200 -#define ATTR_REPARSE 0x0400 -#define ATTR_COMPRESSED 0x0800 -#define ATTR_OFFLINE 0x1000 /* ie file not immediately available - - on offline storage */ -#define ATTR_NOT_CONTENT_INDEXED 0x2000 -#define ATTR_ENCRYPTED 0x4000 -#define ATTR_POSIX_SEMANTICS 0x01000000 -#define ATTR_BACKUP_SEMANTICS 0x02000000 -#define ATTR_DELETE_ON_CLOSE 0x04000000 -#define ATTR_SEQUENTIAL_SCAN 0x08000000 -#define ATTR_RANDOM_ACCESS 0x10000000 -#define ATTR_NO_BUFFERING 0x20000000 -#define ATTR_WRITE_THROUGH 0x80000000 - -/* ShareAccess flags */ -#define FILE_NO_SHARE 0x00000000 -#define FILE_SHARE_READ 0x00000001 -#define FILE_SHARE_WRITE 0x00000002 -#define FILE_SHARE_DELETE 0x00000004 -#define FILE_SHARE_ALL 0x00000007 - -/* CreateDisposition flags, similar to CreateAction as well */ -#define FILE_SUPERSEDE 0x00000000 -#define FILE_OPEN 0x00000001 -#define FILE_CREATE 0x00000002 -#define FILE_OPEN_IF 0x00000003 -#define FILE_OVERWRITE 0x00000004 -#define FILE_OVERWRITE_IF 0x00000005 - -/* CreateOptions */ -#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */ -#define CREATE_WRITE_THROUGH 0x00000002 -#define CREATE_SEQUENTIAL 0x00000004 -#define CREATE_NO_BUFFER 0x00000008 /* should not buffer on srv */ -#define CREATE_SYNC_ALERT 0x00000010 /* MBZ */ -#define CREATE_ASYNC_ALERT 0x00000020 /* MBZ */ -#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */ -#define CREATE_TREE_CONNECTION 0x00000080 /* should be zero */ -#define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */ -#define CREATE_NO_EA_KNOWLEDGE 0x00000200 -#define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete - "open for recovery" flag should - be zero in any case */ -#define CREATE_OPEN_FOR_RECOVERY 0x00000400 -#define CREATE_RANDOM_ACCESS 0x00000800 -#define CREATE_DELETE_ON_CLOSE 0x00001000 -#define CREATE_OPEN_BY_ID 0x00002000 -#define CREATE_OPEN_BACKUP_INTENT 0x00004000 -#define CREATE_NO_COMPRESSION 0x00008000 -#define CREATE_RESERVE_OPFILTER 0x00100000 /* should be zero */ -#define OPEN_REPARSE_POINT 0x00200000 -#define OPEN_NO_RECALL 0x00400000 -#define OPEN_FREE_SPACE_QUERY 0x00800000 /* should be zero */ -#define CREATE_OPTIONS_MASK 0x007FFFFF -#define CREATE_OPTION_READONLY 0x10000000 -#define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */ - -/* ImpersonationLevel flags */ -#define SECURITY_ANONYMOUS 0 -#define SECURITY_IDENTIFICATION 1 -#define SECURITY_IMPERSONATION 2 -#define SECURITY_DELEGATION 3 - -/* SecurityFlags */ -#define SECURITY_CONTEXT_TRACKING 0x01 -#define SECURITY_EFFECTIVE_ONLY 0x02 - -/* - * Default PID value, used in all SMBs where the PID is not important - */ -#define CIFS_DFT_PID 0x1234 - -/* - * We use the same routine for Copy and Move SMBs. This flag is used to - * distinguish - */ -#define CIFS_COPY_OP 1 -#define CIFS_RENAME_OP 2 - -#define GETU16(var) (*((__u16 *)var)) /* BB check for endian issues */ -#define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */ - -struct smb_hdr { - __be32 smb_buf_length; /* BB length is only two (rarely three) bytes, - with one or two byte "type" preceding it that will be - zero - we could mask the type byte off */ - __u8 Protocol[4]; - __u8 Command; - union { - struct { - __u8 ErrorClass; - __u8 Reserved; - __le16 Error; - } __attribute__((packed)) DosError; - __le32 CifsError; - } __attribute__((packed)) Status; - __u8 Flags; - __le16 Flags2; /* note: le */ - __le16 PidHigh; - union { - struct { - __le32 SequenceNumber; /* le */ - __u32 Reserved; /* zero */ - } __attribute__((packed)) Sequence; - __u8 SecuritySignature[8]; /* le */ - } __attribute__((packed)) Signature; - __u8 pad[2]; - __u16 Tid; - __le16 Pid; - __u16 Uid; - __u16 Mid; - __u8 WordCount; -} __attribute__((packed)); - -/* given a pointer to an smb_hdr, retrieve a void pointer to the ByteCount */ -static inline void * -BCC(struct smb_hdr *smb) -{ - return (void *)smb + sizeof(*smb) + 2 * smb->WordCount; -} - -/* given a pointer to an smb_hdr retrieve the pointer to the byte area */ -#define pByteArea(smb_var) (BCC(smb_var) + 2) - -/* get the unconverted ByteCount for a SMB packet and return it */ -static inline __u16 -get_bcc(struct smb_hdr *hdr) -{ - __le16 *bc_ptr = (__le16 *)BCC(hdr); - - return get_unaligned_le16(bc_ptr); -} - -/* set the ByteCount for a SMB packet in little-endian */ -static inline void -put_bcc(__u16 count, struct smb_hdr *hdr) -{ - __le16 *bc_ptr = (__le16 *)BCC(hdr); - - put_unaligned_le16(count, bc_ptr); -} - -/* - * Computer Name Length (since Netbios name was length 16 with last byte 0x20) - * No longer as important, now that TCP names are more commonly used to - * resolve hosts. - */ -#define CNLEN 15 - -/* - * Share Name Length (SNLEN) - * Note: This length was limited by the SMB used to get - * the Share info. NetShareEnum only returned 13 - * chars, including the null termination. - * This was removed because it no longer is limiting. - */ - -/* - * Comment Length - */ -#define MAXCOMMENTLEN 40 - -/* - * The OS/2 maximum path name - */ -#define MAX_PATHCONF 256 - -/* - * SMB frame definitions (following must be packed structs) - * See the SNIA CIFS Specification for details. - * - * The Naming convention is the lower case version of the - * smb command code name for the struct and this is typedef to the - * uppercase version of the same name with the prefix SMB_ removed - * for brevity. Although typedefs are not commonly used for - * structure definitions in the Linux kernel, their use in the - * CIFS standards document, which this code is based on, may - * make this one of the cases where typedefs for structures make - * sense to improve readability for readers of the standards doc. - * Typedefs can always be removed later if they are too distracting - * and they are only used for the CIFSs PDUs themselves, not - * internal cifs vfs structures - * - */ - -typedef struct negotiate_req { - struct smb_hdr hdr; /* wct = 0 */ - __le16 ByteCount; - unsigned char DialectsArray[1]; -} __attribute__((packed)) NEGOTIATE_REQ; - -/* Dialect index is 13 for LANMAN */ - -#define MIN_TZ_ADJ (15 * 60) /* minimum grid for timezones in seconds */ - -typedef struct lanman_neg_rsp { - struct smb_hdr hdr; /* wct = 13 */ - __le16 DialectIndex; - __le16 SecurityMode; - __le16 MaxBufSize; - __le16 MaxMpxCount; - __le16 MaxNumberVcs; - __le16 RawMode; - __le32 SessionKey; - struct { - __le16 Time; - __le16 Date; - } __attribute__((packed)) SrvTime; - __le16 ServerTimeZone; - __le16 EncryptionKeyLength; - __le16 Reserved; - __u16 ByteCount; - unsigned char EncryptionKey[1]; -} __attribute__((packed)) LANMAN_NEG_RSP; - -#define READ_RAW_ENABLE 1 -#define WRITE_RAW_ENABLE 2 -#define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE) - -typedef struct negotiate_rsp { - struct smb_hdr hdr; /* wct = 17 */ - __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */ - __u8 SecurityMode; - __le16 MaxMpxCount; - __le16 MaxNumberVcs; - __le32 MaxBufferSize; - __le32 MaxRawSize; - __le32 SessionKey; - __le32 Capabilities; /* see below */ - __le32 SystemTimeLow; - __le32 SystemTimeHigh; - __le16 ServerTimeZone; - __u8 EncryptionKeyLength; - __u16 ByteCount; - union { - unsigned char EncryptionKey[1]; /* cap extended security off */ - /* followed by Domain name - if extended security is off */ - /* followed by 16 bytes of server GUID */ - /* then security blob if cap_extended_security negotiated */ - struct { - unsigned char GUID[16]; - unsigned char SecurityBlob[1]; - } __attribute__((packed)) extended_response; - } __attribute__((packed)) u; -} __attribute__((packed)) NEGOTIATE_RSP; - -/* SecurityMode bits */ -#define SECMODE_USER 0x01 /* off indicates share level security */ -#define SECMODE_PW_ENCRYPT 0x02 -#define SECMODE_SIGN_ENABLED 0x04 /* SMB security signatures enabled */ -#define SECMODE_SIGN_REQUIRED 0x08 /* SMB security signatures required */ - -/* Negotiate response Capabilities */ -#define CAP_RAW_MODE 0x00000001 -#define CAP_MPX_MODE 0x00000002 -#define CAP_UNICODE 0x00000004 -#define CAP_LARGE_FILES 0x00000008 -#define CAP_NT_SMBS 0x00000010 /* implies CAP_NT_FIND */ -#define CAP_RPC_REMOTE_APIS 0x00000020 -#define CAP_STATUS32 0x00000040 -#define CAP_LEVEL_II_OPLOCKS 0x00000080 -#define CAP_LOCK_AND_READ 0x00000100 -#define CAP_NT_FIND 0x00000200 -#define CAP_DFS 0x00001000 -#define CAP_INFOLEVEL_PASSTHRU 0x00002000 -#define CAP_LARGE_READ_X 0x00004000 -#define CAP_LARGE_WRITE_X 0x00008000 -#define CAP_LWIO 0x00010000 /* support fctl_srv_req_resume_key */ -#define CAP_UNIX 0x00800000 -#define CAP_COMPRESSED_DATA 0x02000000 -#define CAP_DYNAMIC_REAUTH 0x20000000 -#define CAP_PERSISTENT_HANDLES 0x40000000 -#define CAP_EXTENDED_SECURITY 0x80000000 - -typedef union smb_com_session_setup_andx { - struct { /* request format */ - struct smb_hdr hdr; /* wct = 12 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __le16 MaxBufferSize; - __le16 MaxMpxCount; - __le16 VcNumber; - __u32 SessionKey; - __le16 SecurityBlobLength; - __u32 Reserved; - __le32 Capabilities; /* see below */ - __le16 ByteCount; - unsigned char SecurityBlob[1]; /* followed by */ - /* STRING NativeOS */ - /* STRING NativeLanMan */ - } __attribute__((packed)) req; /* NTLM request format (with - extended security */ - - struct { /* request format */ - struct smb_hdr hdr; /* wct = 13 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __le16 MaxBufferSize; - __le16 MaxMpxCount; - __le16 VcNumber; - __u32 SessionKey; - __le16 CaseInsensitivePasswordLength; /* ASCII password len */ - __le16 CaseSensitivePasswordLength; /* Unicode password length*/ - __u32 Reserved; /* see below */ - __le32 Capabilities; - __le16 ByteCount; - unsigned char CaseInsensitivePassword[1]; /* followed by: */ - /* unsigned char * CaseSensitivePassword; */ - /* STRING AccountName */ - /* STRING PrimaryDomain */ - /* STRING NativeOS */ - /* STRING NativeLanMan */ - } __attribute__((packed)) req_no_secext; /* NTLM request format (without - extended security */ - - struct { /* default (NTLM) response format */ - struct smb_hdr hdr; /* wct = 4 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __le16 Action; /* see below */ - __le16 SecurityBlobLength; - __u16 ByteCount; - unsigned char SecurityBlob[1]; /* followed by */ -/* unsigned char * NativeOS; */ -/* unsigned char * NativeLanMan; */ -/* unsigned char * PrimaryDomain; */ - } __attribute__((packed)) resp; /* NTLM response - (with or without extended sec) */ - - struct { /* request format */ - struct smb_hdr hdr; /* wct = 10 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __le16 MaxBufferSize; - __le16 MaxMpxCount; - __le16 VcNumber; - __u32 SessionKey; - __le16 PasswordLength; - __u32 Reserved; /* encrypt key len and offset */ - __le16 ByteCount; - unsigned char AccountPassword[1]; /* followed by */ - /* STRING AccountName */ - /* STRING PrimaryDomain */ - /* STRING NativeOS */ - /* STRING NativeLanMan */ - } __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) req format */ - - struct { /* default (NTLM) response format */ - struct smb_hdr hdr; /* wct = 3 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __le16 Action; /* see below */ - __u16 ByteCount; - unsigned char NativeOS[1]; /* followed by */ -/* unsigned char * NativeLanMan; */ -/* unsigned char * PrimaryDomain; */ - } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response */ -} __attribute__((packed)) SESSION_SETUP_ANDX; - -/* format of NLTMv2 Response ie "case sensitive password" hash when NTLMv2 */ - -#define NTLMSSP_SERVER_TYPE 1 -#define NTLMSSP_DOMAIN_TYPE 2 -#define NTLMSSP_FQ_DOMAIN_TYPE 3 -#define NTLMSSP_DNS_DOMAIN_TYPE 4 -#define NTLMSSP_DNS_PARENT_TYPE 5 - -struct ntlmssp2_name { - __le16 type; - __le16 length; -/* char name[length]; */ -} __attribute__((packed)); - -struct ntlmv2_resp { - char ntlmv2_hash[CIFS_ENCPWD_SIZE]; - __le32 blob_signature; - __u32 reserved; - __le64 time; - __u64 client_chal; /* random */ - __u32 reserved2; - /* array of name entries could follow ending in minimum 4 byte struct */ -} __attribute__((packed)); - - -#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux" - -/* Capabilities bits (for NTLM SessSetup request) */ -#define CAP_UNICODE 0x00000004 -#define CAP_LARGE_FILES 0x00000008 -#define CAP_NT_SMBS 0x00000010 -#define CAP_STATUS32 0x00000040 -#define CAP_LEVEL_II_OPLOCKS 0x00000080 -#define CAP_NT_FIND 0x00000200 /* reserved should be zero - (because NT_SMBs implies the same thing?) */ -#define CAP_BULK_TRANSFER 0x20000000 -#define CAP_EXTENDED_SECURITY 0x80000000 - -/* Action bits */ -#define GUEST_LOGIN 1 - -typedef struct smb_com_tconx_req { - struct smb_hdr hdr; /* wct = 4 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __le16 Flags; /* see below */ - __le16 PasswordLength; - __le16 ByteCount; - unsigned char Password[1]; /* followed by */ -/* STRING Path *//* \\server\share name */ - /* STRING Service */ -} __attribute__((packed)) TCONX_REQ; - -typedef struct smb_com_tconx_rsp { - struct smb_hdr hdr; /* wct = 3 , not extended response */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __le16 OptionalSupport; /* see below */ - __u16 ByteCount; - unsigned char Service[1]; /* always ASCII, not Unicode */ - /* STRING NativeFileSystem */ -} __attribute__((packed)) TCONX_RSP; - -typedef struct smb_com_tconx_rsp_ext { - struct smb_hdr hdr; /* wct = 7, extended response */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __le16 OptionalSupport; /* see below */ - __le32 MaximalShareAccessRights; - __le32 GuestMaximalShareAccessRights; - __u16 ByteCount; - unsigned char Service[1]; /* always ASCII, not Unicode */ - /* STRING NativeFileSystem */ -} __attribute__((packed)) TCONX_RSP_EXT; - - -/* tree connect Flags */ -#define DISCONNECT_TID 0x0001 -#define TCON_EXTENDED_SIGNATURES 0x0004 -#define TCON_EXTENDED_SECINFO 0x0008 - -/* OptionalSupport bits */ -#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* "must have" directory search bits - (exclusive searches supported) */ -#define SMB_SHARE_IS_IN_DFS 0x0002 -#define SMB_CSC_MASK 0x000C -/* CSC flags defined as follows */ -#define SMB_CSC_CACHE_MANUAL_REINT 0x0000 -#define SMB_CSC_CACHE_AUTO_REINT 0x0004 -#define SMB_CSC_CACHE_VDO 0x0008 -#define SMB_CSC_NO_CACHING 0x000C -#define SMB_UNIQUE_FILE_NAME 0x0010 -#define SMB_EXTENDED_SIGNATURES 0x0020 - -/* services - * - * A: ie disk - * LPT1: ie printer - * IPC ie named pipe - * COMM - * ????? ie any type - * - */ - -typedef struct smb_com_echo_req { - struct smb_hdr hdr; - __le16 EchoCount; - __le16 ByteCount; - char Data[1]; -} __attribute__((packed)) ECHO_REQ; - -typedef struct smb_com_echo_rsp { - struct smb_hdr hdr; - __le16 SequenceNumber; - __le16 ByteCount; - char Data[1]; -} __attribute__((packed)) ECHO_RSP; - -typedef struct smb_com_logoff_andx_req { - struct smb_hdr hdr; /* wct = 2 */ - __u8 AndXCommand; - __u8 AndXReserved; - __u16 AndXOffset; - __u16 ByteCount; -} __attribute__((packed)) LOGOFF_ANDX_REQ; - -typedef struct smb_com_logoff_andx_rsp { - struct smb_hdr hdr; /* wct = 2 */ - __u8 AndXCommand; - __u8 AndXReserved; - __u16 AndXOffset; - __u16 ByteCount; -} __attribute__((packed)) LOGOFF_ANDX_RSP; - -typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on - tree_connect PDU to effect disconnect */ - /* tdis is probably simplest SMB PDU */ - struct { - struct smb_hdr hdr; /* wct = 0 */ - __u16 ByteCount; /* bcc = 0 */ - } __attribute__((packed)) req; - struct { - struct smb_hdr hdr; /* wct = 0 */ - __u16 ByteCount; /* bcc = 0 */ - } __attribute__((packed)) resp; -} __attribute__((packed)) TREE_DISCONNECT; - -typedef struct smb_com_close_req { - struct smb_hdr hdr; /* wct = 3 */ - __u16 FileID; - __u32 LastWriteTime; /* should be zero or -1 */ - __u16 ByteCount; /* 0 */ -} __attribute__((packed)) CLOSE_REQ; - -typedef struct smb_com_close_rsp { - struct smb_hdr hdr; /* wct = 0 */ - __u16 ByteCount; /* bct = 0 */ -} __attribute__((packed)) CLOSE_RSP; - -typedef struct smb_com_flush_req { - struct smb_hdr hdr; /* wct = 1 */ - __u16 FileID; - __u16 ByteCount; /* 0 */ -} __attribute__((packed)) FLUSH_REQ; - -typedef struct smb_com_findclose_req { - struct smb_hdr hdr; /* wct = 1 */ - __u16 FileID; - __u16 ByteCount; /* 0 */ -} __attribute__((packed)) FINDCLOSE_REQ; - -/* OpenFlags */ -#define REQ_MORE_INFO 0x00000001 /* legacy (OPEN_AND_X) only */ -#define REQ_OPLOCK 0x00000002 -#define REQ_BATCHOPLOCK 0x00000004 -#define REQ_OPENDIRONLY 0x00000008 -#define REQ_EXTENDED_INFO 0x00000010 - -/* File type */ -#define DISK_TYPE 0x0000 -#define BYTE_PIPE_TYPE 0x0001 -#define MESSAGE_PIPE_TYPE 0x0002 -#define PRINTER_TYPE 0x0003 -#define COMM_DEV_TYPE 0x0004 -#define UNKNOWN_TYPE 0xFFFF - -/* Device Type or File Status Flags */ -#define NO_EAS 0x0001 -#define NO_SUBSTREAMS 0x0002 -#define NO_REPARSETAG 0x0004 -/* following flags can apply if pipe */ -#define ICOUNT_MASK 0x00FF -#define PIPE_READ_MODE 0x0100 -#define NAMED_PIPE_TYPE 0x0400 -#define PIPE_END_POINT 0x4000 -#define BLOCKING_NAMED_PIPE 0x8000 - -typedef struct smb_com_open_req { /* also handles create */ - struct smb_hdr hdr; /* wct = 24 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __u8 Reserved; /* Must Be Zero */ - __le16 NameLength; - __le32 OpenFlags; - __u32 RootDirectoryFid; - __le32 DesiredAccess; - __le64 AllocationSize; - __le32 FileAttributes; - __le32 ShareAccess; - __le32 CreateDisposition; - __le32 CreateOptions; - __le32 ImpersonationLevel; - __u8 SecurityFlags; - __le16 ByteCount; - char fileName[1]; -} __attribute__((packed)) OPEN_REQ; - -/* open response: oplock levels */ -#define OPLOCK_NONE 0 -#define OPLOCK_EXCLUSIVE 1 -#define OPLOCK_BATCH 2 -#define OPLOCK_READ 3 /* level 2 oplock */ - -/* open response for CreateAction shifted left */ -#define CIFS_CREATE_ACTION 0x20000 /* file created */ - -typedef struct smb_com_open_rsp { - struct smb_hdr hdr; /* wct = 34 BB */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __u8 OplockLevel; - __u16 Fid; - __le32 CreateAction; - __le64 CreationTime; - __le64 LastAccessTime; - __le64 LastWriteTime; - __le64 ChangeTime; - __le32 FileAttributes; - __le64 AllocationSize; - __le64 EndOfFile; - __le16 FileType; - __le16 DeviceState; - __u8 DirectoryFlag; - __u16 ByteCount; /* bct = 0 */ -} __attribute__((packed)) OPEN_RSP; - -typedef struct smb_com_open_rsp_ext { - struct smb_hdr hdr; /* wct = 42 but meaningless due to MS bug? */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __u8 OplockLevel; - __u16 Fid; - __le32 CreateAction; - __le64 CreationTime; - __le64 LastAccessTime; - __le64 LastWriteTime; - __le64 ChangeTime; - __le32 FileAttributes; - __le64 AllocationSize; - __le64 EndOfFile; - __le16 FileType; - __le16 DeviceState; - __u8 DirectoryFlag; - __u8 VolumeGUID[16]; - __u64 FileId; /* note no endian conversion - is opaque UniqueID */ - __le32 MaximalAccessRights; - __le32 GuestMaximalAccessRights; - __u16 ByteCount; /* bct = 0 */ -} __attribute__((packed)) OPEN_RSP_EXT; - - -/* format of legacy open request */ -typedef struct smb_com_openx_req { - struct smb_hdr hdr; /* wct = 15 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __le16 OpenFlags; - __le16 Mode; - __le16 Sattr; /* search attributes */ - __le16 FileAttributes; /* dos attrs */ - __le32 CreateTime; /* os2 format */ - __le16 OpenFunction; - __le32 EndOfFile; - __le32 Timeout; - __le32 Reserved; - __le16 ByteCount; /* file name follows */ - char fileName[1]; -} __attribute__((packed)) OPENX_REQ; - -typedef struct smb_com_openx_rsp { - struct smb_hdr hdr; /* wct = 15 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __u16 Fid; - __le16 FileAttributes; - __le32 LastWriteTime; /* os2 format */ - __le32 EndOfFile; - __le16 Access; - __le16 FileType; - __le16 IPCState; - __le16 Action; - __u32 FileId; - __u16 Reserved; - __u16 ByteCount; -} __attribute__((packed)) OPENX_RSP; - -/* For encoding of POSIX Open Request - see trans2 function 0x209 data struct */ - -/* Legacy write request for older servers */ -typedef struct smb_com_writex_req { - struct smb_hdr hdr; /* wct = 12 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __u16 Fid; - __le32 OffsetLow; - __u32 Reserved; /* Timeout */ - __le16 WriteMode; /* 1 = write through */ - __le16 Remaining; - __le16 Reserved2; - __le16 DataLengthLow; - __le16 DataOffset; - __le16 ByteCount; - __u8 Pad; /* BB check for whether padded to DWORD - boundary and optimum performance here */ - char Data[0]; -} __attribute__((packed)) WRITEX_REQ; - -typedef struct smb_com_write_req { - struct smb_hdr hdr; /* wct = 14 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __u16 Fid; - __le32 OffsetLow; - __u32 Reserved; - __le16 WriteMode; - __le16 Remaining; - __le16 DataLengthHigh; - __le16 DataLengthLow; - __le16 DataOffset; - __le32 OffsetHigh; - __le16 ByteCount; - __u8 Pad; /* BB check for whether padded to DWORD - boundary and optimum performance here */ - char Data[0]; -} __attribute__((packed)) WRITE_REQ; - -typedef struct smb_com_write_rsp { - struct smb_hdr hdr; /* wct = 6 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __le16 Count; - __le16 Remaining; - __le16 CountHigh; - __u16 Reserved; - __u16 ByteCount; -} __attribute__((packed)) WRITE_RSP; - -/* legacy read request for older servers */ -typedef struct smb_com_readx_req { - struct smb_hdr hdr; /* wct = 10 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __u16 Fid; - __le32 OffsetLow; - __le16 MaxCount; - __le16 MinCount; /* obsolete */ - __le32 Reserved; - __le16 Remaining; - __le16 ByteCount; -} __attribute__((packed)) READX_REQ; - -typedef struct smb_com_read_req { - struct smb_hdr hdr; /* wct = 12 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __u16 Fid; - __le32 OffsetLow; - __le16 MaxCount; - __le16 MinCount; /* obsolete */ - __le32 MaxCountHigh; - __le16 Remaining; - __le32 OffsetHigh; - __le16 ByteCount; -} __attribute__((packed)) READ_REQ; - -typedef struct smb_com_read_rsp { - struct smb_hdr hdr; /* wct = 12 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __le16 Remaining; - __le16 DataCompactionMode; - __le16 Reserved; - __le16 DataLength; - __le16 DataOffset; - __le16 DataLengthHigh; - __u64 Reserved2; - __u16 ByteCount; - /* read response data immediately follows */ -} __attribute__((packed)) READ_RSP; - -typedef struct locking_andx_range { - __le16 Pid; - __le16 Pad; - __le32 OffsetHigh; - __le32 OffsetLow; - __le32 LengthHigh; - __le32 LengthLow; -} __attribute__((packed)) LOCKING_ANDX_RANGE; - -#define LOCKING_ANDX_SHARED_LOCK 0x01 -#define LOCKING_ANDX_OPLOCK_RELEASE 0x02 -#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04 -#define LOCKING_ANDX_CANCEL_LOCK 0x08 -#define LOCKING_ANDX_LARGE_FILES 0x10 /* always on for us */ - -typedef struct smb_com_lock_req { - struct smb_hdr hdr; /* wct = 8 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __u16 Fid; - __u8 LockType; - __u8 OplockLevel; - __le32 Timeout; - __le16 NumberOfUnlocks; - __le16 NumberOfLocks; - __le16 ByteCount; - LOCKING_ANDX_RANGE Locks[1]; -} __attribute__((packed)) LOCK_REQ; - -/* lock type */ -#define CIFS_RDLCK 0 -#define CIFS_WRLCK 1 -#define CIFS_UNLCK 2 -typedef struct cifs_posix_lock { - __le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */ - __le16 lock_flags; /* 1 = Wait (only valid for setlock) */ - __le32 pid; - __le64 start; - __le64 length; - /* BB what about additional owner info to identify network client */ -} __attribute__((packed)) CIFS_POSIX_LOCK; - -typedef struct smb_com_lock_rsp { - struct smb_hdr hdr; /* wct = 2 */ - __u8 AndXCommand; - __u8 AndXReserved; - __le16 AndXOffset; - __u16 ByteCount; -} __attribute__((packed)) LOCK_RSP; - -typedef struct smb_com_rename_req { - struct smb_hdr hdr; /* wct = 1 */ - __le16 SearchAttributes; /* target file attributes */ - __le16 ByteCount; - __u8 BufferFormat; /* 4 = ASCII or Unicode */ - unsigned char OldFileName[1]; - /* followed by __u8 BufferFormat2 */ - /* followed by NewFileName */ -} __attribute__((packed)) RENAME_REQ; - - /* copy request flags */ -#define COPY_MUST_BE_FILE 0x0001 -#define COPY_MUST_BE_DIR 0x0002 -#define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */ -#define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */ -#define COPY_VERIFY_WRITES 0x0010 -#define COPY_TREE 0x0020 - -typedef struct smb_com_copy_req { - struct smb_hdr hdr; /* wct = 3 */ - __u16 Tid2; - __le16 OpenFunction; - __le16 Flags; - __le16 ByteCount; - __u8 BufferFormat; /* 4 = ASCII or Unicode */ - unsigned char OldFileName[1]; - /* followed by __u8 BufferFormat2 */ - /* followed by NewFileName string */ -} __attribute__((packed)) COPY_REQ; - -typedef struct smb_com_copy_rsp { - struct smb_hdr hdr; /* wct = 1 */ - __le16 CopyCount; /* number of files copied */ - __u16 ByteCount; /* may be zero */ - __u8 BufferFormat; /* 0x04 - only present if errored file follows */ - unsigned char ErrorFileName[1]; /* only present if error in copy */ -} __attribute__((packed)) COPY_RSP; - -#define CREATE_HARD_LINK 0x103 -#define MOVEFILE_COPY_ALLOWED 0x0002 -#define MOVEFILE_REPLACE_EXISTING 0x0001 - -typedef struct smb_com_nt_rename_req { /* A5 - also used for create hardlink */ - struct smb_hdr hdr; /* wct = 4 */ - __le16 SearchAttributes; /* target file attributes */ - __le16 Flags; /* spec says Information Level */ - __le32 ClusterCount; - __le16 ByteCount; - __u8 BufferFormat; /* 4 = ASCII or Unicode */ - unsigned char OldFileName[1]; - /* followed by __u8 BufferFormat2 */ - /* followed by NewFileName */ -} __attribute__((packed)) NT_RENAME_REQ; - -typedef struct smb_com_rename_rsp { - struct smb_hdr hdr; /* wct = 0 */ - __u16 ByteCount; /* bct = 0 */ -} __attribute__((packed)) RENAME_RSP; - -typedef struct smb_com_delete_file_req { - struct smb_hdr hdr; /* wct = 1 */ - __le16 SearchAttributes; - __le16 ByteCount; - __u8 BufferFormat; /* 4 = ASCII */ - unsigned char fileName[1]; -} __attribute__((packed)) DELETE_FILE_REQ; - -typedef struct smb_com_delete_file_rsp { - struct smb_hdr hdr; /* wct = 0 */ - __u16 ByteCount; /* bct = 0 */ -} __attribute__((packed)) DELETE_FILE_RSP; - -typedef struct smb_com_delete_directory_req { - struct smb_hdr hdr; /* wct = 0 */ - __le16 ByteCount; - __u8 BufferFormat; /* 4 = ASCII */ - unsigned char DirName[1]; -} __attribute__((packed)) DELETE_DIRECTORY_REQ; - -typedef struct smb_com_delete_directory_rsp { - struct smb_hdr hdr; /* wct = 0 */ - __u16 ByteCount; /* bct = 0 */ -} __attribute__((packed)) DELETE_DIRECTORY_RSP; - -typedef struct smb_com_create_directory_req { - struct smb_hdr hdr; /* wct = 0 */ - __le16 ByteCount; - __u8 BufferFormat; /* 4 = ASCII */ - unsigned char DirName[1]; -} __attribute__((packed)) CREATE_DIRECTORY_REQ; - -typedef struct smb_com_create_directory_rsp { - struct smb_hdr hdr; /* wct = 0 */ - __u16 ByteCount; /* bct = 0 */ -} __attribute__((packed)) CREATE_DIRECTORY_RSP; - -typedef struct smb_com_query_information_req { - struct smb_hdr hdr; /* wct = 0 */ - __le16 ByteCount; /* 1 + namelen + 1 */ - __u8 BufferFormat; /* 4 = ASCII */ - unsigned char FileName[1]; -} __attribute__((packed)) QUERY_INFORMATION_REQ; - -typedef struct smb_com_query_information_rsp { - struct smb_hdr hdr; /* wct = 10 */ - __le16 attr; - __le32 last_write_time; - __le32 size; - __u16 reserved[5]; - __le16 ByteCount; /* bcc = 0 */ -} __attribute__((packed)) QUERY_INFORMATION_RSP; - -typedef struct smb_com_setattr_req { - struct smb_hdr hdr; /* wct = 8 */ - __le16 attr; - __le16 time_low; - __le16 time_high; - __le16 reserved[5]; /* must be zero */ - __u16 ByteCount; - __u8 BufferFormat; /* 4 = ASCII */ - unsigned char fileName[1]; -} __attribute__((packed)) SETATTR_REQ; - -typedef struct smb_com_setattr_rsp { - struct smb_hdr hdr; /* wct = 0 */ - __u16 ByteCount; /* bct = 0 */ -} __attribute__((packed)) SETATTR_RSP; - -/* empty wct response to setattr */ - -/*******************************************************/ -/* NT Transact structure definitions follow */ -/* Currently only ioctl, acl (get security descriptor) */ -/* and notify are implemented */ -/*******************************************************/ -typedef struct smb_com_ntransact_req { - struct smb_hdr hdr; /* wct >= 19 */ - __u8 MaxSetupCount; - __u16 Reserved; - __le32 TotalParameterCount; - __le32 TotalDataCount; - __le32 MaxParameterCount; - __le32 MaxDataCount; - __le32 ParameterCount; - __le32 ParameterOffset; - __le32 DataCount; - __le32 DataOffset; - __u8 SetupCount; /* four setup words follow subcommand */ - /* SNIA spec incorrectly included spurious pad here */ - __le16 SubCommand; /* 2 = IOCTL/FSCTL */ - /* SetupCount words follow then */ - __le16 ByteCount; - __u8 Pad[3]; - __u8 Parms[0]; -} __attribute__((packed)) NTRANSACT_REQ; - -typedef struct smb_com_ntransact_rsp { - struct smb_hdr hdr; /* wct = 18 */ - __u8 Reserved[3]; - __le32 TotalParameterCount; - __le32 TotalDataCount; - __le32 ParameterCount; - __le32 ParameterOffset; - __le32 ParameterDisplacement; - __le32 DataCount; - __le32 DataOffset; - __le32 DataDisplacement; - __u8 SetupCount; /* 0 */ - __u16 ByteCount; - /* __u8 Pad[3]; */ - /* parms and data follow */ -} __attribute__((packed)) NTRANSACT_RSP; - -typedef struct smb_com_transaction_ioctl_req { - struct smb_hdr hdr; /* wct = 23 */ - __u8 MaxSetupCount; - __u16 Reserved; - __le32 TotalParameterCount; - __le32 TotalDataCount; - __le32 MaxParameterCount; - __le32 MaxDataCount; - __le32 ParameterCount; - __le32 ParameterOffset; - __le32 DataCount; - __le32 DataOffset; - __u8 SetupCount; /* four setup words follow subcommand */ - /* SNIA spec incorrectly included spurious pad here */ - __le16 SubCommand; /* 2 = IOCTL/FSCTL */ - __le32 FunctionCode; - __u16 Fid; - __u8 IsFsctl; /* 1 = File System Control 0 = device control (IOCTL) */ - __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS) */ - __le16 ByteCount; - __u8 Pad[3]; - __u8 Data[1]; -} __attribute__((packed)) TRANSACT_IOCTL_REQ; - -typedef struct smb_com_transaction_ioctl_rsp { - struct smb_hdr hdr; /* wct = 19 */ - __u8 Reserved[3]; - __le32 TotalParameterCount; - __le32 TotalDataCount; - __le32 ParameterCount; - __le32 ParameterOffset; - __le32 ParameterDisplacement; - __le32 DataCount; - __le32 DataOffset; - __le32 DataDisplacement; - __u8 SetupCount; /* 1 */ - __le16 ReturnedDataLen; - __u16 ByteCount; -} __attribute__((packed)) TRANSACT_IOCTL_RSP; - -#define CIFS_ACL_OWNER 1 -#define CIFS_ACL_GROUP 2 -#define CIFS_ACL_DACL 4 -#define CIFS_ACL_SACL 8 - -typedef struct smb_com_transaction_qsec_req { - struct smb_hdr hdr; /* wct = 19 */ - __u8 MaxSetupCount; - __u16 Reserved; - __le32 TotalParameterCount; - __le32 TotalDataCount; - __le32 MaxParameterCount; - __le32 MaxDataCount; - __le32 ParameterCount; - __le32 ParameterOffset; - __le32 DataCount; - __le32 DataOffset; - __u8 SetupCount; /* no setup words follow subcommand */ - /* SNIA spec incorrectly included spurious pad here */ - __le16 SubCommand; /* 6 = QUERY_SECURITY_DESC */ - __le16 ByteCount; /* bcc = 3 + 8 */ - __u8 Pad[3]; - __u16 Fid; - __u16 Reserved2; - __le32 AclFlags; -} __attribute__((packed)) QUERY_SEC_DESC_REQ; - - -typedef struct smb_com_transaction_ssec_req { - struct smb_hdr hdr; /* wct = 19 */ - __u8 MaxSetupCount; - __u16 Reserved; - __le32 TotalParameterCount; - __le32 TotalDataCount; - __le32 MaxParameterCount; - __le32 MaxDataCount; - __le32 ParameterCount; - __le32 ParameterOffset; - __le32 DataCount; - __le32 DataOffset; - __u8 SetupCount; /* no setup words follow subcommand */ - /* SNIA spec incorrectly included spurious pad here */ - __le16 SubCommand; /* 3 = SET_SECURITY_DESC */ - __le16 ByteCount; /* bcc = 3 + 8 */ - __u8 Pad[3]; - __u16 Fid; - __u16 Reserved2; - __le32 AclFlags; -} __attribute__((packed)) SET_SEC_DESC_REQ; - -typedef struct smb_com_transaction_change_notify_req { - struct smb_hdr hdr; /* wct = 23 */ - __u8 MaxSetupCount; - __u16 Reserved; - __le32 TotalParameterCount; - __le32 TotalDataCount; - __le32 MaxParameterCount; - __le32 MaxDataCount; - __le32 ParameterCount; - __le32 ParameterOffset; - __le32 DataCount; - __le32 DataOffset; - __u8 SetupCount; /* four setup words follow subcommand */ - /* SNIA spec incorrectly included spurious pad here */ - __le16 SubCommand;/* 4 = Change Notify */ - __le32 CompletionFilter; /* operation to monitor */ - __u16 Fid; - __u8 WatchTree; /* 1 = Monitor subdirectories */ - __u8 Reserved2; - __le16 ByteCount; -/* __u8 Pad[3];*/ -/* __u8 Data[1];*/ -} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ; - -/* BB eventually change to use generic ntransact rsp struct - and validation routine */ -typedef struct smb_com_transaction_change_notify_rsp { - struct smb_hdr hdr; /* wct = 18 */ - __u8 Reserved[3]; - __le32 TotalParameterCount; - __le32 TotalDataCount; - __le32 ParameterCount; - __le32 ParameterOffset; - __le32 ParameterDisplacement; - __le32 DataCount; - __le32 DataOffset; - __le32 DataDisplacement; - __u8 SetupCount; /* 0 */ - __u16 ByteCount; - /* __u8 Pad[3]; */ -} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_RSP; -/* Completion Filter flags for Notify */ -#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001 -#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002 -#define FILE_NOTIFY_CHANGE_NAME 0x00000003 -#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004 -#define FILE_NOTIFY_CHANGE_SIZE 0x00000008 -#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010 -#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020 -#define FILE_NOTIFY_CHANGE_CREATION 0x00000040 -#define FILE_NOTIFY_CHANGE_EA 0x00000080 -#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100 -#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200 -#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400 -#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800 - -#define FILE_ACTION_ADDED 0x00000001 -#define FILE_ACTION_REMOVED 0x00000002 -#define FILE_ACTION_MODIFIED 0x00000003 -#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004 -#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005 -#define FILE_ACTION_ADDED_STREAM 0x00000006 -#define FILE_ACTION_REMOVED_STREAM 0x00000007 -#define FILE_ACTION_MODIFIED_STREAM 0x00000008 - -/* response contains array of the following structures */ -struct file_notify_information { - __le32 NextEntryOffset; - __le32 Action; - __le32 FileNameLength; - __u8 FileName[0]; -} __attribute__((packed)); - -struct reparse_data { - __u32 ReparseTag; - __u16 ReparseDataLength; - __u16 Reserved; - __u16 AltNameOffset; - __u16 AltNameLen; - __u16 TargetNameOffset; - __u16 TargetNameLen; - char LinkNamesBuf[1]; -} __attribute__((packed)); - -struct cifs_quota_data { - __u32 rsrvd1; /* 0 */ - __u32 sid_size; - __u64 rsrvd2; /* 0 */ - __u64 space_used; - __u64 soft_limit; - __u64 hard_limit; - char sid[1]; /* variable size? */ -} __attribute__((packed)); - -/* quota sub commands */ -#define QUOTA_LIST_CONTINUE 0 -#define QUOTA_LIST_START 0x100 -#define QUOTA_FOR_SID 0x101 - -struct trans2_req { - /* struct smb_hdr hdr precedes. Set wct = 14+ */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __le16 MaxParameterCount; - __le16 MaxDataCount; - __u8 MaxSetupCount; - __u8 Reserved; - __le16 Flags; - __le32 Timeout; - __u16 Reserved2; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 DataCount; - __le16 DataOffset; - __u8 SetupCount; - __u8 Reserved3; - __le16 SubCommand; /* 1st setup word - SetupCount words follow */ - __le16 ByteCount; -} __attribute__((packed)); - -struct smb_t2_req { - struct smb_hdr hdr; - struct trans2_req t2_req; -} __attribute__((packed)); - -struct trans2_resp { - /* struct smb_hdr hdr precedes. Note wct = 10 + setup count */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __u16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; - /* SetupWords[SetupCount]; - __u16 ByteCount; - __u16 Reserved2;*/ - /* data area follows */ -} __attribute__((packed)); - -struct smb_t2_rsp { - struct smb_hdr hdr; - struct trans2_resp t2_rsp; -} __attribute__((packed)); - -/* PathInfo/FileInfo infolevels */ -#define SMB_INFO_STANDARD 1 -#define SMB_SET_FILE_EA 2 -#define SMB_QUERY_FILE_EA_SIZE 2 -#define SMB_INFO_QUERY_EAS_FROM_LIST 3 -#define SMB_INFO_QUERY_ALL_EAS 4 -#define SMB_INFO_IS_NAME_VALID 6 -#define SMB_QUERY_FILE_BASIC_INFO 0x101 -#define SMB_QUERY_FILE_STANDARD_INFO 0x102 -#define SMB_QUERY_FILE_EA_INFO 0x103 -#define SMB_QUERY_FILE_NAME_INFO 0x104 -#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105 -#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106 -#define SMB_QUERY_FILE_ALL_INFO 0x107 -#define SMB_QUERY_ALT_NAME_INFO 0x108 -#define SMB_QUERY_FILE_STREAM_INFO 0x109 -#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B -#define SMB_QUERY_FILE_UNIX_BASIC 0x200 -#define SMB_QUERY_FILE_UNIX_LINK 0x201 -#define SMB_QUERY_POSIX_ACL 0x204 -#define SMB_QUERY_XATTR 0x205 /* e.g. system EA name space */ -#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */ -#define SMB_QUERY_POSIX_PERMISSION 0x207 -#define SMB_QUERY_POSIX_LOCK 0x208 -/* #define SMB_POSIX_OPEN 0x209 */ -/* #define SMB_POSIX_UNLINK 0x20a */ -#define SMB_QUERY_FILE__UNIX_INFO2 0x20b -#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee -#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 -#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ -#define SMB_QUERY_FILE_POSITION_INFO 0x3f6 -#define SMB_QUERY_FILE_MODE_INFO 0x3f8 -#define SMB_QUERY_FILE_ALGN_INFO 0x3f9 - - -#define SMB_SET_FILE_BASIC_INFO 0x101 -#define SMB_SET_FILE_DISPOSITION_INFO 0x102 -#define SMB_SET_FILE_ALLOCATION_INFO 0x103 -#define SMB_SET_FILE_END_OF_FILE_INFO 0x104 -#define SMB_SET_FILE_UNIX_BASIC 0x200 -#define SMB_SET_FILE_UNIX_LINK 0x201 -#define SMB_SET_FILE_UNIX_HLINK 0x203 -#define SMB_SET_POSIX_ACL 0x204 -#define SMB_SET_XATTR 0x205 -#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */ -#define SMB_SET_POSIX_LOCK 0x208 -#define SMB_POSIX_OPEN 0x209 -#define SMB_POSIX_UNLINK 0x20a -#define SMB_SET_FILE_UNIX_INFO2 0x20b -#define SMB_SET_FILE_BASIC_INFO2 0x3ec -#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo too */ -#define SMB_FILE_ALL_INFO2 0x3fa -#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb -#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc -#define SMB_FILE_MOVE_CLUSTER_INFO 0x407 -#define SMB_FILE_QUOTA_INFO 0x408 -#define SMB_FILE_REPARSEPOINT_INFO 0x409 -#define SMB_FILE_MAXIMUM_INFO 0x40d - -/* Find File infolevels */ -#define SMB_FIND_FILE_INFO_STANDARD 0x001 -#define SMB_FIND_FILE_QUERY_EA_SIZE 0x002 -#define SMB_FIND_FILE_QUERY_EAS_FROM_LIST 0x003 -#define SMB_FIND_FILE_DIRECTORY_INFO 0x101 -#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102 -#define SMB_FIND_FILE_NAMES_INFO 0x103 -#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104 -#define SMB_FIND_FILE_ID_FULL_DIR_INFO 0x105 -#define SMB_FIND_FILE_ID_BOTH_DIR_INFO 0x106 -#define SMB_FIND_FILE_UNIX 0x202 - -typedef struct smb_com_transaction2_qpi_req { - struct smb_hdr hdr; /* wct = 14+ */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __le16 MaxParameterCount; - __le16 MaxDataCount; - __u8 MaxSetupCount; - __u8 Reserved; - __le16 Flags; - __le32 Timeout; - __u16 Reserved2; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 DataCount; - __le16 DataOffset; - __u8 SetupCount; - __u8 Reserved3; - __le16 SubCommand; /* one setup word */ - __le16 ByteCount; - __u8 Pad; - __le16 InformationLevel; - __u32 Reserved4; - char FileName[1]; -} __attribute__((packed)) TRANSACTION2_QPI_REQ; - -typedef struct smb_com_transaction2_qpi_rsp { - struct smb_hdr hdr; /* wct = 10 + SetupCount */ - struct trans2_resp t2; - __u16 ByteCount; - __u16 Reserved2; /* parameter word is present for infolevels > 100 */ -} __attribute__((packed)) TRANSACTION2_QPI_RSP; - -typedef struct smb_com_transaction2_spi_req { - struct smb_hdr hdr; /* wct = 15 */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __le16 MaxParameterCount; - __le16 MaxDataCount; - __u8 MaxSetupCount; - __u8 Reserved; - __le16 Flags; - __le32 Timeout; - __u16 Reserved2; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 DataCount; - __le16 DataOffset; - __u8 SetupCount; - __u8 Reserved3; - __le16 SubCommand; /* one setup word */ - __le16 ByteCount; - __u8 Pad; - __u16 Pad1; - __le16 InformationLevel; - __u32 Reserved4; - char FileName[1]; -} __attribute__((packed)) TRANSACTION2_SPI_REQ; - -typedef struct smb_com_transaction2_spi_rsp { - struct smb_hdr hdr; /* wct = 10 + SetupCount */ - struct trans2_resp t2; - __u16 ByteCount; - __u16 Reserved2; /* parameter word is present for infolevels > 100 */ -} __attribute__((packed)) TRANSACTION2_SPI_RSP; - -struct set_file_rename { - __le32 overwrite; /* 1 = overwrite dest */ - __u32 root_fid; /* zero */ - __le32 target_name_len; - char target_name[0]; /* Must be unicode */ -} __attribute__((packed)); - -struct smb_com_transaction2_sfi_req { - struct smb_hdr hdr; /* wct = 15 */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __le16 MaxParameterCount; - __le16 MaxDataCount; - __u8 MaxSetupCount; - __u8 Reserved; - __le16 Flags; - __le32 Timeout; - __u16 Reserved2; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 DataCount; - __le16 DataOffset; - __u8 SetupCount; - __u8 Reserved3; - __le16 SubCommand; /* one setup word */ - __le16 ByteCount; - __u8 Pad; - __u16 Pad1; - __u16 Fid; - __le16 InformationLevel; - __u16 Reserved4; -} __attribute__((packed)); - -struct smb_com_transaction2_sfi_rsp { - struct smb_hdr hdr; /* wct = 10 + SetupCount */ - struct trans2_resp t2; - __u16 ByteCount; - __u16 Reserved2; /* parameter word reserved - - present for infolevels > 100 */ -} __attribute__((packed)); - -struct smb_t2_qfi_req { - struct smb_hdr hdr; - struct trans2_req t2; - __u8 Pad; - __u16 Fid; - __le16 InformationLevel; -} __attribute__((packed)); - -struct smb_t2_qfi_rsp { - struct smb_hdr hdr; /* wct = 10 + SetupCount */ - struct trans2_resp t2; - __u16 ByteCount; - __u16 Reserved2; /* parameter word reserved - - present for infolevels > 100 */ -} __attribute__((packed)); - -/* - * Flags on T2 FINDFIRST and FINDNEXT - */ -#define CIFS_SEARCH_CLOSE_ALWAYS 0x0001 -#define CIFS_SEARCH_CLOSE_AT_END 0x0002 -#define CIFS_SEARCH_RETURN_RESUME 0x0004 -#define CIFS_SEARCH_CONTINUE_FROM_LAST 0x0008 -#define CIFS_SEARCH_BACKUP_SEARCH 0x0010 - -/* - * Size of the resume key on FINDFIRST and FINDNEXT calls - */ -#define CIFS_SMB_RESUME_KEY_SIZE 4 - -typedef struct smb_com_transaction2_ffirst_req { - struct smb_hdr hdr; /* wct = 15 */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __le16 MaxParameterCount; - __le16 MaxDataCount; - __u8 MaxSetupCount; - __u8 Reserved; - __le16 Flags; - __le32 Timeout; - __u16 Reserved2; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 DataCount; - __le16 DataOffset; - __u8 SetupCount; /* one */ - __u8 Reserved3; - __le16 SubCommand; /* TRANS2_FIND_FIRST */ - __le16 ByteCount; - __u8 Pad; - __le16 SearchAttributes; - __le16 SearchCount; - __le16 SearchFlags; - __le16 InformationLevel; - __le32 SearchStorageType; - char FileName[1]; -} __attribute__((packed)) TRANSACTION2_FFIRST_REQ; - -typedef struct smb_com_transaction2_ffirst_rsp { - struct smb_hdr hdr; /* wct = 10 */ - struct trans2_resp t2; - __u16 ByteCount; -} __attribute__((packed)) TRANSACTION2_FFIRST_RSP; - -typedef struct smb_com_transaction2_ffirst_rsp_parms { - __u16 SearchHandle; - __le16 SearchCount; - __le16 EndofSearch; - __le16 EAErrorOffset; - __le16 LastNameOffset; -} __attribute__((packed)) T2_FFIRST_RSP_PARMS; - -typedef struct smb_com_transaction2_fnext_req { - struct smb_hdr hdr; /* wct = 15 */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __le16 MaxParameterCount; - __le16 MaxDataCount; - __u8 MaxSetupCount; - __u8 Reserved; - __le16 Flags; - __le32 Timeout; - __u16 Reserved2; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 DataCount; - __le16 DataOffset; - __u8 SetupCount; /* one */ - __u8 Reserved3; - __le16 SubCommand; /* TRANS2_FIND_NEXT */ - __le16 ByteCount; - __u8 Pad; - __u16 SearchHandle; - __le16 SearchCount; - __le16 InformationLevel; - __u32 ResumeKey; - __le16 SearchFlags; - char ResumeFileName[1]; -} __attribute__((packed)) TRANSACTION2_FNEXT_REQ; - -typedef struct smb_com_transaction2_fnext_rsp { - struct smb_hdr hdr; /* wct = 10 */ - struct trans2_resp t2; - __u16 ByteCount; -} __attribute__((packed)) TRANSACTION2_FNEXT_RSP; - -typedef struct smb_com_transaction2_fnext_rsp_parms { - __le16 SearchCount; - __le16 EndofSearch; - __le16 EAErrorOffset; - __le16 LastNameOffset; -} __attribute__((packed)) T2_FNEXT_RSP_PARMS; - -/* QFSInfo Levels */ -#define SMB_INFO_ALLOCATION 1 -#define SMB_INFO_VOLUME 2 -#define SMB_QUERY_FS_VOLUME_INFO 0x102 -#define SMB_QUERY_FS_SIZE_INFO 0x103 -#define SMB_QUERY_FS_DEVICE_INFO 0x104 -#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105 -#define SMB_QUERY_CIFS_UNIX_INFO 0x200 -#define SMB_QUERY_POSIX_FS_INFO 0x201 -#define SMB_QUERY_POSIX_WHO_AM_I 0x202 -#define SMB_REQUEST_TRANSPORT_ENCRYPTION 0x203 -#define SMB_QUERY_FS_PROXY 0x204 /* WAFS enabled. Returns structure - FILE_SYSTEM__UNIX_INFO to tell - whether new NTIOCTL available - (0xACE) for WAN friendly SMB - operations to be carried */ -#define SMB_QUERY_LABEL_INFO 0x3ea -#define SMB_QUERY_FS_QUOTA_INFO 0x3ee -#define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef -#define SMB_QUERY_OBJECTID_INFO 0x3f0 - -typedef struct smb_com_transaction2_qfsi_req { - struct smb_hdr hdr; /* wct = 14+ */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __le16 MaxParameterCount; - __le16 MaxDataCount; - __u8 MaxSetupCount; - __u8 Reserved; - __le16 Flags; - __le32 Timeout; - __u16 Reserved2; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 DataCount; - __le16 DataOffset; - __u8 SetupCount; - __u8 Reserved3; - __le16 SubCommand; /* one setup word */ - __le16 ByteCount; - __u8 Pad; - __le16 InformationLevel; -} __attribute__((packed)) TRANSACTION2_QFSI_REQ; - -typedef struct smb_com_transaction_qfsi_rsp { - struct smb_hdr hdr; /* wct = 10 + SetupCount */ - struct trans2_resp t2; - __u16 ByteCount; - __u8 Pad; /* may be three bytes? *//* followed by data area */ -} __attribute__((packed)) TRANSACTION2_QFSI_RSP; - -typedef struct whoami_rsp_data { /* Query level 0x202 */ - __u32 flags; /* 0 = Authenticated user 1 = GUEST */ - __u32 mask; /* which flags bits server understands ie 0x0001 */ - __u64 unix_user_id; - __u64 unix_user_gid; - __u32 number_of_supplementary_gids; /* may be zero */ - __u32 number_of_sids; /* may be zero */ - __u32 length_of_sid_array; /* in bytes - may be zero */ - __u32 pad; /* reserved - MBZ */ - /* __u64 gid_array[0]; */ /* may be empty */ - /* __u8 * psid_list */ /* may be empty */ -} __attribute__((packed)) WHOAMI_RSP_DATA; - -/* SETFSInfo Levels */ -#define SMB_SET_CIFS_UNIX_INFO 0x200 -/* level 0x203 is defined above in list of QFS info levels */ -/* #define SMB_REQUEST_TRANSPORT_ENCRYPTION 0x203 */ - -/* Level 0x200 request structure follows */ -typedef struct smb_com_transaction2_setfsi_req { - struct smb_hdr hdr; /* wct = 15 */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __le16 MaxParameterCount; - __le16 MaxDataCount; - __u8 MaxSetupCount; - __u8 Reserved; - __le16 Flags; - __le32 Timeout; - __u16 Reserved2; - __le16 ParameterCount; /* 4 */ - __le16 ParameterOffset; - __le16 DataCount; /* 12 */ - __le16 DataOffset; - __u8 SetupCount; /* one */ - __u8 Reserved3; - __le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */ - __le16 ByteCount; - __u8 Pad; - __u16 FileNum; /* Parameters start. */ - __le16 InformationLevel;/* Parameters end. */ - __le16 ClientUnixMajor; /* Data start. */ - __le16 ClientUnixMinor; - __le64 ClientUnixCap; /* Data end */ -} __attribute__((packed)) TRANSACTION2_SETFSI_REQ; - -/* level 0x203 request structure follows */ -typedef struct smb_com_transaction2_setfs_enc_req { - struct smb_hdr hdr; /* wct = 15 */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __le16 MaxParameterCount; - __le16 MaxDataCount; - __u8 MaxSetupCount; - __u8 Reserved; - __le16 Flags; - __le32 Timeout; - __u16 Reserved2; - __le16 ParameterCount; /* 4 */ - __le16 ParameterOffset; - __le16 DataCount; /* 12 */ - __le16 DataOffset; - __u8 SetupCount; /* one */ - __u8 Reserved3; - __le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */ - __le16 ByteCount; - __u8 Pad; - __u16 Reserved4; /* Parameters start. */ - __le16 InformationLevel;/* Parameters end. */ - /* NTLMSSP Blob, Data start. */ -} __attribute__((packed)) TRANSACTION2_SETFSI_ENC_REQ; - -/* response for setfsinfo levels 0x200 and 0x203 */ -typedef struct smb_com_transaction2_setfsi_rsp { - struct smb_hdr hdr; /* wct = 10 */ - struct trans2_resp t2; - __u16 ByteCount; -} __attribute__((packed)) TRANSACTION2_SETFSI_RSP; - -typedef struct smb_com_transaction2_get_dfs_refer_req { - struct smb_hdr hdr; /* wct = 15 */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __le16 MaxParameterCount; - __le16 MaxDataCount; - __u8 MaxSetupCount; - __u8 Reserved; - __le16 Flags; - __le32 Timeout; - __u16 Reserved2; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 DataCount; - __le16 DataOffset; - __u8 SetupCount; - __u8 Reserved3; - __le16 SubCommand; /* one setup word */ - __le16 ByteCount; - __u8 Pad[3]; /* Win2K has sent 0x0F01 (max response length - perhaps?) followed by one byte pad - doesn't - seem to matter though */ - __le16 MaxReferralLevel; - char RequestFileName[1]; -} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ; - -#define DFS_VERSION cpu_to_le16(0x0003) - -/* DFS server target type */ -#define DFS_TYPE_LINK 0x0000 /* also for sysvol targets */ -#define DFS_TYPE_ROOT 0x0001 - -/* Referral Entry Flags */ -#define DFS_NAME_LIST_REF 0x0200 /* set for domain or DC referral responses */ -#define DFS_TARGET_SET_BOUNDARY 0x0400 /* only valid with version 4 dfs req */ - -typedef struct dfs_referral_level_3 { /* version 4 is same, + one flag bit */ - __le16 VersionNumber; /* must be 3 or 4 */ - __le16 Size; - __le16 ServerType; /* 0x0001 = root targets; 0x0000 = link targets */ - __le16 ReferralEntryFlags; - __le32 TimeToLive; - __le16 DfsPathOffset; - __le16 DfsAlternatePathOffset; - __le16 NetworkAddressOffset; /* offset of the link target */ - __u8 ServiceSiteGuid[16]; /* MBZ, ignored */ -} __attribute__((packed)) REFERRAL3; - -typedef struct smb_com_transaction_get_dfs_refer_rsp { - struct smb_hdr hdr; /* wct = 10 */ - struct trans2_resp t2; - __u16 ByteCount; - __u8 Pad; - __le16 PathConsumed; - __le16 NumberOfReferrals; - __le32 DFSFlags; - REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */ - /* followed by the strings pointed to by the referral structures */ -} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_RSP; - -/* DFS Flags */ -#define DFSREF_REFERRAL_SERVER 0x00000001 /* all targets are DFS roots */ -#define DFSREF_STORAGE_SERVER 0x00000002 /* no further ref requests needed */ -#define DFSREF_TARGET_FAILBACK 0x00000004 /* only for DFS referral version 4 */ - -/* - ************************************************************************ - * All structs for everything above the SMB PDUs themselves - * (such as the T2 level specific data) go here - ************************************************************************ - */ - -/* - * Information on a server - */ - -struct serverInfo { - char name[16]; - unsigned char versionMajor; - unsigned char versionMinor; - unsigned long type; - unsigned int commentOffset; -} __attribute__((packed)); - -/* - * The following structure is the format of the data returned on a NetShareEnum - * with level "90" (x5A) - */ - -struct shareInfo { - char shareName[13]; - char pad; - unsigned short type; - unsigned int commentOffset; -} __attribute__((packed)); - -struct aliasInfo { - char aliasName[9]; - char pad; - unsigned int commentOffset; - unsigned char type[2]; -} __attribute__((packed)); - -struct aliasInfo92 { - int aliasNameOffset; - int serverNameOffset; - int shareNameOffset; -} __attribute__((packed)); - -typedef struct { - __le64 TotalAllocationUnits; - __le64 FreeAllocationUnits; - __le32 SectorsPerAllocationUnit; - __le32 BytesPerSector; -} __attribute__((packed)) FILE_SYSTEM_INFO; /* size info, level 0x103 */ - -typedef struct { - __le32 fsid; - __le32 SectorsPerAllocationUnit; - __le32 TotalAllocationUnits; - __le32 FreeAllocationUnits; - __le16 BytesPerSector; -} __attribute__((packed)) FILE_SYSTEM_ALLOC_INFO; - -typedef struct { - __le16 MajorVersionNumber; - __le16 MinorVersionNumber; - __le64 Capability; -} __attribute__((packed)) FILE_SYSTEM_UNIX_INFO; /* Unix extension level 0x200*/ - -/* Version numbers for CIFS UNIX major and minor. */ -#define CIFS_UNIX_MAJOR_VERSION 1 -#define CIFS_UNIX_MINOR_VERSION 0 - -/* Linux/Unix extensions capability flags */ -#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */ -#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ -#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ -#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ -#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */ -#define CIFS_UNIX_POSIX_PATH_OPS_CAP 0x00000020 /* Allow new POSIX path based - calls including posix open - and posix unlink */ -#define CIFS_UNIX_LARGE_READ_CAP 0x00000040 /* support reads >128K (up - to 0xFFFF00 */ -#define CIFS_UNIX_LARGE_WRITE_CAP 0x00000080 -#define CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP 0x00000100 /* can do SPNEGO crypt */ -#define CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP 0x00000200 /* must do */ -#define CIFS_UNIX_PROXY_CAP 0x00000400 /* Proxy cap: 0xACE ioctl and - QFS PROXY call */ -#ifdef CONFIG_CIFS_POSIX -/* presumably don't need the 0x20 POSIX_PATH_OPS_CAP since we never send - LockingX instead of posix locking call on unix sess (and we do not expect - LockingX to use different (ie Windows) semantics than posix locking on - the same session (if WINE needs to do this later, we can add this cap - back in later */ -/* #define CIFS_UNIX_CAP_MASK 0x000000fb */ -#define CIFS_UNIX_CAP_MASK 0x000003db -#else -#define CIFS_UNIX_CAP_MASK 0x00000013 -#endif /* CONFIG_CIFS_POSIX */ - - -#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */ - -typedef struct { - /* For undefined recommended transfer size return -1 in that field */ - __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */ - __le32 BlockSize; - /* The next three fields are in terms of the block size. - (above). If block size is unknown, 4096 would be a - reasonable block size for a server to report. - Note that returning the blocks/blocksavail removes need - to make a second call (to QFSInfo level 0x103 to get this info. - UserBlockAvail is typically less than or equal to BlocksAvail, - if no distinction is made return the same value in each */ - __le64 TotalBlocks; - __le64 BlocksAvail; /* bfree */ - __le64 UserBlocksAvail; /* bavail */ - /* For undefined Node fields or FSID return -1 */ - __le64 TotalFileNodes; - __le64 FreeFileNodes; - __le64 FileSysIdentifier; /* fsid */ - /* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */ - /* NB flags can come from FILE_SYSTEM_DEVICE_INFO call */ -} __attribute__((packed)) FILE_SYSTEM_POSIX_INFO; - -/* DeviceType Flags */ -#define FILE_DEVICE_CD_ROM 0x00000002 -#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 -#define FILE_DEVICE_DFS 0x00000006 -#define FILE_DEVICE_DISK 0x00000007 -#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 -#define FILE_DEVICE_FILE_SYSTEM 0x00000009 -#define FILE_DEVICE_NAMED_PIPE 0x00000011 -#define FILE_DEVICE_NETWORK 0x00000012 -#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 -#define FILE_DEVICE_NULL 0x00000015 -#define FILE_DEVICE_PARALLEL_PORT 0x00000016 -#define FILE_DEVICE_PRINTER 0x00000018 -#define FILE_DEVICE_SERIAL_PORT 0x0000001b -#define FILE_DEVICE_STREAMS 0x0000001e -#define FILE_DEVICE_TAPE 0x0000001f -#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 -#define FILE_DEVICE_VIRTUAL_DISK 0x00000024 -#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 - -typedef struct { - __le32 DeviceType; - __le32 DeviceCharacteristics; -} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info level 0x104 */ - -typedef struct { - __le32 Attributes; - __le32 MaxPathNameComponentLength; - __le32 FileSystemNameLen; - char FileSystemName[52]; /* do not have to save this - get subset? */ -} __attribute__((packed)) FILE_SYSTEM_ATTRIBUTE_INFO; - -/******************************************************************************/ -/* QueryFileInfo/QueryPathinfo (also for SetPath/SetFile) data buffer formats */ -/******************************************************************************/ -typedef struct { /* data block encoding of response to level 263 QPathInfo */ - __le64 CreationTime; - __le64 LastAccessTime; - __le64 LastWriteTime; - __le64 ChangeTime; - __le32 Attributes; - __u32 Pad1; - __le64 AllocationSize; - __le64 EndOfFile; /* size ie offset to first free byte in file */ - __le32 NumberOfLinks; /* hard links */ - __u8 DeletePending; - __u8 Directory; - __u16 Pad2; - __u64 IndexNumber; - __le32 EASize; - __le32 AccessFlags; - __u64 IndexNumber1; - __le64 CurrentByteOffset; - __le32 Mode; - __le32 AlignmentRequirement; - __le32 FileNameLength; - char FileName[1]; -} __attribute__((packed)) FILE_ALL_INFO; /* level 0x107 QPathInfo */ - -/* defines for enumerating possible values of the Unix type field below */ -#define UNIX_FILE 0 -#define UNIX_DIR 1 -#define UNIX_SYMLINK 2 -#define UNIX_CHARDEV 3 -#define UNIX_BLOCKDEV 4 -#define UNIX_FIFO 5 -#define UNIX_SOCKET 6 -typedef struct { - __le64 EndOfFile; - __le64 NumOfBytes; - __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */ - __le64 LastAccessTime; - __le64 LastModificationTime; - __le64 Uid; - __le64 Gid; - __le32 Type; - __le64 DevMajor; - __le64 DevMinor; - __le64 UniqueId; - __le64 Permissions; - __le64 Nlinks; -} __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */ - -typedef struct { - char LinkDest[1]; -} __attribute__((packed)) FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */ - -/* The following three structures are needed only for - setting time to NT4 and some older servers via - the primitive DOS time format */ -typedef struct { - __u16 Day:5; - __u16 Month:4; - __u16 Year:7; -} __attribute__((packed)) SMB_DATE; - -typedef struct { - __u16 TwoSeconds:5; - __u16 Minutes:6; - __u16 Hours:5; -} __attribute__((packed)) SMB_TIME; - -typedef struct { - __le16 CreationDate; /* SMB Date see above */ - __le16 CreationTime; /* SMB Time */ - __le16 LastAccessDate; - __le16 LastAccessTime; - __le16 LastWriteDate; - __le16 LastWriteTime; - __le32 DataSize; /* File Size (EOF) */ - __le32 AllocationSize; - __le16 Attributes; /* verify not u32 */ - __le32 EASize; -} __attribute__((packed)) FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */ - -typedef struct { - __le64 CreationTime; - __le64 LastAccessTime; - __le64 LastWriteTime; - __le64 ChangeTime; - __le32 Attributes; - __u32 Pad; -} __attribute__((packed)) FILE_BASIC_INFO; /* size info, level 0x101 */ - -struct file_allocation_info { - __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */ -} __attribute__((packed)); /* size used on disk, for level 0x103 for set, - 0x105 for query */ - -struct file_end_of_file_info { - __le64 FileSize; /* offset to end of file */ -} __attribute__((packed)); /* size info, level 0x104 for set, 0x106 for query */ - -struct file_alt_name_info { - __u8 alt_name[1]; -} __attribute__((packed)); /* level 0x0108 */ - -struct file_stream_info { - __le32 number_of_streams; /* BB check sizes and verify location */ - /* followed by info on streams themselves - u64 size; - u64 allocation_size - stream info */ -}; /* level 0x109 */ - -struct file_compression_info { - __le64 compressed_size; - __le16 format; - __u8 unit_shift; - __u8 ch_shift; - __u8 cl_shift; - __u8 pad[3]; -} __attribute__((packed)); /* level 0x10b */ - -/* POSIX ACL set/query path info structures */ -#define CIFS_ACL_VERSION 1 -struct cifs_posix_ace { /* access control entry (ACE) */ - __u8 cifs_e_tag; - __u8 cifs_e_perm; - __le64 cifs_uid; /* or gid */ -} __attribute__((packed)); - -struct cifs_posix_acl { /* access conrol list (ACL) */ - __le16 version; - __le16 access_entry_count; /* access ACL - count of entries */ - __le16 default_entry_count; /* default ACL - count of entries */ - struct cifs_posix_ace ace_array[0]; - /* followed by - struct cifs_posix_ace default_ace_arraay[] */ -} __attribute__((packed)); /* level 0x204 */ - -/* types of access control entries already defined in posix_acl.h */ -/* #define CIFS_POSIX_ACL_USER_OBJ 0x01 -#define CIFS_POSIX_ACL_USER 0x02 -#define CIFS_POSIX_ACL_GROUP_OBJ 0x04 -#define CIFS_POSIX_ACL_GROUP 0x08 -#define CIFS_POSIX_ACL_MASK 0x10 -#define CIFS_POSIX_ACL_OTHER 0x20 */ - -/* types of perms */ -/* #define CIFS_POSIX_ACL_EXECUTE 0x01 -#define CIFS_POSIX_ACL_WRITE 0x02 -#define CIFS_POSIX_ACL_READ 0x04 */ - -/* end of POSIX ACL definitions */ - -/* POSIX Open Flags */ -#define SMB_O_RDONLY 0x1 -#define SMB_O_WRONLY 0x2 -#define SMB_O_RDWR 0x4 -#define SMB_O_CREAT 0x10 -#define SMB_O_EXCL 0x20 -#define SMB_O_TRUNC 0x40 -#define SMB_O_APPEND 0x80 -#define SMB_O_SYNC 0x100 -#define SMB_O_DIRECTORY 0x200 -#define SMB_O_NOFOLLOW 0x400 -#define SMB_O_DIRECT 0x800 - -typedef struct { - __le32 OpenFlags; /* same as NT CreateX */ - __le32 PosixOpenFlags; - __le64 Permissions; - __le16 Level; /* reply level requested (see QPathInfo levels) */ -} __attribute__((packed)) OPEN_PSX_REQ; /* level 0x209 SetPathInfo data */ - -typedef struct { - __le16 OplockFlags; - __u16 Fid; - __le32 CreateAction; - __le16 ReturnedLevel; - __le16 Pad; - /* struct following varies based on requested level */ -} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */ - -#define SMB_POSIX_UNLINK_FILE_TARGET 0 -#define SMB_POSIX_UNLINK_DIRECTORY_TARGET 1 - -struct unlink_psx_rq { /* level 0x20a SetPathInfo */ - __le16 type; -} __attribute__((packed)); - -struct file_internal_info { - __le64 UniqueId; /* inode number */ -} __attribute__((packed)); /* level 0x3ee */ - -struct file_mode_info { - __le32 Mode; -} __attribute__((packed)); /* level 0x3f8 */ - -struct file_attrib_tag { - __le32 Attribute; - __le32 ReparseTag; -} __attribute__((packed)); /* level 0x40b */ - - -/********************************************************/ -/* FindFirst/FindNext transact2 data buffer formats */ -/********************************************************/ - -typedef struct { - __le32 NextEntryOffset; - __u32 ResumeKey; /* as with FileIndex - no need to convert */ - FILE_UNIX_BASIC_INFO basic; - char FileName[1]; -} __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */ - -typedef struct { - __le32 NextEntryOffset; - __u32 FileIndex; - __le64 CreationTime; - __le64 LastAccessTime; - __le64 LastWriteTime; - __le64 ChangeTime; - __le64 EndOfFile; - __le64 AllocationSize; - __le32 ExtFileAttributes; - __le32 FileNameLength; - char FileName[1]; -} __attribute__((packed)) FILE_DIRECTORY_INFO; /* level 0x101 FF resp data */ - -typedef struct { - __le32 NextEntryOffset; - __u32 FileIndex; - __le64 CreationTime; - __le64 LastAccessTime; - __le64 LastWriteTime; - __le64 ChangeTime; - __le64 EndOfFile; - __le64 AllocationSize; - __le32 ExtFileAttributes; - __le32 FileNameLength; - __le32 EaSize; /* length of the xattrs */ - char FileName[1]; -} __attribute__((packed)) FILE_FULL_DIRECTORY_INFO; /* level 0x102 rsp data */ - -typedef struct { - __le32 NextEntryOffset; - __u32 FileIndex; - __le64 CreationTime; - __le64 LastAccessTime; - __le64 LastWriteTime; - __le64 ChangeTime; - __le64 EndOfFile; - __le64 AllocationSize; - __le32 ExtFileAttributes; - __le32 FileNameLength; - __le32 EaSize; /* EA size */ - __le32 Reserved; - __le64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/ - char FileName[1]; -} __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF rsp data */ - -typedef struct { - __le32 NextEntryOffset; - __u32 FileIndex; - __le64 CreationTime; - __le64 LastAccessTime; - __le64 LastWriteTime; - __le64 ChangeTime; - __le64 EndOfFile; - __le64 AllocationSize; - __le32 ExtFileAttributes; - __le32 FileNameLength; - __le32 EaSize; /* length of the xattrs */ - __u8 ShortNameLength; - __u8 Reserved; - __u8 ShortName[12]; - char FileName[1]; -} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FFrsp data */ - -typedef struct { - __u32 ResumeKey; - __le16 CreationDate; /* SMB Date */ - __le16 CreationTime; /* SMB Time */ - __le16 LastAccessDate; - __le16 LastAccessTime; - __le16 LastWriteDate; - __le16 LastWriteTime; - __le32 DataSize; /* File Size (EOF) */ - __le32 AllocationSize; - __le16 Attributes; /* verify not u32 */ - __u8 FileNameLength; - char FileName[1]; -} __attribute__((packed)) FIND_FILE_STANDARD_INFO; /* level 0x1 FF resp data */ - - -struct win_dev { - unsigned char type[8]; /* IntxCHR or IntxBLK */ - __le64 major; - __le64 minor; -} __attribute__((packed)); - -struct gea { - unsigned char name_len; - char name[1]; -} __attribute__((packed)); - -struct gealist { - unsigned long list_len; - struct gea list[1]; -} __attribute__((packed)); - -struct fea { - unsigned char EA_flags; - __u8 name_len; - __le16 value_len; - char name[1]; - /* optionally followed by value */ -} __attribute__((packed)); -/* flags for _FEA.fEA */ -#define FEA_NEEDEA 0x80 /* need EA bit */ - -struct fealist { - __le32 list_len; - struct fea list[1]; -} __attribute__((packed)); - -/* used to hold an arbitrary blob of data */ -struct data_blob { - __u8 *data; - size_t length; - void (*free) (struct data_blob *data_blob); -} __attribute__((packed)); - - -#ifdef CONFIG_CIFS_POSIX -/* - For better POSIX semantics from Linux client, (even better - than the existing CIFS Unix Extensions) we need updated PDUs for: - - 1) PosixCreateX - to set and return the mode, inode#, device info and - perhaps add a CreateDevice - to create Pipes and other special .inodes - Also note POSIX open flags - 2) Close - to return the last write time to do cache across close - more safely - 3) FindFirst return unique inode number - what about resume key, two - forms short (matches readdir) and full (enough info to cache inodes) - 4) Mkdir - set mode - - And under consideration: - 5) FindClose2 (return nanosecond timestamp ??) - 6) Use nanosecond timestamps throughout all time fields if - corresponding attribute flag is set - 7) sendfile - handle based copy - - what about fixing 64 bit alignment - - There are also various legacy SMB/CIFS requests used as is - - From existing Lanman and NTLM dialects: - -------------------------------------- - NEGOTIATE - SESSION_SETUP_ANDX (BB which?) - TREE_CONNECT_ANDX (BB which wct?) - TREE_DISCONNECT (BB add volume timestamp on response) - LOGOFF_ANDX - DELETE (note delete open file behavior) - DELETE_DIRECTORY - READ_AND_X - WRITE_AND_X - LOCKING_AND_X (note posix lock semantics) - RENAME (note rename across dirs and open file rename posix behaviors) - NT_RENAME (for hardlinks) Is this good enough for all features? - FIND_CLOSE2 - TRANSACTION2 (18 cases) - SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2 - (BB verify that never need to set allocation size) - SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via - Unix ext?) - - COPY (note support for copy across directories) - FUTURE, OPTIONAL - setting/getting OS/2 EAs - FUTURE (BB can this handle - setting Linux xattrs perfectly) - OPTIONAL - dnotify - FUTURE, OPTIONAL - quota - FUTURE, OPTIONAL - - Note that various requests implemented for NT interop such as - NT_TRANSACT (IOCTL) QueryReparseInfo - are unneeded to servers compliant with the CIFS POSIX extensions - - From CIFS Unix Extensions: - ------------------------- - T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks - T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2) - T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK) - T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) BB check for missing - inode fields - Actually a need QUERY_FILE_UNIX_INFO - since has inode num - BB what about a) blksize/blkbits/blocks - b) i_version - c) i_rdev - d) notify mask? - e) generation - f) size_seqcount - T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX - TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended - T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL - */ - -/* xsymlink is a symlink format (used by MacOS) that can be used - to save symlink info in a regular file when - mounted to operating systems that do not - support the cifs Unix extensions or EAs (for xattr - based symlinks). For such a file to be recognized - as containing symlink data: - - 1) file size must be 1067, - 2) signature must begin file data, - 3) length field must be set to ASCII representation - of a number which is less than or equal to 1024, - 4) md5 must match that of the path data */ - -struct xsymlink { - /* 1067 bytes */ - char signature[4]; /* XSym */ /* not null terminated */ - char cr0; /* \n */ -/* ASCII representation of length (4 bytes decimal) terminated by \n not null */ - char length[4]; - char cr1; /* \n */ -/* md5 of valid subset of path ie path[0] through path[length-1] */ - __u8 md5[32]; - char cr2; /* \n */ -/* if room left, then end with \n then 0x20s by convention but not required */ - char path[1024]; -} __attribute__((packed)); - -typedef struct file_xattr_info { - /* BB do we need another field for flags? BB */ - __u32 xattr_name_len; - __u32 xattr_value_len; - char xattr_name[0]; - /* followed by xattr_value[xattr_value_len], no pad */ -} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute info - level 0x205 */ - - -/* flags for chattr command */ -#define EXT_SECURE_DELETE 0x00000001 /* EXT3_SECRM_FL */ -#define EXT_ENABLE_UNDELETE 0x00000002 /* EXT3_UNRM_FL */ -/* Reserved for compress file 0x4 */ -#define EXT_SYNCHRONOUS 0x00000008 /* EXT3_SYNC_FL */ -#define EXT_IMMUTABLE_FL 0x00000010 /* EXT3_IMMUTABLE_FL */ -#define EXT_OPEN_APPEND_ONLY 0x00000020 /* EXT3_APPEND_FL */ -#define EXT_DO_NOT_BACKUP 0x00000040 /* EXT3_NODUMP_FL */ -#define EXT_NO_UPDATE_ATIME 0x00000080 /* EXT3_NOATIME_FL */ -/* 0x100 through 0x800 reserved for compression flags and are GET-ONLY */ -#define EXT_HASH_TREE_INDEXED_DIR 0x00001000 /* GET-ONLY EXT3_INDEX_FL */ -/* 0x2000 reserved for IMAGIC_FL */ -#define EXT_JOURNAL_THIS_FILE 0x00004000 /* GET-ONLY EXT3_JOURNAL_DATA_FL */ -/* 0x8000 reserved for EXT3_NOTAIL_FL */ -#define EXT_SYNCHRONOUS_DIR 0x00010000 /* EXT3_DIRSYNC_FL */ -#define EXT_TOPDIR 0x00020000 /* EXT3_TOPDIR_FL */ - -#define EXT_SET_MASK 0x000300FF -#define EXT_GET_MASK 0x0003DFFF - -typedef struct file_chattr_info { - __le64 mask; /* list of all possible attribute bits */ - __le64 mode; /* list of actual attribute bits on this inode */ -} __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes - (chattr, chflags) level 0x206 */ -#endif /* POSIX */ -#endif /* _CIFSPDU_H */ diff --git a/ANDROID_3.4.5/fs/cifs/cifsproto.h b/ANDROID_3.4.5/fs/cifs/cifsproto.h deleted file mode 100644 index 97f5d037..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifsproto.h +++ /dev/null @@ -1,509 +0,0 @@ -/* - * fs/cifs/cifsproto.h - * - * Copyright (c) International Business Machines Corp., 2002,2008 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _CIFSPROTO_H -#define _CIFSPROTO_H -#include <linux/nls.h> - -struct statfs; -struct smb_vol; - -/* - ***************************************************************** - * All Prototypes - ***************************************************************** - */ - -extern struct smb_hdr *cifs_buf_get(void); -extern void cifs_buf_release(void *); -extern struct smb_hdr *cifs_small_buf_get(void); -extern void cifs_small_buf_release(void *); -extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *, - unsigned int /* length */); -extern unsigned int _GetXid(void); -extern void _FreeXid(unsigned int); -#define GetXid() \ -({ \ - int __xid = (int)_GetXid(); \ - cFYI(1, "CIFS VFS: in %s as Xid: %d with uid: %d", \ - __func__, __xid, current_fsuid()); \ - __xid; \ -}) - -#define FreeXid(curr_xid) \ -do { \ - _FreeXid(curr_xid); \ - cFYI(1, "CIFS VFS: leaving %s (xid = %d) rc = %d", \ - __func__, curr_xid, (int)rc); \ -} while (0) -extern int init_cifs_idmap(void); -extern void exit_cifs_idmap(void); -extern void cifs_destroy_idmaptrees(void); -extern char *build_path_from_dentry(struct dentry *); -extern char *cifs_build_path_to_root(struct smb_vol *vol, - struct cifs_sb_info *cifs_sb, - struct cifs_tcon *tcon); -extern char *build_wildcard_path_from_dentry(struct dentry *direntry); -extern char *cifs_compose_mount_options(const char *sb_mountdata, - const char *fullpath, const struct dfs_info3_param *ref, - char **devname); -/* extern void renew_parental_timestamps(struct dentry *direntry);*/ -extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer, - struct TCP_Server_Info *server); -extern void DeleteMidQEntry(struct mid_q_entry *midEntry); -extern int cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, - unsigned int nvec, mid_receive_t *receive, - mid_callback_t *callback, void *cbdata, - bool ignore_pend); -extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *, - struct smb_hdr * /* input */ , - struct smb_hdr * /* out */ , - int * /* bytes returned */ , const int long_op); -extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, - char *in_buf, int flags); -extern int cifs_check_receive(struct mid_q_entry *mid, - struct TCP_Server_Info *server, bool log_error); -extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *, - struct kvec *, int /* nvec to send */, - int * /* type of buf returned */ , const int flags); -extern int SendReceiveBlockingLock(const unsigned int xid, - struct cifs_tcon *ptcon, - struct smb_hdr *in_buf , - struct smb_hdr *out_buf, - int *bytes_returned); -extern void cifs_add_credits(struct TCP_Server_Info *server, - const unsigned int add); -extern void cifs_set_credits(struct TCP_Server_Info *server, const int val); -extern int checkSMB(char *buf, unsigned int length); -extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *); -extern bool backup_cred(struct cifs_sb_info *); -extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); -extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, - unsigned int bytes_written); -extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); -extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); -extern unsigned int smbCalcSize(struct smb_hdr *ptr); -extern int decode_negTokenInit(unsigned char *security_blob, int length, - struct TCP_Server_Info *server); -extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); -extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port); -extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, - const unsigned short int port); -extern int map_smb_to_linux_error(char *buf, bool logErr); -extern void header_assemble(struct smb_hdr *, char /* command */ , - const struct cifs_tcon *, int /* length of - fixed section (word count) in two byte units */); -extern int small_smb_init_no_tc(const int smb_cmd, const int wct, - struct cifs_ses *ses, - void **request_buf); -extern int CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses, - const struct nls_table *nls_cp); -extern __u64 GetNextMid(struct TCP_Server_Info *server); -extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); -extern u64 cifs_UnixTimeToNT(struct timespec); -extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, - int offset); -extern void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock); - -extern struct cifsFileInfo *cifs_new_fileinfo(__u16 fileHandle, - struct file *file, struct tcon_link *tlink, - __u32 oplock); -extern int cifs_posix_open(char *full_path, struct inode **pinode, - struct super_block *sb, - int mode, unsigned int f_flags, - __u32 *poplock, __u16 *pnetfid, int xid); -void cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr); -extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, - FILE_UNIX_BASIC_INFO *info, - struct cifs_sb_info *cifs_sb); -extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr); -extern struct inode *cifs_iget(struct super_block *sb, - struct cifs_fattr *fattr); - -extern int cifs_get_file_info(struct file *filp); -extern int cifs_get_inode_info(struct inode **pinode, - const unsigned char *search_path, - FILE_ALL_INFO *pfile_info, - struct super_block *sb, int xid, const __u16 *pfid); -extern int cifs_get_file_info_unix(struct file *filp); -extern int cifs_get_inode_info_unix(struct inode **pinode, - const unsigned char *search_path, - struct super_block *sb, int xid); -extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, - struct cifs_fattr *fattr, struct inode *inode, - const char *path, const __u16 *pfid); -extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64, - uid_t, gid_t); -extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, - const char *, u32 *); -extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, - const char *, int); - -extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); -extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, - unsigned int to_read); -extern int cifs_readv_from_socket(struct TCP_Server_Info *server, - struct kvec *iov_orig, unsigned int nr_segs, - unsigned int to_read); -extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, - struct cifs_sb_info *cifs_sb); -extern int cifs_match_super(struct super_block *, void *); -extern void cifs_cleanup_volume_info(struct smb_vol *pvolume_info); -extern struct smb_vol *cifs_get_volume_info(char *mount_data, - const char *devname); -extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *); -extern void cifs_umount(struct cifs_sb_info *); - -#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) -extern void cifs_dfs_release_automount_timer(void); -#else /* ! IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) */ -#define cifs_dfs_release_automount_timer() do { } while (0) -#endif /* ! IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) */ - -void cifs_proc_init(void); -void cifs_proc_clean(void); - -extern int cifs_negotiate_protocol(unsigned int xid, - struct cifs_ses *ses); -extern int cifs_setup_session(unsigned int xid, struct cifs_ses *ses, - struct nls_table *nls_info); -extern int CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses); - -extern int CIFSTCon(unsigned int xid, struct cifs_ses *ses, - const char *tree, struct cifs_tcon *tcon, - const struct nls_table *); - -extern int CIFSFindFirst(const int xid, struct cifs_tcon *tcon, - const char *searchName, const struct nls_table *nls_codepage, - __u16 *searchHandle, __u16 search_flags, - struct cifs_search_info *psrch_inf, - int map, const char dirsep); - -extern int CIFSFindNext(const int xid, struct cifs_tcon *tcon, - __u16 searchHandle, __u16 search_flags, - struct cifs_search_info *psrch_inf); - -extern int CIFSFindClose(const int, struct cifs_tcon *tcon, - const __u16 search_handle); - -extern int CIFSSMBQFileInfo(const int xid, struct cifs_tcon *tcon, - u16 netfid, FILE_ALL_INFO *pFindData); -extern int CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - FILE_ALL_INFO *findData, - int legacy /* whether to use old info level */, - const struct nls_table *nls_codepage, int remap); -extern int SMBQueryInformation(const int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - FILE_ALL_INFO *findData, - const struct nls_table *nls_codepage, int remap); - -extern int CIFSSMBUnixQFileInfo(const int xid, struct cifs_tcon *tcon, - u16 netfid, FILE_UNIX_BASIC_INFO *pFindData); -extern int CIFSSMBUnixQPathInfo(const int xid, - struct cifs_tcon *tcon, - const unsigned char *searchName, - FILE_UNIX_BASIC_INFO *pFindData, - const struct nls_table *nls_codepage, int remap); - -extern int CIFSGetDFSRefer(const int xid, struct cifs_ses *ses, - const unsigned char *searchName, - struct dfs_info3_param **target_nodes, - unsigned int *number_of_nodes_in_array, - const struct nls_table *nls_codepage, int remap); - -extern int get_dfs_path(int xid, struct cifs_ses *pSesInfo, - const char *old_path, - const struct nls_table *nls_codepage, - unsigned int *pnum_referrals, - struct dfs_info3_param **preferrals, - int remap); -extern void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, - struct cifs_sb_info *cifs_sb, - struct smb_vol *vol); -extern int CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, - struct kstatfs *FSData); -extern int SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, - struct kstatfs *FSData); -extern int CIFSSMBSetFSUnixInfo(const int xid, struct cifs_tcon *tcon, - __u64 cap); - -extern int CIFSSMBQFSAttributeInfo(const int xid, - struct cifs_tcon *tcon); -extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifs_tcon *tcon); -extern int CIFSSMBQFSUnixInfo(const int xid, struct cifs_tcon *tcon); -extern int CIFSSMBQFSPosixInfo(const int xid, struct cifs_tcon *tcon, - struct kstatfs *FSData); - -extern int CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon, - const char *fileName, const FILE_BASIC_INFO *data, - const struct nls_table *nls_codepage, - int remap_special_chars); -extern int CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon, - const FILE_BASIC_INFO *data, __u16 fid, - __u32 pid_of_opener); -extern int CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon, - bool delete_file, __u16 fid, __u32 pid_of_opener); -#if 0 -extern int CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon, - char *fileName, __u16 dos_attributes, - const struct nls_table *nls_codepage); -#endif /* possibly unneeded function */ -extern int CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, - const char *fileName, __u64 size, - bool setAllocationSizeFlag, - const struct nls_table *nls_codepage, - int remap_special_chars); -extern int CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, - __u64 size, __u16 fileHandle, __u32 opener_pid, - bool AllocSizeFlag); - -struct cifs_unix_set_info_args { - __u64 ctime; - __u64 atime; - __u64 mtime; - __u64 mode; - __u64 uid; - __u64 gid; - dev_t device; -}; - -extern int CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon, - const struct cifs_unix_set_info_args *args, - u16 fid, u32 pid_of_opener); - -extern int CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *pTcon, - char *fileName, - const struct cifs_unix_set_info_args *args, - const struct nls_table *nls_codepage, - int remap_special_chars); - -extern int CIFSSMBMkDir(const int xid, struct cifs_tcon *tcon, - const char *newName, - const struct nls_table *nls_codepage, - int remap_special_chars); -extern int CIFSSMBRmDir(const int xid, struct cifs_tcon *tcon, - const char *name, const struct nls_table *nls_codepage, - int remap_special_chars); -extern int CIFSPOSIXDelFile(const int xid, struct cifs_tcon *tcon, - const char *name, __u16 type, - const struct nls_table *nls_codepage, - int remap_special_chars); -extern int CIFSSMBDelFile(const int xid, struct cifs_tcon *tcon, - const char *name, - const struct nls_table *nls_codepage, - int remap_special_chars); -extern int CIFSSMBRename(const int xid, struct cifs_tcon *tcon, - const char *fromName, const char *toName, - const struct nls_table *nls_codepage, - int remap_special_chars); -extern int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon, - int netfid, const char *target_name, - const struct nls_table *nls_codepage, - int remap_special_chars); -extern int CIFSCreateHardLink(const int xid, - struct cifs_tcon *tcon, - const char *fromName, const char *toName, - const struct nls_table *nls_codepage, - int remap_special_chars); -extern int CIFSUnixCreateHardLink(const int xid, - struct cifs_tcon *tcon, - const char *fromName, const char *toName, - const struct nls_table *nls_codepage, - int remap_special_chars); -extern int CIFSUnixCreateSymLink(const int xid, - struct cifs_tcon *tcon, - const char *fromName, const char *toName, - const struct nls_table *nls_codepage); -extern int CIFSSMBUnixQuerySymLink(const int xid, - struct cifs_tcon *tcon, - const unsigned char *searchName, char **syminfo, - const struct nls_table *nls_codepage); -#ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL -extern int CIFSSMBQueryReparseLinkInfo(const int xid, - struct cifs_tcon *tcon, - const unsigned char *searchName, - char *symlinkinfo, const int buflen, __u16 fid, - const struct nls_table *nls_codepage); -#endif /* temporarily unused until cifs_symlink fixed */ -extern int CIFSSMBOpen(const int xid, struct cifs_tcon *tcon, - const char *fileName, const int disposition, - const int access_flags, const int omode, - __u16 *netfid, int *pOplock, FILE_ALL_INFO *, - const struct nls_table *nls_codepage, int remap); -extern int SMBLegacyOpen(const int xid, struct cifs_tcon *tcon, - const char *fileName, const int disposition, - const int access_flags, const int omode, - __u16 *netfid, int *pOplock, FILE_ALL_INFO *, - const struct nls_table *nls_codepage, int remap); -extern int CIFSPOSIXCreate(const int xid, struct cifs_tcon *tcon, - u32 posix_flags, __u64 mode, __u16 *netfid, - FILE_UNIX_BASIC_INFO *pRetData, - __u32 *pOplock, const char *name, - const struct nls_table *nls_codepage, int remap); -extern int CIFSSMBClose(const int xid, struct cifs_tcon *tcon, - const int smb_file_id); - -extern int CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, - const int smb_file_id); - -extern int CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, - unsigned int *nbytes, char **buf, - int *return_buf_type); -extern int CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms, - unsigned int *nbytes, const char *buf, - const char __user *ubuf, const int long_op); -extern int CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms, - unsigned int *nbytes, struct kvec *iov, const int nvec, - const int long_op); -extern int CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, __u64 *inode_number, - const struct nls_table *nls_codepage, - int remap_special_chars); - -extern int cifs_lockv(const int xid, struct cifs_tcon *tcon, const __u16 netfid, - const __u8 lock_type, const __u32 num_unlock, - const __u32 num_lock, LOCKING_ANDX_RANGE *buf); -extern int CIFSSMBLock(const int xid, struct cifs_tcon *tcon, - const __u16 netfid, const __u32 netpid, const __u64 len, - const __u64 offset, const __u32 numUnlock, - const __u32 numLock, const __u8 lockType, - const bool waitFlag, const __u8 oplock_level); -extern int CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon, - const __u16 smb_file_id, const __u32 netpid, - const int get_flag, const __u64 len, struct file_lock *, - const __u16 lock_type, const bool waitFlag); -extern int CIFSSMBTDis(const int xid, struct cifs_tcon *tcon); -extern int CIFSSMBEcho(struct TCP_Server_Info *server); -extern int CIFSSMBLogoff(const int xid, struct cifs_ses *ses); - -extern struct cifs_ses *sesInfoAlloc(void); -extern void sesInfoFree(struct cifs_ses *); -extern struct cifs_tcon *tconInfoAlloc(void); -extern void tconInfoFree(struct cifs_tcon *); - -extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *); -extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, - __u32 *); -extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov, - struct TCP_Server_Info *server, - __u32 expected_sequence_number); -extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *, - const struct nls_table *); -extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *); -extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *); -extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); -extern void cifs_crypto_shash_release(struct TCP_Server_Info *); -extern int calc_seckey(struct cifs_ses *); - -#ifdef CONFIG_CIFS_WEAK_PW_HASH -extern int calc_lanman_hash(const char *password, const char *cryptkey, - bool encrypt, char *lnm_session_key); -#endif /* CIFS_WEAK_PW_HASH */ -#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */ -extern int CIFSSMBNotify(const int xid, struct cifs_tcon *tcon, - const int notify_subdirs, const __u16 netfid, - __u32 filter, struct file *file, int multishot, - const struct nls_table *nls_codepage); -#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ -extern int CIFSSMBCopy(int xid, - struct cifs_tcon *source_tcon, - const char *fromName, - const __u16 target_tid, - const char *toName, const int flags, - const struct nls_table *nls_codepage, - int remap_special_chars); -extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - const unsigned char *ea_name, char *EAData, - size_t bufsize, const struct nls_table *nls_codepage, - int remap_special_chars); -extern int CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, - const char *fileName, const char *ea_name, - const void *ea_value, const __u16 ea_value_len, - const struct nls_table *nls_codepage, int remap_special_chars); -extern int CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, - __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen); -extern int CIFSSMBSetCIFSACL(const int, struct cifs_tcon *, __u16, - struct cifs_ntsd *, __u32, int); -extern int CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - char *acl_inf, const int buflen, const int acl_type, - const struct nls_table *nls_codepage, int remap_special_chars); -extern int CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon, - const unsigned char *fileName, - const char *local_acl, const int buflen, const int acl_type, - const struct nls_table *nls_codepage, int remap_special_chars); -extern int CIFSGetExtAttr(const int xid, struct cifs_tcon *tcon, - const int netfid, __u64 *pExtAttrBits, __u64 *pMask); -extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb); -extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr); -extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr, - const unsigned char *path, - struct cifs_sb_info *cifs_sb, int xid); -extern int mdfour(unsigned char *, unsigned char *, int); -extern int E_md4hash(const unsigned char *passwd, unsigned char *p16, - const struct nls_table *codepage); -extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8, - unsigned char *p24); - -/* asynchronous read support */ -struct cifs_readdata { - struct cifsFileInfo *cfile; - struct address_space *mapping; - __u64 offset; - unsigned int bytes; - pid_t pid; - int result; - struct list_head pages; - struct work_struct work; - unsigned int nr_iov; - struct kvec iov[1]; -}; - -struct cifs_readdata *cifs_readdata_alloc(unsigned int nr_pages); -void cifs_readdata_free(struct cifs_readdata *rdata); -int cifs_async_readv(struct cifs_readdata *rdata); - -/* asynchronous write support */ -struct cifs_writedata { - struct kref refcount; - struct list_head list; - struct completion done; - enum writeback_sync_modes sync_mode; - struct work_struct work; - struct cifsFileInfo *cfile; - __u64 offset; - pid_t pid; - unsigned int bytes; - int result; - void (*marshal_iov) (struct kvec *iov, - struct cifs_writedata *wdata); - unsigned int nr_pages; - struct page *pages[1]; -}; - -int cifs_async_writev(struct cifs_writedata *wdata); -void cifs_writev_complete(struct work_struct *work); -struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, - work_func_t complete); -void cifs_writedata_release(struct kref *refcount); - -#endif /* _CIFSPROTO_H */ diff --git a/ANDROID_3.4.5/fs/cifs/cifssmb.c b/ANDROID_3.4.5/fs/cifs/cifssmb.c deleted file mode 100644 index 6b79efd7..00000000 --- a/ANDROID_3.4.5/fs/cifs/cifssmb.c +++ /dev/null @@ -1,6504 +0,0 @@ -/* - * fs/cifs/cifssmb.c - * - * Copyright (C) International Business Machines Corp., 2002,2010 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * Contains the routines for constructing the SMB PDUs themselves - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */ - /* These are mostly routines that operate on a pathname, or on a tree id */ - /* (mounted volume), but there are eight handle based routines which must be */ - /* treated slightly differently for reconnection purposes since we never */ - /* want to reuse a stale file handle and only the caller knows the file info */ - -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/vfs.h> -#include <linux/slab.h> -#include <linux/posix_acl_xattr.h> -#include <linux/pagemap.h> -#include <linux/swap.h> -#include <linux/task_io_accounting_ops.h> -#include <asm/uaccess.h> -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsacl.h" -#include "cifsproto.h" -#include "cifs_unicode.h" -#include "cifs_debug.h" -#include "fscache.h" - -#ifdef CONFIG_CIFS_POSIX -static struct { - int index; - char *name; -} protocols[] = { -#ifdef CONFIG_CIFS_WEAK_PW_HASH - {LANMAN_PROT, "\2LM1.2X002"}, - {LANMAN2_PROT, "\2LANMAN2.1"}, -#endif /* weak password hashing for legacy clients */ - {CIFS_PROT, "\2NT LM 0.12"}, - {POSIX_PROT, "\2POSIX 2"}, - {BAD_PROT, "\2"} -}; -#else -static struct { - int index; - char *name; -} protocols[] = { -#ifdef CONFIG_CIFS_WEAK_PW_HASH - {LANMAN_PROT, "\2LM1.2X002"}, - {LANMAN2_PROT, "\2LANMAN2.1"}, -#endif /* weak password hashing for legacy clients */ - {CIFS_PROT, "\2NT LM 0.12"}, - {BAD_PROT, "\2"} -}; -#endif - -/* define the number of elements in the cifs dialect array */ -#ifdef CONFIG_CIFS_POSIX -#ifdef CONFIG_CIFS_WEAK_PW_HASH -#define CIFS_NUM_PROT 4 -#else -#define CIFS_NUM_PROT 2 -#endif /* CIFS_WEAK_PW_HASH */ -#else /* not posix */ -#ifdef CONFIG_CIFS_WEAK_PW_HASH -#define CIFS_NUM_PROT 3 -#else -#define CIFS_NUM_PROT 1 -#endif /* CONFIG_CIFS_WEAK_PW_HASH */ -#endif /* CIFS_POSIX */ - -/* Forward declarations */ -static void cifs_readv_complete(struct work_struct *work); - -/* Mark as invalid, all open files on tree connections since they - were closed when session to server was lost */ -static void mark_open_files_invalid(struct cifs_tcon *pTcon) -{ - struct cifsFileInfo *open_file = NULL; - struct list_head *tmp; - struct list_head *tmp1; - -/* list all files open on tree connection and mark them invalid */ - spin_lock(&cifs_file_list_lock); - list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { - open_file = list_entry(tmp, struct cifsFileInfo, tlist); - open_file->invalidHandle = true; - open_file->oplock_break_cancelled = true; - } - spin_unlock(&cifs_file_list_lock); - /* BB Add call to invalidate_inodes(sb) for all superblocks mounted - to this tcon */ -} - -/* reconnect the socket, tcon, and smb session if needed */ -static int -cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) -{ - int rc; - struct cifs_ses *ses; - struct TCP_Server_Info *server; - struct nls_table *nls_codepage; - - /* - * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for - * tcp and smb session status done differently for those three - in the - * calling routine - */ - if (!tcon) - return 0; - - ses = tcon->ses; - server = ses->server; - - /* - * only tree disconnect, open, and write, (and ulogoff which does not - * have tcon) are allowed as we start force umount - */ - if (tcon->tidStatus == CifsExiting) { - if (smb_command != SMB_COM_WRITE_ANDX && - smb_command != SMB_COM_OPEN_ANDX && - smb_command != SMB_COM_TREE_DISCONNECT) { - cFYI(1, "can not send cmd %d while umounting", - smb_command); - return -ENODEV; - } - } - - /* - * Give demultiplex thread up to 10 seconds to reconnect, should be - * greater than cifs socket timeout which is 7 seconds - */ - while (server->tcpStatus == CifsNeedReconnect) { - wait_event_interruptible_timeout(server->response_q, - (server->tcpStatus != CifsNeedReconnect), 10 * HZ); - - /* are we still trying to reconnect? */ - if (server->tcpStatus != CifsNeedReconnect) - break; - - /* - * on "soft" mounts we wait once. Hard mounts keep - * retrying until process is killed or server comes - * back on-line - */ - if (!tcon->retry) { - cFYI(1, "gave up waiting on reconnect in smb_init"); - return -EHOSTDOWN; - } - } - - if (!ses->need_reconnect && !tcon->need_reconnect) - return 0; - - nls_codepage = load_nls_default(); - - /* - * need to prevent multiple threads trying to simultaneously - * reconnect the same SMB session - */ - mutex_lock(&ses->session_mutex); - rc = cifs_negotiate_protocol(0, ses); - if (rc == 0 && ses->need_reconnect) - rc = cifs_setup_session(0, ses, nls_codepage); - - /* do we need to reconnect tcon? */ - if (rc || !tcon->need_reconnect) { - mutex_unlock(&ses->session_mutex); - goto out; - } - - mark_open_files_invalid(tcon); - rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage); - mutex_unlock(&ses->session_mutex); - cFYI(1, "reconnect tcon rc = %d", rc); - - if (rc) - goto out; - - /* - * FIXME: check if wsize needs updated due to negotiated smb buffer - * size shrinking - */ - atomic_inc(&tconInfoReconnectCount); - - /* tell server Unix caps we support */ - if (ses->capabilities & CAP_UNIX) - reset_cifs_unix_caps(0, tcon, NULL, NULL); - - /* - * Removed call to reopen open files here. It is safer (and faster) to - * reopen files one at a time as needed in read and write. - * - * FIXME: what about file locks? don't we need to reclaim them ASAP? - */ - -out: - /* - * Check if handle based operation so we know whether we can continue - * or not without returning to caller to reset file handle - */ - switch (smb_command) { - case SMB_COM_READ_ANDX: - case SMB_COM_WRITE_ANDX: - case SMB_COM_CLOSE: - case SMB_COM_FIND_CLOSE2: - case SMB_COM_LOCKING_ANDX: - rc = -EAGAIN; - } - - unload_nls(nls_codepage); - return rc; -} - -/* Allocate and return pointer to an SMB request buffer, and set basic - SMB information in the SMB header. If the return code is zero, this - function must have filled in request_buf pointer */ -static int -small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon, - void **request_buf) -{ - int rc; - - rc = cifs_reconnect_tcon(tcon, smb_command); - if (rc) - return rc; - - *request_buf = cifs_small_buf_get(); - if (*request_buf == NULL) { - /* BB should we add a retry in here if not a writepage? */ - return -ENOMEM; - } - - header_assemble((struct smb_hdr *) *request_buf, smb_command, - tcon, wct); - - if (tcon != NULL) - cifs_stats_inc(&tcon->num_smbs_sent); - - return 0; -} - -int -small_smb_init_no_tc(const int smb_command, const int wct, - struct cifs_ses *ses, void **request_buf) -{ - int rc; - struct smb_hdr *buffer; - - rc = small_smb_init(smb_command, wct, NULL, request_buf); - if (rc) - return rc; - - buffer = (struct smb_hdr *)*request_buf; - buffer->Mid = GetNextMid(ses->server); - if (ses->capabilities & CAP_UNICODE) - buffer->Flags2 |= SMBFLG2_UNICODE; - if (ses->capabilities & CAP_STATUS32) - buffer->Flags2 |= SMBFLG2_ERR_STATUS; - - /* uid, tid can stay at zero as set in header assemble */ - - /* BB add support for turning on the signing when - this function is used after 1st of session setup requests */ - - return rc; -} - -/* If the return code is zero, this function must fill in request_buf pointer */ -static int -__smb_init(int smb_command, int wct, struct cifs_tcon *tcon, - void **request_buf, void **response_buf) -{ - *request_buf = cifs_buf_get(); - if (*request_buf == NULL) { - /* BB should we add a retry in here if not a writepage? */ - return -ENOMEM; - } - /* Although the original thought was we needed the response buf for */ - /* potential retries of smb operations it turns out we can determine */ - /* from the mid flags when the request buffer can be resent without */ - /* having to use a second distinct buffer for the response */ - if (response_buf) - *response_buf = *request_buf; - - header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, - wct); - - if (tcon != NULL) - cifs_stats_inc(&tcon->num_smbs_sent); - - return 0; -} - -/* If the return code is zero, this function must fill in request_buf pointer */ -static int -smb_init(int smb_command, int wct, struct cifs_tcon *tcon, - void **request_buf, void **response_buf) -{ - int rc; - - rc = cifs_reconnect_tcon(tcon, smb_command); - if (rc) - return rc; - - return __smb_init(smb_command, wct, tcon, request_buf, response_buf); -} - -static int -smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon, - void **request_buf, void **response_buf) -{ - if (tcon->ses->need_reconnect || tcon->need_reconnect) - return -EHOSTDOWN; - - return __smb_init(smb_command, wct, tcon, request_buf, response_buf); -} - -static int validate_t2(struct smb_t2_rsp *pSMB) -{ - unsigned int total_size; - - /* check for plausible wct */ - if (pSMB->hdr.WordCount < 10) - goto vt2_err; - - /* check for parm and data offset going beyond end of smb */ - if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 || - get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024) - goto vt2_err; - - total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount); - if (total_size >= 512) - goto vt2_err; - - /* check that bcc is at least as big as parms + data, and that it is - * less than negotiated smb buffer - */ - total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount); - if (total_size > get_bcc(&pSMB->hdr) || - total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) - goto vt2_err; - - return 0; -vt2_err: - cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB, - sizeof(struct smb_t2_rsp) + 16); - return -EINVAL; -} - -static inline void inc_rfc1001_len(void *pSMB, int count) -{ - struct smb_hdr *hdr = (struct smb_hdr *)pSMB; - - be32_add_cpu(&hdr->smb_buf_length, count); -} - -int -CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses) -{ - NEGOTIATE_REQ *pSMB; - NEGOTIATE_RSP *pSMBr; - int rc = 0; - int bytes_returned; - int i; - struct TCP_Server_Info *server; - u16 count; - unsigned int secFlags; - - if (ses->server) - server = ses->server; - else { - rc = -EIO; - return rc; - } - rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ , - (void **) &pSMB, (void **) &pSMBr); - if (rc) - return rc; - - /* if any of auth flags (ie not sign or seal) are overriden use them */ - if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL))) - secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */ - else /* if override flags set only sign/seal OR them with global auth */ - secFlags = global_secflags | ses->overrideSecFlg; - - cFYI(1, "secFlags 0x%x", secFlags); - - pSMB->hdr.Mid = GetNextMid(server); - pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); - - if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) - pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; - else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) { - cFYI(1, "Kerberos only mechanism, enable extended security"); - pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; - } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP) - pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; - else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) { - cFYI(1, "NTLMSSP only mechanism, enable extended security"); - pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; - } - - count = 0; - for (i = 0; i < CIFS_NUM_PROT; i++) { - strncpy(pSMB->DialectsArray+count, protocols[i].name, 16); - count += strlen(protocols[i].name) + 1; - /* null at end of source and target buffers anyway */ - } - inc_rfc1001_len(pSMB, count); - pSMB->ByteCount = cpu_to_le16(count); - - rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc != 0) - goto neg_err_exit; - - server->dialect = le16_to_cpu(pSMBr->DialectIndex); - cFYI(1, "Dialect: %d", server->dialect); - /* Check wct = 1 error case */ - if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) { - /* core returns wct = 1, but we do not ask for core - otherwise - small wct just comes when dialect index is -1 indicating we - could not negotiate a common dialect */ - rc = -EOPNOTSUPP; - goto neg_err_exit; -#ifdef CONFIG_CIFS_WEAK_PW_HASH - } else if ((pSMBr->hdr.WordCount == 13) - && ((server->dialect == LANMAN_PROT) - || (server->dialect == LANMAN2_PROT))) { - __s16 tmp; - struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr; - - if ((secFlags & CIFSSEC_MAY_LANMAN) || - (secFlags & CIFSSEC_MAY_PLNTXT)) - server->secType = LANMAN; - else { - cERROR(1, "mount failed weak security disabled" - " in /proc/fs/cifs/SecurityFlags"); - rc = -EOPNOTSUPP; - goto neg_err_exit; - } - server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode); - server->maxReq = min_t(unsigned int, - le16_to_cpu(rsp->MaxMpxCount), - cifs_max_pending); - cifs_set_credits(server, server->maxReq); - server->maxBuf = le16_to_cpu(rsp->MaxBufSize); - server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); - /* even though we do not use raw we might as well set this - accurately, in case we ever find a need for it */ - if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { - server->max_rw = 0xFF00; - server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE; - } else { - server->max_rw = 0;/* do not need to use raw anyway */ - server->capabilities = CAP_MPX_MODE; - } - tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); - if (tmp == -1) { - /* OS/2 often does not set timezone therefore - * we must use server time to calc time zone. - * Could deviate slightly from the right zone. - * Smallest defined timezone difference is 15 minutes - * (i.e. Nepal). Rounding up/down is done to match - * this requirement. - */ - int val, seconds, remain, result; - struct timespec ts, utc; - utc = CURRENT_TIME; - ts = cnvrtDosUnixTm(rsp->SrvTime.Date, - rsp->SrvTime.Time, 0); - cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d", - (int)ts.tv_sec, (int)utc.tv_sec, - (int)(utc.tv_sec - ts.tv_sec)); - val = (int)(utc.tv_sec - ts.tv_sec); - seconds = abs(val); - result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ; - remain = seconds % MIN_TZ_ADJ; - if (remain >= (MIN_TZ_ADJ / 2)) - result += MIN_TZ_ADJ; - if (val < 0) - result = -result; - server->timeAdj = result; - } else { - server->timeAdj = (int)tmp; - server->timeAdj *= 60; /* also in seconds */ - } - cFYI(1, "server->timeAdj: %d seconds", server->timeAdj); - - - /* BB get server time for time conversions and add - code to use it and timezone since this is not UTC */ - - if (rsp->EncryptionKeyLength == - cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) { - memcpy(ses->server->cryptkey, rsp->EncryptionKey, - CIFS_CRYPTO_KEY_SIZE); - } else if (server->sec_mode & SECMODE_PW_ENCRYPT) { - rc = -EIO; /* need cryptkey unless plain text */ - goto neg_err_exit; - } - - cFYI(1, "LANMAN negotiated"); - /* we will not end up setting signing flags - as no signing - was in LANMAN and server did not return the flags on */ - goto signing_check; -#else /* weak security disabled */ - } else if (pSMBr->hdr.WordCount == 13) { - cERROR(1, "mount failed, cifs module not built " - "with CIFS_WEAK_PW_HASH support"); - rc = -EOPNOTSUPP; -#endif /* WEAK_PW_HASH */ - goto neg_err_exit; - } else if (pSMBr->hdr.WordCount != 17) { - /* unknown wct */ - rc = -EOPNOTSUPP; - goto neg_err_exit; - } - /* else wct == 17 NTLM */ - server->sec_mode = pSMBr->SecurityMode; - if ((server->sec_mode & SECMODE_USER) == 0) - cFYI(1, "share mode security"); - - if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0) -#ifdef CONFIG_CIFS_WEAK_PW_HASH - if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0) -#endif /* CIFS_WEAK_PW_HASH */ - cERROR(1, "Server requests plain text password" - " but client support disabled"); - - if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2) - server->secType = NTLMv2; - else if (secFlags & CIFSSEC_MAY_NTLM) - server->secType = NTLM; - else if (secFlags & CIFSSEC_MAY_NTLMV2) - server->secType = NTLMv2; - else if (secFlags & CIFSSEC_MAY_KRB5) - server->secType = Kerberos; - else if (secFlags & CIFSSEC_MAY_NTLMSSP) - server->secType = RawNTLMSSP; - else if (secFlags & CIFSSEC_MAY_LANMAN) - server->secType = LANMAN; - else { - rc = -EOPNOTSUPP; - cERROR(1, "Invalid security type"); - goto neg_err_exit; - } - /* else ... any others ...? */ - - /* one byte, so no need to convert this or EncryptionKeyLen from - little endian */ - server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount), - cifs_max_pending); - cifs_set_credits(server, server->maxReq); - /* probably no need to store and check maxvcs */ - server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize); - server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); - cFYI(DBG2, "Max buf = %d", ses->server->maxBuf); - server->capabilities = le32_to_cpu(pSMBr->Capabilities); - server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); - server->timeAdj *= 60; - if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { - memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey, - CIFS_CRYPTO_KEY_SIZE); - } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC || - server->capabilities & CAP_EXTENDED_SECURITY) && - (pSMBr->EncryptionKeyLength == 0)) { - /* decode security blob */ - count = get_bcc(&pSMBr->hdr); - if (count < 16) { - rc = -EIO; - goto neg_err_exit; - } - spin_lock(&cifs_tcp_ses_lock); - if (server->srv_count > 1) { - spin_unlock(&cifs_tcp_ses_lock); - if (memcmp(server->server_GUID, - pSMBr->u.extended_response. - GUID, 16) != 0) { - cFYI(1, "server UID changed"); - memcpy(server->server_GUID, - pSMBr->u.extended_response.GUID, - 16); - } - } else { - spin_unlock(&cifs_tcp_ses_lock); - memcpy(server->server_GUID, - pSMBr->u.extended_response.GUID, 16); - } - - if (count == 16) { - server->secType = RawNTLMSSP; - } else { - rc = decode_negTokenInit(pSMBr->u.extended_response. - SecurityBlob, count - 16, - server); - if (rc == 1) - rc = 0; - else - rc = -EINVAL; - if (server->secType == Kerberos) { - if (!server->sec_kerberos && - !server->sec_mskerberos) - rc = -EOPNOTSUPP; - } else if (server->secType == RawNTLMSSP) { - if (!server->sec_ntlmssp) - rc = -EOPNOTSUPP; - } else - rc = -EOPNOTSUPP; - } - } else if (server->sec_mode & SECMODE_PW_ENCRYPT) { - rc = -EIO; /* no crypt key only if plain text pwd */ - goto neg_err_exit; - } else - server->capabilities &= ~CAP_EXTENDED_SECURITY; - -#ifdef CONFIG_CIFS_WEAK_PW_HASH -signing_check: -#endif - if ((secFlags & CIFSSEC_MAY_SIGN) == 0) { - /* MUST_SIGN already includes the MAY_SIGN FLAG - so if this is zero it means that signing is disabled */ - cFYI(1, "Signing disabled"); - if (server->sec_mode & SECMODE_SIGN_REQUIRED) { - cERROR(1, "Server requires " - "packet signing to be enabled in " - "/proc/fs/cifs/SecurityFlags."); - rc = -EOPNOTSUPP; - } - server->sec_mode &= - ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); - } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) { - /* signing required */ - cFYI(1, "Must sign - secFlags 0x%x", secFlags); - if ((server->sec_mode & - (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) { - cERROR(1, "signing required but server lacks support"); - rc = -EOPNOTSUPP; - } else - server->sec_mode |= SECMODE_SIGN_REQUIRED; - } else { - /* signing optional ie CIFSSEC_MAY_SIGN */ - if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0) - server->sec_mode &= - ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); - } - -neg_err_exit: - cifs_buf_release(pSMB); - - cFYI(1, "negprot rc %d", rc); - return rc; -} - -int -CIFSSMBTDis(const int xid, struct cifs_tcon *tcon) -{ - struct smb_hdr *smb_buffer; - int rc = 0; - - cFYI(1, "In tree disconnect"); - - /* BB: do we need to check this? These should never be NULL. */ - if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) - return -EIO; - - /* - * No need to return error on this operation if tid invalidated and - * closed on server already e.g. due to tcp session crashing. Also, - * the tcon is no longer on the list, so no need to take lock before - * checking this. - */ - if ((tcon->need_reconnect) || (tcon->ses->need_reconnect)) - return 0; - - rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, - (void **)&smb_buffer); - if (rc) - return rc; - - rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0); - if (rc) - cFYI(1, "Tree disconnect failed %d", rc); - - /* No need to return error on this operation if tid invalidated and - closed on server already e.g. due to tcp session crashing */ - if (rc == -EAGAIN) - rc = 0; - - return rc; -} - -/* - * This is a no-op for now. We're not really interested in the reply, but - * rather in the fact that the server sent one and that server->lstrp - * gets updated. - * - * FIXME: maybe we should consider checking that the reply matches request? - */ -static void -cifs_echo_callback(struct mid_q_entry *mid) -{ - struct TCP_Server_Info *server = mid->callback_data; - - DeleteMidQEntry(mid); - cifs_add_credits(server, 1); -} - -int -CIFSSMBEcho(struct TCP_Server_Info *server) -{ - ECHO_REQ *smb; - int rc = 0; - struct kvec iov; - - cFYI(1, "In echo request"); - - rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb); - if (rc) - return rc; - - /* set up echo request */ - smb->hdr.Tid = 0xffff; - smb->hdr.WordCount = 1; - put_unaligned_le16(1, &smb->EchoCount); - put_bcc(1, &smb->hdr); - smb->Data[0] = 'a'; - inc_rfc1001_len(smb, 3); - iov.iov_base = smb; - iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; - - rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback, - server, true); - if (rc) - cFYI(1, "Echo request failed: %d", rc); - - cifs_small_buf_release(smb); - - return rc; -} - -int -CIFSSMBLogoff(const int xid, struct cifs_ses *ses) -{ - LOGOFF_ANDX_REQ *pSMB; - int rc = 0; - - cFYI(1, "In SMBLogoff for session disconnect"); - - /* - * BB: do we need to check validity of ses and server? They should - * always be valid since we have an active reference. If not, that - * should probably be a BUG() - */ - if (!ses || !ses->server) - return -EIO; - - mutex_lock(&ses->session_mutex); - if (ses->need_reconnect) - goto session_already_dead; /* no need to send SMBlogoff if uid - already closed due to reconnect */ - rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB); - if (rc) { - mutex_unlock(&ses->session_mutex); - return rc; - } - - pSMB->hdr.Mid = GetNextMid(ses->server); - - if (ses->server->sec_mode & - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) - pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - - pSMB->hdr.Uid = ses->Suid; - - pSMB->AndXCommand = 0xFF; - rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0); -session_already_dead: - mutex_unlock(&ses->session_mutex); - - /* if session dead then we do not need to do ulogoff, - since server closed smb session, no sense reporting - error */ - if (rc == -EAGAIN) - rc = 0; - return rc; -} - -int -CIFSPOSIXDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName, - __u16 type, const struct nls_table *nls_codepage, int remap) -{ - TRANSACTION2_SPI_REQ *pSMB = NULL; - TRANSACTION2_SPI_RSP *pSMBr = NULL; - struct unlink_psx_rq *pRqD; - int name_len; - int rc = 0; - int bytes_returned = 0; - __u16 params, param_offset, offset, byte_count; - - cFYI(1, "In POSIX delete"); -PsxDelete: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB add path length overrun check */ - name_len = strnlen(fileName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, fileName, name_len); - } - - params = 6 + name_len; - pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = 0; /* BB double check this with jra */ - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_spi_req, - InformationLevel) - 4; - offset = param_offset + params; - - /* Setup pointer to Request Data (inode type) */ - pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset); - pRqD->type = cpu_to_le16(type); - pSMB->ParameterOffset = cpu_to_le16(param_offset); - pSMB->DataOffset = cpu_to_le16(offset); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); - byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq); - - pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq)); - pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq)); - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) - cFYI(1, "Posix delete returned %d", rc); - cifs_buf_release(pSMB); - - cifs_stats_inc(&tcon->num_deletes); - - if (rc == -EAGAIN) - goto PsxDelete; - - return rc; -} - -int -CIFSSMBDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName, - const struct nls_table *nls_codepage, int remap) -{ - DELETE_FILE_REQ *pSMB = NULL; - DELETE_FILE_RSP *pSMBr = NULL; - int rc = 0; - int bytes_returned; - int name_len; - -DelFileRetry: - rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve check for buffer overruns BB */ - name_len = strnlen(fileName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->fileName, fileName, name_len); - } - pSMB->SearchAttributes = - cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); - pSMB->BufferFormat = 0x04; - inc_rfc1001_len(pSMB, name_len + 1); - pSMB->ByteCount = cpu_to_le16(name_len + 1); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - cifs_stats_inc(&tcon->num_deletes); - if (rc) - cFYI(1, "Error in RMFile = %d", rc); - - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto DelFileRetry; - - return rc; -} - -int -CIFSSMBRmDir(const int xid, struct cifs_tcon *tcon, const char *dirName, - const struct nls_table *nls_codepage, int remap) -{ - DELETE_DIRECTORY_REQ *pSMB = NULL; - DELETE_DIRECTORY_RSP *pSMBr = NULL; - int rc = 0; - int bytes_returned; - int name_len; - - cFYI(1, "In CIFSSMBRmDir"); -RmDirRetry: - rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve check for buffer overruns BB */ - name_len = strnlen(dirName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->DirName, dirName, name_len); - } - - pSMB->BufferFormat = 0x04; - inc_rfc1001_len(pSMB, name_len + 1); - pSMB->ByteCount = cpu_to_le16(name_len + 1); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - cifs_stats_inc(&tcon->num_rmdirs); - if (rc) - cFYI(1, "Error in RMDir = %d", rc); - - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto RmDirRetry; - return rc; -} - -int -CIFSSMBMkDir(const int xid, struct cifs_tcon *tcon, - const char *name, const struct nls_table *nls_codepage, int remap) -{ - int rc = 0; - CREATE_DIRECTORY_REQ *pSMB = NULL; - CREATE_DIRECTORY_RSP *pSMBr = NULL; - int bytes_returned; - int name_len; - - cFYI(1, "In CIFSSMBMkDir"); -MkDirRetry: - rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve check for buffer overruns BB */ - name_len = strnlen(name, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->DirName, name, name_len); - } - - pSMB->BufferFormat = 0x04; - inc_rfc1001_len(pSMB, name_len + 1); - pSMB->ByteCount = cpu_to_le16(name_len + 1); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - cifs_stats_inc(&tcon->num_mkdirs); - if (rc) - cFYI(1, "Error in Mkdir = %d", rc); - - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto MkDirRetry; - return rc; -} - -int -CIFSPOSIXCreate(const int xid, struct cifs_tcon *tcon, __u32 posix_flags, - __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData, - __u32 *pOplock, const char *name, - const struct nls_table *nls_codepage, int remap) -{ - TRANSACTION2_SPI_REQ *pSMB = NULL; - TRANSACTION2_SPI_RSP *pSMBr = NULL; - int name_len; - int rc = 0; - int bytes_returned = 0; - __u16 params, param_offset, offset, byte_count, count; - OPEN_PSX_REQ *pdata; - OPEN_PSX_RSP *psx_rsp; - - cFYI(1, "In POSIX Create"); -PsxCreat: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, name, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(name, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, name, name_len); - } - - params = 6 + name_len; - count = sizeof(OPEN_PSX_REQ); - pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */ - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_spi_req, - InformationLevel) - 4; - offset = param_offset + params; - pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset); - pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); - pdata->Permissions = cpu_to_le64(mode); - pdata->PosixOpenFlags = cpu_to_le32(posix_flags); - pdata->OpenFlags = cpu_to_le32(*pOplock); - pSMB->ParameterOffset = cpu_to_le16(param_offset); - pSMB->DataOffset = cpu_to_le16(offset); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); - byte_count = 3 /* pad */ + params + count; - - pSMB->DataCount = cpu_to_le16(count); - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Posix create returned %d", rc); - goto psx_create_err; - } - - cFYI(1, "copying inode info"); - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) { - rc = -EIO; /* bad smb */ - goto psx_create_err; - } - - /* copy return information to pRetData */ - psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol - + le16_to_cpu(pSMBr->t2.DataOffset)); - - *pOplock = le16_to_cpu(psx_rsp->OplockFlags); - if (netfid) - *netfid = psx_rsp->Fid; /* cifs fid stays in le */ - /* Let caller know file was created so we can set the mode. */ - /* Do we care about the CreateAction in any other cases? */ - if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction) - *pOplock |= CIFS_CREATE_ACTION; - /* check to make sure response data is there */ - if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) { - pRetData->Type = cpu_to_le32(-1); /* unknown */ - cFYI(DBG2, "unknown type"); - } else { - if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP) - + sizeof(FILE_UNIX_BASIC_INFO)) { - cERROR(1, "Open response data too small"); - pRetData->Type = cpu_to_le32(-1); - goto psx_create_err; - } - memcpy((char *) pRetData, - (char *)psx_rsp + sizeof(OPEN_PSX_RSP), - sizeof(FILE_UNIX_BASIC_INFO)); - } - -psx_create_err: - cifs_buf_release(pSMB); - - if (posix_flags & SMB_O_DIRECTORY) - cifs_stats_inc(&tcon->num_posixmkdirs); - else - cifs_stats_inc(&tcon->num_posixopens); - - if (rc == -EAGAIN) - goto PsxCreat; - - return rc; -} - -static __u16 convert_disposition(int disposition) -{ - __u16 ofun = 0; - - switch (disposition) { - case FILE_SUPERSEDE: - ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC; - break; - case FILE_OPEN: - ofun = SMBOPEN_OAPPEND; - break; - case FILE_CREATE: - ofun = SMBOPEN_OCREATE; - break; - case FILE_OPEN_IF: - ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND; - break; - case FILE_OVERWRITE: - ofun = SMBOPEN_OTRUNC; - break; - case FILE_OVERWRITE_IF: - ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC; - break; - default: - cFYI(1, "unknown disposition %d", disposition); - ofun = SMBOPEN_OAPPEND; /* regular open */ - } - return ofun; -} - -static int -access_flags_to_smbopen_mode(const int access_flags) -{ - int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE); - - if (masked_flags == GENERIC_READ) - return SMBOPEN_READ; - else if (masked_flags == GENERIC_WRITE) - return SMBOPEN_WRITE; - - /* just go for read/write */ - return SMBOPEN_READWRITE; -} - -int -SMBLegacyOpen(const int xid, struct cifs_tcon *tcon, - const char *fileName, const int openDisposition, - const int access_flags, const int create_options, __u16 *netfid, - int *pOplock, FILE_ALL_INFO *pfile_info, - const struct nls_table *nls_codepage, int remap) -{ - int rc = -EACCES; - OPENX_REQ *pSMB = NULL; - OPENX_RSP *pSMBr = NULL; - int bytes_returned; - int name_len; - __u16 count; - -OldOpenRetry: - rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - pSMB->AndXCommand = 0xFF; /* none */ - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - count = 1; /* account for one byte pad to word boundary */ - name_len = - cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1), - fileName, PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve check for buffer overruns BB */ - count = 0; /* no pad */ - name_len = strnlen(fileName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->fileName, fileName, name_len); - } - if (*pOplock & REQ_OPLOCK) - pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK); - else if (*pOplock & REQ_BATCHOPLOCK) - pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK); - - pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO); - pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags)); - pSMB->Mode |= cpu_to_le16(0x40); /* deny none */ - /* set file as system file if special file such - as fifo and server expecting SFU style and - no Unix extensions */ - - if (create_options & CREATE_OPTION_SPECIAL) - pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM); - else /* BB FIXME BB */ - pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); - - if (create_options & CREATE_OPTION_READONLY) - pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY); - - /* BB FIXME BB */ -/* pSMB->CreateOptions = cpu_to_le32(create_options & - CREATE_OPTIONS_MASK); */ - /* BB FIXME END BB */ - - pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); - pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition)); - count += name_len; - inc_rfc1001_len(pSMB, count); - - pSMB->ByteCount = cpu_to_le16(count); - /* long_op set to 1 to allow for oplock break timeouts */ - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *)pSMBr, &bytes_returned, 0); - cifs_stats_inc(&tcon->num_opens); - if (rc) { - cFYI(1, "Error in Open = %d", rc); - } else { - /* BB verify if wct == 15 */ - -/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/ - - *netfid = pSMBr->Fid; /* cifs fid stays in le */ - /* Let caller know file was created so we can set the mode. */ - /* Do we care about the CreateAction in any other cases? */ - /* BB FIXME BB */ -/* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction) - *pOplock |= CIFS_CREATE_ACTION; */ - /* BB FIXME END */ - - if (pfile_info) { - pfile_info->CreationTime = 0; /* BB convert CreateTime*/ - pfile_info->LastAccessTime = 0; /* BB fixme */ - pfile_info->LastWriteTime = 0; /* BB fixme */ - pfile_info->ChangeTime = 0; /* BB fixme */ - pfile_info->Attributes = - cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes)); - /* the file_info buf is endian converted by caller */ - pfile_info->AllocationSize = - cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile)); - pfile_info->EndOfFile = pfile_info->AllocationSize; - pfile_info->NumberOfLinks = cpu_to_le32(1); - pfile_info->DeletePending = 0; - } - } - - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto OldOpenRetry; - return rc; -} - -int -CIFSSMBOpen(const int xid, struct cifs_tcon *tcon, - const char *fileName, const int openDisposition, - const int access_flags, const int create_options, __u16 *netfid, - int *pOplock, FILE_ALL_INFO *pfile_info, - const struct nls_table *nls_codepage, int remap) -{ - int rc = -EACCES; - OPEN_REQ *pSMB = NULL; - OPEN_RSP *pSMBr = NULL; - int bytes_returned; - int name_len; - __u16 count; - -openRetry: - rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - pSMB->AndXCommand = 0xFF; /* none */ - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - count = 1; /* account for one byte pad to word boundary */ - name_len = - cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1), - fileName, PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - pSMB->NameLength = cpu_to_le16(name_len); - } else { /* BB improve check for buffer overruns BB */ - count = 0; /* no pad */ - name_len = strnlen(fileName, PATH_MAX); - name_len++; /* trailing null */ - pSMB->NameLength = cpu_to_le16(name_len); - strncpy(pSMB->fileName, fileName, name_len); - } - if (*pOplock & REQ_OPLOCK) - pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK); - else if (*pOplock & REQ_BATCHOPLOCK) - pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); - pSMB->DesiredAccess = cpu_to_le32(access_flags); - pSMB->AllocationSize = 0; - /* set file as system file if special file such - as fifo and server expecting SFU style and - no Unix extensions */ - if (create_options & CREATE_OPTION_SPECIAL) - pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM); - else - pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); - - /* XP does not handle ATTR_POSIX_SEMANTICS */ - /* but it helps speed up case sensitive checks for other - servers such as Samba */ - if (tcon->ses->capabilities & CAP_UNIX) - pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS); - - if (create_options & CREATE_OPTION_READONLY) - pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY); - - pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); - pSMB->CreateDisposition = cpu_to_le32(openDisposition); - pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); - /* BB Expirement with various impersonation levels and verify */ - pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); - pSMB->SecurityFlags = - SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; - - count += name_len; - inc_rfc1001_len(pSMB, count); - - pSMB->ByteCount = cpu_to_le16(count); - /* long_op set to 1 to allow for oplock break timeouts */ - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *)pSMBr, &bytes_returned, 0); - cifs_stats_inc(&tcon->num_opens); - if (rc) { - cFYI(1, "Error in Open = %d", rc); - } else { - *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */ - *netfid = pSMBr->Fid; /* cifs fid stays in le */ - /* Let caller know file was created so we can set the mode. */ - /* Do we care about the CreateAction in any other cases? */ - if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction) - *pOplock |= CIFS_CREATE_ACTION; - if (pfile_info) { - memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime, - 36 /* CreationTime to Attributes */); - /* the file_info buf is endian converted by caller */ - pfile_info->AllocationSize = pSMBr->AllocationSize; - pfile_info->EndOfFile = pSMBr->EndOfFile; - pfile_info->NumberOfLinks = cpu_to_le32(1); - pfile_info->DeletePending = 0; - } - } - - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto openRetry; - return rc; -} - -struct cifs_readdata * -cifs_readdata_alloc(unsigned int nr_pages) -{ - struct cifs_readdata *rdata; - - /* readdata + 1 kvec for each page */ - rdata = kzalloc(sizeof(*rdata) + - sizeof(struct kvec) * nr_pages, GFP_KERNEL); - if (rdata != NULL) { - INIT_WORK(&rdata->work, cifs_readv_complete); - INIT_LIST_HEAD(&rdata->pages); - } - return rdata; -} - -void -cifs_readdata_free(struct cifs_readdata *rdata) -{ - cifsFileInfo_put(rdata->cfile); - kfree(rdata); -} - -/* - * Discard any remaining data in the current SMB. To do this, we borrow the - * current bigbuf. - */ -static int -cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) -{ - unsigned int rfclen = get_rfc1002_length(server->smallbuf); - int remaining = rfclen + 4 - server->total_read; - struct cifs_readdata *rdata = mid->callback_data; - - while (remaining > 0) { - int length; - - length = cifs_read_from_socket(server, server->bigbuf, - min_t(unsigned int, remaining, - CIFSMaxBufSize + max_header_size())); - if (length < 0) - return length; - server->total_read += length; - remaining -= length; - } - - dequeue_mid(mid, rdata->result); - return 0; -} - -static inline size_t -read_rsp_size(void) -{ - return sizeof(READ_RSP); -} - -static inline unsigned int -read_data_offset(char *buf) -{ - READ_RSP *rsp = (READ_RSP *)buf; - return le16_to_cpu(rsp->DataOffset); -} - -static inline unsigned int -read_data_length(char *buf) -{ - READ_RSP *rsp = (READ_RSP *)buf; - return (le16_to_cpu(rsp->DataLengthHigh) << 16) + - le16_to_cpu(rsp->DataLength); -} - -static int -cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) -{ - int length, len; - unsigned int data_offset, remaining, data_len; - struct cifs_readdata *rdata = mid->callback_data; - char *buf = server->smallbuf; - unsigned int buflen = get_rfc1002_length(buf) + 4; - u64 eof; - pgoff_t eof_index; - struct page *page, *tpage; - - cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__, - mid->mid, rdata->offset, rdata->bytes); - - /* - * read the rest of READ_RSP header (sans Data array), or whatever we - * can if there's not enough data. At this point, we've read down to - * the Mid. - */ - len = min_t(unsigned int, buflen, read_rsp_size()) - header_size() + 1; - - rdata->iov[0].iov_base = buf + header_size() - 1; - rdata->iov[0].iov_len = len; - - length = cifs_readv_from_socket(server, rdata->iov, 1, len); - if (length < 0) - return length; - server->total_read += length; - - /* Was the SMB read successful? */ - rdata->result = map_smb_to_linux_error(buf, false); - if (rdata->result != 0) { - cFYI(1, "%s: server returned error %d", __func__, - rdata->result); - return cifs_readv_discard(server, mid); - } - - /* Is there enough to get to the rest of the READ_RSP header? */ - if (server->total_read < read_rsp_size()) { - cFYI(1, "%s: server returned short header. got=%u expected=%zu", - __func__, server->total_read, read_rsp_size()); - rdata->result = -EIO; - return cifs_readv_discard(server, mid); - } - - data_offset = read_data_offset(buf) + 4; - if (data_offset < server->total_read) { - /* - * win2k8 sometimes sends an offset of 0 when the read - * is beyond the EOF. Treat it as if the data starts just after - * the header. - */ - cFYI(1, "%s: data offset (%u) inside read response header", - __func__, data_offset); - data_offset = server->total_read; - } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) { - /* data_offset is beyond the end of smallbuf */ - cFYI(1, "%s: data offset (%u) beyond end of smallbuf", - __func__, data_offset); - rdata->result = -EIO; - return cifs_readv_discard(server, mid); - } - - cFYI(1, "%s: total_read=%u data_offset=%u", __func__, - server->total_read, data_offset); - - len = data_offset - server->total_read; - if (len > 0) { - /* read any junk before data into the rest of smallbuf */ - rdata->iov[0].iov_base = buf + server->total_read; - rdata->iov[0].iov_len = len; - length = cifs_readv_from_socket(server, rdata->iov, 1, len); - if (length < 0) - return length; - server->total_read += length; - } - - /* set up first iov for signature check */ - rdata->iov[0].iov_base = buf; - rdata->iov[0].iov_len = server->total_read; - cFYI(1, "0: iov_base=%p iov_len=%zu", - rdata->iov[0].iov_base, rdata->iov[0].iov_len); - - /* how much data is in the response? */ - data_len = read_data_length(buf); - if (data_offset + data_len > buflen) { - /* data_len is corrupt -- discard frame */ - rdata->result = -EIO; - return cifs_readv_discard(server, mid); - } - - /* marshal up the page array */ - len = 0; - remaining = data_len; - rdata->nr_iov = 1; - - /* determine the eof that the server (probably) has */ - eof = CIFS_I(rdata->mapping->host)->server_eof; - eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0; - cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index); - - list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { - if (remaining >= PAGE_CACHE_SIZE) { - /* enough data to fill the page */ - rdata->iov[rdata->nr_iov].iov_base = kmap(page); - rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE; - cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu", - rdata->nr_iov, page->index, - rdata->iov[rdata->nr_iov].iov_base, - rdata->iov[rdata->nr_iov].iov_len); - ++rdata->nr_iov; - len += PAGE_CACHE_SIZE; - remaining -= PAGE_CACHE_SIZE; - } else if (remaining > 0) { - /* enough for partial page, fill and zero the rest */ - rdata->iov[rdata->nr_iov].iov_base = kmap(page); - rdata->iov[rdata->nr_iov].iov_len = remaining; - cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu", - rdata->nr_iov, page->index, - rdata->iov[rdata->nr_iov].iov_base, - rdata->iov[rdata->nr_iov].iov_len); - memset(rdata->iov[rdata->nr_iov].iov_base + remaining, - '\0', PAGE_CACHE_SIZE - remaining); - ++rdata->nr_iov; - len += remaining; - remaining = 0; - } else if (page->index > eof_index) { - /* - * The VFS will not try to do readahead past the - * i_size, but it's possible that we have outstanding - * writes with gaps in the middle and the i_size hasn't - * caught up yet. Populate those with zeroed out pages - * to prevent the VFS from repeatedly attempting to - * fill them until the writes are flushed. - */ - zero_user(page, 0, PAGE_CACHE_SIZE); - list_del(&page->lru); - lru_cache_add_file(page); - flush_dcache_page(page); - SetPageUptodate(page); - unlock_page(page); - page_cache_release(page); - } else { - /* no need to hold page hostage */ - list_del(&page->lru); - lru_cache_add_file(page); - unlock_page(page); - page_cache_release(page); - } - } - - /* issue the read if we have any iovecs left to fill */ - if (rdata->nr_iov > 1) { - length = cifs_readv_from_socket(server, &rdata->iov[1], - rdata->nr_iov - 1, len); - if (length < 0) - return length; - server->total_read += length; - } else { - length = 0; - } - - rdata->bytes = length; - - cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read, - buflen, remaining); - - /* discard anything left over */ - if (server->total_read < buflen) - return cifs_readv_discard(server, mid); - - dequeue_mid(mid, false); - return length; -} - -static void -cifs_readv_complete(struct work_struct *work) -{ - struct cifs_readdata *rdata = container_of(work, - struct cifs_readdata, work); - struct page *page, *tpage; - - list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { - list_del(&page->lru); - lru_cache_add_file(page); - - if (rdata->result == 0) { - kunmap(page); - flush_dcache_page(page); - SetPageUptodate(page); - } - - unlock_page(page); - - if (rdata->result == 0) - cifs_readpage_to_fscache(rdata->mapping->host, page); - - page_cache_release(page); - } - cifs_readdata_free(rdata); -} - -static void -cifs_readv_callback(struct mid_q_entry *mid) -{ - struct cifs_readdata *rdata = mid->callback_data; - struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); - struct TCP_Server_Info *server = tcon->ses->server; - - cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__, - mid->mid, mid->mid_state, rdata->result, rdata->bytes); - - switch (mid->mid_state) { - case MID_RESPONSE_RECEIVED: - /* result already set, check signature */ - if (server->sec_mode & - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { - if (cifs_verify_signature(rdata->iov, rdata->nr_iov, - server, mid->sequence_number + 1)) - cERROR(1, "Unexpected SMB signature"); - } - /* FIXME: should this be counted toward the initiating task? */ - task_io_account_read(rdata->bytes); - cifs_stats_bytes_read(tcon, rdata->bytes); - break; - case MID_REQUEST_SUBMITTED: - case MID_RETRY_NEEDED: - rdata->result = -EAGAIN; - break; - default: - rdata->result = -EIO; - } - - queue_work(cifsiod_wq, &rdata->work); - DeleteMidQEntry(mid); - cifs_add_credits(server, 1); -} - -/* cifs_async_readv - send an async write, and set up mid to handle result */ -int -cifs_async_readv(struct cifs_readdata *rdata) -{ - int rc; - READ_REQ *smb = NULL; - int wct; - struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); - - cFYI(1, "%s: offset=%llu bytes=%u", __func__, - rdata->offset, rdata->bytes); - - if (tcon->ses->capabilities & CAP_LARGE_FILES) - wct = 12; - else { - wct = 10; /* old style read */ - if ((rdata->offset >> 32) > 0) { - /* can not handle this big offset for old */ - return -EIO; - } - } - - rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb); - if (rc) - return rc; - - smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid); - smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16)); - - smb->AndXCommand = 0xFF; /* none */ - smb->Fid = rdata->cfile->netfid; - smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF); - if (wct == 12) - smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32); - smb->Remaining = 0; - smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF); - smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16); - if (wct == 12) - smb->ByteCount = 0; - else { - /* old style read */ - struct smb_com_readx_req *smbr = - (struct smb_com_readx_req *)smb; - smbr->ByteCount = 0; - } - - /* 4 for RFC1001 length + 1 for BCC */ - rdata->iov[0].iov_base = smb; - rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; - - rc = cifs_call_async(tcon->ses->server, rdata->iov, 1, - cifs_readv_receive, cifs_readv_callback, - rdata, false); - - if (rc == 0) - cifs_stats_inc(&tcon->num_reads); - - cifs_small_buf_release(smb); - return rc; -} - -int -CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes, - char **buf, int *pbuf_type) -{ - int rc = -EACCES; - READ_REQ *pSMB = NULL; - READ_RSP *pSMBr = NULL; - char *pReadData = NULL; - int wct; - int resp_buf_type = 0; - struct kvec iov[1]; - __u32 pid = io_parms->pid; - __u16 netfid = io_parms->netfid; - __u64 offset = io_parms->offset; - struct cifs_tcon *tcon = io_parms->tcon; - unsigned int count = io_parms->length; - - cFYI(1, "Reading %d bytes on fid %d", count, netfid); - if (tcon->ses->capabilities & CAP_LARGE_FILES) - wct = 12; - else { - wct = 10; /* old style read */ - if ((offset >> 32) > 0) { - /* can not handle this big offset for old */ - return -EIO; - } - } - - *nbytes = 0; - rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB); - if (rc) - return rc; - - pSMB->hdr.Pid = cpu_to_le16((__u16)pid); - pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16)); - - /* tcon and ses pointer are checked in smb_init */ - if (tcon->ses->server == NULL) - return -ECONNABORTED; - - pSMB->AndXCommand = 0xFF; /* none */ - pSMB->Fid = netfid; - pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); - if (wct == 12) - pSMB->OffsetHigh = cpu_to_le32(offset >> 32); - - pSMB->Remaining = 0; - pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); - pSMB->MaxCountHigh = cpu_to_le32(count >> 16); - if (wct == 12) - pSMB->ByteCount = 0; /* no need to do le conversion since 0 */ - else { - /* old style read */ - struct smb_com_readx_req *pSMBW = - (struct smb_com_readx_req *)pSMB; - pSMBW->ByteCount = 0; - } - - iov[0].iov_base = (char *)pSMB; - iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; - rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, - &resp_buf_type, CIFS_LOG_ERROR); - cifs_stats_inc(&tcon->num_reads); - pSMBr = (READ_RSP *)iov[0].iov_base; - if (rc) { - cERROR(1, "Send error in read = %d", rc); - } else { - int data_length = le16_to_cpu(pSMBr->DataLengthHigh); - data_length = data_length << 16; - data_length += le16_to_cpu(pSMBr->DataLength); - *nbytes = data_length; - - /*check that DataLength would not go beyond end of SMB */ - if ((data_length > CIFSMaxBufSize) - || (data_length > count)) { - cFYI(1, "bad length %d for count %d", - data_length, count); - rc = -EIO; - *nbytes = 0; - } else { - pReadData = (char *) (&pSMBr->hdr.Protocol) + - le16_to_cpu(pSMBr->DataOffset); -/* if (rc = copy_to_user(buf, pReadData, data_length)) { - cERROR(1, "Faulting on read rc = %d",rc); - rc = -EFAULT; - }*/ /* can not use copy_to_user when using page cache*/ - if (*buf) - memcpy(*buf, pReadData, data_length); - } - } - -/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ - if (*buf) { - if (resp_buf_type == CIFS_SMALL_BUFFER) - cifs_small_buf_release(iov[0].iov_base); - else if (resp_buf_type == CIFS_LARGE_BUFFER) - cifs_buf_release(iov[0].iov_base); - } else if (resp_buf_type != CIFS_NO_BUFFER) { - /* return buffer to caller to free */ - *buf = iov[0].iov_base; - if (resp_buf_type == CIFS_SMALL_BUFFER) - *pbuf_type = CIFS_SMALL_BUFFER; - else if (resp_buf_type == CIFS_LARGE_BUFFER) - *pbuf_type = CIFS_LARGE_BUFFER; - } /* else no valid buffer on return - leave as null */ - - /* Note: On -EAGAIN error only caller can retry on handle based calls - since file handle passed in no longer valid */ - return rc; -} - - -int -CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms, - unsigned int *nbytes, const char *buf, - const char __user *ubuf, const int long_op) -{ - int rc = -EACCES; - WRITE_REQ *pSMB = NULL; - WRITE_RSP *pSMBr = NULL; - int bytes_returned, wct; - __u32 bytes_sent; - __u16 byte_count; - __u32 pid = io_parms->pid; - __u16 netfid = io_parms->netfid; - __u64 offset = io_parms->offset; - struct cifs_tcon *tcon = io_parms->tcon; - unsigned int count = io_parms->length; - - *nbytes = 0; - - /* cFYI(1, "write at %lld %d bytes", offset, count);*/ - if (tcon->ses == NULL) - return -ECONNABORTED; - - if (tcon->ses->capabilities & CAP_LARGE_FILES) - wct = 14; - else { - wct = 12; - if ((offset >> 32) > 0) { - /* can not handle big offset for old srv */ - return -EIO; - } - } - - rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - pSMB->hdr.Pid = cpu_to_le16((__u16)pid); - pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16)); - - /* tcon and ses pointer are checked in smb_init */ - if (tcon->ses->server == NULL) - return -ECONNABORTED; - - pSMB->AndXCommand = 0xFF; /* none */ - pSMB->Fid = netfid; - pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); - if (wct == 14) - pSMB->OffsetHigh = cpu_to_le32(offset >> 32); - - pSMB->Reserved = 0xFFFFFFFF; - pSMB->WriteMode = 0; - pSMB->Remaining = 0; - - /* Can increase buffer size if buffer is big enough in some cases ie we - can send more if LARGE_WRITE_X capability returned by the server and if - our buffer is big enough or if we convert to iovecs on socket writes - and eliminate the copy to the CIFS buffer */ - if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) { - bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count); - } else { - bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) - & ~0xFF; - } - - if (bytes_sent > count) - bytes_sent = count; - pSMB->DataOffset = - cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); - if (buf) - memcpy(pSMB->Data, buf, bytes_sent); - else if (ubuf) { - if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) { - cifs_buf_release(pSMB); - return -EFAULT; - } - } else if (count != 0) { - /* No buffer */ - cifs_buf_release(pSMB); - return -EINVAL; - } /* else setting file size with write of zero bytes */ - if (wct == 14) - byte_count = bytes_sent + 1; /* pad */ - else /* wct == 12 */ - byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */ - - pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); - pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); - inc_rfc1001_len(pSMB, byte_count); - - if (wct == 14) - pSMB->ByteCount = cpu_to_le16(byte_count); - else { /* old style write has byte count 4 bytes earlier - so 4 bytes pad */ - struct smb_com_writex_req *pSMBW = - (struct smb_com_writex_req *)pSMB; - pSMBW->ByteCount = cpu_to_le16(byte_count); - } - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, long_op); - cifs_stats_inc(&tcon->num_writes); - if (rc) { - cFYI(1, "Send error in write = %d", rc); - } else { - *nbytes = le16_to_cpu(pSMBr->CountHigh); - *nbytes = (*nbytes) << 16; - *nbytes += le16_to_cpu(pSMBr->Count); - - /* - * Mask off high 16 bits when bytes written as returned by the - * server is greater than bytes requested by the client. Some - * OS/2 servers are known to set incorrect CountHigh values. - */ - if (*nbytes > count) - *nbytes &= 0xFFFF; - } - - cifs_buf_release(pSMB); - - /* Note: On -EAGAIN error only caller can retry on handle based calls - since file handle passed in no longer valid */ - - return rc; -} - -void -cifs_writedata_release(struct kref *refcount) -{ - struct cifs_writedata *wdata = container_of(refcount, - struct cifs_writedata, refcount); - - if (wdata->cfile) - cifsFileInfo_put(wdata->cfile); - - kfree(wdata); -} - -/* - * Write failed with a retryable error. Resend the write request. It's also - * possible that the page was redirtied so re-clean the page. - */ -static void -cifs_writev_requeue(struct cifs_writedata *wdata) -{ - int i, rc; - struct inode *inode = wdata->cfile->dentry->d_inode; - - for (i = 0; i < wdata->nr_pages; i++) { - lock_page(wdata->pages[i]); - clear_page_dirty_for_io(wdata->pages[i]); - } - - do { - rc = cifs_async_writev(wdata); - } while (rc == -EAGAIN); - - for (i = 0; i < wdata->nr_pages; i++) { - if (rc != 0) - SetPageError(wdata->pages[i]); - unlock_page(wdata->pages[i]); - } - - mapping_set_error(inode->i_mapping, rc); - kref_put(&wdata->refcount, cifs_writedata_release); -} - -void -cifs_writev_complete(struct work_struct *work) -{ - struct cifs_writedata *wdata = container_of(work, - struct cifs_writedata, work); - struct inode *inode = wdata->cfile->dentry->d_inode; - int i = 0; - - if (wdata->result == 0) { - spin_lock(&inode->i_lock); - cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes); - spin_unlock(&inode->i_lock); - cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink), - wdata->bytes); - } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN) - return cifs_writev_requeue(wdata); - - for (i = 0; i < wdata->nr_pages; i++) { - struct page *page = wdata->pages[i]; - if (wdata->result == -EAGAIN) - __set_page_dirty_nobuffers(page); - else if (wdata->result < 0) - SetPageError(page); - end_page_writeback(page); - page_cache_release(page); - } - if (wdata->result != -EAGAIN) - mapping_set_error(inode->i_mapping, wdata->result); - kref_put(&wdata->refcount, cifs_writedata_release); -} - -struct cifs_writedata * -cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete) -{ - struct cifs_writedata *wdata; - - /* this would overflow */ - if (nr_pages == 0) { - cERROR(1, "%s: called with nr_pages == 0!", __func__); - return NULL; - } - - /* writedata + number of page pointers */ - wdata = kzalloc(sizeof(*wdata) + - sizeof(struct page *) * (nr_pages - 1), GFP_NOFS); - if (wdata != NULL) { - kref_init(&wdata->refcount); - INIT_LIST_HEAD(&wdata->list); - init_completion(&wdata->done); - INIT_WORK(&wdata->work, complete); - } - return wdata; -} - -/* - * Check the mid_state and signature on received buffer (if any), and queue the - * workqueue completion task. - */ -static void -cifs_writev_callback(struct mid_q_entry *mid) -{ - struct cifs_writedata *wdata = mid->callback_data; - struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); - unsigned int written; - WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf; - - switch (mid->mid_state) { - case MID_RESPONSE_RECEIVED: - wdata->result = cifs_check_receive(mid, tcon->ses->server, 0); - if (wdata->result != 0) - break; - - written = le16_to_cpu(smb->CountHigh); - written <<= 16; - written += le16_to_cpu(smb->Count); - /* - * Mask off high 16 bits when bytes written as returned - * by the server is greater than bytes requested by the - * client. OS/2 servers are known to set incorrect - * CountHigh values. - */ - if (written > wdata->bytes) - written &= 0xFFFF; - - if (written < wdata->bytes) - wdata->result = -ENOSPC; - else - wdata->bytes = written; - break; - case MID_REQUEST_SUBMITTED: - case MID_RETRY_NEEDED: - wdata->result = -EAGAIN; - break; - default: - wdata->result = -EIO; - break; - } - - queue_work(cifsiod_wq, &wdata->work); - DeleteMidQEntry(mid); - cifs_add_credits(tcon->ses->server, 1); -} - -/* cifs_async_writev - send an async write, and set up mid to handle result */ -int -cifs_async_writev(struct cifs_writedata *wdata) -{ - int i, rc = -EACCES; - WRITE_REQ *smb = NULL; - int wct; - struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); - struct kvec *iov = NULL; - - if (tcon->ses->capabilities & CAP_LARGE_FILES) { - wct = 14; - } else { - wct = 12; - if (wdata->offset >> 32 > 0) { - /* can not handle big offset for old srv */ - return -EIO; - } - } - - rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb); - if (rc) - goto async_writev_out; - - /* 1 iov per page + 1 for header */ - iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS); - if (iov == NULL) { - rc = -ENOMEM; - goto async_writev_out; - } - - smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid); - smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16)); - - smb->AndXCommand = 0xFF; /* none */ - smb->Fid = wdata->cfile->netfid; - smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF); - if (wct == 14) - smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32); - smb->Reserved = 0xFFFFFFFF; - smb->WriteMode = 0; - smb->Remaining = 0; - - smb->DataOffset = - cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); - - /* 4 for RFC1001 length + 1 for BCC */ - iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; - iov[0].iov_base = smb; - - /* - * This function should marshal up the page array into the kvec - * array, reserving [0] for the header. It should kmap the pages - * and set the iov_len properly for each one. It may also set - * wdata->bytes too. - */ - wdata->marshal_iov(iov, wdata); - - cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); - - smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF); - smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16); - - if (wct == 14) { - inc_rfc1001_len(&smb->hdr, wdata->bytes + 1); - put_bcc(wdata->bytes + 1, &smb->hdr); - } else { - /* wct == 12 */ - struct smb_com_writex_req *smbw = - (struct smb_com_writex_req *)smb; - inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5); - put_bcc(wdata->bytes + 5, &smbw->hdr); - iov[0].iov_len += 4; /* pad bigger by four bytes */ - } - - kref_get(&wdata->refcount); - rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1, - NULL, cifs_writev_callback, wdata, false); - - if (rc == 0) - cifs_stats_inc(&tcon->num_writes); - else - kref_put(&wdata->refcount, cifs_writedata_release); - - /* send is done, unmap pages */ - for (i = 0; i < wdata->nr_pages; i++) - kunmap(wdata->pages[i]); - -async_writev_out: - cifs_small_buf_release(smb); - kfree(iov); - return rc; -} - -int -CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms, - unsigned int *nbytes, struct kvec *iov, int n_vec, - const int long_op) -{ - int rc = -EACCES; - WRITE_REQ *pSMB = NULL; - int wct; - int smb_hdr_len; - int resp_buf_type = 0; - __u32 pid = io_parms->pid; - __u16 netfid = io_parms->netfid; - __u64 offset = io_parms->offset; - struct cifs_tcon *tcon = io_parms->tcon; - unsigned int count = io_parms->length; - - *nbytes = 0; - - cFYI(1, "write2 at %lld %d bytes", (long long)offset, count); - - if (tcon->ses->capabilities & CAP_LARGE_FILES) { - wct = 14; - } else { - wct = 12; - if ((offset >> 32) > 0) { - /* can not handle big offset for old srv */ - return -EIO; - } - } - rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB); - if (rc) - return rc; - - pSMB->hdr.Pid = cpu_to_le16((__u16)pid); - pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16)); - - /* tcon and ses pointer are checked in smb_init */ - if (tcon->ses->server == NULL) - return -ECONNABORTED; - - pSMB->AndXCommand = 0xFF; /* none */ - pSMB->Fid = netfid; - pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); - if (wct == 14) - pSMB->OffsetHigh = cpu_to_le32(offset >> 32); - pSMB->Reserved = 0xFFFFFFFF; - pSMB->WriteMode = 0; - pSMB->Remaining = 0; - - pSMB->DataOffset = - cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); - - pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF); - pSMB->DataLengthHigh = cpu_to_le16(count >> 16); - /* header + 1 byte pad */ - smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1; - if (wct == 14) - inc_rfc1001_len(pSMB, count + 1); - else /* wct == 12 */ - inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */ - if (wct == 14) - pSMB->ByteCount = cpu_to_le16(count + 1); - else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ { - struct smb_com_writex_req *pSMBW = - (struct smb_com_writex_req *)pSMB; - pSMBW->ByteCount = cpu_to_le16(count + 5); - } - iov[0].iov_base = pSMB; - if (wct == 14) - iov[0].iov_len = smb_hdr_len + 4; - else /* wct == 12 pad bigger by four bytes */ - iov[0].iov_len = smb_hdr_len + 8; - - - rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, - long_op); - cifs_stats_inc(&tcon->num_writes); - if (rc) { - cFYI(1, "Send error Write2 = %d", rc); - } else if (resp_buf_type == 0) { - /* presumably this can not happen, but best to be safe */ - rc = -EIO; - } else { - WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base; - *nbytes = le16_to_cpu(pSMBr->CountHigh); - *nbytes = (*nbytes) << 16; - *nbytes += le16_to_cpu(pSMBr->Count); - - /* - * Mask off high 16 bits when bytes written as returned by the - * server is greater than bytes requested by the client. OS/2 - * servers are known to set incorrect CountHigh values. - */ - if (*nbytes > count) - *nbytes &= 0xFFFF; - } - -/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ - if (resp_buf_type == CIFS_SMALL_BUFFER) - cifs_small_buf_release(iov[0].iov_base); - else if (resp_buf_type == CIFS_LARGE_BUFFER) - cifs_buf_release(iov[0].iov_base); - - /* Note: On -EAGAIN error only caller can retry on handle based calls - since file handle passed in no longer valid */ - - return rc; -} - -int cifs_lockv(const int xid, struct cifs_tcon *tcon, const __u16 netfid, - const __u8 lock_type, const __u32 num_unlock, - const __u32 num_lock, LOCKING_ANDX_RANGE *buf) -{ - int rc = 0; - LOCK_REQ *pSMB = NULL; - struct kvec iov[2]; - int resp_buf_type; - __u16 count; - - cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock); - - rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB); - if (rc) - return rc; - - pSMB->Timeout = 0; - pSMB->NumberOfLocks = cpu_to_le16(num_lock); - pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock); - pSMB->LockType = lock_type; - pSMB->AndXCommand = 0xFF; /* none */ - pSMB->Fid = netfid; /* netfid stays le */ - - count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE); - inc_rfc1001_len(pSMB, count); - pSMB->ByteCount = cpu_to_le16(count); - - iov[0].iov_base = (char *)pSMB; - iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 - - (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE); - iov[1].iov_base = (char *)buf; - iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE); - - cifs_stats_inc(&tcon->num_locks); - rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP); - if (rc) - cFYI(1, "Send error in cifs_lockv = %d", rc); - - return rc; -} - -int -CIFSSMBLock(const int xid, struct cifs_tcon *tcon, - const __u16 smb_file_id, const __u32 netpid, const __u64 len, - const __u64 offset, const __u32 numUnlock, - const __u32 numLock, const __u8 lockType, - const bool waitFlag, const __u8 oplock_level) -{ - int rc = 0; - LOCK_REQ *pSMB = NULL; -/* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */ - int bytes_returned; - int timeout = 0; - __u16 count; - - cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock); - rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB); - - if (rc) - return rc; - - if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { - timeout = CIFS_ASYNC_OP; /* no response expected */ - pSMB->Timeout = 0; - } else if (waitFlag) { - timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */ - pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */ - } else { - pSMB->Timeout = 0; - } - - pSMB->NumberOfLocks = cpu_to_le16(numLock); - pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock); - pSMB->LockType = lockType; - pSMB->OplockLevel = oplock_level; - pSMB->AndXCommand = 0xFF; /* none */ - pSMB->Fid = smb_file_id; /* netfid stays le */ - - if ((numLock != 0) || (numUnlock != 0)) { - pSMB->Locks[0].Pid = cpu_to_le16(netpid); - /* BB where to store pid high? */ - pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len); - pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32)); - pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset); - pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32)); - count = sizeof(LOCKING_ANDX_RANGE); - } else { - /* oplock break */ - count = 0; - } - inc_rfc1001_len(pSMB, count); - pSMB->ByteCount = cpu_to_le16(count); - - if (waitFlag) { - rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMB, &bytes_returned); - cifs_small_buf_release(pSMB); - } else { - rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, timeout); - /* SMB buffer freed by function above */ - } - cifs_stats_inc(&tcon->num_locks); - if (rc) - cFYI(1, "Send error in Lock = %d", rc); - - /* Note: On -EAGAIN error only caller can retry on handle based calls - since file handle passed in no longer valid */ - return rc; -} - -int -CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon, - const __u16 smb_file_id, const __u32 netpid, const int get_flag, - const __u64 len, struct file_lock *pLockData, - const __u16 lock_type, const bool waitFlag) -{ - struct smb_com_transaction2_sfi_req *pSMB = NULL; - struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; - struct cifs_posix_lock *parm_data; - int rc = 0; - int timeout = 0; - int bytes_returned = 0; - int resp_buf_type = 0; - __u16 params, param_offset, offset, byte_count, count; - struct kvec iov[1]; - - cFYI(1, "Posix Lock"); - - if (pLockData == NULL) - return -EINVAL; - - rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); - - if (rc) - return rc; - - pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB; - - params = 6; - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; - offset = param_offset + params; - - count = sizeof(struct cifs_posix_lock); - pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */ - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - if (get_flag) - pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION); - else - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); - byte_count = 3 /* pad */ + params + count; - pSMB->DataCount = cpu_to_le16(count); - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->ParameterOffset = cpu_to_le16(param_offset); - parm_data = (struct cifs_posix_lock *) - (((char *) &pSMB->hdr.Protocol) + offset); - - parm_data->lock_type = cpu_to_le16(lock_type); - if (waitFlag) { - timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */ - parm_data->lock_flags = cpu_to_le16(1); - pSMB->Timeout = cpu_to_le32(-1); - } else - pSMB->Timeout = 0; - - parm_data->pid = cpu_to_le32(netpid); - parm_data->start = cpu_to_le64(pLockData->fl_start); - parm_data->length = cpu_to_le64(len); /* normalize negative numbers */ - - pSMB->DataOffset = cpu_to_le16(offset); - pSMB->Fid = smb_file_id; - pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - if (waitFlag) { - rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned); - } else { - iov[0].iov_base = (char *)pSMB; - iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; - rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, - &resp_buf_type, timeout); - pSMB = NULL; /* request buf already freed by SendReceive2. Do - not try to free it twice below on exit */ - pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base; - } - - if (rc) { - cFYI(1, "Send error in Posix Lock = %d", rc); - } else if (get_flag) { - /* lock structure can be returned on get */ - __u16 data_offset; - __u16 data_count; - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) { - rc = -EIO; /* bad smb */ - goto plk_err_exit; - } - data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - data_count = le16_to_cpu(pSMBr->t2.DataCount); - if (data_count < sizeof(struct cifs_posix_lock)) { - rc = -EIO; - goto plk_err_exit; - } - parm_data = (struct cifs_posix_lock *) - ((char *)&pSMBr->hdr.Protocol + data_offset); - if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK)) - pLockData->fl_type = F_UNLCK; - else { - if (parm_data->lock_type == - __constant_cpu_to_le16(CIFS_RDLCK)) - pLockData->fl_type = F_RDLCK; - else if (parm_data->lock_type == - __constant_cpu_to_le16(CIFS_WRLCK)) - pLockData->fl_type = F_WRLCK; - - pLockData->fl_start = le64_to_cpu(parm_data->start); - pLockData->fl_end = pLockData->fl_start + - le64_to_cpu(parm_data->length) - 1; - pLockData->fl_pid = le32_to_cpu(parm_data->pid); - } - } - -plk_err_exit: - if (pSMB) - cifs_small_buf_release(pSMB); - - if (resp_buf_type == CIFS_SMALL_BUFFER) - cifs_small_buf_release(iov[0].iov_base); - else if (resp_buf_type == CIFS_LARGE_BUFFER) - cifs_buf_release(iov[0].iov_base); - - /* Note: On -EAGAIN error only caller can retry on handle based calls - since file handle passed in no longer valid */ - - return rc; -} - - -int -CIFSSMBClose(const int xid, struct cifs_tcon *tcon, int smb_file_id) -{ - int rc = 0; - CLOSE_REQ *pSMB = NULL; - cFYI(1, "In CIFSSMBClose"); - -/* do not retry on dead session on close */ - rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB); - if (rc == -EAGAIN) - return 0; - if (rc) - return rc; - - pSMB->FileID = (__u16) smb_file_id; - pSMB->LastWriteTime = 0xFFFFFFFF; - pSMB->ByteCount = 0; - rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); - cifs_stats_inc(&tcon->num_closes); - if (rc) { - if (rc != -EINTR) { - /* EINTR is expected when user ctl-c to kill app */ - cERROR(1, "Send error in Close = %d", rc); - } - } - - /* Since session is dead, file will be closed on server already */ - if (rc == -EAGAIN) - rc = 0; - - return rc; -} - -int -CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, int smb_file_id) -{ - int rc = 0; - FLUSH_REQ *pSMB = NULL; - cFYI(1, "In CIFSSMBFlush"); - - rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB); - if (rc) - return rc; - - pSMB->FileID = (__u16) smb_file_id; - pSMB->ByteCount = 0; - rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); - cifs_stats_inc(&tcon->num_flushes); - if (rc) - cERROR(1, "Send error in Flush = %d", rc); - - return rc; -} - -int -CIFSSMBRename(const int xid, struct cifs_tcon *tcon, - const char *fromName, const char *toName, - const struct nls_table *nls_codepage, int remap) -{ - int rc = 0; - RENAME_REQ *pSMB = NULL; - RENAME_RSP *pSMBr = NULL; - int bytes_returned; - int name_len, name_len2; - __u16 count; - - cFYI(1, "In CIFSSMBRename"); -renameRetry: - rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - pSMB->BufferFormat = 0x04; - pSMB->SearchAttributes = - cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | - ATTR_DIRECTORY); - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - pSMB->OldFileName[name_len] = 0x04; /* pad */ - /* protocol requires ASCII signature byte on Unicode string */ - pSMB->OldFileName[name_len + 1] = 0x00; - name_len2 = - cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2], - toName, PATH_MAX, nls_codepage, remap); - name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; - name_len2 *= 2; /* convert to bytes */ - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fromName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->OldFileName, fromName, name_len); - name_len2 = strnlen(toName, PATH_MAX); - name_len2++; /* trailing null */ - pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ - strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); - name_len2++; /* trailing null */ - name_len2++; /* signature byte */ - } - - count = 1 /* 1st signature byte */ + name_len + name_len2; - inc_rfc1001_len(pSMB, count); - pSMB->ByteCount = cpu_to_le16(count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - cifs_stats_inc(&tcon->num_renames); - if (rc) - cFYI(1, "Send error in rename = %d", rc); - - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto renameRetry; - - return rc; -} - -int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon, - int netfid, const char *target_name, - const struct nls_table *nls_codepage, int remap) -{ - struct smb_com_transaction2_sfi_req *pSMB = NULL; - struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; - struct set_file_rename *rename_info; - char *data_offset; - char dummy_string[30]; - int rc = 0; - int bytes_returned = 0; - int len_of_str; - __u16 params, param_offset, offset, count, byte_count; - - cFYI(1, "Rename to File by handle"); - rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - params = 6; - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; - offset = param_offset + params; - - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; - rename_info = (struct set_file_rename *) data_offset; - pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */ - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); - byte_count = 3 /* pad */ + params; - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->ParameterOffset = cpu_to_le16(param_offset); - pSMB->DataOffset = cpu_to_le16(offset); - /* construct random name ".cifs_tmp<inodenum><mid>" */ - rename_info->overwrite = cpu_to_le32(1); - rename_info->root_fid = 0; - /* unicode only call */ - if (target_name == NULL) { - sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid); - len_of_str = - cifsConvertToUTF16((__le16 *)rename_info->target_name, - dummy_string, 24, nls_codepage, remap); - } else { - len_of_str = - cifsConvertToUTF16((__le16 *)rename_info->target_name, - target_name, PATH_MAX, nls_codepage, - remap); - } - rename_info->target_name_len = cpu_to_le32(2 * len_of_str); - count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str); - byte_count += count; - pSMB->DataCount = cpu_to_le16(count); - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->Fid = netfid; - pSMB->InformationLevel = - cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - cifs_stats_inc(&pTcon->num_t2renames); - if (rc) - cFYI(1, "Send error in Rename (by file handle) = %d", rc); - - cifs_buf_release(pSMB); - - /* Note: On -EAGAIN error only caller can retry on handle based calls - since file handle passed in no longer valid */ - - return rc; -} - -int -CIFSSMBCopy(const int xid, struct cifs_tcon *tcon, const char *fromName, - const __u16 target_tid, const char *toName, const int flags, - const struct nls_table *nls_codepage, int remap) -{ - int rc = 0; - COPY_REQ *pSMB = NULL; - COPY_RSP *pSMBr = NULL; - int bytes_returned; - int name_len, name_len2; - __u16 count; - - cFYI(1, "In CIFSSMBCopy"); -copyRetry: - rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - pSMB->BufferFormat = 0x04; - pSMB->Tid2 = target_tid; - - pSMB->Flags = cpu_to_le16(flags & COPY_TREE); - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName, - fromName, PATH_MAX, nls_codepage, - remap); - name_len++; /* trailing null */ - name_len *= 2; - pSMB->OldFileName[name_len] = 0x04; /* pad */ - /* protocol requires ASCII signature byte on Unicode string */ - pSMB->OldFileName[name_len + 1] = 0x00; - name_len2 = - cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2], - toName, PATH_MAX, nls_codepage, remap); - name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; - name_len2 *= 2; /* convert to bytes */ - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fromName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->OldFileName, fromName, name_len); - name_len2 = strnlen(toName, PATH_MAX); - name_len2++; /* trailing null */ - pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ - strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); - name_len2++; /* trailing null */ - name_len2++; /* signature byte */ - } - - count = 1 /* 1st signature byte */ + name_len + name_len2; - inc_rfc1001_len(pSMB, count); - pSMB->ByteCount = cpu_to_le16(count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Send error in copy = %d with %d files copied", - rc, le16_to_cpu(pSMBr->CopyCount)); - } - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto copyRetry; - - return rc; -} - -int -CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon, - const char *fromName, const char *toName, - const struct nls_table *nls_codepage) -{ - TRANSACTION2_SPI_REQ *pSMB = NULL; - TRANSACTION2_SPI_RSP *pSMBr = NULL; - char *data_offset; - int name_len; - int name_len_target; - int rc = 0; - int bytes_returned = 0; - __u16 params, param_offset, offset, byte_count; - - cFYI(1, "In Symlink Unix style"); -createSymLinkRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName, - /* find define for this maxpathcomponent */ - PATH_MAX, nls_codepage); - name_len++; /* trailing null */ - name_len *= 2; - - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fromName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, fromName, name_len); - } - params = 6 + name_len; - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_spi_req, - InformationLevel) - 4; - offset = param_offset + params; - - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len_target = - cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); - name_len_target++; /* trailing null */ - name_len_target *= 2; - } else { /* BB improve the check for buffer overruns BB */ - name_len_target = strnlen(toName, PATH_MAX); - name_len_target++; /* trailing null */ - strncpy(data_offset, toName, name_len_target); - } - - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find exact max on data count below from sess */ - pSMB->MaxDataCount = cpu_to_le16(1000); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); - byte_count = 3 /* pad */ + params + name_len_target; - pSMB->DataCount = cpu_to_le16(name_len_target); - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->ParameterOffset = cpu_to_le16(param_offset); - pSMB->DataOffset = cpu_to_le16(offset); - pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - cifs_stats_inc(&tcon->num_symlinks); - if (rc) - cFYI(1, "Send error in SetPathInfo create symlink = %d", rc); - - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto createSymLinkRetry; - - return rc; -} - -int -CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon, - const char *fromName, const char *toName, - const struct nls_table *nls_codepage, int remap) -{ - TRANSACTION2_SPI_REQ *pSMB = NULL; - TRANSACTION2_SPI_RSP *pSMBr = NULL; - char *data_offset; - int name_len; - int name_len_target; - int rc = 0; - int bytes_returned = 0; - __u16 params, param_offset, offset, byte_count; - - cFYI(1, "In Create Hard link Unix style"); -createHardLinkRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(toName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, toName, name_len); - } - params = 6 + name_len; - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_spi_req, - InformationLevel) - 4; - offset = param_offset + params; - - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len_target = - cifsConvertToUTF16((__le16 *) data_offset, fromName, - PATH_MAX, nls_codepage, remap); - name_len_target++; /* trailing null */ - name_len_target *= 2; - } else { /* BB improve the check for buffer overruns BB */ - name_len_target = strnlen(fromName, PATH_MAX); - name_len_target++; /* trailing null */ - strncpy(data_offset, fromName, name_len_target); - } - - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find exact max on data count below from sess*/ - pSMB->MaxDataCount = cpu_to_le16(1000); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); - byte_count = 3 /* pad */ + params + name_len_target; - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->DataCount = cpu_to_le16(name_len_target); - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->ParameterOffset = cpu_to_le16(param_offset); - pSMB->DataOffset = cpu_to_le16(offset); - pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - cifs_stats_inc(&tcon->num_hardlinks); - if (rc) - cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc); - - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto createHardLinkRetry; - - return rc; -} - -int -CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon, - const char *fromName, const char *toName, - const struct nls_table *nls_codepage, int remap) -{ - int rc = 0; - NT_RENAME_REQ *pSMB = NULL; - RENAME_RSP *pSMBr = NULL; - int bytes_returned; - int name_len, name_len2; - __u16 count; - - cFYI(1, "In CIFSCreateHardLink"); -winCreateHardLinkRetry: - - rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - pSMB->SearchAttributes = - cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | - ATTR_DIRECTORY); - pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK); - pSMB->ClusterCount = 0; - - pSMB->BufferFormat = 0x04; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - - /* protocol specifies ASCII buffer format (0x04) for unicode */ - pSMB->OldFileName[name_len] = 0x04; - pSMB->OldFileName[name_len + 1] = 0x00; /* pad */ - name_len2 = - cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2], - toName, PATH_MAX, nls_codepage, remap); - name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; - name_len2 *= 2; /* convert to bytes */ - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fromName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->OldFileName, fromName, name_len); - name_len2 = strnlen(toName, PATH_MAX); - name_len2++; /* trailing null */ - pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ - strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); - name_len2++; /* trailing null */ - name_len2++; /* signature byte */ - } - - count = 1 /* string type byte */ + name_len + name_len2; - inc_rfc1001_len(pSMB, count); - pSMB->ByteCount = cpu_to_le16(count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - cifs_stats_inc(&tcon->num_hardlinks); - if (rc) - cFYI(1, "Send error in hard link (NT rename) = %d", rc); - - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto winCreateHardLinkRetry; - - return rc; -} - -int -CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, char **symlinkinfo, - const struct nls_table *nls_codepage) -{ -/* SMB_QUERY_FILE_UNIX_LINK */ - TRANSACTION2_QPI_REQ *pSMB = NULL; - TRANSACTION2_QPI_RSP *pSMBr = NULL; - int rc = 0; - int bytes_returned; - int name_len; - __u16 params, byte_count; - char *data_start; - - cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName); - -querySymLinkRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName, - PATH_MAX, nls_codepage); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, searchName, name_len); - } - - params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; - pSMB->TotalDataCount = 0; - pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - pSMB->ParameterOffset = cpu_to_le16(offsetof( - struct smb_com_transaction2_qpi_req, InformationLevel) - 4); - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION); - byte_count = params + 1 /* pad */ ; - pSMB->TotalParameterCount = cpu_to_le16(params); - pSMB->ParameterCount = pSMB->TotalParameterCount; - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Send error in QuerySymLinkInfo = %d", rc); - } else { - /* decode response */ - - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - /* BB also check enough total bytes returned */ - if (rc || get_bcc(&pSMBr->hdr) < 2) - rc = -EIO; - else { - bool is_unicode; - u16 count = le16_to_cpu(pSMBr->t2.DataCount); - - data_start = ((char *) &pSMBr->hdr.Protocol) + - le16_to_cpu(pSMBr->t2.DataOffset); - - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) - is_unicode = true; - else - is_unicode = false; - - /* BB FIXME investigate remapping reserved chars here */ - *symlinkinfo = cifs_strndup_from_utf16(data_start, - count, is_unicode, nls_codepage); - if (!*symlinkinfo) - rc = -ENOMEM; - } - } - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto querySymLinkRetry; - return rc; -} - -#ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL -/* - * Recent Windows versions now create symlinks more frequently - * and they use the "reparse point" mechanism below. We can of course - * do symlinks nicely to Samba and other servers which support the - * CIFS Unix Extensions and we can also do SFU symlinks and "client only" - * "MF" symlinks optionally, but for recent Windows we really need to - * reenable the code below and fix the cifs_symlink callers to handle this. - * In the interim this code has been moved to its own config option so - * it is not compiled in by default until callers fixed up and more tested. - */ -int -CIFSSMBQueryReparseLinkInfo(const int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - char *symlinkinfo, const int buflen, __u16 fid, - const struct nls_table *nls_codepage) -{ - int rc = 0; - int bytes_returned; - struct smb_com_transaction_ioctl_req *pSMB; - struct smb_com_transaction_ioctl_rsp *pSMBr; - - cFYI(1, "In Windows reparse style QueryLink for path %s", searchName); - rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - pSMB->TotalParameterCount = 0 ; - pSMB->TotalDataCount = 0; - pSMB->MaxParameterCount = cpu_to_le32(2); - /* BB find exact data count max from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00); - pSMB->MaxSetupCount = 4; - pSMB->Reserved = 0; - pSMB->ParameterOffset = 0; - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 4; - pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL); - pSMB->ParameterCount = pSMB->TotalParameterCount; - pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT); - pSMB->IsFsctl = 1; /* FSCTL */ - pSMB->IsRootFlag = 0; - pSMB->Fid = fid; /* file handle always le */ - pSMB->ByteCount = 0; - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc); - } else { /* decode response */ - __u32 data_offset = le32_to_cpu(pSMBr->DataOffset); - __u32 data_count = le32_to_cpu(pSMBr->DataCount); - if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) { - /* BB also check enough total bytes returned */ - rc = -EIO; /* bad smb */ - goto qreparse_out; - } - if (data_count && (data_count < 2048)) { - char *end_of_smb = 2 /* sizeof byte count */ + - get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount; - - struct reparse_data *reparse_buf = - (struct reparse_data *) - ((char *)&pSMBr->hdr.Protocol - + data_offset); - if ((char *)reparse_buf >= end_of_smb) { - rc = -EIO; - goto qreparse_out; - } - if ((reparse_buf->LinkNamesBuf + - reparse_buf->TargetNameOffset + - reparse_buf->TargetNameLen) > end_of_smb) { - cFYI(1, "reparse buf beyond SMB"); - rc = -EIO; - goto qreparse_out; - } - - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { - cifs_from_ucs2(symlinkinfo, (__le16 *) - (reparse_buf->LinkNamesBuf + - reparse_buf->TargetNameOffset), - buflen, - reparse_buf->TargetNameLen, - nls_codepage, 0); - } else { /* ASCII names */ - strncpy(symlinkinfo, - reparse_buf->LinkNamesBuf + - reparse_buf->TargetNameOffset, - min_t(const int, buflen, - reparse_buf->TargetNameLen)); - } - } else { - rc = -EIO; - cFYI(1, "Invalid return data count on " - "get reparse info ioctl"); - } - symlinkinfo[buflen] = 0; /* just in case so the caller - does not go off the end of the buffer */ - cFYI(1, "readlink result - %s", symlinkinfo); - } - -qreparse_out: - cifs_buf_release(pSMB); - - /* Note: On -EAGAIN error only caller can retry on handle based calls - since file handle passed in no longer valid */ - - return rc; -} -#endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */ - -#ifdef CONFIG_CIFS_POSIX - -/*Convert an Access Control Entry from wire format to local POSIX xattr format*/ -static void cifs_convert_ace(posix_acl_xattr_entry *ace, - struct cifs_posix_ace *cifs_ace) -{ - /* u8 cifs fields do not need le conversion */ - ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm); - ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag); - ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid)); - /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */ - - return; -} - -/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */ -static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen, - const int acl_type, const int size_of_data_area) -{ - int size = 0; - int i; - __u16 count; - struct cifs_posix_ace *pACE; - struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src; - posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt; - - if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION) - return -EOPNOTSUPP; - - if (acl_type & ACL_TYPE_ACCESS) { - count = le16_to_cpu(cifs_acl->access_entry_count); - pACE = &cifs_acl->ace_array[0]; - size = sizeof(struct cifs_posix_acl); - size += sizeof(struct cifs_posix_ace) * count; - /* check if we would go beyond end of SMB */ - if (size_of_data_area < size) { - cFYI(1, "bad CIFS POSIX ACL size %d vs. %d", - size_of_data_area, size); - return -EINVAL; - } - } else if (acl_type & ACL_TYPE_DEFAULT) { - count = le16_to_cpu(cifs_acl->access_entry_count); - size = sizeof(struct cifs_posix_acl); - size += sizeof(struct cifs_posix_ace) * count; -/* skip past access ACEs to get to default ACEs */ - pACE = &cifs_acl->ace_array[count]; - count = le16_to_cpu(cifs_acl->default_entry_count); - size += sizeof(struct cifs_posix_ace) * count; - /* check if we would go beyond end of SMB */ - if (size_of_data_area < size) - return -EINVAL; - } else { - /* illegal type */ - return -EINVAL; - } - - size = posix_acl_xattr_size(count); - if ((buflen == 0) || (local_acl == NULL)) { - /* used to query ACL EA size */ - } else if (size > buflen) { - return -ERANGE; - } else /* buffer big enough */ { - local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION); - for (i = 0; i < count ; i++) { - cifs_convert_ace(&local_acl->a_entries[i], pACE); - pACE++; - } - } - return size; -} - -static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace, - const posix_acl_xattr_entry *local_ace) -{ - __u16 rc = 0; /* 0 = ACL converted ok */ - - cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm); - cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag); - /* BB is there a better way to handle the large uid? */ - if (local_ace->e_id == cpu_to_le32(-1)) { - /* Probably no need to le convert -1 on any arch but can not hurt */ - cifs_ace->cifs_uid = cpu_to_le64(-1); - } else - cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id)); - /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/ - return rc; -} - -/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */ -static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL, - const int buflen, const int acl_type) -{ - __u16 rc = 0; - struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data; - posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL; - int count; - int i; - - if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL)) - return 0; - - count = posix_acl_xattr_count((size_t)buflen); - cFYI(1, "setting acl with %d entries from buf of length %d and " - "version of %d", - count, buflen, le32_to_cpu(local_acl->a_version)); - if (le32_to_cpu(local_acl->a_version) != 2) { - cFYI(1, "unknown POSIX ACL version %d", - le32_to_cpu(local_acl->a_version)); - return 0; - } - cifs_acl->version = cpu_to_le16(1); - if (acl_type == ACL_TYPE_ACCESS) - cifs_acl->access_entry_count = cpu_to_le16(count); - else if (acl_type == ACL_TYPE_DEFAULT) - cifs_acl->default_entry_count = cpu_to_le16(count); - else { - cFYI(1, "unknown ACL type %d", acl_type); - return 0; - } - for (i = 0; i < count; i++) { - rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], - &local_acl->a_entries[i]); - if (rc != 0) { - /* ACE not converted */ - break; - } - } - if (rc == 0) { - rc = (__u16)(count * sizeof(struct cifs_posix_ace)); - rc += sizeof(struct cifs_posix_acl); - /* BB add check to make sure ACL does not overflow SMB */ - } - return rc; -} - -int -CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - char *acl_inf, const int buflen, const int acl_type, - const struct nls_table *nls_codepage, int remap) -{ -/* SMB_QUERY_POSIX_ACL */ - TRANSACTION2_QPI_REQ *pSMB = NULL; - TRANSACTION2_QPI_RSP *pSMBr = NULL; - int rc = 0; - int bytes_returned; - int name_len; - __u16 params, byte_count; - - cFYI(1, "In GetPosixACL (Unix) for path %s", searchName); - -queryAclRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, - searchName, PATH_MAX, nls_codepage, - remap); - name_len++; /* trailing null */ - name_len *= 2; - pSMB->FileName[name_len] = 0; - pSMB->FileName[name_len+1] = 0; - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, searchName, name_len); - } - - params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; - pSMB->TotalDataCount = 0; - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find exact max data count below from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le16(4000); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - pSMB->ParameterOffset = cpu_to_le16( - offsetof(struct smb_com_transaction2_qpi_req, - InformationLevel) - 4); - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION); - byte_count = params + 1 /* pad */ ; - pSMB->TotalParameterCount = cpu_to_le16(params); - pSMB->ParameterCount = pSMB->TotalParameterCount; - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - cifs_stats_inc(&tcon->num_acl_get); - if (rc) { - cFYI(1, "Send error in Query POSIX ACL = %d", rc); - } else { - /* decode response */ - - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - /* BB also check enough total bytes returned */ - if (rc || get_bcc(&pSMBr->hdr) < 2) - rc = -EIO; /* bad smb */ - else { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - __u16 count = le16_to_cpu(pSMBr->t2.DataCount); - rc = cifs_copy_posix_acl(acl_inf, - (char *)&pSMBr->hdr.Protocol+data_offset, - buflen, acl_type, count); - } - } - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto queryAclRetry; - return rc; -} - -int -CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon, - const unsigned char *fileName, - const char *local_acl, const int buflen, - const int acl_type, - const struct nls_table *nls_codepage, int remap) -{ - struct smb_com_transaction2_spi_req *pSMB = NULL; - struct smb_com_transaction2_spi_rsp *pSMBr = NULL; - char *parm_data; - int name_len; - int rc = 0; - int bytes_returned = 0; - __u16 params, byte_count, data_count, param_offset, offset; - - cFYI(1, "In SetPosixACL (Unix) for path %s", fileName); -setAclRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, fileName, name_len); - } - params = 6 + name_len; - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find max SMB size from sess */ - pSMB->MaxDataCount = cpu_to_le16(1000); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_spi_req, - InformationLevel) - 4; - offset = param_offset + params; - parm_data = ((char *) &pSMB->hdr.Protocol) + offset; - pSMB->ParameterOffset = cpu_to_le16(param_offset); - - /* convert to on the wire format for POSIX ACL */ - data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type); - - if (data_count == 0) { - rc = -EOPNOTSUPP; - goto setACLerrorExit; - } - pSMB->DataOffset = cpu_to_le16(offset); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); - pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL); - byte_count = 3 /* pad */ + params + data_count; - pSMB->DataCount = cpu_to_le16(data_count); - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) - cFYI(1, "Set POSIX ACL returned %d", rc); - -setACLerrorExit: - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto setAclRetry; - return rc; -} - -/* BB fix tabs in this function FIXME BB */ -int -CIFSGetExtAttr(const int xid, struct cifs_tcon *tcon, - const int netfid, __u64 *pExtAttrBits, __u64 *pMask) -{ - int rc = 0; - struct smb_t2_qfi_req *pSMB = NULL; - struct smb_t2_qfi_rsp *pSMBr = NULL; - int bytes_returned; - __u16 params, byte_count; - - cFYI(1, "In GetExtAttr"); - if (tcon == NULL) - return -ENODEV; - -GetExtAttrRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - params = 2 /* level */ + 2 /* fid */; - pSMB->t2.TotalDataCount = 0; - pSMB->t2.MaxParameterCount = cpu_to_le16(4); - /* BB find exact max data count below from sess structure BB */ - pSMB->t2.MaxDataCount = cpu_to_le16(4000); - pSMB->t2.MaxSetupCount = 0; - pSMB->t2.Reserved = 0; - pSMB->t2.Flags = 0; - pSMB->t2.Timeout = 0; - pSMB->t2.Reserved2 = 0; - pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req, - Fid) - 4); - pSMB->t2.DataCount = 0; - pSMB->t2.DataOffset = 0; - pSMB->t2.SetupCount = 1; - pSMB->t2.Reserved3 = 0; - pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION); - byte_count = params + 1 /* pad */ ; - pSMB->t2.TotalParameterCount = cpu_to_le16(params); - pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount; - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS); - pSMB->Pad = 0; - pSMB->Fid = netfid; - inc_rfc1001_len(pSMB, byte_count); - pSMB->t2.ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "error %d in GetExtAttr", rc); - } else { - /* decode response */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - /* BB also check enough total bytes returned */ - if (rc || get_bcc(&pSMBr->hdr) < 2) - /* If rc should we check for EOPNOSUPP and - disable the srvino flag? or in caller? */ - rc = -EIO; /* bad smb */ - else { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - __u16 count = le16_to_cpu(pSMBr->t2.DataCount); - struct file_chattr_info *pfinfo; - /* BB Do we need a cast or hash here ? */ - if (count != 16) { - cFYI(1, "Illegal size ret in GetExtAttr"); - rc = -EIO; - goto GetExtAttrOut; - } - pfinfo = (struct file_chattr_info *) - (data_offset + (char *) &pSMBr->hdr.Protocol); - *pExtAttrBits = le64_to_cpu(pfinfo->mode); - *pMask = le64_to_cpu(pfinfo->mask); - } - } -GetExtAttrOut: - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto GetExtAttrRetry; - return rc; -} - -#endif /* CONFIG_POSIX */ - -#ifdef CONFIG_CIFS_ACL -/* - * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that - * all NT TRANSACTS that we init here have total parm and data under about 400 - * bytes (to fit in small cifs buffer size), which is the case so far, it - * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of - * returned setup area) and MaxParameterCount (returned parms size) must be set - * by caller - */ -static int -smb_init_nttransact(const __u16 sub_command, const int setup_count, - const int parm_len, struct cifs_tcon *tcon, - void **ret_buf) -{ - int rc; - __u32 temp_offset; - struct smb_com_ntransact_req *pSMB; - - rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon, - (void **)&pSMB); - if (rc) - return rc; - *ret_buf = (void *)pSMB; - pSMB->Reserved = 0; - pSMB->TotalParameterCount = cpu_to_le32(parm_len); - pSMB->TotalDataCount = 0; - pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00); - pSMB->ParameterCount = pSMB->TotalParameterCount; - pSMB->DataCount = pSMB->TotalDataCount; - temp_offset = offsetof(struct smb_com_ntransact_req, Parms) + - (setup_count * 2) - 4 /* for rfc1001 length itself */; - pSMB->ParameterOffset = cpu_to_le32(temp_offset); - pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len); - pSMB->SetupCount = setup_count; /* no need to le convert byte fields */ - pSMB->SubCommand = cpu_to_le16(sub_command); - return 0; -} - -static int -validate_ntransact(char *buf, char **ppparm, char **ppdata, - __u32 *pparmlen, __u32 *pdatalen) -{ - char *end_of_smb; - __u32 data_count, data_offset, parm_count, parm_offset; - struct smb_com_ntransact_rsp *pSMBr; - u16 bcc; - - *pdatalen = 0; - *pparmlen = 0; - - if (buf == NULL) - return -EINVAL; - - pSMBr = (struct smb_com_ntransact_rsp *)buf; - - bcc = get_bcc(&pSMBr->hdr); - end_of_smb = 2 /* sizeof byte count */ + bcc + - (char *)&pSMBr->ByteCount; - - data_offset = le32_to_cpu(pSMBr->DataOffset); - data_count = le32_to_cpu(pSMBr->DataCount); - parm_offset = le32_to_cpu(pSMBr->ParameterOffset); - parm_count = le32_to_cpu(pSMBr->ParameterCount); - - *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset; - *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset; - - /* should we also check that parm and data areas do not overlap? */ - if (*ppparm > end_of_smb) { - cFYI(1, "parms start after end of smb"); - return -EINVAL; - } else if (parm_count + *ppparm > end_of_smb) { - cFYI(1, "parm end after end of smb"); - return -EINVAL; - } else if (*ppdata > end_of_smb) { - cFYI(1, "data starts after end of smb"); - return -EINVAL; - } else if (data_count + *ppdata > end_of_smb) { - cFYI(1, "data %p + count %d (%p) past smb end %p start %p", - *ppdata, data_count, (data_count + *ppdata), - end_of_smb, pSMBr); - return -EINVAL; - } else if (parm_count + data_count > bcc) { - cFYI(1, "parm count and data count larger than SMB"); - return -EINVAL; - } - *pdatalen = data_count; - *pparmlen = parm_count; - return 0; -} - -/* Get Security Descriptor (by handle) from remote server for a file or dir */ -int -CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid, - struct cifs_ntsd **acl_inf, __u32 *pbuflen) -{ - int rc = 0; - int buf_type = 0; - QUERY_SEC_DESC_REQ *pSMB; - struct kvec iov[1]; - - cFYI(1, "GetCifsACL"); - - *pbuflen = 0; - *acl_inf = NULL; - - rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0, - 8 /* parm len */, tcon, (void **) &pSMB); - if (rc) - return rc; - - pSMB->MaxParameterCount = cpu_to_le32(4); - /* BB TEST with big acls that might need to be e.g. larger than 16K */ - pSMB->MaxSetupCount = 0; - pSMB->Fid = fid; /* file handle always le */ - pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP | - CIFS_ACL_DACL); - pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */ - inc_rfc1001_len(pSMB, 11); - iov[0].iov_base = (char *)pSMB; - iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; - - rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, - 0); - cifs_stats_inc(&tcon->num_acl_get); - if (rc) { - cFYI(1, "Send error in QuerySecDesc = %d", rc); - } else { /* decode response */ - __le32 *parm; - __u32 parm_len; - __u32 acl_len; - struct smb_com_ntransact_rsp *pSMBr; - char *pdata; - -/* validate_nttransact */ - rc = validate_ntransact(iov[0].iov_base, (char **)&parm, - &pdata, &parm_len, pbuflen); - if (rc) - goto qsec_out; - pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base; - - cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf); - - if (le32_to_cpu(pSMBr->ParameterCount) != 4) { - rc = -EIO; /* bad smb */ - *pbuflen = 0; - goto qsec_out; - } - -/* BB check that data area is minimum length and as big as acl_len */ - - acl_len = le32_to_cpu(*parm); - if (acl_len != *pbuflen) { - cERROR(1, "acl length %d does not match %d", - acl_len, *pbuflen); - if (*pbuflen > acl_len) - *pbuflen = acl_len; - } - - /* check if buffer is big enough for the acl - header followed by the smallest SID */ - if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) || - (*pbuflen >= 64 * 1024)) { - cERROR(1, "bad acl length %d", *pbuflen); - rc = -EINVAL; - *pbuflen = 0; - } else { - *acl_inf = kmalloc(*pbuflen, GFP_KERNEL); - if (*acl_inf == NULL) { - *pbuflen = 0; - rc = -ENOMEM; - } - memcpy(*acl_inf, pdata, *pbuflen); - } - } -qsec_out: - if (buf_type == CIFS_SMALL_BUFFER) - cifs_small_buf_release(iov[0].iov_base); - else if (buf_type == CIFS_LARGE_BUFFER) - cifs_buf_release(iov[0].iov_base); -/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ - return rc; -} - -int -CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid, - struct cifs_ntsd *pntsd, __u32 acllen, int aclflag) -{ - __u16 byte_count, param_count, data_count, param_offset, data_offset; - int rc = 0; - int bytes_returned = 0; - SET_SEC_DESC_REQ *pSMB = NULL; - void *pSMBr; - -setCifsAclRetry: - rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr); - if (rc) - return rc; - - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - - param_count = 8; - param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4; - data_count = acllen; - data_offset = param_offset + param_count; - byte_count = 3 /* pad */ + param_count; - - pSMB->DataCount = cpu_to_le32(data_count); - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->MaxParameterCount = cpu_to_le32(4); - pSMB->MaxDataCount = cpu_to_le32(16384); - pSMB->ParameterCount = cpu_to_le32(param_count); - pSMB->ParameterOffset = cpu_to_le32(param_offset); - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->DataOffset = cpu_to_le32(data_offset); - pSMB->SetupCount = 0; - pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC); - pSMB->ByteCount = cpu_to_le16(byte_count+data_count); - - pSMB->Fid = fid; /* file handle always le */ - pSMB->Reserved2 = 0; - pSMB->AclFlags = cpu_to_le32(aclflag); - - if (pntsd && acllen) { - memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) + - data_offset, pntsd, acllen); - inc_rfc1001_len(pSMB, byte_count + data_count); - } else - inc_rfc1001_len(pSMB, byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - - cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc); - if (rc) - cFYI(1, "Set CIFS ACL returned %d", rc); - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto setCifsAclRetry; - - return (rc); -} - -#endif /* CONFIG_CIFS_ACL */ - -/* Legacy Query Path Information call for lookup to old servers such - as Win9x/WinME */ -int SMBQueryInformation(const int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - FILE_ALL_INFO *pFinfo, - const struct nls_table *nls_codepage, int remap) -{ - QUERY_INFORMATION_REQ *pSMB; - QUERY_INFORMATION_RSP *pSMBr; - int rc = 0; - int bytes_returned; - int name_len; - - cFYI(1, "In SMBQPath path %s", searchName); -QInfRetry: - rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, - searchName, PATH_MAX, nls_codepage, - remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { - name_len = strnlen(searchName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, searchName, name_len); - } - pSMB->BufferFormat = 0x04; - name_len++; /* account for buffer type byte */ - inc_rfc1001_len(pSMB, (__u16)name_len); - pSMB->ByteCount = cpu_to_le16(name_len); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Send error in QueryInfo = %d", rc); - } else if (pFinfo) { - struct timespec ts; - __u32 time = le32_to_cpu(pSMBr->last_write_time); - - /* decode response */ - /* BB FIXME - add time zone adjustment BB */ - memset(pFinfo, 0, sizeof(FILE_ALL_INFO)); - ts.tv_nsec = 0; - ts.tv_sec = time; - /* decode time fields */ - pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts)); - pFinfo->LastWriteTime = pFinfo->ChangeTime; - pFinfo->LastAccessTime = 0; - pFinfo->AllocationSize = - cpu_to_le64(le32_to_cpu(pSMBr->size)); - pFinfo->EndOfFile = pFinfo->AllocationSize; - pFinfo->Attributes = - cpu_to_le32(le16_to_cpu(pSMBr->attr)); - } else - rc = -EIO; /* bad buffer passed in */ - - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto QInfRetry; - - return rc; -} - -int -CIFSSMBQFileInfo(const int xid, struct cifs_tcon *tcon, - u16 netfid, FILE_ALL_INFO *pFindData) -{ - struct smb_t2_qfi_req *pSMB = NULL; - struct smb_t2_qfi_rsp *pSMBr = NULL; - int rc = 0; - int bytes_returned; - __u16 params, byte_count; - -QFileInfoRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - params = 2 /* level */ + 2 /* fid */; - pSMB->t2.TotalDataCount = 0; - pSMB->t2.MaxParameterCount = cpu_to_le16(4); - /* BB find exact max data count below from sess structure BB */ - pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize); - pSMB->t2.MaxSetupCount = 0; - pSMB->t2.Reserved = 0; - pSMB->t2.Flags = 0; - pSMB->t2.Timeout = 0; - pSMB->t2.Reserved2 = 0; - pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req, - Fid) - 4); - pSMB->t2.DataCount = 0; - pSMB->t2.DataOffset = 0; - pSMB->t2.SetupCount = 1; - pSMB->t2.Reserved3 = 0; - pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION); - byte_count = params + 1 /* pad */ ; - pSMB->t2.TotalParameterCount = cpu_to_le16(params); - pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount; - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); - pSMB->Pad = 0; - pSMB->Fid = netfid; - inc_rfc1001_len(pSMB, byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Send error in QPathInfo = %d", rc); - } else { /* decode response */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - if (rc) /* BB add auto retry on EOPNOTSUPP? */ - rc = -EIO; - else if (get_bcc(&pSMBr->hdr) < 40) - rc = -EIO; /* bad smb */ - else if (pFindData) { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - memcpy((char *) pFindData, - (char *) &pSMBr->hdr.Protocol + - data_offset, sizeof(FILE_ALL_INFO)); - } else - rc = -ENOMEM; - } - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto QFileInfoRetry; - - return rc; -} - -int -CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - FILE_ALL_INFO *pFindData, - int legacy /* old style infolevel */, - const struct nls_table *nls_codepage, int remap) -{ -/* level 263 SMB_QUERY_FILE_ALL_INFO */ - TRANSACTION2_QPI_REQ *pSMB = NULL; - TRANSACTION2_QPI_RSP *pSMBr = NULL; - int rc = 0; - int bytes_returned; - int name_len; - __u16 params, byte_count; - -/* cFYI(1, "In QPathInfo path %s", searchName); */ -QPathInfoRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, searchName, name_len); - } - - params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; - pSMB->TotalDataCount = 0; - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find exact max SMB PDU from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le16(4000); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - pSMB->ParameterOffset = cpu_to_le16(offsetof( - struct smb_com_transaction2_qpi_req, InformationLevel) - 4); - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION); - byte_count = params + 1 /* pad */ ; - pSMB->TotalParameterCount = cpu_to_le16(params); - pSMB->ParameterCount = pSMB->TotalParameterCount; - if (legacy) - pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD); - else - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Send error in QPathInfo = %d", rc); - } else { /* decode response */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - if (rc) /* BB add auto retry on EOPNOTSUPP? */ - rc = -EIO; - else if (!legacy && get_bcc(&pSMBr->hdr) < 40) - rc = -EIO; /* bad smb */ - else if (legacy && get_bcc(&pSMBr->hdr) < 24) - rc = -EIO; /* 24 or 26 expected but we do not read - last field */ - else if (pFindData) { - int size; - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - - /* On legacy responses we do not read the last field, - EAsize, fortunately since it varies by subdialect and - also note it differs on Set vs. Get, ie two bytes or 4 - bytes depending but we don't care here */ - if (legacy) - size = sizeof(FILE_INFO_STANDARD); - else - size = sizeof(FILE_ALL_INFO); - memcpy((char *) pFindData, - (char *) &pSMBr->hdr.Protocol + - data_offset, size); - } else - rc = -ENOMEM; - } - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto QPathInfoRetry; - - return rc; -} - -int -CIFSSMBUnixQFileInfo(const int xid, struct cifs_tcon *tcon, - u16 netfid, FILE_UNIX_BASIC_INFO *pFindData) -{ - struct smb_t2_qfi_req *pSMB = NULL; - struct smb_t2_qfi_rsp *pSMBr = NULL; - int rc = 0; - int bytes_returned; - __u16 params, byte_count; - -UnixQFileInfoRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - params = 2 /* level */ + 2 /* fid */; - pSMB->t2.TotalDataCount = 0; - pSMB->t2.MaxParameterCount = cpu_to_le16(4); - /* BB find exact max data count below from sess structure BB */ - pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize); - pSMB->t2.MaxSetupCount = 0; - pSMB->t2.Reserved = 0; - pSMB->t2.Flags = 0; - pSMB->t2.Timeout = 0; - pSMB->t2.Reserved2 = 0; - pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req, - Fid) - 4); - pSMB->t2.DataCount = 0; - pSMB->t2.DataOffset = 0; - pSMB->t2.SetupCount = 1; - pSMB->t2.Reserved3 = 0; - pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION); - byte_count = params + 1 /* pad */ ; - pSMB->t2.TotalParameterCount = cpu_to_le16(params); - pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount; - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); - pSMB->Pad = 0; - pSMB->Fid = netfid; - inc_rfc1001_len(pSMB, byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Send error in QPathInfo = %d", rc); - } else { /* decode response */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) { - cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" - "Unix Extensions can be disabled on mount " - "by specifying the nosfu mount option."); - rc = -EIO; /* bad smb */ - } else { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - memcpy((char *) pFindData, - (char *) &pSMBr->hdr.Protocol + - data_offset, - sizeof(FILE_UNIX_BASIC_INFO)); - } - } - - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto UnixQFileInfoRetry; - - return rc; -} - -int -CIFSSMBUnixQPathInfo(const int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - FILE_UNIX_BASIC_INFO *pFindData, - const struct nls_table *nls_codepage, int remap) -{ -/* SMB_QUERY_FILE_UNIX_BASIC */ - TRANSACTION2_QPI_REQ *pSMB = NULL; - TRANSACTION2_QPI_RSP *pSMBr = NULL; - int rc = 0; - int bytes_returned = 0; - int name_len; - __u16 params, byte_count; - - cFYI(1, "In QPathInfo (Unix) the path %s", searchName); -UnixQPathInfoRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, searchName, name_len); - } - - params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; - pSMB->TotalDataCount = 0; - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find exact max SMB PDU from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le16(4000); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - pSMB->ParameterOffset = cpu_to_le16(offsetof( - struct smb_com_transaction2_qpi_req, InformationLevel) - 4); - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION); - byte_count = params + 1 /* pad */ ; - pSMB->TotalParameterCount = cpu_to_le16(params); - pSMB->ParameterCount = pSMB->TotalParameterCount; - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Send error in QPathInfo = %d", rc); - } else { /* decode response */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) { - cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" - "Unix Extensions can be disabled on mount " - "by specifying the nosfu mount option."); - rc = -EIO; /* bad smb */ - } else { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - memcpy((char *) pFindData, - (char *) &pSMBr->hdr.Protocol + - data_offset, - sizeof(FILE_UNIX_BASIC_INFO)); - } - } - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto UnixQPathInfoRetry; - - return rc; -} - -/* xid, tcon, searchName and codepage are input parms, rest are returned */ -int -CIFSFindFirst(const int xid, struct cifs_tcon *tcon, - const char *searchName, - const struct nls_table *nls_codepage, - __u16 *pnetfid, __u16 search_flags, - struct cifs_search_info *psrch_inf, int remap, const char dirsep) -{ -/* level 257 SMB_ */ - TRANSACTION2_FFIRST_REQ *pSMB = NULL; - TRANSACTION2_FFIRST_RSP *pSMBr = NULL; - T2_FFIRST_RSP_PARMS *parms; - int rc = 0; - int bytes_returned = 0; - int name_len; - __u16 params, byte_count; - - cFYI(1, "In FindFirst for %s", searchName); - -findFirstRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName, - PATH_MAX, nls_codepage, remap); - /* We can not add the asterik earlier in case - it got remapped to 0xF03A as if it were part of the - directory name instead of a wildcard */ - name_len *= 2; - pSMB->FileName[name_len] = dirsep; - pSMB->FileName[name_len+1] = 0; - pSMB->FileName[name_len+2] = '*'; - pSMB->FileName[name_len+3] = 0; - name_len += 4; /* now the trailing null */ - pSMB->FileName[name_len] = 0; /* null terminate just in case */ - pSMB->FileName[name_len+1] = 0; - name_len += 2; - } else { /* BB add check for overrun of SMB buf BB */ - name_len = strnlen(searchName, PATH_MAX); -/* BB fix here and in unicode clause above ie - if (name_len > buffersize-header) - free buffer exit; BB */ - strncpy(pSMB->FileName, searchName, name_len); - pSMB->FileName[name_len] = dirsep; - pSMB->FileName[name_len+1] = '*'; - pSMB->FileName[name_len+2] = 0; - name_len += 3; - } - - params = 12 + name_len /* includes null */ ; - pSMB->TotalDataCount = 0; /* no EAs */ - pSMB->MaxParameterCount = cpu_to_le16(10); - pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - byte_count = params + 1 /* pad */ ; - pSMB->TotalParameterCount = cpu_to_le16(params); - pSMB->ParameterCount = pSMB->TotalParameterCount; - pSMB->ParameterOffset = cpu_to_le16( - offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - - 4); - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */ - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST); - pSMB->SearchAttributes = - cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | - ATTR_DIRECTORY); - pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO)); - pSMB->SearchFlags = cpu_to_le16(search_flags); - pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); - - /* BB what should we set StorageType to? Does it matter? BB */ - pSMB->SearchStorageType = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - cifs_stats_inc(&tcon->num_ffirst); - - if (rc) {/* BB add logic to retry regular search if Unix search - rejected unexpectedly by server */ - /* BB Add code to handle unsupported level rc */ - cFYI(1, "Error in FindFirst = %d", rc); - - cifs_buf_release(pSMB); - - /* BB eventually could optimize out free and realloc of buf */ - /* for this case */ - if (rc == -EAGAIN) - goto findFirstRetry; - } else { /* decode response */ - /* BB remember to free buffer if error BB */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - if (rc == 0) { - unsigned int lnoff; - - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) - psrch_inf->unicode = true; - else - psrch_inf->unicode = false; - - psrch_inf->ntwrk_buf_start = (char *)pSMBr; - psrch_inf->smallBuf = 0; - psrch_inf->srch_entries_start = - (char *) &pSMBr->hdr.Protocol + - le16_to_cpu(pSMBr->t2.DataOffset); - parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol + - le16_to_cpu(pSMBr->t2.ParameterOffset)); - - if (parms->EndofSearch) - psrch_inf->endOfSearch = true; - else - psrch_inf->endOfSearch = false; - - psrch_inf->entries_in_buffer = - le16_to_cpu(parms->SearchCount); - psrch_inf->index_of_last_entry = 2 /* skip . and .. */ + - psrch_inf->entries_in_buffer; - lnoff = le16_to_cpu(parms->LastNameOffset); - if (CIFSMaxBufSize < lnoff) { - cERROR(1, "ignoring corrupt resume name"); - psrch_inf->last_entry = NULL; - return rc; - } - - psrch_inf->last_entry = psrch_inf->srch_entries_start + - lnoff; - - *pnetfid = parms->SearchHandle; - } else { - cifs_buf_release(pSMB); - } - } - - return rc; -} - -int CIFSFindNext(const int xid, struct cifs_tcon *tcon, __u16 searchHandle, - __u16 search_flags, struct cifs_search_info *psrch_inf) -{ - TRANSACTION2_FNEXT_REQ *pSMB = NULL; - TRANSACTION2_FNEXT_RSP *pSMBr = NULL; - T2_FNEXT_RSP_PARMS *parms; - char *response_data; - int rc = 0; - int bytes_returned; - unsigned int name_len; - __u16 params, byte_count; - - cFYI(1, "In FindNext"); - - if (psrch_inf->endOfSearch) - return -ENOENT; - - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - params = 14; /* includes 2 bytes of null string, converted to LE below*/ - byte_count = 0; - pSMB->TotalDataCount = 0; /* no EAs */ - pSMB->MaxParameterCount = cpu_to_le16(8); - pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - pSMB->ParameterOffset = cpu_to_le16( - offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4); - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT); - pSMB->SearchHandle = searchHandle; /* always kept as le */ - pSMB->SearchCount = - cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO)); - pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); - pSMB->ResumeKey = psrch_inf->resume_key; - pSMB->SearchFlags = cpu_to_le16(search_flags); - - name_len = psrch_inf->resume_name_len; - params += name_len; - if (name_len < PATH_MAX) { - memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len); - byte_count += name_len; - /* 14 byte parm len above enough for 2 byte null terminator */ - pSMB->ResumeFileName[name_len] = 0; - pSMB->ResumeFileName[name_len+1] = 0; - } else { - rc = -EINVAL; - goto FNext2_err_exit; - } - byte_count = params + 1 /* pad */ ; - pSMB->TotalParameterCount = cpu_to_le16(params); - pSMB->ParameterCount = pSMB->TotalParameterCount; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - cifs_stats_inc(&tcon->num_fnext); - if (rc) { - if (rc == -EBADF) { - psrch_inf->endOfSearch = true; - cifs_buf_release(pSMB); - rc = 0; /* search probably was closed at end of search*/ - } else - cFYI(1, "FindNext returned = %d", rc); - } else { /* decode response */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - if (rc == 0) { - unsigned int lnoff; - - /* BB fixme add lock for file (srch_info) struct here */ - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) - psrch_inf->unicode = true; - else - psrch_inf->unicode = false; - response_data = (char *) &pSMBr->hdr.Protocol + - le16_to_cpu(pSMBr->t2.ParameterOffset); - parms = (T2_FNEXT_RSP_PARMS *)response_data; - response_data = (char *)&pSMBr->hdr.Protocol + - le16_to_cpu(pSMBr->t2.DataOffset); - if (psrch_inf->smallBuf) - cifs_small_buf_release( - psrch_inf->ntwrk_buf_start); - else - cifs_buf_release(psrch_inf->ntwrk_buf_start); - psrch_inf->srch_entries_start = response_data; - psrch_inf->ntwrk_buf_start = (char *)pSMB; - psrch_inf->smallBuf = 0; - if (parms->EndofSearch) - psrch_inf->endOfSearch = true; - else - psrch_inf->endOfSearch = false; - psrch_inf->entries_in_buffer = - le16_to_cpu(parms->SearchCount); - psrch_inf->index_of_last_entry += - psrch_inf->entries_in_buffer; - lnoff = le16_to_cpu(parms->LastNameOffset); - if (CIFSMaxBufSize < lnoff) { - cERROR(1, "ignoring corrupt resume name"); - psrch_inf->last_entry = NULL; - return rc; - } else - psrch_inf->last_entry = - psrch_inf->srch_entries_start + lnoff; - -/* cFYI(1, "fnxt2 entries in buf %d index_of_last %d", - psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */ - - /* BB fixme add unlock here */ - } - - } - - /* BB On error, should we leave previous search buf (and count and - last entry fields) intact or free the previous one? */ - - /* Note: On -EAGAIN error only caller can retry on handle based calls - since file handle passed in no longer valid */ -FNext2_err_exit: - if (rc != 0) - cifs_buf_release(pSMB); - return rc; -} - -int -CIFSFindClose(const int xid, struct cifs_tcon *tcon, - const __u16 searchHandle) -{ - int rc = 0; - FINDCLOSE_REQ *pSMB = NULL; - - cFYI(1, "In CIFSSMBFindClose"); - rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB); - - /* no sense returning error if session restarted - as file handle has been closed */ - if (rc == -EAGAIN) - return 0; - if (rc) - return rc; - - pSMB->FileID = searchHandle; - pSMB->ByteCount = 0; - rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); - if (rc) - cERROR(1, "Send error in FindClose = %d", rc); - - cifs_stats_inc(&tcon->num_fclose); - - /* Since session is dead, search handle closed on server already */ - if (rc == -EAGAIN) - rc = 0; - - return rc; -} - -int -CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - __u64 *inode_number, - const struct nls_table *nls_codepage, int remap) -{ - int rc = 0; - TRANSACTION2_QPI_REQ *pSMB = NULL; - TRANSACTION2_QPI_RSP *pSMBr = NULL; - int name_len, bytes_returned; - __u16 params, byte_count; - - cFYI(1, "In GetSrvInodeNum for %s", searchName); - if (tcon == NULL) - return -ENODEV; - -GetInodeNumberRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, - searchName, PATH_MAX, nls_codepage, - remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, searchName, name_len); - } - - params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; - pSMB->TotalDataCount = 0; - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find exact max data count below from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le16(4000); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - pSMB->ParameterOffset = cpu_to_le16(offsetof( - struct smb_com_transaction2_qpi_req, InformationLevel) - 4); - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION); - byte_count = params + 1 /* pad */ ; - pSMB->TotalParameterCount = cpu_to_le16(params); - pSMB->ParameterCount = pSMB->TotalParameterCount; - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "error %d in QueryInternalInfo", rc); - } else { - /* decode response */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - /* BB also check enough total bytes returned */ - if (rc || get_bcc(&pSMBr->hdr) < 2) - /* If rc should we check for EOPNOSUPP and - disable the srvino flag? or in caller? */ - rc = -EIO; /* bad smb */ - else { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - __u16 count = le16_to_cpu(pSMBr->t2.DataCount); - struct file_internal_info *pfinfo; - /* BB Do we need a cast or hash here ? */ - if (count < 8) { - cFYI(1, "Illegal size ret in QryIntrnlInf"); - rc = -EIO; - goto GetInodeNumOut; - } - pfinfo = (struct file_internal_info *) - (data_offset + (char *) &pSMBr->hdr.Protocol); - *inode_number = le64_to_cpu(pfinfo->UniqueId); - } - } -GetInodeNumOut: - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto GetInodeNumberRetry; - return rc; -} - -/* parses DFS refferal V3 structure - * caller is responsible for freeing target_nodes - * returns: - * on success - 0 - * on failure - errno - */ -static int -parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, - unsigned int *num_of_nodes, - struct dfs_info3_param **target_nodes, - const struct nls_table *nls_codepage, int remap, - const char *searchName) -{ - int i, rc = 0; - char *data_end; - bool is_unicode; - struct dfs_referral_level_3 *ref; - - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) - is_unicode = true; - else - is_unicode = false; - *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals); - - if (*num_of_nodes < 1) { - cERROR(1, "num_referrals: must be at least > 0," - "but we get num_referrals = %d\n", *num_of_nodes); - rc = -EINVAL; - goto parse_DFS_referrals_exit; - } - - ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals); - if (ref->VersionNumber != cpu_to_le16(3)) { - cERROR(1, "Referrals of V%d version are not supported," - "should be V3", le16_to_cpu(ref->VersionNumber)); - rc = -EINVAL; - goto parse_DFS_referrals_exit; - } - - /* get the upper boundary of the resp buffer */ - data_end = (char *)(&(pSMBr->PathConsumed)) + - le16_to_cpu(pSMBr->t2.DataCount); - - cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n", - *num_of_nodes, - le32_to_cpu(pSMBr->DFSFlags)); - - *target_nodes = kzalloc(sizeof(struct dfs_info3_param) * - *num_of_nodes, GFP_KERNEL); - if (*target_nodes == NULL) { - cERROR(1, "Failed to allocate buffer for target_nodes\n"); - rc = -ENOMEM; - goto parse_DFS_referrals_exit; - } - - /* collect necessary data from referrals */ - for (i = 0; i < *num_of_nodes; i++) { - char *temp; - int max_len; - struct dfs_info3_param *node = (*target_nodes)+i; - - node->flags = le32_to_cpu(pSMBr->DFSFlags); - if (is_unicode) { - __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, - GFP_KERNEL); - if (tmp == NULL) { - rc = -ENOMEM; - goto parse_DFS_referrals_exit; - } - cifsConvertToUTF16((__le16 *) tmp, searchName, - PATH_MAX, nls_codepage, remap); - node->path_consumed = cifs_utf16_bytes(tmp, - le16_to_cpu(pSMBr->PathConsumed), - nls_codepage); - kfree(tmp); - } else - node->path_consumed = le16_to_cpu(pSMBr->PathConsumed); - - node->server_type = le16_to_cpu(ref->ServerType); - node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); - - /* copy DfsPath */ - temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset); - max_len = data_end - temp; - node->path_name = cifs_strndup_from_utf16(temp, max_len, - is_unicode, nls_codepage); - if (!node->path_name) { - rc = -ENOMEM; - goto parse_DFS_referrals_exit; - } - - /* copy link target UNC */ - temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset); - max_len = data_end - temp; - node->node_name = cifs_strndup_from_utf16(temp, max_len, - is_unicode, nls_codepage); - if (!node->node_name) { - rc = -ENOMEM; - goto parse_DFS_referrals_exit; - } - - ref++; - } - -parse_DFS_referrals_exit: - if (rc) { - free_dfs_info_array(*target_nodes, *num_of_nodes); - *target_nodes = NULL; - *num_of_nodes = 0; - } - return rc; -} - -int -CIFSGetDFSRefer(const int xid, struct cifs_ses *ses, - const unsigned char *searchName, - struct dfs_info3_param **target_nodes, - unsigned int *num_of_nodes, - const struct nls_table *nls_codepage, int remap) -{ -/* TRANS2_GET_DFS_REFERRAL */ - TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL; - TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL; - int rc = 0; - int bytes_returned; - int name_len; - __u16 params, byte_count; - *num_of_nodes = 0; - *target_nodes = NULL; - - cFYI(1, "In GetDFSRefer the path %s", searchName); - if (ses == NULL) - return -ENODEV; -getDFSRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - /* server pointer checked in called function, - but should never be null here anyway */ - pSMB->hdr.Mid = GetNextMid(ses->server); - pSMB->hdr.Tid = ses->ipc_tid; - pSMB->hdr.Uid = ses->Suid; - if (ses->capabilities & CAP_STATUS32) - pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS; - if (ses->capabilities & CAP_DFS) - pSMB->hdr.Flags2 |= SMBFLG2_DFS; - - if (ses->capabilities & CAP_UNICODE) { - pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; - name_len = - cifsConvertToUTF16((__le16 *) pSMB->RequestFileName, - searchName, PATH_MAX, nls_codepage, - remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->RequestFileName, searchName, name_len); - } - - if (ses->server) { - if (ses->server->sec_mode & - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) - pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - } - - pSMB->hdr.Uid = ses->Suid; - - params = 2 /* level */ + name_len /*includes null */ ; - pSMB->TotalDataCount = 0; - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->MaxParameterCount = 0; - /* BB find exact max SMB PDU from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le16(4000); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - pSMB->ParameterOffset = cpu_to_le16(offsetof( - struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL); - byte_count = params + 3 /* pad */ ; - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->MaxReferralLevel = cpu_to_le16(3); - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Send error in GetDFSRefer = %d", rc); - goto GetDFSRefExit; - } - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - /* BB Also check if enough total bytes returned? */ - if (rc || get_bcc(&pSMBr->hdr) < 17) { - rc = -EIO; /* bad smb */ - goto GetDFSRefExit; - } - - cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d", - get_bcc(&pSMBr->hdr), - le16_to_cpu(pSMBr->t2.DataOffset)); - - /* parse returned result into more usable form */ - rc = parse_DFS_referrals(pSMBr, num_of_nodes, - target_nodes, nls_codepage, remap, - searchName); - -GetDFSRefExit: - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto getDFSRetry; - - return rc; -} - -/* Query File System Info such as free space to old servers such as Win 9x */ -int -SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData) -{ -/* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */ - TRANSACTION2_QFSI_REQ *pSMB = NULL; - TRANSACTION2_QFSI_RSP *pSMBr = NULL; - FILE_SYSTEM_ALLOC_INFO *response_data; - int rc = 0; - int bytes_returned = 0; - __u16 params, byte_count; - - cFYI(1, "OldQFSInfo"); -oldQFSInfoRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - params = 2; /* level */ - pSMB->TotalDataCount = 0; - pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(1000); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - byte_count = params + 1 /* pad */ ; - pSMB->TotalParameterCount = cpu_to_le16(params); - pSMB->ParameterCount = pSMB->TotalParameterCount; - pSMB->ParameterOffset = cpu_to_le16(offsetof( - struct smb_com_transaction2_qfsi_req, InformationLevel) - 4); - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); - pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION); - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Send error in QFSInfo = %d", rc); - } else { /* decode response */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - if (rc || get_bcc(&pSMBr->hdr) < 18) - rc = -EIO; /* bad smb */ - else { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - cFYI(1, "qfsinf resp BCC: %d Offset %d", - get_bcc(&pSMBr->hdr), data_offset); - - response_data = (FILE_SYSTEM_ALLOC_INFO *) - (((char *) &pSMBr->hdr.Protocol) + data_offset); - FSData->f_bsize = - le16_to_cpu(response_data->BytesPerSector) * - le32_to_cpu(response_data-> - SectorsPerAllocationUnit); - FSData->f_blocks = - le32_to_cpu(response_data->TotalAllocationUnits); - FSData->f_bfree = FSData->f_bavail = - le32_to_cpu(response_data->FreeAllocationUnits); - cFYI(1, "Blocks: %lld Free: %lld Block size %ld", - (unsigned long long)FSData->f_blocks, - (unsigned long long)FSData->f_bfree, - FSData->f_bsize); - } - } - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto oldQFSInfoRetry; - - return rc; -} - -int -CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData) -{ -/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */ - TRANSACTION2_QFSI_REQ *pSMB = NULL; - TRANSACTION2_QFSI_RSP *pSMBr = NULL; - FILE_SYSTEM_INFO *response_data; - int rc = 0; - int bytes_returned = 0; - __u16 params, byte_count; - - cFYI(1, "In QFSInfo"); -QFSInfoRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - params = 2; /* level */ - pSMB->TotalDataCount = 0; - pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(1000); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - byte_count = params + 1 /* pad */ ; - pSMB->TotalParameterCount = cpu_to_le16(params); - pSMB->ParameterCount = pSMB->TotalParameterCount; - pSMB->ParameterOffset = cpu_to_le16(offsetof( - struct smb_com_transaction2_qfsi_req, InformationLevel) - 4); - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO); - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Send error in QFSInfo = %d", rc); - } else { /* decode response */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - if (rc || get_bcc(&pSMBr->hdr) < 24) - rc = -EIO; /* bad smb */ - else { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - - response_data = - (FILE_SYSTEM_INFO - *) (((char *) &pSMBr->hdr.Protocol) + - data_offset); - FSData->f_bsize = - le32_to_cpu(response_data->BytesPerSector) * - le32_to_cpu(response_data-> - SectorsPerAllocationUnit); - FSData->f_blocks = - le64_to_cpu(response_data->TotalAllocationUnits); - FSData->f_bfree = FSData->f_bavail = - le64_to_cpu(response_data->FreeAllocationUnits); - cFYI(1, "Blocks: %lld Free: %lld Block size %ld", - (unsigned long long)FSData->f_blocks, - (unsigned long long)FSData->f_bfree, - FSData->f_bsize); - } - } - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto QFSInfoRetry; - - return rc; -} - -int -CIFSSMBQFSAttributeInfo(const int xid, struct cifs_tcon *tcon) -{ -/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */ - TRANSACTION2_QFSI_REQ *pSMB = NULL; - TRANSACTION2_QFSI_RSP *pSMBr = NULL; - FILE_SYSTEM_ATTRIBUTE_INFO *response_data; - int rc = 0; - int bytes_returned = 0; - __u16 params, byte_count; - - cFYI(1, "In QFSAttributeInfo"); -QFSAttributeRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - params = 2; /* level */ - pSMB->TotalDataCount = 0; - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find exact max SMB PDU from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le16(1000); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - byte_count = params + 1 /* pad */ ; - pSMB->TotalParameterCount = cpu_to_le16(params); - pSMB->ParameterCount = pSMB->TotalParameterCount; - pSMB->ParameterOffset = cpu_to_le16(offsetof( - struct smb_com_transaction2_qfsi_req, InformationLevel) - 4); - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO); - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cERROR(1, "Send error in QFSAttributeInfo = %d", rc); - } else { /* decode response */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - if (rc || get_bcc(&pSMBr->hdr) < 13) { - /* BB also check if enough bytes returned */ - rc = -EIO; /* bad smb */ - } else { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - response_data = - (FILE_SYSTEM_ATTRIBUTE_INFO - *) (((char *) &pSMBr->hdr.Protocol) + - data_offset); - memcpy(&tcon->fsAttrInfo, response_data, - sizeof(FILE_SYSTEM_ATTRIBUTE_INFO)); - } - } - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto QFSAttributeRetry; - - return rc; -} - -int -CIFSSMBQFSDeviceInfo(const int xid, struct cifs_tcon *tcon) -{ -/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */ - TRANSACTION2_QFSI_REQ *pSMB = NULL; - TRANSACTION2_QFSI_RSP *pSMBr = NULL; - FILE_SYSTEM_DEVICE_INFO *response_data; - int rc = 0; - int bytes_returned = 0; - __u16 params, byte_count; - - cFYI(1, "In QFSDeviceInfo"); -QFSDeviceRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - params = 2; /* level */ - pSMB->TotalDataCount = 0; - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find exact max SMB PDU from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le16(1000); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - byte_count = params + 1 /* pad */ ; - pSMB->TotalParameterCount = cpu_to_le16(params); - pSMB->ParameterCount = pSMB->TotalParameterCount; - pSMB->ParameterOffset = cpu_to_le16(offsetof( - struct smb_com_transaction2_qfsi_req, InformationLevel) - 4); - - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO); - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Send error in QFSDeviceInfo = %d", rc); - } else { /* decode response */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - if (rc || get_bcc(&pSMBr->hdr) < - sizeof(FILE_SYSTEM_DEVICE_INFO)) - rc = -EIO; /* bad smb */ - else { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - response_data = - (FILE_SYSTEM_DEVICE_INFO *) - (((char *) &pSMBr->hdr.Protocol) + - data_offset); - memcpy(&tcon->fsDevInfo, response_data, - sizeof(FILE_SYSTEM_DEVICE_INFO)); - } - } - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto QFSDeviceRetry; - - return rc; -} - -int -CIFSSMBQFSUnixInfo(const int xid, struct cifs_tcon *tcon) -{ -/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */ - TRANSACTION2_QFSI_REQ *pSMB = NULL; - TRANSACTION2_QFSI_RSP *pSMBr = NULL; - FILE_SYSTEM_UNIX_INFO *response_data; - int rc = 0; - int bytes_returned = 0; - __u16 params, byte_count; - - cFYI(1, "In QFSUnixInfo"); -QFSUnixRetry: - rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon, - (void **) &pSMB, (void **) &pSMBr); - if (rc) - return rc; - - params = 2; /* level */ - pSMB->TotalDataCount = 0; - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find exact max SMB PDU from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le16(100); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - byte_count = params + 1 /* pad */ ; - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->ParameterOffset = cpu_to_le16(offsetof(struct - smb_com_transaction2_qfsi_req, InformationLevel) - 4); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO); - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cERROR(1, "Send error in QFSUnixInfo = %d", rc); - } else { /* decode response */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - if (rc || get_bcc(&pSMBr->hdr) < 13) { - rc = -EIO; /* bad smb */ - } else { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - response_data = - (FILE_SYSTEM_UNIX_INFO - *) (((char *) &pSMBr->hdr.Protocol) + - data_offset); - memcpy(&tcon->fsUnixInfo, response_data, - sizeof(FILE_SYSTEM_UNIX_INFO)); - } - } - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto QFSUnixRetry; - - - return rc; -} - -int -CIFSSMBSetFSUnixInfo(const int xid, struct cifs_tcon *tcon, __u64 cap) -{ -/* level 0x200 SMB_SET_CIFS_UNIX_INFO */ - TRANSACTION2_SETFSI_REQ *pSMB = NULL; - TRANSACTION2_SETFSI_RSP *pSMBr = NULL; - int rc = 0; - int bytes_returned = 0; - __u16 params, param_offset, offset, byte_count; - - cFYI(1, "In SETFSUnixInfo"); -SETFSUnixRetry: - /* BB switch to small buf init to save memory */ - rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon, - (void **) &pSMB, (void **) &pSMBr); - if (rc) - return rc; - - params = 4; /* 2 bytes zero followed by info level. */ - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - - 4; - offset = param_offset + params; - - pSMB->MaxParameterCount = cpu_to_le16(4); - /* BB find exact max SMB PDU from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le16(100); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION); - byte_count = 1 /* pad */ + params + 12; - - pSMB->DataCount = cpu_to_le16(12); - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->ParameterOffset = cpu_to_le16(param_offset); - pSMB->DataOffset = cpu_to_le16(offset); - - /* Params. */ - pSMB->FileNum = 0; - pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO); - - /* Data. */ - pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION); - pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION); - pSMB->ClientUnixCap = cpu_to_le64(cap); - - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cERROR(1, "Send error in SETFSUnixInfo = %d", rc); - } else { /* decode response */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - if (rc) - rc = -EIO; /* bad smb */ - } - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto SETFSUnixRetry; - - return rc; -} - - - -int -CIFSSMBQFSPosixInfo(const int xid, struct cifs_tcon *tcon, - struct kstatfs *FSData) -{ -/* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */ - TRANSACTION2_QFSI_REQ *pSMB = NULL; - TRANSACTION2_QFSI_RSP *pSMBr = NULL; - FILE_SYSTEM_POSIX_INFO *response_data; - int rc = 0; - int bytes_returned = 0; - __u16 params, byte_count; - - cFYI(1, "In QFSPosixInfo"); -QFSPosixRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - params = 2; /* level */ - pSMB->TotalDataCount = 0; - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find exact max SMB PDU from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le16(100); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - byte_count = params + 1 /* pad */ ; - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->ParameterOffset = cpu_to_le16(offsetof(struct - smb_com_transaction2_qfsi_req, InformationLevel) - 4); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO); - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Send error in QFSUnixInfo = %d", rc); - } else { /* decode response */ - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - - if (rc || get_bcc(&pSMBr->hdr) < 13) { - rc = -EIO; /* bad smb */ - } else { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - response_data = - (FILE_SYSTEM_POSIX_INFO - *) (((char *) &pSMBr->hdr.Protocol) + - data_offset); - FSData->f_bsize = - le32_to_cpu(response_data->BlockSize); - FSData->f_blocks = - le64_to_cpu(response_data->TotalBlocks); - FSData->f_bfree = - le64_to_cpu(response_data->BlocksAvail); - if (response_data->UserBlocksAvail == cpu_to_le64(-1)) { - FSData->f_bavail = FSData->f_bfree; - } else { - FSData->f_bavail = - le64_to_cpu(response_data->UserBlocksAvail); - } - if (response_data->TotalFileNodes != cpu_to_le64(-1)) - FSData->f_files = - le64_to_cpu(response_data->TotalFileNodes); - if (response_data->FreeFileNodes != cpu_to_le64(-1)) - FSData->f_ffree = - le64_to_cpu(response_data->FreeFileNodes); - } - } - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto QFSPosixRetry; - - return rc; -} - - -/* We can not use write of zero bytes trick to - set file size due to need for large file support. Also note that - this SetPathInfo is preferred to SetFileInfo based method in next - routine which is only needed to work around a sharing violation bug - in Samba which this routine can run into */ - -int -CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName, - __u64 size, bool SetAllocation, - const struct nls_table *nls_codepage, int remap) -{ - struct smb_com_transaction2_spi_req *pSMB = NULL; - struct smb_com_transaction2_spi_rsp *pSMBr = NULL; - struct file_end_of_file_info *parm_data; - int name_len; - int rc = 0; - int bytes_returned = 0; - __u16 params, byte_count, data_count, param_offset, offset; - - cFYI(1, "In SetEOF"); -SetEOFRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, fileName, name_len); - } - params = 6 + name_len; - data_count = sizeof(struct file_end_of_file_info); - pSMB->MaxParameterCount = cpu_to_le16(2); - pSMB->MaxDataCount = cpu_to_le16(4100); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_spi_req, - InformationLevel) - 4; - offset = param_offset + params; - if (SetAllocation) { - if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) - pSMB->InformationLevel = - cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2); - else - pSMB->InformationLevel = - cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO); - } else /* Set File Size */ { - if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) - pSMB->InformationLevel = - cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2); - else - pSMB->InformationLevel = - cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO); - } - - parm_data = - (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) + - offset); - pSMB->ParameterOffset = cpu_to_le16(param_offset); - pSMB->DataOffset = cpu_to_le16(offset); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); - byte_count = 3 /* pad */ + params + data_count; - pSMB->DataCount = cpu_to_le16(data_count); - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - parm_data->FileSize = cpu_to_le64(size); - pSMB->ByteCount = cpu_to_le16(byte_count); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) - cFYI(1, "SetPathInfo (file size) returned %d", rc); - - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto SetEOFRetry; - - return rc; -} - -int -CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size, - __u16 fid, __u32 pid_of_opener, bool SetAllocation) -{ - struct smb_com_transaction2_sfi_req *pSMB = NULL; - struct file_end_of_file_info *parm_data; - int rc = 0; - __u16 params, param_offset, offset, byte_count, count; - - cFYI(1, "SetFileSize (via SetFileInfo) %lld", - (long long)size); - rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); - - if (rc) - return rc; - - pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); - pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); - - params = 6; - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; - offset = param_offset + params; - - count = sizeof(struct file_end_of_file_info); - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find exact max SMB PDU from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le16(1000); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); - byte_count = 3 /* pad */ + params + count; - pSMB->DataCount = cpu_to_le16(count); - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->ParameterOffset = cpu_to_le16(param_offset); - parm_data = - (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) - + offset); - pSMB->DataOffset = cpu_to_le16(offset); - parm_data->FileSize = cpu_to_le64(size); - pSMB->Fid = fid; - if (SetAllocation) { - if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) - pSMB->InformationLevel = - cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2); - else - pSMB->InformationLevel = - cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO); - } else /* Set File Size */ { - if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) - pSMB->InformationLevel = - cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2); - else - pSMB->InformationLevel = - cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO); - } - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); - if (rc) { - cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc); - } - - /* Note: On -EAGAIN error only caller can retry on handle based calls - since file handle passed in no longer valid */ - - return rc; -} - -/* Some legacy servers such as NT4 require that the file times be set on - an open handle, rather than by pathname - this is awkward due to - potential access conflicts on the open, but it is unavoidable for these - old servers since the only other choice is to go from 100 nanosecond DCE - time and resort to the original setpathinfo level which takes the ancient - DOS time format with 2 second granularity */ -int -CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon, - const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener) -{ - struct smb_com_transaction2_sfi_req *pSMB = NULL; - char *data_offset; - int rc = 0; - __u16 params, param_offset, offset, byte_count, count; - - cFYI(1, "Set Times (via SetFileInfo)"); - rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); - - if (rc) - return rc; - - pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); - pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); - - params = 6; - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; - offset = param_offset + params; - - data_offset = (char *)pSMB + - offsetof(struct smb_hdr, Protocol) + offset; - - count = sizeof(FILE_BASIC_INFO); - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find max SMB PDU from sess */ - pSMB->MaxDataCount = cpu_to_le16(1000); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); - byte_count = 3 /* pad */ + params + count; - pSMB->DataCount = cpu_to_le16(count); - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->ParameterOffset = cpu_to_le16(param_offset); - pSMB->DataOffset = cpu_to_le16(offset); - pSMB->Fid = fid; - if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) - pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2); - else - pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); - rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); - if (rc) - cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc); - - /* Note: On -EAGAIN error only caller can retry on handle based calls - since file handle passed in no longer valid */ - - return rc; -} - -int -CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon, - bool delete_file, __u16 fid, __u32 pid_of_opener) -{ - struct smb_com_transaction2_sfi_req *pSMB = NULL; - char *data_offset; - int rc = 0; - __u16 params, param_offset, offset, byte_count, count; - - cFYI(1, "Set File Disposition (via SetFileInfo)"); - rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); - - if (rc) - return rc; - - pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); - pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); - - params = 6; - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; - offset = param_offset + params; - - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; - - count = 1; - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find max SMB PDU from sess */ - pSMB->MaxDataCount = cpu_to_le16(1000); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); - byte_count = 3 /* pad */ + params + count; - pSMB->DataCount = cpu_to_le16(count); - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->ParameterOffset = cpu_to_le16(param_offset); - pSMB->DataOffset = cpu_to_le16(offset); - pSMB->Fid = fid; - pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - *data_offset = delete_file ? 1 : 0; - rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); - if (rc) - cFYI(1, "Send error in SetFileDisposition = %d", rc); - - return rc; -} - -int -CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon, - const char *fileName, const FILE_BASIC_INFO *data, - const struct nls_table *nls_codepage, int remap) -{ - TRANSACTION2_SPI_REQ *pSMB = NULL; - TRANSACTION2_SPI_RSP *pSMBr = NULL; - int name_len; - int rc = 0; - int bytes_returned = 0; - char *data_offset; - __u16 params, param_offset, offset, byte_count, count; - - cFYI(1, "In SetTimes"); - -SetTimesRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, fileName, name_len); - } - - params = 6 + name_len; - count = sizeof(FILE_BASIC_INFO); - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find max SMB PDU from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le16(1000); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_spi_req, - InformationLevel) - 4; - offset = param_offset + params; - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; - pSMB->ParameterOffset = cpu_to_le16(param_offset); - pSMB->DataOffset = cpu_to_le16(offset); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); - byte_count = 3 /* pad */ + params + count; - - pSMB->DataCount = cpu_to_le16(count); - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->TotalParameterCount = pSMB->ParameterCount; - if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) - pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2); - else - pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); - pSMB->ByteCount = cpu_to_le16(byte_count); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) - cFYI(1, "SetPathInfo (times) returned %d", rc); - - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto SetTimesRetry; - - return rc; -} - -/* Can not be used to set time stamps yet (due to old DOS time format) */ -/* Can be used to set attributes */ -#if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug - handling it anyway and NT4 was what we thought it would be needed for - Do not delete it until we prove whether needed for Win9x though */ -int -CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon, char *fileName, - __u16 dos_attrs, const struct nls_table *nls_codepage) -{ - SETATTR_REQ *pSMB = NULL; - SETATTR_RSP *pSMBr = NULL; - int rc = 0; - int bytes_returned; - int name_len; - - cFYI(1, "In SetAttrLegacy"); - -SetAttrLgcyRetry: - rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - ConvertToUTF16((__le16 *) pSMB->fileName, fileName, - PATH_MAX, nls_codepage); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->fileName, fileName, name_len); - } - pSMB->attr = cpu_to_le16(dos_attrs); - pSMB->BufferFormat = 0x04; - inc_rfc1001_len(pSMB, name_len + 1); - pSMB->ByteCount = cpu_to_le16(name_len + 1); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) - cFYI(1, "Error in LegacySetAttr = %d", rc); - - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto SetAttrLgcyRetry; - - return rc; -} -#endif /* temporarily unneeded SetAttr legacy function */ - -static void -cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, - const struct cifs_unix_set_info_args *args) -{ - u64 mode = args->mode; - - /* - * Samba server ignores set of file size to zero due to bugs in some - * older clients, but we should be precise - we use SetFileSize to - * set file size and do not want to truncate file size to zero - * accidentally as happened on one Samba server beta by putting - * zero instead of -1 here - */ - data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); - data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64); - data_offset->LastStatusChange = cpu_to_le64(args->ctime); - data_offset->LastAccessTime = cpu_to_le64(args->atime); - data_offset->LastModificationTime = cpu_to_le64(args->mtime); - data_offset->Uid = cpu_to_le64(args->uid); - data_offset->Gid = cpu_to_le64(args->gid); - /* better to leave device as zero when it is */ - data_offset->DevMajor = cpu_to_le64(MAJOR(args->device)); - data_offset->DevMinor = cpu_to_le64(MINOR(args->device)); - data_offset->Permissions = cpu_to_le64(mode); - - if (S_ISREG(mode)) - data_offset->Type = cpu_to_le32(UNIX_FILE); - else if (S_ISDIR(mode)) - data_offset->Type = cpu_to_le32(UNIX_DIR); - else if (S_ISLNK(mode)) - data_offset->Type = cpu_to_le32(UNIX_SYMLINK); - else if (S_ISCHR(mode)) - data_offset->Type = cpu_to_le32(UNIX_CHARDEV); - else if (S_ISBLK(mode)) - data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV); - else if (S_ISFIFO(mode)) - data_offset->Type = cpu_to_le32(UNIX_FIFO); - else if (S_ISSOCK(mode)) - data_offset->Type = cpu_to_le32(UNIX_SOCKET); -} - -int -CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon, - const struct cifs_unix_set_info_args *args, - u16 fid, u32 pid_of_opener) -{ - struct smb_com_transaction2_sfi_req *pSMB = NULL; - char *data_offset; - int rc = 0; - u16 params, param_offset, offset, byte_count, count; - - cFYI(1, "Set Unix Info (via SetFileInfo)"); - rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); - - if (rc) - return rc; - - pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); - pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); - - params = 6; - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; - offset = param_offset + params; - - data_offset = (char *)pSMB + - offsetof(struct smb_hdr, Protocol) + offset; - - count = sizeof(FILE_UNIX_BASIC_INFO); - - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find max SMB PDU from sess */ - pSMB->MaxDataCount = cpu_to_le16(1000); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); - byte_count = 3 /* pad */ + params + count; - pSMB->DataCount = cpu_to_le16(count); - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->ParameterOffset = cpu_to_le16(param_offset); - pSMB->DataOffset = cpu_to_le16(offset); - pSMB->Fid = fid; - pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args); - - rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); - if (rc) - cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc); - - /* Note: On -EAGAIN error only caller can retry on handle based calls - since file handle passed in no longer valid */ - - return rc; -} - -int -CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *tcon, char *fileName, - const struct cifs_unix_set_info_args *args, - const struct nls_table *nls_codepage, int remap) -{ - TRANSACTION2_SPI_REQ *pSMB = NULL; - TRANSACTION2_SPI_RSP *pSMBr = NULL; - int name_len; - int rc = 0; - int bytes_returned = 0; - FILE_UNIX_BASIC_INFO *data_offset; - __u16 params, param_offset, offset, count, byte_count; - - cFYI(1, "In SetUID/GID/Mode"); -setPermsRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, fileName, name_len); - } - - params = 6 + name_len; - count = sizeof(FILE_UNIX_BASIC_INFO); - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find max SMB PDU from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le16(1000); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_spi_req, - InformationLevel) - 4; - offset = param_offset + params; - data_offset = - (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol + - offset); - memset(data_offset, 0, count); - pSMB->DataOffset = cpu_to_le16(offset); - pSMB->ParameterOffset = cpu_to_le16(param_offset); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); - byte_count = 3 /* pad */ + params + count; - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->DataCount = cpu_to_le16(count); - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - - cifs_fill_unix_set_info(data_offset, args); - - pSMB->ByteCount = cpu_to_le16(byte_count); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) - cFYI(1, "SetPathInfo (perms) returned %d", rc); - - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto setPermsRetry; - return rc; -} - -#ifdef CONFIG_CIFS_XATTR -/* - * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common - * function used by listxattr and getxattr type calls. When ea_name is set, - * it looks for that attribute name and stuffs that value into the EAData - * buffer. When ea_name is NULL, it stuffs a list of attribute names into the - * buffer. In both cases, the return value is either the length of the - * resulting data or a negative error code. If EAData is a NULL pointer then - * the data isn't copied to it, but the length is returned. - */ -ssize_t -CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, const unsigned char *ea_name, - char *EAData, size_t buf_size, - const struct nls_table *nls_codepage, int remap) -{ - /* BB assumes one setup word */ - TRANSACTION2_QPI_REQ *pSMB = NULL; - TRANSACTION2_QPI_RSP *pSMBr = NULL; - int rc = 0; - int bytes_returned; - int list_len; - struct fealist *ea_response_data; - struct fea *temp_fea; - char *temp_ptr; - char *end_of_smb; - __u16 params, byte_count, data_offset; - unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0; - - cFYI(1, "In Query All EAs path %s", searchName); -QAllEAsRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - list_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName, - PATH_MAX, nls_codepage, remap); - list_len++; /* trailing null */ - list_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ - list_len = strnlen(searchName, PATH_MAX); - list_len++; /* trailing null */ - strncpy(pSMB->FileName, searchName, list_len); - } - - params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */; - pSMB->TotalDataCount = 0; - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find exact max SMB PDU from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - pSMB->ParameterOffset = cpu_to_le16(offsetof( - struct smb_com_transaction2_qpi_req, InformationLevel) - 4); - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION); - byte_count = params + 1 /* pad */ ; - pSMB->TotalParameterCount = cpu_to_le16(params); - pSMB->ParameterCount = pSMB->TotalParameterCount; - pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS); - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) { - cFYI(1, "Send error in QueryAllEAs = %d", rc); - goto QAllEAsOut; - } - - - /* BB also check enough total bytes returned */ - /* BB we need to improve the validity checking - of these trans2 responses */ - - rc = validate_t2((struct smb_t2_rsp *)pSMBr); - if (rc || get_bcc(&pSMBr->hdr) < 4) { - rc = -EIO; /* bad smb */ - goto QAllEAsOut; - } - - /* check that length of list is not more than bcc */ - /* check that each entry does not go beyond length - of list */ - /* check that each element of each entry does not - go beyond end of list */ - /* validate_trans2_offsets() */ - /* BB check if start of smb + data_offset > &bcc+ bcc */ - - data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - ea_response_data = (struct fealist *) - (((char *) &pSMBr->hdr.Protocol) + data_offset); - - list_len = le32_to_cpu(ea_response_data->list_len); - cFYI(1, "ea length %d", list_len); - if (list_len <= 8) { - cFYI(1, "empty EA list returned from server"); - goto QAllEAsOut; - } - - /* make sure list_len doesn't go past end of SMB */ - end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr); - if ((char *)ea_response_data + list_len > end_of_smb) { - cFYI(1, "EA list appears to go beyond SMB"); - rc = -EIO; - goto QAllEAsOut; - } - - /* account for ea list len */ - list_len -= 4; - temp_fea = ea_response_data->list; - temp_ptr = (char *)temp_fea; - while (list_len > 0) { - unsigned int name_len; - __u16 value_len; - - list_len -= 4; - temp_ptr += 4; - /* make sure we can read name_len and value_len */ - if (list_len < 0) { - cFYI(1, "EA entry goes beyond length of list"); - rc = -EIO; - goto QAllEAsOut; - } - - name_len = temp_fea->name_len; - value_len = le16_to_cpu(temp_fea->value_len); - list_len -= name_len + 1 + value_len; - if (list_len < 0) { - cFYI(1, "EA entry goes beyond length of list"); - rc = -EIO; - goto QAllEAsOut; - } - - if (ea_name) { - if (ea_name_len == name_len && - memcmp(ea_name, temp_ptr, name_len) == 0) { - temp_ptr += name_len + 1; - rc = value_len; - if (buf_size == 0) - goto QAllEAsOut; - if ((size_t)value_len > buf_size) { - rc = -ERANGE; - goto QAllEAsOut; - } - memcpy(EAData, temp_ptr, value_len); - goto QAllEAsOut; - } - } else { - /* account for prefix user. and trailing null */ - rc += (5 + 1 + name_len); - if (rc < (int) buf_size) { - memcpy(EAData, "user.", 5); - EAData += 5; - memcpy(EAData, temp_ptr, name_len); - EAData += name_len; - /* null terminate name */ - *EAData = 0; - ++EAData; - } else if (buf_size == 0) { - /* skip copy - calc size only */ - } else { - /* stop before overrun buffer */ - rc = -ERANGE; - break; - } - } - temp_ptr += name_len + 1 + value_len; - temp_fea = (struct fea *)temp_ptr; - } - - /* didn't find the named attribute */ - if (ea_name) - rc = -ENODATA; - -QAllEAsOut: - cifs_buf_release(pSMB); - if (rc == -EAGAIN) - goto QAllEAsRetry; - - return (ssize_t)rc; -} - -int -CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, const char *fileName, - const char *ea_name, const void *ea_value, - const __u16 ea_value_len, const struct nls_table *nls_codepage, - int remap) -{ - struct smb_com_transaction2_spi_req *pSMB = NULL; - struct smb_com_transaction2_spi_rsp *pSMBr = NULL; - struct fealist *parm_data; - int name_len; - int rc = 0; - int bytes_returned = 0; - __u16 params, param_offset, byte_count, offset, count; - - cFYI(1, "In SetEA"); -SetEARetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(fileName, PATH_MAX); - name_len++; /* trailing null */ - strncpy(pSMB->FileName, fileName, name_len); - } - - params = 6 + name_len; - - /* done calculating parms using name_len of file name, - now use name_len to calculate length of ea name - we are going to create in the inode xattrs */ - if (ea_name == NULL) - name_len = 0; - else - name_len = strnlen(ea_name, 255); - - count = sizeof(*parm_data) + ea_value_len + name_len; - pSMB->MaxParameterCount = cpu_to_le16(2); - /* BB find max SMB PDU from sess */ - pSMB->MaxDataCount = cpu_to_le16(1000); - pSMB->MaxSetupCount = 0; - pSMB->Reserved = 0; - pSMB->Flags = 0; - pSMB->Timeout = 0; - pSMB->Reserved2 = 0; - param_offset = offsetof(struct smb_com_transaction2_spi_req, - InformationLevel) - 4; - offset = param_offset + params; - pSMB->InformationLevel = - cpu_to_le16(SMB_SET_FILE_EA); - - parm_data = - (struct fealist *) (((char *) &pSMB->hdr.Protocol) + - offset); - pSMB->ParameterOffset = cpu_to_le16(param_offset); - pSMB->DataOffset = cpu_to_le16(offset); - pSMB->SetupCount = 1; - pSMB->Reserved3 = 0; - pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); - byte_count = 3 /* pad */ + params + count; - pSMB->DataCount = cpu_to_le16(count); - parm_data->list_len = cpu_to_le32(count); - parm_data->list[0].EA_flags = 0; - /* we checked above that name len is less than 255 */ - parm_data->list[0].name_len = (__u8)name_len; - /* EA names are always ASCII */ - if (ea_name) - strncpy(parm_data->list[0].name, ea_name, name_len); - parm_data->list[0].name[name_len] = 0; - parm_data->list[0].value_len = cpu_to_le16(ea_value_len); - /* caller ensures that ea_value_len is less than 64K but - we need to ensure that it fits within the smb */ - - /*BB add length check to see if it would fit in - negotiated SMB buffer size BB */ - /* if (ea_value_len > buffer_size - 512 (enough for header)) */ - if (ea_value_len) - memcpy(parm_data->list[0].name+name_len+1, - ea_value, ea_value_len); - - pSMB->TotalDataCount = pSMB->DataCount; - pSMB->ParameterCount = cpu_to_le16(params); - pSMB->TotalParameterCount = pSMB->ParameterCount; - pSMB->Reserved4 = 0; - inc_rfc1001_len(pSMB, byte_count); - pSMB->ByteCount = cpu_to_le16(byte_count); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); - if (rc) - cFYI(1, "SetPathInfo (EA) returned %d", rc); - - cifs_buf_release(pSMB); - - if (rc == -EAGAIN) - goto SetEARetry; - - return rc; -} -#endif - -#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */ -/* - * Years ago the kernel added a "dnotify" function for Samba server, - * to allow network clients (such as Windows) to display updated - * lists of files in directory listings automatically when - * files are added by one user when another user has the - * same directory open on their desktop. The Linux cifs kernel - * client hooked into the kernel side of this interface for - * the same reason, but ironically when the VFS moved from - * "dnotify" to "inotify" it became harder to plug in Linux - * network file system clients (the most obvious use case - * for notify interfaces is when multiple users can update - * the contents of the same directory - exactly what network - * file systems can do) although the server (Samba) could - * still use it. For the short term we leave the worker - * function ifdeffed out (below) until inotify is fixed - * in the VFS to make it easier to plug in network file - * system clients. If inotify turns out to be permanently - * incompatible for network fs clients, we could instead simply - * expose this config flag by adding a future cifs (and smb2) notify ioctl. - */ -int CIFSSMBNotify(const int xid, struct cifs_tcon *tcon, - const int notify_subdirs, const __u16 netfid, - __u32 filter, struct file *pfile, int multishot, - const struct nls_table *nls_codepage) -{ - int rc = 0; - struct smb_com_transaction_change_notify_req *pSMB = NULL; - struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL; - struct dir_notify_req *dnotify_req; - int bytes_returned; - - cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid); - rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - pSMB->TotalParameterCount = 0 ; - pSMB->TotalDataCount = 0; - pSMB->MaxParameterCount = cpu_to_le32(2); - pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00); - pSMB->MaxSetupCount = 4; - pSMB->Reserved = 0; - pSMB->ParameterOffset = 0; - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 4; /* single byte does not need le conversion */ - pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE); - pSMB->ParameterCount = pSMB->TotalParameterCount; - if (notify_subdirs) - pSMB->WatchTree = 1; /* one byte - no le conversion needed */ - pSMB->Reserved2 = 0; - pSMB->CompletionFilter = cpu_to_le32(filter); - pSMB->Fid = netfid; /* file handle always le */ - pSMB->ByteCount = 0; - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *)pSMBr, &bytes_returned, - CIFS_ASYNC_OP); - if (rc) { - cFYI(1, "Error in Notify = %d", rc); - } else { - /* Add file to outstanding requests */ - /* BB change to kmem cache alloc */ - dnotify_req = kmalloc( - sizeof(struct dir_notify_req), - GFP_KERNEL); - if (dnotify_req) { - dnotify_req->Pid = pSMB->hdr.Pid; - dnotify_req->PidHigh = pSMB->hdr.PidHigh; - dnotify_req->Mid = pSMB->hdr.Mid; - dnotify_req->Tid = pSMB->hdr.Tid; - dnotify_req->Uid = pSMB->hdr.Uid; - dnotify_req->netfid = netfid; - dnotify_req->pfile = pfile; - dnotify_req->filter = filter; - dnotify_req->multishot = multishot; - spin_lock(&GlobalMid_Lock); - list_add_tail(&dnotify_req->lhead, - &GlobalDnotifyReqList); - spin_unlock(&GlobalMid_Lock); - } else - rc = -ENOMEM; - } - cifs_buf_release(pSMB); - return rc; -} -#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ diff --git a/ANDROID_3.4.5/fs/cifs/connect.c b/ANDROID_3.4.5/fs/cifs/connect.c deleted file mode 100644 index 402fa0f9..00000000 --- a/ANDROID_3.4.5/fs/cifs/connect.c +++ /dev/null @@ -1,4348 +0,0 @@ -/* - * fs/cifs/connect.c - * - * Copyright (C) International Business Machines Corp., 2002,2009 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/fs.h> -#include <linux/net.h> -#include <linux/string.h> -#include <linux/list.h> -#include <linux/wait.h> -#include <linux/slab.h> -#include <linux/pagemap.h> -#include <linux/ctype.h> -#include <linux/utsname.h> -#include <linux/mempool.h> -#include <linux/delay.h> -#include <linux/completion.h> -#include <linux/kthread.h> -#include <linux/pagevec.h> -#include <linux/freezer.h> -#include <linux/namei.h> -#include <asm/uaccess.h> -#include <asm/processor.h> -#include <linux/inet.h> -#include <linux/module.h> -#include <keys/user-type.h> -#include <net/ipv6.h> -#include <linux/parser.h> - -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifs_unicode.h" -#include "cifs_debug.h" -#include "cifs_fs_sb.h" -#include "ntlmssp.h" -#include "nterr.h" -#include "rfc1002pdu.h" -#include "fscache.h" - -#define CIFS_PORT 445 -#define RFC1001_PORT 139 - -/* SMB echo "timeout" -- FIXME: tunable? */ -#define SMB_ECHO_INTERVAL (60 * HZ) - -extern mempool_t *cifs_req_poolp; - -/* FIXME: should these be tunable? */ -#define TLINK_ERROR_EXPIRE (1 * HZ) -#define TLINK_IDLE_EXPIRE (600 * HZ) - -enum { - - /* Mount options that take no arguments */ - Opt_user_xattr, Opt_nouser_xattr, - Opt_forceuid, Opt_noforceuid, - Opt_noblocksend, Opt_noautotune, - Opt_hard, Opt_soft, Opt_perm, Opt_noperm, - Opt_mapchars, Opt_nomapchars, Opt_sfu, - Opt_nosfu, Opt_nodfs, Opt_posixpaths, - Opt_noposixpaths, Opt_nounix, - Opt_nocase, - Opt_brl, Opt_nobrl, - Opt_forcemandatorylock, Opt_setuids, - Opt_nosetuids, Opt_dynperm, Opt_nodynperm, - Opt_nohard, Opt_nosoft, - Opt_nointr, Opt_intr, - Opt_nostrictsync, Opt_strictsync, - Opt_serverino, Opt_noserverino, - Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl, - Opt_acl, Opt_noacl, Opt_locallease, - Opt_sign, Opt_seal, Opt_direct, - Opt_strictcache, Opt_noac, - Opt_fsc, Opt_mfsymlinks, - Opt_multiuser, Opt_sloppy, - - /* Mount options which take numeric value */ - Opt_backupuid, Opt_backupgid, Opt_uid, - Opt_cruid, Opt_gid, Opt_file_mode, - Opt_dirmode, Opt_port, - Opt_rsize, Opt_wsize, Opt_actimeo, - - /* Mount options which take string value */ - Opt_user, Opt_pass, Opt_ip, - Opt_unc, Opt_domain, - Opt_srcaddr, Opt_prefixpath, - Opt_iocharset, Opt_sockopt, - Opt_netbiosname, Opt_servern, - Opt_ver, Opt_sec, - - /* Mount options to be ignored */ - Opt_ignore, - - /* Options which could be blank */ - Opt_blank_pass, - Opt_blank_user, - Opt_blank_ip, - - Opt_err -}; - -static const match_table_t cifs_mount_option_tokens = { - - { Opt_user_xattr, "user_xattr" }, - { Opt_nouser_xattr, "nouser_xattr" }, - { Opt_forceuid, "forceuid" }, - { Opt_noforceuid, "noforceuid" }, - { Opt_noblocksend, "noblocksend" }, - { Opt_noautotune, "noautotune" }, - { Opt_hard, "hard" }, - { Opt_soft, "soft" }, - { Opt_perm, "perm" }, - { Opt_noperm, "noperm" }, - { Opt_mapchars, "mapchars" }, - { Opt_nomapchars, "nomapchars" }, - { Opt_sfu, "sfu" }, - { Opt_nosfu, "nosfu" }, - { Opt_nodfs, "nodfs" }, - { Opt_posixpaths, "posixpaths" }, - { Opt_noposixpaths, "noposixpaths" }, - { Opt_nounix, "nounix" }, - { Opt_nounix, "nolinux" }, - { Opt_nocase, "nocase" }, - { Opt_nocase, "ignorecase" }, - { Opt_brl, "brl" }, - { Opt_nobrl, "nobrl" }, - { Opt_nobrl, "nolock" }, - { Opt_forcemandatorylock, "forcemandatorylock" }, - { Opt_forcemandatorylock, "forcemand" }, - { Opt_setuids, "setuids" }, - { Opt_nosetuids, "nosetuids" }, - { Opt_dynperm, "dynperm" }, - { Opt_nodynperm, "nodynperm" }, - { Opt_nohard, "nohard" }, - { Opt_nosoft, "nosoft" }, - { Opt_nointr, "nointr" }, - { Opt_intr, "intr" }, - { Opt_nostrictsync, "nostrictsync" }, - { Opt_strictsync, "strictsync" }, - { Opt_serverino, "serverino" }, - { Opt_noserverino, "noserverino" }, - { Opt_rwpidforward, "rwpidforward" }, - { Opt_cifsacl, "cifsacl" }, - { Opt_nocifsacl, "nocifsacl" }, - { Opt_acl, "acl" }, - { Opt_noacl, "noacl" }, - { Opt_locallease, "locallease" }, - { Opt_sign, "sign" }, - { Opt_seal, "seal" }, - { Opt_direct, "direct" }, - { Opt_direct, "directio" }, - { Opt_direct, "forcedirectio" }, - { Opt_strictcache, "strictcache" }, - { Opt_noac, "noac" }, - { Opt_fsc, "fsc" }, - { Opt_mfsymlinks, "mfsymlinks" }, - { Opt_multiuser, "multiuser" }, - { Opt_sloppy, "sloppy" }, - - { Opt_backupuid, "backupuid=%s" }, - { Opt_backupgid, "backupgid=%s" }, - { Opt_uid, "uid=%s" }, - { Opt_cruid, "cruid=%s" }, - { Opt_gid, "gid=%s" }, - { Opt_file_mode, "file_mode=%s" }, - { Opt_dirmode, "dirmode=%s" }, - { Opt_dirmode, "dir_mode=%s" }, - { Opt_port, "port=%s" }, - { Opt_rsize, "rsize=%s" }, - { Opt_wsize, "wsize=%s" }, - { Opt_actimeo, "actimeo=%s" }, - - { Opt_blank_user, "user=" }, - { Opt_blank_user, "username=" }, - { Opt_user, "user=%s" }, - { Opt_user, "username=%s" }, - { Opt_blank_pass, "pass=" }, - { Opt_pass, "pass=%s" }, - { Opt_pass, "password=%s" }, - { Opt_blank_ip, "ip=" }, - { Opt_blank_ip, "addr=" }, - { Opt_ip, "ip=%s" }, - { Opt_ip, "addr=%s" }, - { Opt_unc, "unc=%s" }, - { Opt_unc, "target=%s" }, - { Opt_unc, "path=%s" }, - { Opt_domain, "dom=%s" }, - { Opt_domain, "domain=%s" }, - { Opt_domain, "workgroup=%s" }, - { Opt_srcaddr, "srcaddr=%s" }, - { Opt_prefixpath, "prefixpath=%s" }, - { Opt_iocharset, "iocharset=%s" }, - { Opt_sockopt, "sockopt=%s" }, - { Opt_netbiosname, "netbiosname=%s" }, - { Opt_servern, "servern=%s" }, - { Opt_ver, "ver=%s" }, - { Opt_ver, "vers=%s" }, - { Opt_ver, "version=%s" }, - { Opt_sec, "sec=%s" }, - - { Opt_ignore, "cred" }, - { Opt_ignore, "credentials" }, - { Opt_ignore, "cred=%s" }, - { Opt_ignore, "credentials=%s" }, - { Opt_ignore, "guest" }, - { Opt_ignore, "rw" }, - { Opt_ignore, "ro" }, - { Opt_ignore, "suid" }, - { Opt_ignore, "nosuid" }, - { Opt_ignore, "exec" }, - { Opt_ignore, "noexec" }, - { Opt_ignore, "nodev" }, - { Opt_ignore, "noauto" }, - { Opt_ignore, "dev" }, - { Opt_ignore, "mand" }, - { Opt_ignore, "nomand" }, - { Opt_ignore, "_netdev" }, - - { Opt_err, NULL } -}; - -enum { - Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p, - Opt_sec_ntlmsspi, Opt_sec_ntlmssp, - Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2i, - Opt_sec_nontlm, Opt_sec_lanman, - Opt_sec_none, - - Opt_sec_err -}; - -static const match_table_t cifs_secflavor_tokens = { - { Opt_sec_krb5, "krb5" }, - { Opt_sec_krb5i, "krb5i" }, - { Opt_sec_krb5p, "krb5p" }, - { Opt_sec_ntlmsspi, "ntlmsspi" }, - { Opt_sec_ntlmssp, "ntlmssp" }, - { Opt_ntlm, "ntlm" }, - { Opt_sec_ntlmi, "ntlmi" }, - { Opt_sec_ntlmv2i, "ntlmv2i" }, - { Opt_sec_nontlm, "nontlm" }, - { Opt_sec_lanman, "lanman" }, - { Opt_sec_none, "none" }, - - { Opt_sec_err, NULL } -}; - -static int ip_connect(struct TCP_Server_Info *server); -static int generic_ip_connect(struct TCP_Server_Info *server); -static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); -static void cifs_prune_tlinks(struct work_struct *work); -static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data, - const char *devname); - -/* - * cifs tcp session reconnection - * - * mark tcp session as reconnecting so temporarily locked - * mark all smb sessions as reconnecting for tcp session - * reconnect tcp session - * wake up waiters on reconnection? - (not needed currently) - */ -static int -cifs_reconnect(struct TCP_Server_Info *server) -{ - int rc = 0; - struct list_head *tmp, *tmp2; - struct cifs_ses *ses; - struct cifs_tcon *tcon; - struct mid_q_entry *mid_entry; - struct list_head retry_list; - - spin_lock(&GlobalMid_Lock); - if (server->tcpStatus == CifsExiting) { - /* the demux thread will exit normally - next time through the loop */ - spin_unlock(&GlobalMid_Lock); - return rc; - } else - server->tcpStatus = CifsNeedReconnect; - spin_unlock(&GlobalMid_Lock); - server->maxBuf = 0; - - cFYI(1, "Reconnecting tcp session"); - - /* before reconnecting the tcp session, mark the smb session (uid) - and the tid bad so they are not used until reconnected */ - cFYI(1, "%s: marking sessions and tcons for reconnect", __func__); - spin_lock(&cifs_tcp_ses_lock); - list_for_each(tmp, &server->smb_ses_list) { - ses = list_entry(tmp, struct cifs_ses, smb_ses_list); - ses->need_reconnect = true; - ses->ipc_tid = 0; - list_for_each(tmp2, &ses->tcon_list) { - tcon = list_entry(tmp2, struct cifs_tcon, tcon_list); - tcon->need_reconnect = true; - } - } - spin_unlock(&cifs_tcp_ses_lock); - - /* do not want to be sending data on a socket we are freeing */ - cFYI(1, "%s: tearing down socket", __func__); - mutex_lock(&server->srv_mutex); - if (server->ssocket) { - cFYI(1, "State: 0x%x Flags: 0x%lx", server->ssocket->state, - server->ssocket->flags); - kernel_sock_shutdown(server->ssocket, SHUT_WR); - cFYI(1, "Post shutdown state: 0x%x Flags: 0x%lx", - server->ssocket->state, - server->ssocket->flags); - sock_release(server->ssocket); - server->ssocket = NULL; - } - server->sequence_number = 0; - server->session_estab = false; - kfree(server->session_key.response); - server->session_key.response = NULL; - server->session_key.len = 0; - server->lstrp = jiffies; - mutex_unlock(&server->srv_mutex); - - /* mark submitted MIDs for retry and issue callback */ - INIT_LIST_HEAD(&retry_list); - cFYI(1, "%s: moving mids to private list", __func__); - spin_lock(&GlobalMid_Lock); - list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { - mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - if (mid_entry->mid_state == MID_REQUEST_SUBMITTED) - mid_entry->mid_state = MID_RETRY_NEEDED; - list_move(&mid_entry->qhead, &retry_list); - } - spin_unlock(&GlobalMid_Lock); - - cFYI(1, "%s: issuing mid callbacks", __func__); - list_for_each_safe(tmp, tmp2, &retry_list) { - mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - list_del_init(&mid_entry->qhead); - mid_entry->callback(mid_entry); - } - - do { - try_to_freeze(); - - /* we should try only the port we connected to before */ - rc = generic_ip_connect(server); - if (rc) { - cFYI(1, "reconnect error %d", rc); - msleep(3000); - } else { - atomic_inc(&tcpSesReconnectCount); - spin_lock(&GlobalMid_Lock); - if (server->tcpStatus != CifsExiting) - server->tcpStatus = CifsNeedNegotiate; - spin_unlock(&GlobalMid_Lock); - } - } while (server->tcpStatus == CifsNeedReconnect); - - return rc; -} - -/* - return codes: - 0 not a transact2, or all data present - >0 transact2 with that much data missing - -EINVAL = invalid transact2 - - */ -static int check2ndT2(char *buf) -{ - struct smb_hdr *pSMB = (struct smb_hdr *)buf; - struct smb_t2_rsp *pSMBt; - int remaining; - __u16 total_data_size, data_in_this_rsp; - - if (pSMB->Command != SMB_COM_TRANSACTION2) - return 0; - - /* check for plausible wct, bcc and t2 data and parm sizes */ - /* check for parm and data offset going beyond end of smb */ - if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */ - cFYI(1, "invalid transact2 word count"); - return -EINVAL; - } - - pSMBt = (struct smb_t2_rsp *)pSMB; - - total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); - data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); - - if (total_data_size == data_in_this_rsp) - return 0; - else if (total_data_size < data_in_this_rsp) { - cFYI(1, "total data %d smaller than data in frame %d", - total_data_size, data_in_this_rsp); - return -EINVAL; - } - - remaining = total_data_size - data_in_this_rsp; - - cFYI(1, "missing %d bytes from transact2, check next response", - remaining); - if (total_data_size > CIFSMaxBufSize) { - cERROR(1, "TotalDataSize %d is over maximum buffer %d", - total_data_size, CIFSMaxBufSize); - return -EINVAL; - } - return remaining; -} - -static int coalesce_t2(char *second_buf, struct smb_hdr *target_hdr) -{ - struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf; - struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr; - char *data_area_of_tgt; - char *data_area_of_src; - int remaining; - unsigned int byte_count, total_in_tgt; - __u16 tgt_total_cnt, src_total_cnt, total_in_src; - - src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount); - tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); - - if (tgt_total_cnt != src_total_cnt) - cFYI(1, "total data count of primary and secondary t2 differ " - "source=%hu target=%hu", src_total_cnt, tgt_total_cnt); - - total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); - - remaining = tgt_total_cnt - total_in_tgt; - - if (remaining < 0) { - cFYI(1, "Server sent too much data. tgt_total_cnt=%hu " - "total_in_tgt=%hu", tgt_total_cnt, total_in_tgt); - return -EPROTO; - } - - if (remaining == 0) { - /* nothing to do, ignore */ - cFYI(1, "no more data remains"); - return 0; - } - - total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount); - if (remaining < total_in_src) - cFYI(1, "transact2 2nd response contains too much data"); - - /* find end of first SMB data area */ - data_area_of_tgt = (char *)&pSMBt->hdr.Protocol + - get_unaligned_le16(&pSMBt->t2_rsp.DataOffset); - - /* validate target area */ - data_area_of_src = (char *)&pSMBs->hdr.Protocol + - get_unaligned_le16(&pSMBs->t2_rsp.DataOffset); - - data_area_of_tgt += total_in_tgt; - - total_in_tgt += total_in_src; - /* is the result too big for the field? */ - if (total_in_tgt > USHRT_MAX) { - cFYI(1, "coalesced DataCount too large (%u)", total_in_tgt); - return -EPROTO; - } - put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount); - - /* fix up the BCC */ - byte_count = get_bcc(target_hdr); - byte_count += total_in_src; - /* is the result too big for the field? */ - if (byte_count > USHRT_MAX) { - cFYI(1, "coalesced BCC too large (%u)", byte_count); - return -EPROTO; - } - put_bcc(byte_count, target_hdr); - - byte_count = be32_to_cpu(target_hdr->smb_buf_length); - byte_count += total_in_src; - /* don't allow buffer to overflow */ - if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { - cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count); - return -ENOBUFS; - } - target_hdr->smb_buf_length = cpu_to_be32(byte_count); - - /* copy second buffer into end of first buffer */ - memcpy(data_area_of_tgt, data_area_of_src, total_in_src); - - if (remaining != total_in_src) { - /* more responses to go */ - cFYI(1, "waiting for more secondary responses"); - return 1; - } - - /* we are done */ - cFYI(1, "found the last secondary response"); - return 0; -} - -static void -cifs_echo_request(struct work_struct *work) -{ - int rc; - struct TCP_Server_Info *server = container_of(work, - struct TCP_Server_Info, echo.work); - - /* - * We cannot send an echo until the NEGOTIATE_PROTOCOL request is - * done, which is indicated by maxBuf != 0. Also, no need to ping if - * we got a response recently - */ - if (server->maxBuf == 0 || - time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) - goto requeue_echo; - - rc = CIFSSMBEcho(server); - if (rc) - cFYI(1, "Unable to send echo request to server: %s", - server->hostname); - -requeue_echo: - queue_delayed_work(cifsiod_wq, &server->echo, SMB_ECHO_INTERVAL); -} - -static bool -allocate_buffers(struct TCP_Server_Info *server) -{ - if (!server->bigbuf) { - server->bigbuf = (char *)cifs_buf_get(); - if (!server->bigbuf) { - cERROR(1, "No memory for large SMB response"); - msleep(3000); - /* retry will check if exiting */ - return false; - } - } else if (server->large_buf) { - /* we are reusing a dirty large buf, clear its start */ - memset(server->bigbuf, 0, header_size()); - } - - if (!server->smallbuf) { - server->smallbuf = (char *)cifs_small_buf_get(); - if (!server->smallbuf) { - cERROR(1, "No memory for SMB response"); - msleep(1000); - /* retry will check if exiting */ - return false; - } - /* beginning of smb buffer is cleared in our buf_get */ - } else { - /* if existing small buf clear beginning */ - memset(server->smallbuf, 0, header_size()); - } - - return true; -} - -static bool -server_unresponsive(struct TCP_Server_Info *server) -{ - /* - * We need to wait 2 echo intervals to make sure we handle such - * situations right: - * 1s client sends a normal SMB request - * 2s client gets a response - * 30s echo workqueue job pops, and decides we got a response recently - * and don't need to send another - * ... - * 65s kernel_recvmsg times out, and we see that we haven't gotten - * a response in >60s. - */ - if (server->tcpStatus == CifsGood && - time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) { - cERROR(1, "Server %s has not responded in %d seconds. " - "Reconnecting...", server->hostname, - (2 * SMB_ECHO_INTERVAL) / HZ); - cifs_reconnect(server); - wake_up(&server->response_q); - return true; - } - - return false; -} - -/* - * kvec_array_init - clone a kvec array, and advance into it - * @new: pointer to memory for cloned array - * @iov: pointer to original array - * @nr_segs: number of members in original array - * @bytes: number of bytes to advance into the cloned array - * - * This function will copy the array provided in iov to a section of memory - * and advance the specified number of bytes into the new array. It returns - * the number of segments in the new array. "new" must be at least as big as - * the original iov array. - */ -static unsigned int -kvec_array_init(struct kvec *new, struct kvec *iov, unsigned int nr_segs, - size_t bytes) -{ - size_t base = 0; - - while (bytes || !iov->iov_len) { - int copy = min(bytes, iov->iov_len); - - bytes -= copy; - base += copy; - if (iov->iov_len == base) { - iov++; - nr_segs--; - base = 0; - } - } - memcpy(new, iov, sizeof(*iov) * nr_segs); - new->iov_base += base; - new->iov_len -= base; - return nr_segs; -} - -static struct kvec * -get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs) -{ - struct kvec *new_iov; - - if (server->iov && nr_segs <= server->nr_iov) - return server->iov; - - /* not big enough -- allocate a new one and release the old */ - new_iov = kmalloc(sizeof(*new_iov) * nr_segs, GFP_NOFS); - if (new_iov) { - kfree(server->iov); - server->iov = new_iov; - server->nr_iov = nr_segs; - } - return new_iov; -} - -int -cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig, - unsigned int nr_segs, unsigned int to_read) -{ - int length = 0; - int total_read; - unsigned int segs; - struct msghdr smb_msg; - struct kvec *iov; - - iov = get_server_iovec(server, nr_segs); - if (!iov) - return -ENOMEM; - - smb_msg.msg_control = NULL; - smb_msg.msg_controllen = 0; - - for (total_read = 0; to_read; total_read += length, to_read -= length) { - try_to_freeze(); - - if (server_unresponsive(server)) { - total_read = -EAGAIN; - break; - } - - segs = kvec_array_init(iov, iov_orig, nr_segs, total_read); - - length = kernel_recvmsg(server->ssocket, &smb_msg, - iov, segs, to_read, 0); - - if (server->tcpStatus == CifsExiting) { - total_read = -ESHUTDOWN; - break; - } else if (server->tcpStatus == CifsNeedReconnect) { - cifs_reconnect(server); - total_read = -EAGAIN; - break; - } else if (length == -ERESTARTSYS || - length == -EAGAIN || - length == -EINTR) { - /* - * Minimum sleep to prevent looping, allowing socket - * to clear and app threads to set tcpStatus - * CifsNeedReconnect if server hung. - */ - usleep_range(1000, 2000); - length = 0; - continue; - } else if (length <= 0) { - cFYI(1, "Received no data or error: expecting %d " - "got %d", to_read, length); - cifs_reconnect(server); - total_read = -EAGAIN; - break; - } - } - return total_read; -} - -int -cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, - unsigned int to_read) -{ - struct kvec iov; - - iov.iov_base = buf; - iov.iov_len = to_read; - - return cifs_readv_from_socket(server, &iov, 1, to_read); -} - -static bool -is_smb_response(struct TCP_Server_Info *server, unsigned char type) -{ - /* - * The first byte big endian of the length field, - * is actually not part of the length but the type - * with the most common, zero, as regular data. - */ - switch (type) { - case RFC1002_SESSION_MESSAGE: - /* Regular SMB response */ - return true; - case RFC1002_SESSION_KEEP_ALIVE: - cFYI(1, "RFC 1002 session keep alive"); - break; - case RFC1002_POSITIVE_SESSION_RESPONSE: - cFYI(1, "RFC 1002 positive session response"); - break; - case RFC1002_NEGATIVE_SESSION_RESPONSE: - /* - * We get this from Windows 98 instead of an error on - * SMB negprot response. - */ - cFYI(1, "RFC 1002 negative session response"); - /* give server a second to clean up */ - msleep(1000); - /* - * Always try 445 first on reconnect since we get NACK - * on some if we ever connected to port 139 (the NACK - * is since we do not begin with RFC1001 session - * initialize frame). - */ - cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT); - cifs_reconnect(server); - wake_up(&server->response_q); - break; - default: - cERROR(1, "RFC 1002 unknown response type 0x%x", type); - cifs_reconnect(server); - } - - return false; -} - -static struct mid_q_entry * -find_mid(struct TCP_Server_Info *server, char *buffer) -{ - struct smb_hdr *buf = (struct smb_hdr *)buffer; - struct mid_q_entry *mid; - - spin_lock(&GlobalMid_Lock); - list_for_each_entry(mid, &server->pending_mid_q, qhead) { - if (mid->mid == buf->Mid && - mid->mid_state == MID_REQUEST_SUBMITTED && - le16_to_cpu(mid->command) == buf->Command) { - spin_unlock(&GlobalMid_Lock); - return mid; - } - } - spin_unlock(&GlobalMid_Lock); - return NULL; -} - -void -dequeue_mid(struct mid_q_entry *mid, bool malformed) -{ -#ifdef CONFIG_CIFS_STATS2 - mid->when_received = jiffies; -#endif - spin_lock(&GlobalMid_Lock); - if (!malformed) - mid->mid_state = MID_RESPONSE_RECEIVED; - else - mid->mid_state = MID_RESPONSE_MALFORMED; - list_del_init(&mid->qhead); - spin_unlock(&GlobalMid_Lock); -} - -static void -handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server, - char *buf, int malformed) -{ - if (malformed == 0 && check2ndT2(buf) > 0) { - mid->multiRsp = true; - if (mid->resp_buf) { - /* merge response - fix up 1st*/ - malformed = coalesce_t2(buf, mid->resp_buf); - if (malformed > 0) - return; - - /* All parts received or packet is malformed. */ - mid->multiEnd = true; - return dequeue_mid(mid, malformed); - } - if (!server->large_buf) { - /*FIXME: switch to already allocated largebuf?*/ - cERROR(1, "1st trans2 resp needs bigbuf"); - } else { - /* Have first buffer */ - mid->resp_buf = buf; - mid->large_buf = true; - server->bigbuf = NULL; - } - return; - } - mid->resp_buf = buf; - mid->large_buf = server->large_buf; - /* Was previous buf put in mpx struct for multi-rsp? */ - if (!mid->multiRsp) { - /* smb buffer will be freed by user thread */ - if (server->large_buf) - server->bigbuf = NULL; - else - server->smallbuf = NULL; - } - dequeue_mid(mid, malformed); -} - -static void clean_demultiplex_info(struct TCP_Server_Info *server) -{ - int length; - - /* take it off the list, if it's not already */ - spin_lock(&cifs_tcp_ses_lock); - list_del_init(&server->tcp_ses_list); - spin_unlock(&cifs_tcp_ses_lock); - - spin_lock(&GlobalMid_Lock); - server->tcpStatus = CifsExiting; - spin_unlock(&GlobalMid_Lock); - wake_up_all(&server->response_q); - - /* check if we have blocked requests that need to free */ - spin_lock(&server->req_lock); - if (server->credits <= 0) - server->credits = 1; - spin_unlock(&server->req_lock); - /* - * Although there should not be any requests blocked on this queue it - * can not hurt to be paranoid and try to wake up requests that may - * haven been blocked when more than 50 at time were on the wire to the - * same server - they now will see the session is in exit state and get - * out of SendReceive. - */ - wake_up_all(&server->request_q); - /* give those requests time to exit */ - msleep(125); - - if (server->ssocket) { - sock_release(server->ssocket); - server->ssocket = NULL; - } - - if (!list_empty(&server->pending_mid_q)) { - struct list_head dispose_list; - struct mid_q_entry *mid_entry; - struct list_head *tmp, *tmp2; - - INIT_LIST_HEAD(&dispose_list); - spin_lock(&GlobalMid_Lock); - list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { - mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - cFYI(1, "Clearing mid 0x%llx", mid_entry->mid); - mid_entry->mid_state = MID_SHUTDOWN; - list_move(&mid_entry->qhead, &dispose_list); - } - spin_unlock(&GlobalMid_Lock); - - /* now walk dispose list and issue callbacks */ - list_for_each_safe(tmp, tmp2, &dispose_list) { - mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - cFYI(1, "Callback mid 0x%llx", mid_entry->mid); - list_del_init(&mid_entry->qhead); - mid_entry->callback(mid_entry); - } - /* 1/8th of sec is more than enough time for them to exit */ - msleep(125); - } - - if (!list_empty(&server->pending_mid_q)) { - /* - * mpx threads have not exited yet give them at least the smb - * send timeout time for long ops. - * - * Due to delays on oplock break requests, we need to wait at - * least 45 seconds before giving up on a request getting a - * response and going ahead and killing cifsd. - */ - cFYI(1, "Wait for exit from demultiplex thread"); - msleep(46000); - /* - * If threads still have not exited they are probably never - * coming home not much else we can do but free the memory. - */ - } - - kfree(server->hostname); - kfree(server->iov); - kfree(server); - - length = atomic_dec_return(&tcpSesAllocCount); - if (length > 0) - mempool_resize(cifs_req_poolp, length + cifs_min_rcv, - GFP_KERNEL); -} - -static int -standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) -{ - int length; - char *buf = server->smallbuf; - unsigned int pdu_length = get_rfc1002_length(buf); - - /* make sure this will fit in a large buffer */ - if (pdu_length > CIFSMaxBufSize + max_header_size() - 4) { - cERROR(1, "SMB response too long (%u bytes)", - pdu_length); - cifs_reconnect(server); - wake_up(&server->response_q); - return -EAGAIN; - } - - /* switch to large buffer if too big for a small one */ - if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { - server->large_buf = true; - memcpy(server->bigbuf, buf, server->total_read); - buf = server->bigbuf; - } - - /* now read the rest */ - length = cifs_read_from_socket(server, buf + header_size() - 1, - pdu_length - header_size() + 1 + 4); - if (length < 0) - return length; - server->total_read += length; - - dump_smb(buf, server->total_read); - - /* - * We know that we received enough to get to the MID as we - * checked the pdu_length earlier. Now check to see - * if the rest of the header is OK. We borrow the length - * var for the rest of the loop to avoid a new stack var. - * - * 48 bytes is enough to display the header and a little bit - * into the payload for debugging purposes. - */ - length = checkSMB(buf, server->total_read); - if (length != 0) - cifs_dump_mem("Bad SMB: ", buf, - min_t(unsigned int, server->total_read, 48)); - - if (!mid) - return length; - - handle_mid(mid, server, buf, length); - return 0; -} - -static int -cifs_demultiplex_thread(void *p) -{ - int length; - struct TCP_Server_Info *server = p; - unsigned int pdu_length; - char *buf = NULL; - struct task_struct *task_to_wake = NULL; - struct mid_q_entry *mid_entry; - - current->flags |= PF_MEMALLOC; - cFYI(1, "Demultiplex PID: %d", task_pid_nr(current)); - - length = atomic_inc_return(&tcpSesAllocCount); - if (length > 1) - mempool_resize(cifs_req_poolp, length + cifs_min_rcv, - GFP_KERNEL); - - set_freezable(); - while (server->tcpStatus != CifsExiting) { - if (try_to_freeze()) - continue; - - if (!allocate_buffers(server)) - continue; - - server->large_buf = false; - buf = server->smallbuf; - pdu_length = 4; /* enough to get RFC1001 header */ - - length = cifs_read_from_socket(server, buf, pdu_length); - if (length < 0) - continue; - server->total_read = length; - - /* - * The right amount was read from socket - 4 bytes, - * so we can now interpret the length field. - */ - pdu_length = get_rfc1002_length(buf); - - cFYI(1, "RFC1002 header 0x%x", pdu_length); - if (!is_smb_response(server, buf[0])) - continue; - - /* make sure we have enough to get to the MID */ - if (pdu_length < header_size() - 1 - 4) { - cERROR(1, "SMB response too short (%u bytes)", - pdu_length); - cifs_reconnect(server); - wake_up(&server->response_q); - continue; - } - - /* read down to the MID */ - length = cifs_read_from_socket(server, buf + 4, - header_size() - 1 - 4); - if (length < 0) - continue; - server->total_read += length; - - mid_entry = find_mid(server, buf); - - if (!mid_entry || !mid_entry->receive) - length = standard_receive3(server, mid_entry); - else - length = mid_entry->receive(server, mid_entry); - - if (length < 0) - continue; - - if (server->large_buf) - buf = server->bigbuf; - - server->lstrp = jiffies; - if (mid_entry != NULL) { - if (!mid_entry->multiRsp || mid_entry->multiEnd) - mid_entry->callback(mid_entry); - } else if (!is_valid_oplock_break(buf, server)) { - cERROR(1, "No task to wake, unknown frame received! " - "NumMids %d", atomic_read(&midCount)); - cifs_dump_mem("Received Data is: ", buf, header_size()); -#ifdef CONFIG_CIFS_DEBUG2 - cifs_dump_detail(buf); - cifs_dump_mids(server); -#endif /* CIFS_DEBUG2 */ - - } - } /* end while !EXITING */ - - /* buffer usually freed in free_mid - need to free it here on exit */ - cifs_buf_release(server->bigbuf); - if (server->smallbuf) /* no sense logging a debug message if NULL */ - cifs_small_buf_release(server->smallbuf); - - task_to_wake = xchg(&server->tsk, NULL); - clean_demultiplex_info(server); - - /* if server->tsk was NULL then wait for a signal before exiting */ - if (!task_to_wake) { - set_current_state(TASK_INTERRUPTIBLE); - while (!signal_pending(current)) { - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - } - set_current_state(TASK_RUNNING); - } - - module_put_and_exit(0); -} - -/* extract the host portion of the UNC string */ -static char * -extract_hostname(const char *unc) -{ - const char *src; - char *dst, *delim; - unsigned int len; - - /* skip double chars at beginning of string */ - /* BB: check validity of these bytes? */ - src = unc + 2; - - /* delimiter between hostname and sharename is always '\\' now */ - delim = strchr(src, '\\'); - if (!delim) - return ERR_PTR(-EINVAL); - - len = delim - src; - dst = kmalloc((len + 1), GFP_KERNEL); - if (dst == NULL) - return ERR_PTR(-ENOMEM); - - memcpy(dst, src, len); - dst[len] = '\0'; - - return dst; -} - -static int get_option_ul(substring_t args[], unsigned long *option) -{ - int rc; - char *string; - - string = match_strdup(args); - if (string == NULL) - return -ENOMEM; - rc = kstrtoul(string, 0, option); - kfree(string); - - return rc; -} - - -static int cifs_parse_security_flavors(char *value, - struct smb_vol *vol) -{ - - substring_t args[MAX_OPT_ARGS]; - - switch (match_token(value, cifs_secflavor_tokens, args)) { - case Opt_sec_krb5: - vol->secFlg |= CIFSSEC_MAY_KRB5; - break; - case Opt_sec_krb5i: - vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN; - break; - case Opt_sec_krb5p: - /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */ - cERROR(1, "Krb5 cifs privacy not supported"); - break; - case Opt_sec_ntlmssp: - vol->secFlg |= CIFSSEC_MAY_NTLMSSP; - break; - case Opt_sec_ntlmsspi: - vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN; - break; - case Opt_ntlm: - /* ntlm is default so can be turned off too */ - vol->secFlg |= CIFSSEC_MAY_NTLM; - break; - case Opt_sec_ntlmi: - vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN; - break; - case Opt_sec_nontlm: - vol->secFlg |= CIFSSEC_MAY_NTLMV2; - break; - case Opt_sec_ntlmv2i: - vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN; - break; -#ifdef CONFIG_CIFS_WEAK_PW_HASH - case Opt_sec_lanman: - vol->secFlg |= CIFSSEC_MAY_LANMAN; - break; -#endif - case Opt_sec_none: - vol->nullauth = 1; - break; - default: - cERROR(1, "bad security option: %s", value); - return 1; - } - - return 0; -} - -static int -cifs_parse_mount_options(const char *mountdata, const char *devname, - struct smb_vol *vol) -{ - char *data, *end; - char *mountdata_copy = NULL, *options; - unsigned int temp_len, i, j; - char separator[2]; - short int override_uid = -1; - short int override_gid = -1; - bool uid_specified = false; - bool gid_specified = false; - bool sloppy = false; - char *invalid = NULL; - char *nodename = utsname()->nodename; - char *string = NULL; - char *tmp_end, *value; - char delim; - - separator[0] = ','; - separator[1] = 0; - delim = separator[0]; - - /* - * does not have to be perfect mapping since field is - * informational, only used for servers that do not support - * port 445 and it can be overridden at mount time - */ - memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN); - for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++) - vol->source_rfc1001_name[i] = toupper(nodename[i]); - - vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0; - /* null target name indicates to use *SMBSERVR default called name - if we end up sending RFC1001 session initialize */ - vol->target_rfc1001_name[0] = 0; - vol->cred_uid = current_uid(); - vol->linux_uid = current_uid(); - vol->linux_gid = current_gid(); - - /* default to only allowing write access to owner of the mount */ - vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR; - - /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ - /* default is always to request posix paths. */ - vol->posix_paths = 1; - /* default to using server inode numbers where available */ - vol->server_ino = 1; - - vol->actimeo = CIFS_DEF_ACTIMEO; - - if (!mountdata) - goto cifs_parse_mount_err; - - mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL); - if (!mountdata_copy) - goto cifs_parse_mount_err; - - options = mountdata_copy; - end = options + strlen(options); - - if (strncmp(options, "sep=", 4) == 0) { - if (options[4] != 0) { - separator[0] = options[4]; - options += 5; - } else { - cFYI(1, "Null separator not allowed"); - } - } - vol->backupuid_specified = false; /* no backup intent for a user */ - vol->backupgid_specified = false; /* no backup intent for a group */ - - while ((data = strsep(&options, separator)) != NULL) { - substring_t args[MAX_OPT_ARGS]; - unsigned long option; - int token; - - if (!*data) - continue; - - token = match_token(data, cifs_mount_option_tokens, args); - - switch (token) { - - /* Ingnore the following */ - case Opt_ignore: - break; - - /* Boolean values */ - case Opt_user_xattr: - vol->no_xattr = 0; - break; - case Opt_nouser_xattr: - vol->no_xattr = 1; - break; - case Opt_forceuid: - override_uid = 1; - break; - case Opt_noforceuid: - override_uid = 0; - break; - case Opt_noblocksend: - vol->noblocksnd = 1; - break; - case Opt_noautotune: - vol->noautotune = 1; - break; - case Opt_hard: - vol->retry = 1; - break; - case Opt_soft: - vol->retry = 0; - break; - case Opt_perm: - vol->noperm = 0; - break; - case Opt_noperm: - vol->noperm = 1; - break; - case Opt_mapchars: - vol->remap = 1; - break; - case Opt_nomapchars: - vol->remap = 0; - break; - case Opt_sfu: - vol->sfu_emul = 1; - break; - case Opt_nosfu: - vol->sfu_emul = 0; - break; - case Opt_nodfs: - vol->nodfs = 1; - break; - case Opt_posixpaths: - vol->posix_paths = 1; - break; - case Opt_noposixpaths: - vol->posix_paths = 0; - break; - case Opt_nounix: - vol->no_linux_ext = 1; - break; - case Opt_nocase: - vol->nocase = 1; - break; - case Opt_brl: - vol->nobrl = 0; - break; - case Opt_nobrl: - vol->nobrl = 1; - /* - * turn off mandatory locking in mode - * if remote locking is turned off since the - * local vfs will do advisory - */ - if (vol->file_mode == - (S_IALLUGO & ~(S_ISUID | S_IXGRP))) - vol->file_mode = S_IALLUGO; - break; - case Opt_forcemandatorylock: - vol->mand_lock = 1; - break; - case Opt_setuids: - vol->setuids = 1; - break; - case Opt_nosetuids: - vol->setuids = 0; - break; - case Opt_dynperm: - vol->dynperm = true; - break; - case Opt_nodynperm: - vol->dynperm = false; - break; - case Opt_nohard: - vol->retry = 0; - break; - case Opt_nosoft: - vol->retry = 1; - break; - case Opt_nointr: - vol->intr = 0; - break; - case Opt_intr: - vol->intr = 1; - break; - case Opt_nostrictsync: - vol->nostrictsync = 1; - break; - case Opt_strictsync: - vol->nostrictsync = 0; - break; - case Opt_serverino: - vol->server_ino = 1; - break; - case Opt_noserverino: - vol->server_ino = 0; - break; - case Opt_rwpidforward: - vol->rwpidforward = 1; - break; - case Opt_cifsacl: - vol->cifs_acl = 1; - break; - case Opt_nocifsacl: - vol->cifs_acl = 0; - break; - case Opt_acl: - vol->no_psx_acl = 0; - break; - case Opt_noacl: - vol->no_psx_acl = 1; - break; - case Opt_locallease: - vol->local_lease = 1; - break; - case Opt_sign: - vol->secFlg |= CIFSSEC_MUST_SIGN; - break; - case Opt_seal: - /* we do not do the following in secFlags because seal - * is a per tree connection (mount) not a per socket - * or per-smb connection option in the protocol - * vol->secFlg |= CIFSSEC_MUST_SEAL; - */ - vol->seal = 1; - break; - case Opt_direct: - vol->direct_io = 1; - break; - case Opt_strictcache: - vol->strict_io = 1; - break; - case Opt_noac: - printk(KERN_WARNING "CIFS: Mount option noac not " - "supported. Instead set " - "/proc/fs/cifs/LookupCacheEnabled to 0\n"); - break; - case Opt_fsc: -#ifndef CONFIG_CIFS_FSCACHE - cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE " - "kernel config option set"); - goto cifs_parse_mount_err; -#endif - vol->fsc = true; - break; - case Opt_mfsymlinks: - vol->mfsymlinks = true; - break; - case Opt_multiuser: - vol->multiuser = true; - break; - case Opt_sloppy: - sloppy = true; - break; - - /* Numeric Values */ - case Opt_backupuid: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid backupuid value", - __func__); - goto cifs_parse_mount_err; - } - vol->backupuid = option; - vol->backupuid_specified = true; - break; - case Opt_backupgid: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid backupgid value", - __func__); - goto cifs_parse_mount_err; - } - vol->backupgid = option; - vol->backupgid_specified = true; - break; - case Opt_uid: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid uid value", - __func__); - goto cifs_parse_mount_err; - } - vol->linux_uid = option; - uid_specified = true; - break; - case Opt_cruid: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid cruid value", - __func__); - goto cifs_parse_mount_err; - } - vol->cred_uid = option; - break; - case Opt_gid: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid gid value", - __func__); - goto cifs_parse_mount_err; - } - vol->linux_gid = option; - gid_specified = true; - break; - case Opt_file_mode: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid file_mode value", - __func__); - goto cifs_parse_mount_err; - } - vol->file_mode = option; - break; - case Opt_dirmode: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid dir_mode value", - __func__); - goto cifs_parse_mount_err; - } - vol->dir_mode = option; - break; - case Opt_port: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid port value", - __func__); - goto cifs_parse_mount_err; - } - vol->port = option; - break; - case Opt_rsize: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid rsize value", - __func__); - goto cifs_parse_mount_err; - } - vol->rsize = option; - break; - case Opt_wsize: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid wsize value", - __func__); - goto cifs_parse_mount_err; - } - vol->wsize = option; - break; - case Opt_actimeo: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid actimeo value", - __func__); - goto cifs_parse_mount_err; - } - vol->actimeo = HZ * option; - if (vol->actimeo > CIFS_MAX_ACTIMEO) { - cERROR(1, "CIFS: attribute cache" - "timeout too large"); - goto cifs_parse_mount_err; - } - break; - - /* String Arguments */ - - case Opt_blank_user: - /* null user, ie. anonymous authentication */ - vol->nullauth = 1; - vol->username = NULL; - break; - case Opt_user: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (strnlen(string, MAX_USERNAME_SIZE) > - MAX_USERNAME_SIZE) { - printk(KERN_WARNING "CIFS: username too long\n"); - goto cifs_parse_mount_err; - } - vol->username = kstrdup(string, GFP_KERNEL); - if (!vol->username) { - printk(KERN_WARNING "CIFS: no memory " - "for username\n"); - goto cifs_parse_mount_err; - } - break; - case Opt_blank_pass: - vol->password = NULL; - break; - case Opt_pass: - /* passwords have to be handled differently - * to allow the character used for deliminator - * to be passed within them - */ - - /* Obtain the value string */ - value = strchr(data, '='); - value++; - - /* Set tmp_end to end of the string */ - tmp_end = (char *) value + strlen(value); - - /* Check if following character is the deliminator - * If yes, we have encountered a double deliminator - * reset the NULL character to the deliminator - */ - if (tmp_end < end && tmp_end[1] == delim) { - tmp_end[0] = delim; - - /* Keep iterating until we get to a single - * deliminator OR the end - */ - while ((tmp_end = strchr(tmp_end, delim)) - != NULL && (tmp_end[1] == delim)) { - tmp_end = (char *) &tmp_end[2]; - } - - /* Reset var options to point to next element */ - if (tmp_end) { - tmp_end[0] = '\0'; - options = (char *) &tmp_end[1]; - } else - /* Reached the end of the mount option - * string */ - options = end; - } - - /* Now build new password string */ - temp_len = strlen(value); - vol->password = kzalloc(temp_len+1, GFP_KERNEL); - if (vol->password == NULL) { - printk(KERN_WARNING "CIFS: no memory " - "for password\n"); - goto cifs_parse_mount_err; - } - - for (i = 0, j = 0; i < temp_len; i++, j++) { - vol->password[j] = value[i]; - if ((value[i] == delim) && - value[i+1] == delim) - /* skip the second deliminator */ - i++; - } - vol->password[j] = '\0'; - break; - case Opt_blank_ip: - vol->UNCip = NULL; - break; - case Opt_ip: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (strnlen(string, INET6_ADDRSTRLEN) > - INET6_ADDRSTRLEN) { - printk(KERN_WARNING "CIFS: ip address " - "too long\n"); - goto cifs_parse_mount_err; - } - vol->UNCip = kstrdup(string, GFP_KERNEL); - if (!vol->UNCip) { - printk(KERN_WARNING "CIFS: no memory " - "for UNC IP\n"); - goto cifs_parse_mount_err; - } - break; - case Opt_unc: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - temp_len = strnlen(string, 300); - if (temp_len == 300) { - printk(KERN_WARNING "CIFS: UNC name too long\n"); - goto cifs_parse_mount_err; - } - - vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); - if (vol->UNC == NULL) { - printk(KERN_WARNING "CIFS: no memory for UNC\n"); - goto cifs_parse_mount_err; - } - strcpy(vol->UNC, string); - - if (strncmp(string, "//", 2) == 0) { - vol->UNC[0] = '\\'; - vol->UNC[1] = '\\'; - } else if (strncmp(string, "\\\\", 2) != 0) { - printk(KERN_WARNING "CIFS: UNC Path does not " - "begin with // or \\\\\n"); - goto cifs_parse_mount_err; - } - - break; - case Opt_domain: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (strnlen(string, 256) == 256) { - printk(KERN_WARNING "CIFS: domain name too" - " long\n"); - goto cifs_parse_mount_err; - } - - vol->domainname = kstrdup(string, GFP_KERNEL); - if (!vol->domainname) { - printk(KERN_WARNING "CIFS: no memory " - "for domainname\n"); - goto cifs_parse_mount_err; - } - cFYI(1, "Domain name set"); - break; - case Opt_srcaddr: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (!cifs_convert_address( - (struct sockaddr *)&vol->srcaddr, - string, strlen(string))) { - printk(KERN_WARNING "CIFS: Could not parse" - " srcaddr: %s\n", string); - goto cifs_parse_mount_err; - } - break; - case Opt_prefixpath: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - temp_len = strnlen(string, 1024); - if (string[0] != '/') - temp_len++; /* missing leading slash */ - if (temp_len > 1024) { - printk(KERN_WARNING "CIFS: prefix too long\n"); - goto cifs_parse_mount_err; - } - - vol->prepath = kmalloc(temp_len+1, GFP_KERNEL); - if (vol->prepath == NULL) { - printk(KERN_WARNING "CIFS: no memory " - "for path prefix\n"); - goto cifs_parse_mount_err; - } - - if (string[0] != '/') { - vol->prepath[0] = '/'; - strcpy(vol->prepath+1, string); - } else - strcpy(vol->prepath, string); - - break; - case Opt_iocharset: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (strnlen(string, 1024) >= 65) { - printk(KERN_WARNING "CIFS: iocharset name " - "too long.\n"); - goto cifs_parse_mount_err; - } - - if (strnicmp(string, "default", 7) != 0) { - vol->iocharset = kstrdup(string, - GFP_KERNEL); - if (!vol->iocharset) { - printk(KERN_WARNING "CIFS: no memory" - "for charset\n"); - goto cifs_parse_mount_err; - } - } - /* if iocharset not set then load_nls_default - * is used by caller - */ - cFYI(1, "iocharset set to %s", string); - break; - case Opt_sockopt: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (strnicmp(string, "TCP_NODELAY", 11) == 0) - vol->sockopt_tcp_nodelay = 1; - break; - case Opt_netbiosname: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - memset(vol->source_rfc1001_name, 0x20, - RFC1001_NAME_LEN); - /* - * FIXME: are there cases in which a comma can - * be valid in workstation netbios name (and - * need special handling)? - */ - for (i = 0; i < RFC1001_NAME_LEN; i++) { - /* don't ucase netbiosname for user */ - if (string[i] == 0) - break; - vol->source_rfc1001_name[i] = string[i]; - } - /* The string has 16th byte zero still from - * set at top of the function - */ - if (i == RFC1001_NAME_LEN && string[i] != 0) - printk(KERN_WARNING "CIFS: netbiosname" - " longer than 15 truncated.\n"); - - break; - case Opt_servern: - /* servernetbiosname specified override *SMBSERVER */ - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - /* last byte, type, is 0x20 for servr type */ - memset(vol->target_rfc1001_name, 0x20, - RFC1001_NAME_LEN_WITH_NULL); - - /* BB are there cases in which a comma can be - valid in this workstation netbios name - (and need special handling)? */ - - /* user or mount helper must uppercase the - netbios name */ - for (i = 0; i < 15; i++) { - if (string[i] == 0) - break; - vol->target_rfc1001_name[i] = string[i]; - } - /* The string has 16th byte zero still from - set at top of the function */ - if (i == RFC1001_NAME_LEN && string[i] != 0) - printk(KERN_WARNING "CIFS: server net" - "biosname longer than 15 truncated.\n"); - break; - case Opt_ver: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (strnicmp(string, "cifs", 4) == 0 || - strnicmp(string, "1", 1) == 0) { - /* This is the default */ - break; - } - /* For all other value, error */ - printk(KERN_WARNING "CIFS: Invalid version" - " specified\n"); - goto cifs_parse_mount_err; - case Opt_sec: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (cifs_parse_security_flavors(string, vol) != 0) - goto cifs_parse_mount_err; - break; - default: - /* - * An option we don't recognize. Save it off for later - * if we haven't already found one - */ - if (!invalid) - invalid = data; - break; - } - /* Free up any allocated string */ - kfree(string); - string = NULL; - } - - if (!sloppy && invalid) { - printk(KERN_ERR "CIFS: Unknown mount option \"%s\"\n", invalid); - goto cifs_parse_mount_err; - } - -#ifndef CONFIG_KEYS - /* Muliuser mounts require CONFIG_KEYS support */ - if (vol->multiuser) { - cERROR(1, "Multiuser mounts require kernels with " - "CONFIG_KEYS enabled."); - goto cifs_parse_mount_err; - } -#endif - - if (vol->UNCip == NULL) - vol->UNCip = &vol->UNC[2]; - - if (uid_specified) - vol->override_uid = override_uid; - else if (override_uid == 1) - printk(KERN_NOTICE "CIFS: ignoring forceuid mount option " - "specified with no uid= option.\n"); - - if (gid_specified) - vol->override_gid = override_gid; - else if (override_gid == 1) - printk(KERN_NOTICE "CIFS: ignoring forcegid mount option " - "specified with no gid= option.\n"); - - kfree(mountdata_copy); - return 0; - -out_nomem: - printk(KERN_WARNING "Could not allocate temporary buffer\n"); -cifs_parse_mount_err: - kfree(string); - kfree(mountdata_copy); - return 1; -} - -/** Returns true if srcaddr isn't specified and rhs isn't - * specified, or if srcaddr is specified and - * matches the IP address of the rhs argument. - */ -static bool -srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs) -{ - switch (srcaddr->sa_family) { - case AF_UNSPEC: - return (rhs->sa_family == AF_UNSPEC); - case AF_INET: { - struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr; - struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs; - return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr); - } - case AF_INET6: { - struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr; - struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs; - return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr); - } - default: - WARN_ON(1); - return false; /* don't expect to be here */ - } -} - -/* - * If no port is specified in addr structure, we try to match with 445 port - * and if it fails - with 139 ports. It should be called only if address - * families of server and addr are equal. - */ -static bool -match_port(struct TCP_Server_Info *server, struct sockaddr *addr) -{ - __be16 port, *sport; - - switch (addr->sa_family) { - case AF_INET: - sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port; - port = ((struct sockaddr_in *) addr)->sin_port; - break; - case AF_INET6: - sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port; - port = ((struct sockaddr_in6 *) addr)->sin6_port; - break; - default: - WARN_ON(1); - return false; - } - - if (!port) { - port = htons(CIFS_PORT); - if (port == *sport) - return true; - - port = htons(RFC1001_PORT); - } - - return port == *sport; -} - -static bool -match_address(struct TCP_Server_Info *server, struct sockaddr *addr, - struct sockaddr *srcaddr) -{ - switch (addr->sa_family) { - case AF_INET: { - struct sockaddr_in *addr4 = (struct sockaddr_in *)addr; - struct sockaddr_in *srv_addr4 = - (struct sockaddr_in *)&server->dstaddr; - - if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr) - return false; - break; - } - case AF_INET6: { - struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; - struct sockaddr_in6 *srv_addr6 = - (struct sockaddr_in6 *)&server->dstaddr; - - if (!ipv6_addr_equal(&addr6->sin6_addr, - &srv_addr6->sin6_addr)) - return false; - if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id) - return false; - break; - } - default: - WARN_ON(1); - return false; /* don't expect to be here */ - } - - if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr)) - return false; - - return true; -} - -static bool -match_security(struct TCP_Server_Info *server, struct smb_vol *vol) -{ - unsigned int secFlags; - - if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL))) - secFlags = vol->secFlg; - else - secFlags = global_secflags | vol->secFlg; - - switch (server->secType) { - case LANMAN: - if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT))) - return false; - break; - case NTLMv2: - if (!(secFlags & CIFSSEC_MAY_NTLMV2)) - return false; - break; - case NTLM: - if (!(secFlags & CIFSSEC_MAY_NTLM)) - return false; - break; - case Kerberos: - if (!(secFlags & CIFSSEC_MAY_KRB5)) - return false; - break; - case RawNTLMSSP: - if (!(secFlags & CIFSSEC_MAY_NTLMSSP)) - return false; - break; - default: - /* shouldn't happen */ - return false; - } - - /* now check if signing mode is acceptable */ - if ((secFlags & CIFSSEC_MAY_SIGN) == 0 && - (server->sec_mode & SECMODE_SIGN_REQUIRED)) - return false; - else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) && - (server->sec_mode & - (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0) - return false; - - return true; -} - -static int match_server(struct TCP_Server_Info *server, struct sockaddr *addr, - struct smb_vol *vol) -{ - if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns)) - return 0; - - if (!match_address(server, addr, - (struct sockaddr *)&vol->srcaddr)) - return 0; - - if (!match_port(server, addr)) - return 0; - - if (!match_security(server, vol)) - return 0; - - return 1; -} - -static struct TCP_Server_Info * -cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol) -{ - struct TCP_Server_Info *server; - - spin_lock(&cifs_tcp_ses_lock); - list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { - if (!match_server(server, addr, vol)) - continue; - - ++server->srv_count; - spin_unlock(&cifs_tcp_ses_lock); - cFYI(1, "Existing tcp session with server found"); - return server; - } - spin_unlock(&cifs_tcp_ses_lock); - return NULL; -} - -static void -cifs_put_tcp_session(struct TCP_Server_Info *server) -{ - struct task_struct *task; - - spin_lock(&cifs_tcp_ses_lock); - if (--server->srv_count > 0) { - spin_unlock(&cifs_tcp_ses_lock); - return; - } - - put_net(cifs_net_ns(server)); - - list_del_init(&server->tcp_ses_list); - spin_unlock(&cifs_tcp_ses_lock); - - cancel_delayed_work_sync(&server->echo); - - spin_lock(&GlobalMid_Lock); - server->tcpStatus = CifsExiting; - spin_unlock(&GlobalMid_Lock); - - cifs_crypto_shash_release(server); - cifs_fscache_release_client_cookie(server); - - kfree(server->session_key.response); - server->session_key.response = NULL; - server->session_key.len = 0; - - task = xchg(&server->tsk, NULL); - if (task) - force_sig(SIGKILL, task); -} - -static struct TCP_Server_Info * -cifs_get_tcp_session(struct smb_vol *volume_info) -{ - struct TCP_Server_Info *tcp_ses = NULL; - struct sockaddr_storage addr; - struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr; - struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr; - int rc; - - memset(&addr, 0, sizeof(struct sockaddr_storage)); - - cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip); - - if (volume_info->UNCip && volume_info->UNC) { - rc = cifs_fill_sockaddr((struct sockaddr *)&addr, - volume_info->UNCip, - strlen(volume_info->UNCip), - volume_info->port); - if (!rc) { - /* we failed translating address */ - rc = -EINVAL; - goto out_err; - } - } else if (volume_info->UNCip) { - /* BB using ip addr as tcp_ses name to connect to the - DFS root below */ - cERROR(1, "Connecting to DFS root not implemented yet"); - rc = -EINVAL; - goto out_err; - } else /* which tcp_sess DFS root would we conect to */ { - cERROR(1, "CIFS mount error: No UNC path (e.g. -o " - "unc=//192.168.1.100/public) specified"); - rc = -EINVAL; - goto out_err; - } - - /* see if we already have a matching tcp_ses */ - tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info); - if (tcp_ses) - return tcp_ses; - - tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL); - if (!tcp_ses) { - rc = -ENOMEM; - goto out_err; - } - - rc = cifs_crypto_shash_allocate(tcp_ses); - if (rc) { - cERROR(1, "could not setup hash structures rc %d", rc); - goto out_err; - } - - cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); - tcp_ses->hostname = extract_hostname(volume_info->UNC); - if (IS_ERR(tcp_ses->hostname)) { - rc = PTR_ERR(tcp_ses->hostname); - goto out_err_crypto_release; - } - - tcp_ses->noblocksnd = volume_info->noblocksnd; - tcp_ses->noautotune = volume_info->noautotune; - tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay; - tcp_ses->in_flight = 0; - tcp_ses->credits = 1; - init_waitqueue_head(&tcp_ses->response_q); - init_waitqueue_head(&tcp_ses->request_q); - INIT_LIST_HEAD(&tcp_ses->pending_mid_q); - mutex_init(&tcp_ses->srv_mutex); - memcpy(tcp_ses->workstation_RFC1001_name, - volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); - memcpy(tcp_ses->server_RFC1001_name, - volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); - tcp_ses->session_estab = false; - tcp_ses->sequence_number = 0; - tcp_ses->lstrp = jiffies; - spin_lock_init(&tcp_ses->req_lock); - INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); - INIT_LIST_HEAD(&tcp_ses->smb_ses_list); - INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request); - - /* - * at this point we are the only ones with the pointer - * to the struct since the kernel thread not created yet - * no need to spinlock this init of tcpStatus or srv_count - */ - tcp_ses->tcpStatus = CifsNew; - memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr, - sizeof(tcp_ses->srcaddr)); - ++tcp_ses->srv_count; - - if (addr.ss_family == AF_INET6) { - cFYI(1, "attempting ipv6 connect"); - /* BB should we allow ipv6 on port 139? */ - /* other OS never observed in Wild doing 139 with v6 */ - memcpy(&tcp_ses->dstaddr, sin_server6, - sizeof(struct sockaddr_in6)); - } else - memcpy(&tcp_ses->dstaddr, sin_server, - sizeof(struct sockaddr_in)); - - rc = ip_connect(tcp_ses); - if (rc < 0) { - cERROR(1, "Error connecting to socket. Aborting operation"); - goto out_err_crypto_release; - } - - /* - * since we're in a cifs function already, we know that - * this will succeed. No need for try_module_get(). - */ - __module_get(THIS_MODULE); - tcp_ses->tsk = kthread_run(cifs_demultiplex_thread, - tcp_ses, "cifsd"); - if (IS_ERR(tcp_ses->tsk)) { - rc = PTR_ERR(tcp_ses->tsk); - cERROR(1, "error %d create cifsd thread", rc); - module_put(THIS_MODULE); - goto out_err_crypto_release; - } - tcp_ses->tcpStatus = CifsNeedNegotiate; - - /* thread spawned, put it on the list */ - spin_lock(&cifs_tcp_ses_lock); - list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); - spin_unlock(&cifs_tcp_ses_lock); - - cifs_fscache_get_client_cookie(tcp_ses); - - /* queue echo request delayed work */ - queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL); - - return tcp_ses; - -out_err_crypto_release: - cifs_crypto_shash_release(tcp_ses); - - put_net(cifs_net_ns(tcp_ses)); - -out_err: - if (tcp_ses) { - if (!IS_ERR(tcp_ses->hostname)) - kfree(tcp_ses->hostname); - if (tcp_ses->ssocket) - sock_release(tcp_ses->ssocket); - kfree(tcp_ses); - } - return ERR_PTR(rc); -} - -static int match_session(struct cifs_ses *ses, struct smb_vol *vol) -{ - switch (ses->server->secType) { - case Kerberos: - if (vol->cred_uid != ses->cred_uid) - return 0; - break; - default: - /* NULL username means anonymous session */ - if (ses->user_name == NULL) { - if (!vol->nullauth) - return 0; - break; - } - - /* anything else takes username/password */ - if (strncmp(ses->user_name, - vol->username ? vol->username : "", - MAX_USERNAME_SIZE)) - return 0; - if (strlen(vol->username) != 0 && - ses->password != NULL && - strncmp(ses->password, - vol->password ? vol->password : "", - MAX_PASSWORD_SIZE)) - return 0; - } - return 1; -} - -static struct cifs_ses * -cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol) -{ - struct cifs_ses *ses; - - spin_lock(&cifs_tcp_ses_lock); - list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { - if (!match_session(ses, vol)) - continue; - ++ses->ses_count; - spin_unlock(&cifs_tcp_ses_lock); - return ses; - } - spin_unlock(&cifs_tcp_ses_lock); - return NULL; -} - -static void -cifs_put_smb_ses(struct cifs_ses *ses) -{ - int xid; - struct TCP_Server_Info *server = ses->server; - - cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count); - spin_lock(&cifs_tcp_ses_lock); - if (--ses->ses_count > 0) { - spin_unlock(&cifs_tcp_ses_lock); - return; - } - - list_del_init(&ses->smb_ses_list); - spin_unlock(&cifs_tcp_ses_lock); - - if (ses->status == CifsGood) { - xid = GetXid(); - CIFSSMBLogoff(xid, ses); - _FreeXid(xid); - } - sesInfoFree(ses); - cifs_put_tcp_session(server); -} - -#ifdef CONFIG_KEYS - -/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */ -#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1) - -/* Populate username and pw fields from keyring if possible */ -static int -cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) -{ - int rc = 0; - char *desc, *delim, *payload; - ssize_t len; - struct key *key; - struct TCP_Server_Info *server = ses->server; - struct sockaddr_in *sa; - struct sockaddr_in6 *sa6; - struct user_key_payload *upayload; - - desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL); - if (!desc) - return -ENOMEM; - - /* try to find an address key first */ - switch (server->dstaddr.ss_family) { - case AF_INET: - sa = (struct sockaddr_in *)&server->dstaddr; - sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr); - break; - case AF_INET6: - sa6 = (struct sockaddr_in6 *)&server->dstaddr; - sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr); - break; - default: - cFYI(1, "Bad ss_family (%hu)", server->dstaddr.ss_family); - rc = -EINVAL; - goto out_err; - } - - cFYI(1, "%s: desc=%s", __func__, desc); - key = request_key(&key_type_logon, desc, ""); - if (IS_ERR(key)) { - if (!ses->domainName) { - cFYI(1, "domainName is NULL"); - rc = PTR_ERR(key); - goto out_err; - } - - /* didn't work, try to find a domain key */ - sprintf(desc, "cifs:d:%s", ses->domainName); - cFYI(1, "%s: desc=%s", __func__, desc); - key = request_key(&key_type_logon, desc, ""); - if (IS_ERR(key)) { - rc = PTR_ERR(key); - goto out_err; - } - } - - down_read(&key->sem); - upayload = key->payload.data; - if (IS_ERR_OR_NULL(upayload)) { - rc = upayload ? PTR_ERR(upayload) : -EINVAL; - goto out_key_put; - } - - /* find first : in payload */ - payload = (char *)upayload->data; - delim = strnchr(payload, upayload->datalen, ':'); - cFYI(1, "payload=%s", payload); - if (!delim) { - cFYI(1, "Unable to find ':' in payload (datalen=%d)", - upayload->datalen); - rc = -EINVAL; - goto out_key_put; - } - - len = delim - payload; - if (len > MAX_USERNAME_SIZE || len <= 0) { - cFYI(1, "Bad value from username search (len=%zd)", len); - rc = -EINVAL; - goto out_key_put; - } - - vol->username = kstrndup(payload, len, GFP_KERNEL); - if (!vol->username) { - cFYI(1, "Unable to allocate %zd bytes for username", len); - rc = -ENOMEM; - goto out_key_put; - } - cFYI(1, "%s: username=%s", __func__, vol->username); - - len = key->datalen - (len + 1); - if (len > MAX_PASSWORD_SIZE || len <= 0) { - cFYI(1, "Bad len for password search (len=%zd)", len); - rc = -EINVAL; - kfree(vol->username); - vol->username = NULL; - goto out_key_put; - } - - ++delim; - vol->password = kstrndup(delim, len, GFP_KERNEL); - if (!vol->password) { - cFYI(1, "Unable to allocate %zd bytes for password", len); - rc = -ENOMEM; - kfree(vol->username); - vol->username = NULL; - goto out_key_put; - } - -out_key_put: - up_read(&key->sem); - key_put(key); -out_err: - kfree(desc); - cFYI(1, "%s: returning %d", __func__, rc); - return rc; -} -#else /* ! CONFIG_KEYS */ -static inline int -cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)), - struct cifs_ses *ses __attribute__((unused))) -{ - return -ENOSYS; -} -#endif /* CONFIG_KEYS */ - -static bool warned_on_ntlm; /* globals init to false automatically */ - -static struct cifs_ses * -cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) -{ - int rc = -ENOMEM, xid; - struct cifs_ses *ses; - struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr; - struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr; - - xid = GetXid(); - - ses = cifs_find_smb_ses(server, volume_info); - if (ses) { - cFYI(1, "Existing smb sess found (status=%d)", ses->status); - - mutex_lock(&ses->session_mutex); - rc = cifs_negotiate_protocol(xid, ses); - if (rc) { - mutex_unlock(&ses->session_mutex); - /* problem -- put our ses reference */ - cifs_put_smb_ses(ses); - FreeXid(xid); - return ERR_PTR(rc); - } - if (ses->need_reconnect) { - cFYI(1, "Session needs reconnect"); - rc = cifs_setup_session(xid, ses, - volume_info->local_nls); - if (rc) { - mutex_unlock(&ses->session_mutex); - /* problem -- put our reference */ - cifs_put_smb_ses(ses); - FreeXid(xid); - return ERR_PTR(rc); - } - } - mutex_unlock(&ses->session_mutex); - - /* existing SMB ses has a server reference already */ - cifs_put_tcp_session(server); - FreeXid(xid); - return ses; - } - - cFYI(1, "Existing smb sess not found"); - ses = sesInfoAlloc(); - if (ses == NULL) - goto get_ses_fail; - - /* new SMB session uses our server ref */ - ses->server = server; - if (server->dstaddr.ss_family == AF_INET6) - sprintf(ses->serverName, "%pI6", &addr6->sin6_addr); - else - sprintf(ses->serverName, "%pI4", &addr->sin_addr); - - if (volume_info->username) { - ses->user_name = kstrdup(volume_info->username, GFP_KERNEL); - if (!ses->user_name) - goto get_ses_fail; - } - - /* volume_info->password freed at unmount */ - if (volume_info->password) { - ses->password = kstrdup(volume_info->password, GFP_KERNEL); - if (!ses->password) - goto get_ses_fail; - } - if (volume_info->domainname) { - ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL); - if (!ses->domainName) - goto get_ses_fail; - } - ses->cred_uid = volume_info->cred_uid; - ses->linux_uid = volume_info->linux_uid; - - /* ntlmv2 is much stronger than ntlm security, and has been broadly - supported for many years, time to update default security mechanism */ - if ((volume_info->secFlg == 0) && warned_on_ntlm == false) { - warned_on_ntlm = true; - cERROR(1, "default security mechanism requested. The default " - "security mechanism will be upgraded from ntlm to " - "ntlmv2 in kernel release 3.3"); - } - ses->overrideSecFlg = volume_info->secFlg; - - mutex_lock(&ses->session_mutex); - rc = cifs_negotiate_protocol(xid, ses); - if (!rc) - rc = cifs_setup_session(xid, ses, volume_info->local_nls); - mutex_unlock(&ses->session_mutex); - if (rc) - goto get_ses_fail; - - /* success, put it on the list */ - spin_lock(&cifs_tcp_ses_lock); - list_add(&ses->smb_ses_list, &server->smb_ses_list); - spin_unlock(&cifs_tcp_ses_lock); - - FreeXid(xid); - return ses; - -get_ses_fail: - sesInfoFree(ses); - FreeXid(xid); - return ERR_PTR(rc); -} - -static int match_tcon(struct cifs_tcon *tcon, const char *unc) -{ - if (tcon->tidStatus == CifsExiting) - return 0; - if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE)) - return 0; - return 1; -} - -static struct cifs_tcon * -cifs_find_tcon(struct cifs_ses *ses, const char *unc) -{ - struct list_head *tmp; - struct cifs_tcon *tcon; - - spin_lock(&cifs_tcp_ses_lock); - list_for_each(tmp, &ses->tcon_list) { - tcon = list_entry(tmp, struct cifs_tcon, tcon_list); - if (!match_tcon(tcon, unc)) - continue; - ++tcon->tc_count; - spin_unlock(&cifs_tcp_ses_lock); - return tcon; - } - spin_unlock(&cifs_tcp_ses_lock); - return NULL; -} - -static void -cifs_put_tcon(struct cifs_tcon *tcon) -{ - int xid; - struct cifs_ses *ses = tcon->ses; - - cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count); - spin_lock(&cifs_tcp_ses_lock); - if (--tcon->tc_count > 0) { - spin_unlock(&cifs_tcp_ses_lock); - return; - } - - list_del_init(&tcon->tcon_list); - spin_unlock(&cifs_tcp_ses_lock); - - xid = GetXid(); - CIFSSMBTDis(xid, tcon); - _FreeXid(xid); - - cifs_fscache_release_super_cookie(tcon); - tconInfoFree(tcon); - cifs_put_smb_ses(ses); -} - -static struct cifs_tcon * -cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) -{ - int rc, xid; - struct cifs_tcon *tcon; - - tcon = cifs_find_tcon(ses, volume_info->UNC); - if (tcon) { - cFYI(1, "Found match on UNC path"); - /* existing tcon already has a reference */ - cifs_put_smb_ses(ses); - if (tcon->seal != volume_info->seal) - cERROR(1, "transport encryption setting " - "conflicts with existing tid"); - return tcon; - } - - tcon = tconInfoAlloc(); - if (tcon == NULL) { - rc = -ENOMEM; - goto out_fail; - } - - tcon->ses = ses; - if (volume_info->password) { - tcon->password = kstrdup(volume_info->password, GFP_KERNEL); - if (!tcon->password) { - rc = -ENOMEM; - goto out_fail; - } - } - - if (strchr(volume_info->UNC + 3, '\\') == NULL - && strchr(volume_info->UNC + 3, '/') == NULL) { - cERROR(1, "Missing share name"); - rc = -ENODEV; - goto out_fail; - } - - /* BB Do we need to wrap session_mutex around - * this TCon call and Unix SetFS as - * we do on SessSetup and reconnect? */ - xid = GetXid(); - rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls); - FreeXid(xid); - cFYI(1, "CIFS Tcon rc = %d", rc); - if (rc) - goto out_fail; - - if (volume_info->nodfs) { - tcon->Flags &= ~SMB_SHARE_IS_IN_DFS; - cFYI(1, "DFS disabled (%d)", tcon->Flags); - } - tcon->seal = volume_info->seal; - /* we can have only one retry value for a connection - to a share so for resources mounted more than once - to the same server share the last value passed in - for the retry flag is used */ - tcon->retry = volume_info->retry; - tcon->nocase = volume_info->nocase; - tcon->local_lease = volume_info->local_lease; - - spin_lock(&cifs_tcp_ses_lock); - list_add(&tcon->tcon_list, &ses->tcon_list); - spin_unlock(&cifs_tcp_ses_lock); - - cifs_fscache_get_super_cookie(tcon); - - return tcon; - -out_fail: - tconInfoFree(tcon); - return ERR_PTR(rc); -} - -void -cifs_put_tlink(struct tcon_link *tlink) -{ - if (!tlink || IS_ERR(tlink)) - return; - - if (!atomic_dec_and_test(&tlink->tl_count) || - test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) { - tlink->tl_time = jiffies; - return; - } - - if (!IS_ERR(tlink_tcon(tlink))) - cifs_put_tcon(tlink_tcon(tlink)); - kfree(tlink); - return; -} - -static inline struct tcon_link * -cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb) -{ - return cifs_sb->master_tlink; -} - -static int -compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data) -{ - struct cifs_sb_info *old = CIFS_SB(sb); - struct cifs_sb_info *new = mnt_data->cifs_sb; - - if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK)) - return 0; - - if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) != - (new->mnt_cifs_flags & CIFS_MOUNT_MASK)) - return 0; - - /* - * We want to share sb only if we don't specify an r/wsize or - * specified r/wsize is greater than or equal to existing one. - */ - if (new->wsize && new->wsize < old->wsize) - return 0; - - if (new->rsize && new->rsize < old->rsize) - return 0; - - if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid) - return 0; - - if (old->mnt_file_mode != new->mnt_file_mode || - old->mnt_dir_mode != new->mnt_dir_mode) - return 0; - - if (strcmp(old->local_nls->charset, new->local_nls->charset)) - return 0; - - if (old->actimeo != new->actimeo) - return 0; - - return 1; -} - -int -cifs_match_super(struct super_block *sb, void *data) -{ - struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data; - struct smb_vol *volume_info; - struct cifs_sb_info *cifs_sb; - struct TCP_Server_Info *tcp_srv; - struct cifs_ses *ses; - struct cifs_tcon *tcon; - struct tcon_link *tlink; - struct sockaddr_storage addr; - int rc = 0; - - memset(&addr, 0, sizeof(struct sockaddr_storage)); - - spin_lock(&cifs_tcp_ses_lock); - cifs_sb = CIFS_SB(sb); - tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb)); - if (IS_ERR(tlink)) { - spin_unlock(&cifs_tcp_ses_lock); - return rc; - } - tcon = tlink_tcon(tlink); - ses = tcon->ses; - tcp_srv = ses->server; - - volume_info = mnt_data->vol; - - if (!volume_info->UNCip || !volume_info->UNC) - goto out; - - rc = cifs_fill_sockaddr((struct sockaddr *)&addr, - volume_info->UNCip, - strlen(volume_info->UNCip), - volume_info->port); - if (!rc) - goto out; - - if (!match_server(tcp_srv, (struct sockaddr *)&addr, volume_info) || - !match_session(ses, volume_info) || - !match_tcon(tcon, volume_info->UNC)) { - rc = 0; - goto out; - } - - rc = compare_mount_options(sb, mnt_data); -out: - spin_unlock(&cifs_tcp_ses_lock); - cifs_put_tlink(tlink); - return rc; -} - -int -get_dfs_path(int xid, struct cifs_ses *pSesInfo, const char *old_path, - const struct nls_table *nls_codepage, unsigned int *pnum_referrals, - struct dfs_info3_param **preferrals, int remap) -{ - char *temp_unc; - int rc = 0; - - *pnum_referrals = 0; - *preferrals = NULL; - - if (pSesInfo->ipc_tid == 0) { - temp_unc = kmalloc(2 /* for slashes */ + - strnlen(pSesInfo->serverName, - SERVER_NAME_LEN_WITH_NULL * 2) - + 1 + 4 /* slash IPC$ */ + 2, - GFP_KERNEL); - if (temp_unc == NULL) - return -ENOMEM; - temp_unc[0] = '\\'; - temp_unc[1] = '\\'; - strcpy(temp_unc + 2, pSesInfo->serverName); - strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$"); - rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage); - cFYI(1, "CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid); - kfree(temp_unc); - } - if (rc == 0) - rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals, - pnum_referrals, nls_codepage, remap); - /* BB map targetUNCs to dfs_info3 structures, here or - in CIFSGetDFSRefer BB */ - - return rc; -} - -#ifdef CONFIG_DEBUG_LOCK_ALLOC -static struct lock_class_key cifs_key[2]; -static struct lock_class_key cifs_slock_key[2]; - -static inline void -cifs_reclassify_socket4(struct socket *sock) -{ - struct sock *sk = sock->sk; - BUG_ON(sock_owned_by_user(sk)); - sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS", - &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]); -} - -static inline void -cifs_reclassify_socket6(struct socket *sock) -{ - struct sock *sk = sock->sk; - BUG_ON(sock_owned_by_user(sk)); - sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS", - &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]); -} -#else -static inline void -cifs_reclassify_socket4(struct socket *sock) -{ -} - -static inline void -cifs_reclassify_socket6(struct socket *sock) -{ -} -#endif - -/* See RFC1001 section 14 on representation of Netbios names */ -static void rfc1002mangle(char *target, char *source, unsigned int length) -{ - unsigned int i, j; - - for (i = 0, j = 0; i < (length); i++) { - /* mask a nibble at a time and encode */ - target[j] = 'A' + (0x0F & (source[i] >> 4)); - target[j+1] = 'A' + (0x0F & source[i]); - j += 2; - } - -} - -static int -bind_socket(struct TCP_Server_Info *server) -{ - int rc = 0; - if (server->srcaddr.ss_family != AF_UNSPEC) { - /* Bind to the specified local IP address */ - struct socket *socket = server->ssocket; - rc = socket->ops->bind(socket, - (struct sockaddr *) &server->srcaddr, - sizeof(server->srcaddr)); - if (rc < 0) { - struct sockaddr_in *saddr4; - struct sockaddr_in6 *saddr6; - saddr4 = (struct sockaddr_in *)&server->srcaddr; - saddr6 = (struct sockaddr_in6 *)&server->srcaddr; - if (saddr6->sin6_family == AF_INET6) - cERROR(1, "cifs: " - "Failed to bind to: %pI6c, error: %d\n", - &saddr6->sin6_addr, rc); - else - cERROR(1, "cifs: " - "Failed to bind to: %pI4, error: %d\n", - &saddr4->sin_addr.s_addr, rc); - } - } - return rc; -} - -static int -ip_rfc1001_connect(struct TCP_Server_Info *server) -{ - int rc = 0; - /* - * some servers require RFC1001 sessinit before sending - * negprot - BB check reconnection in case where second - * sessinit is sent but no second negprot - */ - struct rfc1002_session_packet *ses_init_buf; - struct smb_hdr *smb_buf; - ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), - GFP_KERNEL); - if (ses_init_buf) { - ses_init_buf->trailer.session_req.called_len = 32; - - if (server->server_RFC1001_name && - server->server_RFC1001_name[0] != 0) - rfc1002mangle(ses_init_buf->trailer. - session_req.called_name, - server->server_RFC1001_name, - RFC1001_NAME_LEN_WITH_NULL); - else - rfc1002mangle(ses_init_buf->trailer. - session_req.called_name, - DEFAULT_CIFS_CALLED_NAME, - RFC1001_NAME_LEN_WITH_NULL); - - ses_init_buf->trailer.session_req.calling_len = 32; - - /* - * calling name ends in null (byte 16) from old smb - * convention. - */ - if (server->workstation_RFC1001_name && - server->workstation_RFC1001_name[0] != 0) - rfc1002mangle(ses_init_buf->trailer. - session_req.calling_name, - server->workstation_RFC1001_name, - RFC1001_NAME_LEN_WITH_NULL); - else - rfc1002mangle(ses_init_buf->trailer. - session_req.calling_name, - "LINUX_CIFS_CLNT", - RFC1001_NAME_LEN_WITH_NULL); - - ses_init_buf->trailer.session_req.scope1 = 0; - ses_init_buf->trailer.session_req.scope2 = 0; - smb_buf = (struct smb_hdr *)ses_init_buf; - - /* sizeof RFC1002_SESSION_REQUEST with no scope */ - smb_buf->smb_buf_length = cpu_to_be32(0x81000044); - rc = smb_send(server, smb_buf, 0x44); - kfree(ses_init_buf); - /* - * RFC1001 layer in at least one server - * requires very short break before negprot - * presumably because not expecting negprot - * to follow so fast. This is a simple - * solution that works without - * complicating the code and causes no - * significant slowing down on mount - * for everyone else - */ - usleep_range(1000, 2000); - } - /* - * else the negprot may still work without this - * even though malloc failed - */ - - return rc; -} - -static int -generic_ip_connect(struct TCP_Server_Info *server) -{ - int rc = 0; - __be16 sport; - int slen, sfamily; - struct socket *socket = server->ssocket; - struct sockaddr *saddr; - - saddr = (struct sockaddr *) &server->dstaddr; - - if (server->dstaddr.ss_family == AF_INET6) { - sport = ((struct sockaddr_in6 *) saddr)->sin6_port; - slen = sizeof(struct sockaddr_in6); - sfamily = AF_INET6; - } else { - sport = ((struct sockaddr_in *) saddr)->sin_port; - slen = sizeof(struct sockaddr_in); - sfamily = AF_INET; - } - - if (socket == NULL) { - rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM, - IPPROTO_TCP, &socket, 1); - if (rc < 0) { - cERROR(1, "Error %d creating socket", rc); - server->ssocket = NULL; - return rc; - } - - /* BB other socket options to set KEEPALIVE, NODELAY? */ - cFYI(1, "Socket created"); - server->ssocket = socket; - socket->sk->sk_allocation = GFP_NOFS; - if (sfamily == AF_INET6) - cifs_reclassify_socket6(socket); - else - cifs_reclassify_socket4(socket); - } - - rc = bind_socket(server); - if (rc < 0) - return rc; - - /* - * Eventually check for other socket options to change from - * the default. sock_setsockopt not used because it expects - * user space buffer - */ - socket->sk->sk_rcvtimeo = 7 * HZ; - socket->sk->sk_sndtimeo = 5 * HZ; - - /* make the bufsizes depend on wsize/rsize and max requests */ - if (server->noautotune) { - if (socket->sk->sk_sndbuf < (200 * 1024)) - socket->sk->sk_sndbuf = 200 * 1024; - if (socket->sk->sk_rcvbuf < (140 * 1024)) - socket->sk->sk_rcvbuf = 140 * 1024; - } - - if (server->tcp_nodelay) { - int val = 1; - rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY, - (char *)&val, sizeof(val)); - if (rc) - cFYI(1, "set TCP_NODELAY socket option error %d", rc); - } - - cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx", - socket->sk->sk_sndbuf, - socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); - - rc = socket->ops->connect(socket, saddr, slen, 0); - if (rc < 0) { - cFYI(1, "Error %d connecting to server", rc); - sock_release(socket); - server->ssocket = NULL; - return rc; - } - - if (sport == htons(RFC1001_PORT)) - rc = ip_rfc1001_connect(server); - - return rc; -} - -static int -ip_connect(struct TCP_Server_Info *server) -{ - __be16 *sport; - struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr; - struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr; - - if (server->dstaddr.ss_family == AF_INET6) - sport = &addr6->sin6_port; - else - sport = &addr->sin_port; - - if (*sport == 0) { - int rc; - - /* try with 445 port at first */ - *sport = htons(CIFS_PORT); - - rc = generic_ip_connect(server); - if (rc >= 0) - return rc; - - /* if it failed, try with 139 port */ - *sport = htons(RFC1001_PORT); - } - - return generic_ip_connect(server); -} - -void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, - struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info) -{ - /* if we are reconnecting then should we check to see if - * any requested capabilities changed locally e.g. via - * remount but we can not do much about it here - * if they have (even if we could detect it by the following) - * Perhaps we could add a backpointer to array of sb from tcon - * or if we change to make all sb to same share the same - * sb as NFS - then we only have one backpointer to sb. - * What if we wanted to mount the server share twice once with - * and once without posixacls or posix paths? */ - __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); - - if (vol_info && vol_info->no_linux_ext) { - tcon->fsUnixInfo.Capability = 0; - tcon->unix_ext = 0; /* Unix Extensions disabled */ - cFYI(1, "Linux protocol extensions disabled"); - return; - } else if (vol_info) - tcon->unix_ext = 1; /* Unix Extensions supported */ - - if (tcon->unix_ext == 0) { - cFYI(1, "Unix extensions disabled so not set on reconnect"); - return; - } - - if (!CIFSSMBQFSUnixInfo(xid, tcon)) { - __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability); - cFYI(1, "unix caps which server supports %lld", cap); - /* check for reconnect case in which we do not - want to change the mount behavior if we can avoid it */ - if (vol_info == NULL) { - /* turn off POSIX ACL and PATHNAMES if not set - originally at mount time */ - if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0) - cap &= ~CIFS_UNIX_POSIX_ACL_CAP; - if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) { - if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) - cERROR(1, "POSIXPATH support change"); - cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; - } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) { - cERROR(1, "possible reconnect error"); - cERROR(1, "server disabled POSIX path support"); - } - } - - if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP) - cERROR(1, "per-share encryption not supported yet"); - - cap &= CIFS_UNIX_CAP_MASK; - if (vol_info && vol_info->no_psx_acl) - cap &= ~CIFS_UNIX_POSIX_ACL_CAP; - else if (CIFS_UNIX_POSIX_ACL_CAP & cap) { - cFYI(1, "negotiated posix acl support"); - if (cifs_sb) - cifs_sb->mnt_cifs_flags |= - CIFS_MOUNT_POSIXACL; - } - - if (vol_info && vol_info->posix_paths == 0) - cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; - else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { - cFYI(1, "negotiate posix pathnames"); - if (cifs_sb) - cifs_sb->mnt_cifs_flags |= - CIFS_MOUNT_POSIX_PATHS; - } - - cFYI(1, "Negotiate caps 0x%x", (int)cap); -#ifdef CONFIG_CIFS_DEBUG2 - if (cap & CIFS_UNIX_FCNTL_CAP) - cFYI(1, "FCNTL cap"); - if (cap & CIFS_UNIX_EXTATTR_CAP) - cFYI(1, "EXTATTR cap"); - if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) - cFYI(1, "POSIX path cap"); - if (cap & CIFS_UNIX_XATTR_CAP) - cFYI(1, "XATTR cap"); - if (cap & CIFS_UNIX_POSIX_ACL_CAP) - cFYI(1, "POSIX ACL cap"); - if (cap & CIFS_UNIX_LARGE_READ_CAP) - cFYI(1, "very large read cap"); - if (cap & CIFS_UNIX_LARGE_WRITE_CAP) - cFYI(1, "very large write cap"); - if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP) - cFYI(1, "transport encryption cap"); - if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP) - cFYI(1, "mandatory transport encryption cap"); -#endif /* CIFS_DEBUG2 */ - if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { - if (vol_info == NULL) { - cFYI(1, "resetting capabilities failed"); - } else - cERROR(1, "Negotiating Unix capabilities " - "with the server failed. Consider " - "mounting with the Unix Extensions\n" - "disabled, if problems are found, " - "by specifying the nounix mount " - "option."); - - } - } -} - -void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, - struct cifs_sb_info *cifs_sb) -{ - INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks); - - spin_lock_init(&cifs_sb->tlink_tree_lock); - cifs_sb->tlink_tree = RB_ROOT; - - /* - * Temporarily set r/wsize for matching superblock. If we end up using - * new sb then client will later negotiate it downward if needed. - */ - cifs_sb->rsize = pvolume_info->rsize; - cifs_sb->wsize = pvolume_info->wsize; - - cifs_sb->mnt_uid = pvolume_info->linux_uid; - cifs_sb->mnt_gid = pvolume_info->linux_gid; - cifs_sb->mnt_file_mode = pvolume_info->file_mode; - cifs_sb->mnt_dir_mode = pvolume_info->dir_mode; - cFYI(1, "file mode: 0x%hx dir mode: 0x%hx", - cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode); - - cifs_sb->actimeo = pvolume_info->actimeo; - cifs_sb->local_nls = pvolume_info->local_nls; - - if (pvolume_info->noperm) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; - if (pvolume_info->setuids) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; - if (pvolume_info->server_ino) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; - if (pvolume_info->remap) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; - if (pvolume_info->no_xattr) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; - if (pvolume_info->sfu_emul) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; - if (pvolume_info->nobrl) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; - if (pvolume_info->nostrictsync) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC; - if (pvolume_info->mand_lock) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL; - if (pvolume_info->rwpidforward) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD; - if (pvolume_info->cifs_acl) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; - if (pvolume_info->backupuid_specified) { - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID; - cifs_sb->mnt_backupuid = pvolume_info->backupuid; - } - if (pvolume_info->backupgid_specified) { - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID; - cifs_sb->mnt_backupgid = pvolume_info->backupgid; - } - if (pvolume_info->override_uid) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID; - if (pvolume_info->override_gid) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; - if (pvolume_info->dynperm) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM; - if (pvolume_info->fsc) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE; - if (pvolume_info->multiuser) - cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER | - CIFS_MOUNT_NO_PERM); - if (pvolume_info->strict_io) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO; - if (pvolume_info->direct_io) { - cFYI(1, "mounting share using direct i/o"); - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; - } - if (pvolume_info->mfsymlinks) { - if (pvolume_info->sfu_emul) { - cERROR(1, "mount option mfsymlinks ignored if sfu " - "mount option is used"); - } else { - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS; - } - } - - if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm)) - cERROR(1, "mount option dynperm ignored if cifsacl " - "mount option supported"); -} - -/* - * When the server supports very large reads and writes via POSIX extensions, - * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not - * including the RFC1001 length. - * - * Note that this might make for "interesting" allocation problems during - * writeback however as we have to allocate an array of pointers for the - * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096. - * - * For reads, there is a similar problem as we need to allocate an array - * of kvecs to handle the receive, though that should only need to be done - * once. - */ -#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4) -#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4) - -/* - * When the server doesn't allow large posix writes, only allow a rsize/wsize - * of 2^17-1 minus the size of the call header. That allows for a read or - * write up to the maximum size described by RFC1002. - */ -#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4) -#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4) - -/* - * The default wsize is 1M. find_get_pages seems to return a maximum of 256 - * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill - * a single wsize request with a single call. - */ -#define CIFS_DEFAULT_IOSIZE (1024 * 1024) - -/* - * Windows only supports a max of 60kb reads and 65535 byte writes. Default to - * those values when posix extensions aren't in force. In actuality here, we - * use 65536 to allow for a write that is a multiple of 4k. Most servers seem - * to be ok with the extra byte even though Windows doesn't send writes that - * are that large. - * - * Citation: - * - * http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx - */ -#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024) -#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536) - -static unsigned int -cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) -{ - __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); - struct TCP_Server_Info *server = tcon->ses->server; - unsigned int wsize; - - /* start with specified wsize, or default */ - if (pvolume_info->wsize) - wsize = pvolume_info->wsize; - else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) - wsize = CIFS_DEFAULT_IOSIZE; - else - wsize = CIFS_DEFAULT_NON_POSIX_WSIZE; - - /* can server support 24-bit write sizes? (via UNIX extensions) */ - if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) - wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE); - - /* - * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set? - * Limit it to max buffer offered by the server, minus the size of the - * WRITEX header, not including the 4 byte RFC1001 length. - */ - if (!(server->capabilities & CAP_LARGE_WRITE_X) || - (!(server->capabilities & CAP_UNIX) && - (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)))) - wsize = min_t(unsigned int, wsize, - server->maxBuf - sizeof(WRITE_REQ) + 4); - - /* hard limit of CIFS_MAX_WSIZE */ - wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE); - - return wsize; -} - -static unsigned int -cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) -{ - __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); - struct TCP_Server_Info *server = tcon->ses->server; - unsigned int rsize, defsize; - - /* - * Set default value... - * - * HACK alert! Ancient servers have very small buffers. Even though - * MS-CIFS indicates that servers are only limited by the client's - * bufsize for reads, testing against win98se shows that it throws - * INVALID_PARAMETER errors if you try to request too large a read. - * OS/2 just sends back short reads. - * - * If the server doesn't advertise CAP_LARGE_READ_X, then assume that - * it can't handle a read request larger than its MaxBufferSize either. - */ - if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP)) - defsize = CIFS_DEFAULT_IOSIZE; - else if (server->capabilities & CAP_LARGE_READ_X) - defsize = CIFS_DEFAULT_NON_POSIX_RSIZE; - else - defsize = server->maxBuf - sizeof(READ_RSP); - - rsize = pvolume_info->rsize ? pvolume_info->rsize : defsize; - - /* - * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to - * the client's MaxBufferSize. - */ - if (!(server->capabilities & CAP_LARGE_READ_X)) - rsize = min_t(unsigned int, CIFSMaxBufSize, rsize); - - /* hard limit of CIFS_MAX_RSIZE */ - rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE); - - return rsize; -} - -static int -is_path_accessible(int xid, struct cifs_tcon *tcon, - struct cifs_sb_info *cifs_sb, const char *full_path) -{ - int rc; - FILE_ALL_INFO *pfile_info; - - pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); - if (pfile_info == NULL) - return -ENOMEM; - - rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info, - 0 /* not legacy */, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - - if (rc == -EOPNOTSUPP || rc == -EINVAL) - rc = SMBQueryInformation(xid, tcon, full_path, pfile_info, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - kfree(pfile_info); - return rc; -} - -static void -cleanup_volume_info_contents(struct smb_vol *volume_info) -{ - kfree(volume_info->username); - kzfree(volume_info->password); - if (volume_info->UNCip != volume_info->UNC + 2) - kfree(volume_info->UNCip); - kfree(volume_info->UNC); - kfree(volume_info->domainname); - kfree(volume_info->iocharset); - kfree(volume_info->prepath); -} - -void -cifs_cleanup_volume_info(struct smb_vol *volume_info) -{ - if (!volume_info) - return; - cleanup_volume_info_contents(volume_info); - kfree(volume_info); -} - - -#ifdef CONFIG_CIFS_DFS_UPCALL -/* build_path_to_root returns full path to root when - * we do not have an exiting connection (tcon) */ -static char * -build_unc_path_to_root(const struct smb_vol *vol, - const struct cifs_sb_info *cifs_sb) -{ - char *full_path, *pos; - unsigned int pplen = vol->prepath ? strlen(vol->prepath) : 0; - unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1); - - full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL); - if (full_path == NULL) - return ERR_PTR(-ENOMEM); - - strncpy(full_path, vol->UNC, unc_len); - pos = full_path + unc_len; - - if (pplen) { - strncpy(pos, vol->prepath, pplen); - pos += pplen; - } - - *pos = '\0'; /* add trailing null */ - convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb)); - cFYI(1, "%s: full_path=%s", __func__, full_path); - return full_path; -} - -/* - * Perform a dfs referral query for a share and (optionally) prefix - * - * If a referral is found, cifs_sb->mountdata will be (re-)allocated - * to a string containing updated options for the submount. Otherwise it - * will be left untouched. - * - * Returns the rc from get_dfs_path to the caller, which can be used to - * determine whether there were referrals. - */ -static int -expand_dfs_referral(int xid, struct cifs_ses *pSesInfo, - struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb, - int check_prefix) -{ - int rc; - unsigned int num_referrals = 0; - struct dfs_info3_param *referrals = NULL; - char *full_path = NULL, *ref_path = NULL, *mdata = NULL; - - full_path = build_unc_path_to_root(volume_info, cifs_sb); - if (IS_ERR(full_path)) - return PTR_ERR(full_path); - - /* For DFS paths, skip the first '\' of the UNC */ - ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1; - - rc = get_dfs_path(xid, pSesInfo , ref_path, cifs_sb->local_nls, - &num_referrals, &referrals, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - - if (!rc && num_referrals > 0) { - char *fake_devname = NULL; - - mdata = cifs_compose_mount_options(cifs_sb->mountdata, - full_path + 1, referrals, - &fake_devname); - - free_dfs_info_array(referrals, num_referrals); - - if (IS_ERR(mdata)) { - rc = PTR_ERR(mdata); - mdata = NULL; - } else { - cleanup_volume_info_contents(volume_info); - memset(volume_info, '\0', sizeof(*volume_info)); - rc = cifs_setup_volume_info(volume_info, mdata, - fake_devname); - } - kfree(fake_devname); - kfree(cifs_sb->mountdata); - cifs_sb->mountdata = mdata; - } - kfree(full_path); - return rc; -} -#endif - -static int -cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data, - const char *devname) -{ - int rc = 0; - - if (cifs_parse_mount_options(mount_data, devname, volume_info)) - return -EINVAL; - - if (volume_info->nullauth) { - cFYI(1, "Anonymous login"); - kfree(volume_info->username); - volume_info->username = NULL; - } else if (volume_info->username) { - /* BB fixme parse for domain name here */ - cFYI(1, "Username: %s", volume_info->username); - } else { - cifserror("No username specified"); - /* In userspace mount helper we can get user name from alternate - locations such as env variables and files on disk */ - return -EINVAL; - } - - /* this is needed for ASCII cp to Unicode converts */ - if (volume_info->iocharset == NULL) { - /* load_nls_default cannot return null */ - volume_info->local_nls = load_nls_default(); - } else { - volume_info->local_nls = load_nls(volume_info->iocharset); - if (volume_info->local_nls == NULL) { - cERROR(1, "CIFS mount error: iocharset %s not found", - volume_info->iocharset); - return -ELIBACC; - } - } - - return rc; -} - -struct smb_vol * -cifs_get_volume_info(char *mount_data, const char *devname) -{ - int rc; - struct smb_vol *volume_info; - - volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL); - if (!volume_info) - return ERR_PTR(-ENOMEM); - - rc = cifs_setup_volume_info(volume_info, mount_data, devname); - if (rc) { - cifs_cleanup_volume_info(volume_info); - volume_info = ERR_PTR(rc); - } - - return volume_info; -} - -int -cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) -{ - int rc; - int xid; - struct cifs_ses *pSesInfo; - struct cifs_tcon *tcon; - struct TCP_Server_Info *srvTcp; - char *full_path; - struct tcon_link *tlink; -#ifdef CONFIG_CIFS_DFS_UPCALL - int referral_walks_count = 0; -#endif - - rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); - if (rc) - return rc; - -#ifdef CONFIG_CIFS_DFS_UPCALL -try_mount_again: - /* cleanup activities if we're chasing a referral */ - if (referral_walks_count) { - if (tcon) - cifs_put_tcon(tcon); - else if (pSesInfo) - cifs_put_smb_ses(pSesInfo); - - FreeXid(xid); - } -#endif - rc = 0; - tcon = NULL; - pSesInfo = NULL; - srvTcp = NULL; - full_path = NULL; - tlink = NULL; - - xid = GetXid(); - - /* get a reference to a tcp session */ - srvTcp = cifs_get_tcp_session(volume_info); - if (IS_ERR(srvTcp)) { - rc = PTR_ERR(srvTcp); - bdi_destroy(&cifs_sb->bdi); - goto out; - } - - /* get a reference to a SMB session */ - pSesInfo = cifs_get_smb_ses(srvTcp, volume_info); - if (IS_ERR(pSesInfo)) { - rc = PTR_ERR(pSesInfo); - pSesInfo = NULL; - goto mount_fail_check; - } - - /* search for existing tcon to this server share */ - tcon = cifs_get_tcon(pSesInfo, volume_info); - if (IS_ERR(tcon)) { - rc = PTR_ERR(tcon); - tcon = NULL; - goto remote_path_check; - } - - /* tell server which Unix caps we support */ - if (tcon->ses->capabilities & CAP_UNIX) { - /* reset of caps checks mount to see if unix extensions - disabled for just this mount */ - reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info); - if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && - (le64_to_cpu(tcon->fsUnixInfo.Capability) & - CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) { - rc = -EACCES; - goto mount_fail_check; - } - } else - tcon->unix_ext = 0; /* server does not support them */ - - /* do not care if following two calls succeed - informational */ - if (!tcon->ipc) { - CIFSSMBQFSDeviceInfo(xid, tcon); - CIFSSMBQFSAttributeInfo(xid, tcon); - } - - cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info); - cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info); - - /* tune readahead according to rsize */ - cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE; - -remote_path_check: -#ifdef CONFIG_CIFS_DFS_UPCALL - /* - * Perform an unconditional check for whether there are DFS - * referrals for this path without prefix, to provide support - * for DFS referrals from w2k8 servers which don't seem to respond - * with PATH_NOT_COVERED to requests that include the prefix. - * Chase the referral if found, otherwise continue normally. - */ - if (referral_walks_count == 0) { - int refrc = expand_dfs_referral(xid, pSesInfo, volume_info, - cifs_sb, false); - if (!refrc) { - referral_walks_count++; - goto try_mount_again; - } - } -#endif - - /* check if a whole path is not remote */ - if (!rc && tcon) { - /* build_path_to_root works only when we have a valid tcon */ - full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon); - if (full_path == NULL) { - rc = -ENOMEM; - goto mount_fail_check; - } - rc = is_path_accessible(xid, tcon, cifs_sb, full_path); - if (rc != 0 && rc != -EREMOTE) { - kfree(full_path); - goto mount_fail_check; - } - kfree(full_path); - } - - /* get referral if needed */ - if (rc == -EREMOTE) { -#ifdef CONFIG_CIFS_DFS_UPCALL - if (referral_walks_count > MAX_NESTED_LINKS) { - /* - * BB: when we implement proper loop detection, - * we will remove this check. But now we need it - * to prevent an indefinite loop if 'DFS tree' is - * misconfigured (i.e. has loops). - */ - rc = -ELOOP; - goto mount_fail_check; - } - - rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb, - true); - - if (!rc) { - referral_walks_count++; - goto try_mount_again; - } - goto mount_fail_check; -#else /* No DFS support, return error on mount */ - rc = -EOPNOTSUPP; -#endif - } - - if (rc) - goto mount_fail_check; - - /* now, hang the tcon off of the superblock */ - tlink = kzalloc(sizeof *tlink, GFP_KERNEL); - if (tlink == NULL) { - rc = -ENOMEM; - goto mount_fail_check; - } - - tlink->tl_uid = pSesInfo->linux_uid; - tlink->tl_tcon = tcon; - tlink->tl_time = jiffies; - set_bit(TCON_LINK_MASTER, &tlink->tl_flags); - set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); - - cifs_sb->master_tlink = tlink; - spin_lock(&cifs_sb->tlink_tree_lock); - tlink_rb_insert(&cifs_sb->tlink_tree, tlink); - spin_unlock(&cifs_sb->tlink_tree_lock); - - queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks, - TLINK_IDLE_EXPIRE); - -mount_fail_check: - /* on error free sesinfo and tcon struct if needed */ - if (rc) { - /* If find_unc succeeded then rc == 0 so we can not end */ - /* up accidentally freeing someone elses tcon struct */ - if (tcon) - cifs_put_tcon(tcon); - else if (pSesInfo) - cifs_put_smb_ses(pSesInfo); - else - cifs_put_tcp_session(srvTcp); - bdi_destroy(&cifs_sb->bdi); - } - -out: - FreeXid(xid); - return rc; -} - -/* - * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon - * pointer may be NULL. - */ -int -CIFSTCon(unsigned int xid, struct cifs_ses *ses, - const char *tree, struct cifs_tcon *tcon, - const struct nls_table *nls_codepage) -{ - struct smb_hdr *smb_buffer; - struct smb_hdr *smb_buffer_response; - TCONX_REQ *pSMB; - TCONX_RSP *pSMBr; - unsigned char *bcc_ptr; - int rc = 0; - int length; - __u16 bytes_left, count; - - if (ses == NULL) - return -EIO; - - smb_buffer = cifs_buf_get(); - if (smb_buffer == NULL) - return -ENOMEM; - - smb_buffer_response = smb_buffer; - - header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, - NULL /*no tid */ , 4 /*wct */ ); - - smb_buffer->Mid = GetNextMid(ses->server); - smb_buffer->Uid = ses->Suid; - pSMB = (TCONX_REQ *) smb_buffer; - pSMBr = (TCONX_RSP *) smb_buffer_response; - - pSMB->AndXCommand = 0xFF; - pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); - bcc_ptr = &pSMB->Password[0]; - if (!tcon || (ses->server->sec_mode & SECMODE_USER)) { - pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ - *bcc_ptr = 0; /* password is null byte */ - bcc_ptr++; /* skip password */ - /* already aligned so no need to do it below */ - } else { - pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE); - /* BB FIXME add code to fail this if NTLMv2 or Kerberos - specified as required (when that support is added to - the vfs in the future) as only NTLM or the much - weaker LANMAN (which we do not send by default) is accepted - by Samba (not sure whether other servers allow - NTLMv2 password here) */ -#ifdef CONFIG_CIFS_WEAK_PW_HASH - if ((global_secflags & CIFSSEC_MAY_LANMAN) && - (ses->server->secType == LANMAN)) - calc_lanman_hash(tcon->password, ses->server->cryptkey, - ses->server->sec_mode & - SECMODE_PW_ENCRYPT ? true : false, - bcc_ptr); - else -#endif /* CIFS_WEAK_PW_HASH */ - rc = SMBNTencrypt(tcon->password, ses->server->cryptkey, - bcc_ptr, nls_codepage); - - bcc_ptr += CIFS_AUTH_RESP_SIZE; - if (ses->capabilities & CAP_UNICODE) { - /* must align unicode strings */ - *bcc_ptr = 0; /* null byte password */ - bcc_ptr++; - } - } - - if (ses->server->sec_mode & - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) - smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - - if (ses->capabilities & CAP_STATUS32) { - smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; - } - if (ses->capabilities & CAP_DFS) { - smb_buffer->Flags2 |= SMBFLG2_DFS; - } - if (ses->capabilities & CAP_UNICODE) { - smb_buffer->Flags2 |= SMBFLG2_UNICODE; - length = - cifs_strtoUTF16((__le16 *) bcc_ptr, tree, - 6 /* max utf8 char length in bytes */ * - (/* server len*/ + 256 /* share len */), nls_codepage); - bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */ - bcc_ptr += 2; /* skip trailing null */ - } else { /* ASCII */ - strcpy(bcc_ptr, tree); - bcc_ptr += strlen(tree) + 1; - } - strcpy(bcc_ptr, "?????"); - bcc_ptr += strlen("?????"); - bcc_ptr += 1; - count = bcc_ptr - &pSMB->Password[0]; - pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu( - pSMB->hdr.smb_buf_length) + count); - pSMB->ByteCount = cpu_to_le16(count); - - rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, - 0); - - /* above now done in SendReceive */ - if ((rc == 0) && (tcon != NULL)) { - bool is_unicode; - - tcon->tidStatus = CifsGood; - tcon->need_reconnect = false; - tcon->tid = smb_buffer_response->Tid; - bcc_ptr = pByteArea(smb_buffer_response); - bytes_left = get_bcc(smb_buffer_response); - length = strnlen(bcc_ptr, bytes_left - 2); - if (smb_buffer->Flags2 & SMBFLG2_UNICODE) - is_unicode = true; - else - is_unicode = false; - - - /* skip service field (NB: this field is always ASCII) */ - if (length == 3) { - if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') && - (bcc_ptr[2] == 'C')) { - cFYI(1, "IPC connection"); - tcon->ipc = 1; - } - } else if (length == 2) { - if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) { - /* the most common case */ - cFYI(1, "disk share connection"); - } - } - bcc_ptr += length + 1; - bytes_left -= (length + 1); - strncpy(tcon->treeName, tree, MAX_TREE_SIZE); - - /* mostly informational -- no need to fail on error here */ - kfree(tcon->nativeFileSystem); - tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr, - bytes_left, is_unicode, - nls_codepage); - - cFYI(1, "nativeFileSystem=%s", tcon->nativeFileSystem); - - if ((smb_buffer_response->WordCount == 3) || - (smb_buffer_response->WordCount == 7)) - /* field is in same location */ - tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); - else - tcon->Flags = 0; - cFYI(1, "Tcon flags: 0x%x ", tcon->Flags); - } else if ((rc == 0) && tcon == NULL) { - /* all we need to save for IPC$ connection */ - ses->ipc_tid = smb_buffer_response->Tid; - } - - cifs_buf_release(smb_buffer); - return rc; -} - -void -cifs_umount(struct cifs_sb_info *cifs_sb) -{ - struct rb_root *root = &cifs_sb->tlink_tree; - struct rb_node *node; - struct tcon_link *tlink; - - cancel_delayed_work_sync(&cifs_sb->prune_tlinks); - - spin_lock(&cifs_sb->tlink_tree_lock); - while ((node = rb_first(root))) { - tlink = rb_entry(node, struct tcon_link, tl_rbnode); - cifs_get_tlink(tlink); - clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); - rb_erase(node, root); - - spin_unlock(&cifs_sb->tlink_tree_lock); - cifs_put_tlink(tlink); - spin_lock(&cifs_sb->tlink_tree_lock); - } - spin_unlock(&cifs_sb->tlink_tree_lock); - - bdi_destroy(&cifs_sb->bdi); - kfree(cifs_sb->mountdata); - unload_nls(cifs_sb->local_nls); - kfree(cifs_sb); -} - -int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses) -{ - int rc = 0; - struct TCP_Server_Info *server = ses->server; - - /* only send once per connect */ - if (server->maxBuf != 0) - return 0; - - cifs_set_credits(server, 1); - rc = CIFSSMBNegotiate(xid, ses); - if (rc == -EAGAIN) { - /* retry only once on 1st time connection */ - cifs_set_credits(server, 1); - rc = CIFSSMBNegotiate(xid, ses); - if (rc == -EAGAIN) - rc = -EHOSTDOWN; - } - if (rc == 0) { - spin_lock(&GlobalMid_Lock); - if (server->tcpStatus == CifsNeedNegotiate) - server->tcpStatus = CifsGood; - else - rc = -EHOSTDOWN; - spin_unlock(&GlobalMid_Lock); - - } - - return rc; -} - - -int cifs_setup_session(unsigned int xid, struct cifs_ses *ses, - struct nls_table *nls_info) -{ - int rc = 0; - struct TCP_Server_Info *server = ses->server; - - ses->flags = 0; - ses->capabilities = server->capabilities; - if (linuxExtEnabled == 0) - ses->capabilities &= (~CAP_UNIX); - - cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", - server->sec_mode, server->capabilities, server->timeAdj); - - rc = CIFS_SessSetup(xid, ses, nls_info); - if (rc) { - cERROR(1, "Send error in SessSetup = %d", rc); - } else { - mutex_lock(&ses->server->srv_mutex); - if (!server->session_estab) { - server->session_key.response = ses->auth_key.response; - server->session_key.len = ses->auth_key.len; - server->sequence_number = 0x2; - server->session_estab = true; - ses->auth_key.response = NULL; - } - mutex_unlock(&server->srv_mutex); - - cFYI(1, "CIFS Session Established successfully"); - spin_lock(&GlobalMid_Lock); - ses->status = CifsGood; - ses->need_reconnect = false; - spin_unlock(&GlobalMid_Lock); - } - - kfree(ses->auth_key.response); - ses->auth_key.response = NULL; - ses->auth_key.len = 0; - kfree(ses->ntlmssp); - ses->ntlmssp = NULL; - - return rc; -} - -static int -cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses) -{ - switch (ses->server->secType) { - case Kerberos: - vol->secFlg = CIFSSEC_MUST_KRB5; - return 0; - case NTLMv2: - vol->secFlg = CIFSSEC_MUST_NTLMV2; - break; - case NTLM: - vol->secFlg = CIFSSEC_MUST_NTLM; - break; - case RawNTLMSSP: - vol->secFlg = CIFSSEC_MUST_NTLMSSP; - break; - case LANMAN: - vol->secFlg = CIFSSEC_MUST_LANMAN; - break; - } - - return cifs_set_cifscreds(vol, ses); -} - -static struct cifs_tcon * -cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) -{ - int rc; - struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb); - struct cifs_ses *ses; - struct cifs_tcon *tcon = NULL; - struct smb_vol *vol_info; - - vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL); - if (vol_info == NULL) - return ERR_PTR(-ENOMEM); - - vol_info->local_nls = cifs_sb->local_nls; - vol_info->linux_uid = fsuid; - vol_info->cred_uid = fsuid; - vol_info->UNC = master_tcon->treeName; - vol_info->retry = master_tcon->retry; - vol_info->nocase = master_tcon->nocase; - vol_info->local_lease = master_tcon->local_lease; - vol_info->no_linux_ext = !master_tcon->unix_ext; - - rc = cifs_set_vol_auth(vol_info, master_tcon->ses); - if (rc) { - tcon = ERR_PTR(rc); - goto out; - } - - /* get a reference for the same TCP session */ - spin_lock(&cifs_tcp_ses_lock); - ++master_tcon->ses->server->srv_count; - spin_unlock(&cifs_tcp_ses_lock); - - ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info); - if (IS_ERR(ses)) { - tcon = (struct cifs_tcon *)ses; - cifs_put_tcp_session(master_tcon->ses->server); - goto out; - } - - tcon = cifs_get_tcon(ses, vol_info); - if (IS_ERR(tcon)) { - cifs_put_smb_ses(ses); - goto out; - } - - if (ses->capabilities & CAP_UNIX) - reset_cifs_unix_caps(0, tcon, NULL, vol_info); -out: - kfree(vol_info->username); - kfree(vol_info->password); - kfree(vol_info); - - return tcon; -} - -struct cifs_tcon * -cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb) -{ - return tlink_tcon(cifs_sb_master_tlink(cifs_sb)); -} - -static int -cifs_sb_tcon_pending_wait(void *unused) -{ - schedule(); - return signal_pending(current) ? -ERESTARTSYS : 0; -} - -/* find and return a tlink with given uid */ -static struct tcon_link * -tlink_rb_search(struct rb_root *root, uid_t uid) -{ - struct rb_node *node = root->rb_node; - struct tcon_link *tlink; - - while (node) { - tlink = rb_entry(node, struct tcon_link, tl_rbnode); - - if (tlink->tl_uid > uid) - node = node->rb_left; - else if (tlink->tl_uid < uid) - node = node->rb_right; - else - return tlink; - } - return NULL; -} - -/* insert a tcon_link into the tree */ -static void -tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink) -{ - struct rb_node **new = &(root->rb_node), *parent = NULL; - struct tcon_link *tlink; - - while (*new) { - tlink = rb_entry(*new, struct tcon_link, tl_rbnode); - parent = *new; - - if (tlink->tl_uid > new_tlink->tl_uid) - new = &((*new)->rb_left); - else - new = &((*new)->rb_right); - } - - rb_link_node(&new_tlink->tl_rbnode, parent, new); - rb_insert_color(&new_tlink->tl_rbnode, root); -} - -/* - * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the - * current task. - * - * If the superblock doesn't refer to a multiuser mount, then just return - * the master tcon for the mount. - * - * First, search the rbtree for an existing tcon for this fsuid. If one - * exists, then check to see if it's pending construction. If it is then wait - * for construction to complete. Once it's no longer pending, check to see if - * it failed and either return an error or retry construction, depending on - * the timeout. - * - * If one doesn't exist then insert a new tcon_link struct into the tree and - * try to construct a new one. - */ -struct tcon_link * -cifs_sb_tlink(struct cifs_sb_info *cifs_sb) -{ - int ret; - uid_t fsuid = current_fsuid(); - struct tcon_link *tlink, *newtlink; - - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) - return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb)); - - spin_lock(&cifs_sb->tlink_tree_lock); - tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid); - if (tlink) - cifs_get_tlink(tlink); - spin_unlock(&cifs_sb->tlink_tree_lock); - - if (tlink == NULL) { - newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL); - if (newtlink == NULL) - return ERR_PTR(-ENOMEM); - newtlink->tl_uid = fsuid; - newtlink->tl_tcon = ERR_PTR(-EACCES); - set_bit(TCON_LINK_PENDING, &newtlink->tl_flags); - set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags); - cifs_get_tlink(newtlink); - - spin_lock(&cifs_sb->tlink_tree_lock); - /* was one inserted after previous search? */ - tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid); - if (tlink) { - cifs_get_tlink(tlink); - spin_unlock(&cifs_sb->tlink_tree_lock); - kfree(newtlink); - goto wait_for_construction; - } - tlink = newtlink; - tlink_rb_insert(&cifs_sb->tlink_tree, tlink); - spin_unlock(&cifs_sb->tlink_tree_lock); - } else { -wait_for_construction: - ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING, - cifs_sb_tcon_pending_wait, - TASK_INTERRUPTIBLE); - if (ret) { - cifs_put_tlink(tlink); - return ERR_PTR(ret); - } - - /* if it's good, return it */ - if (!IS_ERR(tlink->tl_tcon)) - return tlink; - - /* return error if we tried this already recently */ - if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) { - cifs_put_tlink(tlink); - return ERR_PTR(-EACCES); - } - - if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags)) - goto wait_for_construction; - } - - tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid); - clear_bit(TCON_LINK_PENDING, &tlink->tl_flags); - wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING); - - if (IS_ERR(tlink->tl_tcon)) { - cifs_put_tlink(tlink); - return ERR_PTR(-EACCES); - } - - return tlink; -} - -/* - * periodic workqueue job that scans tcon_tree for a superblock and closes - * out tcons. - */ -static void -cifs_prune_tlinks(struct work_struct *work) -{ - struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info, - prune_tlinks.work); - struct rb_root *root = &cifs_sb->tlink_tree; - struct rb_node *node = rb_first(root); - struct rb_node *tmp; - struct tcon_link *tlink; - - /* - * Because we drop the spinlock in the loop in order to put the tlink - * it's not guarded against removal of links from the tree. The only - * places that remove entries from the tree are this function and - * umounts. Because this function is non-reentrant and is canceled - * before umount can proceed, this is safe. - */ - spin_lock(&cifs_sb->tlink_tree_lock); - node = rb_first(root); - while (node != NULL) { - tmp = node; - node = rb_next(tmp); - tlink = rb_entry(tmp, struct tcon_link, tl_rbnode); - - if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) || - atomic_read(&tlink->tl_count) != 0 || - time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies)) - continue; - - cifs_get_tlink(tlink); - clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); - rb_erase(tmp, root); - - spin_unlock(&cifs_sb->tlink_tree_lock); - cifs_put_tlink(tlink); - spin_lock(&cifs_sb->tlink_tree_lock); - } - spin_unlock(&cifs_sb->tlink_tree_lock); - - queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks, - TLINK_IDLE_EXPIRE); -} diff --git a/ANDROID_3.4.5/fs/cifs/dir.c b/ANDROID_3.4.5/fs/cifs/dir.c deleted file mode 100644 index ec4e9a2a..00000000 --- a/ANDROID_3.4.5/fs/cifs/dir.c +++ /dev/null @@ -1,758 +0,0 @@ -/* - * fs/cifs/dir.c - * - * vfs operations that deal with dentries - * - * Copyright (C) International Business Machines Corp., 2002,2009 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/fs.h> -#include <linux/stat.h> -#include <linux/slab.h> -#include <linux/namei.h> -#include <linux/mount.h> -#include <linux/file.h> -#include "cifsfs.h" -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifs_debug.h" -#include "cifs_fs_sb.h" - -static void -renew_parental_timestamps(struct dentry *direntry) -{ - /* BB check if there is a way to get the kernel to do this or if we - really need this */ - do { - direntry->d_time = jiffies; - direntry = direntry->d_parent; - } while (!IS_ROOT(direntry)); -} - -/* Note: caller must free return buffer */ -char * -build_path_from_dentry(struct dentry *direntry) -{ - struct dentry *temp; - int namelen; - int dfsplen; - char *full_path; - char dirsep; - struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); - struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); - unsigned seq; - - dirsep = CIFS_DIR_SEP(cifs_sb); - if (tcon->Flags & SMB_SHARE_IS_IN_DFS) - dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1); - else - dfsplen = 0; -cifs_bp_rename_retry: - namelen = dfsplen; - seq = read_seqbegin(&rename_lock); - rcu_read_lock(); - for (temp = direntry; !IS_ROOT(temp);) { - namelen += (1 + temp->d_name.len); - temp = temp->d_parent; - if (temp == NULL) { - cERROR(1, "corrupt dentry"); - rcu_read_unlock(); - return NULL; - } - } - rcu_read_unlock(); - - full_path = kmalloc(namelen+1, GFP_KERNEL); - if (full_path == NULL) - return full_path; - full_path[namelen] = 0; /* trailing null */ - rcu_read_lock(); - for (temp = direntry; !IS_ROOT(temp);) { - spin_lock(&temp->d_lock); - namelen -= 1 + temp->d_name.len; - if (namelen < 0) { - spin_unlock(&temp->d_lock); - break; - } else { - full_path[namelen] = dirsep; - strncpy(full_path + namelen + 1, temp->d_name.name, - temp->d_name.len); - cFYI(0, "name: %s", full_path + namelen); - } - spin_unlock(&temp->d_lock); - temp = temp->d_parent; - if (temp == NULL) { - cERROR(1, "corrupt dentry"); - rcu_read_unlock(); - kfree(full_path); - return NULL; - } - } - rcu_read_unlock(); - if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) { - cFYI(1, "did not end path lookup where expected. namelen=%d " - "dfsplen=%d", namelen, dfsplen); - /* presumably this is only possible if racing with a rename - of one of the parent directories (we can not lock the dentries - above us to prevent this, but retrying should be harmless) */ - kfree(full_path); - goto cifs_bp_rename_retry; - } - /* DIR_SEP already set for byte 0 / vs \ but not for - subsequent slashes in prepath which currently must - be entered the right way - not sure if there is an alternative - since the '\' is a valid posix character so we can not switch - those safely to '/' if any are found in the middle of the prepath */ - /* BB test paths to Windows with '/' in the midst of prepath */ - - if (dfsplen) { - strncpy(full_path, tcon->treeName, dfsplen); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) { - int i; - for (i = 0; i < dfsplen; i++) { - if (full_path[i] == '\\') - full_path[i] = '/'; - } - } - } - return full_path; -} - -/* Inode operations in similar order to how they appear in Linux file fs.h */ - -int -cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, - struct nameidata *nd) -{ - int rc = -ENOENT; - int xid; - int create_options = CREATE_NOT_DIR; - __u32 oplock = 0; - int oflags; - /* - * BB below access is probably too much for mknod to request - * but we have to do query and setpathinfo so requesting - * less could fail (unless we want to request getatr and setatr - * permissions (only). At least for POSIX we do not have to - * request so much. - */ - int desiredAccess = GENERIC_READ | GENERIC_WRITE; - __u16 fileHandle; - struct cifs_sb_info *cifs_sb; - struct tcon_link *tlink; - struct cifs_tcon *tcon; - char *full_path = NULL; - FILE_ALL_INFO *buf = NULL; - struct inode *newinode = NULL; - int disposition = FILE_OVERWRITE_IF; - - xid = GetXid(); - - cifs_sb = CIFS_SB(inode->i_sb); - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) { - FreeXid(xid); - return PTR_ERR(tlink); - } - tcon = tlink_tcon(tlink); - - if (tcon->ses->server->oplocks) - oplock = REQ_OPLOCK; - - if (nd) - oflags = nd->intent.open.file->f_flags; - else - oflags = O_RDONLY | O_CREAT; - - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - goto cifs_create_out; - } - - if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && - (CIFS_UNIX_POSIX_PATH_OPS_CAP & - le64_to_cpu(tcon->fsUnixInfo.Capability))) { - rc = cifs_posix_open(full_path, &newinode, - inode->i_sb, mode, oflags, &oplock, &fileHandle, xid); - /* EIO could indicate that (posix open) operation is not - supported, despite what server claimed in capability - negotiation. EREMOTE indicates DFS junction, which is not - handled in posix open */ - - if (rc == 0) { - if (newinode == NULL) /* query inode info */ - goto cifs_create_get_file_info; - else /* success, no need to query */ - goto cifs_create_set_dentry; - } else if ((rc != -EIO) && (rc != -EREMOTE) && - (rc != -EOPNOTSUPP) && (rc != -EINVAL)) - goto cifs_create_out; - /* else fallthrough to retry, using older open call, this is - case where server does not support this SMB level, and - falsely claims capability (also get here for DFS case - which should be rare for path not covered on files) */ - } - - if (nd) { - /* if the file is going to stay open, then we - need to set the desired access properly */ - desiredAccess = 0; - if (OPEN_FMODE(oflags) & FMODE_READ) - desiredAccess |= GENERIC_READ; /* is this too little? */ - if (OPEN_FMODE(oflags) & FMODE_WRITE) - desiredAccess |= GENERIC_WRITE; - - if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) - disposition = FILE_CREATE; - else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) - disposition = FILE_OVERWRITE_IF; - else if ((oflags & O_CREAT) == O_CREAT) - disposition = FILE_OPEN_IF; - else - cFYI(1, "Create flag not set in create function"); - } - - /* BB add processing to set equivalent of mode - e.g. via CreateX with - ACLs */ - - buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); - if (buf == NULL) { - rc = -ENOMEM; - goto cifs_create_out; - } - - /* - * if we're not using unix extensions, see if we need to set - * ATTR_READONLY on the create call - */ - if (!tcon->unix_ext && (mode & S_IWUGO) == 0) - create_options |= CREATE_OPTION_READONLY; - - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - - if (tcon->ses->capabilities & CAP_NT_SMBS) - rc = CIFSSMBOpen(xid, tcon, full_path, disposition, - desiredAccess, create_options, - &fileHandle, &oplock, buf, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - else - rc = -EIO; /* no NT SMB support fall into legacy open below */ - - if (rc == -EIO) { - /* old server, retry the open legacy style */ - rc = SMBLegacyOpen(xid, tcon, full_path, disposition, - desiredAccess, create_options, - &fileHandle, &oplock, buf, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - } - if (rc) { - cFYI(1, "cifs_create returned 0x%x", rc); - goto cifs_create_out; - } - - /* If Open reported that we actually created a file - then we now have to set the mode if possible */ - if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { - struct cifs_unix_set_info_args args = { - .mode = mode, - .ctime = NO_CHANGE_64, - .atime = NO_CHANGE_64, - .mtime = NO_CHANGE_64, - .device = 0, - }; - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { - args.uid = (__u64) current_fsuid(); - if (inode->i_mode & S_ISGID) - args.gid = (__u64) inode->i_gid; - else - args.gid = (__u64) current_fsgid(); - } else { - args.uid = NO_CHANGE_64; - args.gid = NO_CHANGE_64; - } - CIFSSMBUnixSetFileInfo(xid, tcon, &args, fileHandle, - current->tgid); - } else { - /* BB implement mode setting via Windows security - descriptors e.g. */ - /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/ - - /* Could set r/o dos attribute if mode & 0222 == 0 */ - } - -cifs_create_get_file_info: - /* server might mask mode so we have to query for it */ - if (tcon->unix_ext) - rc = cifs_get_inode_info_unix(&newinode, full_path, - inode->i_sb, xid); - else { - rc = cifs_get_inode_info(&newinode, full_path, buf, - inode->i_sb, xid, &fileHandle); - if (newinode) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) - newinode->i_mode = mode; - if ((oplock & CIFS_CREATE_ACTION) && - (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { - newinode->i_uid = current_fsuid(); - if (inode->i_mode & S_ISGID) - newinode->i_gid = inode->i_gid; - else - newinode->i_gid = current_fsgid(); - } - } - } - -cifs_create_set_dentry: - if (rc == 0) - d_instantiate(direntry, newinode); - else - cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); - - if (newinode && nd) { - struct cifsFileInfo *pfile_info; - struct file *filp; - - filp = lookup_instantiate_filp(nd, direntry, generic_file_open); - if (IS_ERR(filp)) { - rc = PTR_ERR(filp); - CIFSSMBClose(xid, tcon, fileHandle); - goto cifs_create_out; - } - - pfile_info = cifs_new_fileinfo(fileHandle, filp, tlink, oplock); - if (pfile_info == NULL) { - fput(filp); - CIFSSMBClose(xid, tcon, fileHandle); - rc = -ENOMEM; - } - } else { - CIFSSMBClose(xid, tcon, fileHandle); - } - -cifs_create_out: - kfree(buf); - kfree(full_path); - cifs_put_tlink(tlink); - FreeXid(xid); - return rc; -} - -int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, - dev_t device_number) -{ - int rc = -EPERM; - int xid; - int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL; - struct cifs_sb_info *cifs_sb; - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - struct cifs_io_parms io_parms; - char *full_path = NULL; - struct inode *newinode = NULL; - int oplock = 0; - u16 fileHandle; - FILE_ALL_INFO *buf = NULL; - unsigned int bytes_written; - struct win_dev *pdev; - - if (!old_valid_dev(device_number)) - return -EINVAL; - - cifs_sb = CIFS_SB(inode->i_sb); - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - - pTcon = tlink_tcon(tlink); - - xid = GetXid(); - - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - goto mknod_out; - } - - if (pTcon->unix_ext) { - struct cifs_unix_set_info_args args = { - .mode = mode & ~current_umask(), - .ctime = NO_CHANGE_64, - .atime = NO_CHANGE_64, - .mtime = NO_CHANGE_64, - .device = device_number, - }; - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { - args.uid = (__u64) current_fsuid(); - args.gid = (__u64) current_fsgid(); - } else { - args.uid = NO_CHANGE_64; - args.gid = NO_CHANGE_64; - } - rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc) - goto mknod_out; - - rc = cifs_get_inode_info_unix(&newinode, full_path, - inode->i_sb, xid); - - if (rc == 0) - d_instantiate(direntry, newinode); - goto mknod_out; - } - - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) - goto mknod_out; - - - cFYI(1, "sfu compat create special file"); - - buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); - if (buf == NULL) { - kfree(full_path); - rc = -ENOMEM; - FreeXid(xid); - return rc; - } - - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - - rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE, - GENERIC_WRITE, create_options, - &fileHandle, &oplock, buf, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc) - goto mknod_out; - - /* BB Do not bother to decode buf since no local inode yet to put - * timestamps in, but we can reuse it safely */ - - pdev = (struct win_dev *)buf; - io_parms.netfid = fileHandle; - io_parms.pid = current->tgid; - io_parms.tcon = pTcon; - io_parms.offset = 0; - io_parms.length = sizeof(struct win_dev); - if (S_ISCHR(mode)) { - memcpy(pdev->type, "IntxCHR", 8); - pdev->major = - cpu_to_le64(MAJOR(device_number)); - pdev->minor = - cpu_to_le64(MINOR(device_number)); - rc = CIFSSMBWrite(xid, &io_parms, - &bytes_written, (char *)pdev, - NULL, 0); - } else if (S_ISBLK(mode)) { - memcpy(pdev->type, "IntxBLK", 8); - pdev->major = - cpu_to_le64(MAJOR(device_number)); - pdev->minor = - cpu_to_le64(MINOR(device_number)); - rc = CIFSSMBWrite(xid, &io_parms, - &bytes_written, (char *)pdev, - NULL, 0); - } /* else if (S_ISFIFO) */ - CIFSSMBClose(xid, pTcon, fileHandle); - d_drop(direntry); - - /* FIXME: add code here to set EAs */ - -mknod_out: - kfree(full_path); - kfree(buf); - FreeXid(xid); - cifs_put_tlink(tlink); - return rc; -} - -struct dentry * -cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, - struct nameidata *nd) -{ - int xid; - int rc = 0; /* to get around spurious gcc warning, set to zero here */ - __u32 oplock; - __u16 fileHandle = 0; - bool posix_open = false; - struct cifs_sb_info *cifs_sb; - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - struct cifsFileInfo *cfile; - struct inode *newInode = NULL; - char *full_path = NULL; - struct file *filp; - - xid = GetXid(); - - cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p", - parent_dir_inode, direntry->d_name.name, direntry); - - /* check whether path exists */ - - cifs_sb = CIFS_SB(parent_dir_inode->i_sb); - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) { - FreeXid(xid); - return (struct dentry *)tlink; - } - pTcon = tlink_tcon(tlink); - - oplock = pTcon->ses->server->oplocks ? REQ_OPLOCK : 0; - - /* - * Don't allow the separator character in a path component. - * The VFS will not allow "/", but "\" is allowed by posix. - */ - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) { - int i; - for (i = 0; i < direntry->d_name.len; i++) - if (direntry->d_name.name[i] == '\\') { - cFYI(1, "Invalid file name"); - rc = -EINVAL; - goto lookup_out; - } - } - - /* - * O_EXCL: optimize away the lookup, but don't hash the dentry. Let - * the VFS handle the create. - */ - if (nd && (nd->flags & LOOKUP_EXCL)) { - d_instantiate(direntry, NULL); - rc = 0; - goto lookup_out; - } - - /* can not grab the rename sem here since it would - deadlock in the cases (beginning of sys_rename itself) - in which we already have the sb rename sem */ - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - goto lookup_out; - } - - if (direntry->d_inode != NULL) { - cFYI(1, "non-NULL inode in lookup"); - } else { - cFYI(1, "NULL inode in lookup"); - } - cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode); - - /* Posix open is only called (at lookup time) for file create now. - * For opens (rather than creates), because we do not know if it - * is a file or directory yet, and current Samba no longer allows - * us to do posix open on dirs, we could end up wasting an open call - * on what turns out to be a dir. For file opens, we wait to call posix - * open till cifs_open. It could be added here (lookup) in the future - * but the performance tradeoff of the extra network request when EISDIR - * or EACCES is returned would have to be weighed against the 50% - * reduction in network traffic in the other paths. - */ - if (pTcon->unix_ext) { - if (nd && !(nd->flags & LOOKUP_DIRECTORY) && - (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && - (nd->intent.open.file->f_flags & O_CREAT)) { - rc = cifs_posix_open(full_path, &newInode, - parent_dir_inode->i_sb, - nd->intent.open.create_mode, - nd->intent.open.file->f_flags, &oplock, - &fileHandle, xid); - /* - * The check below works around a bug in POSIX - * open in samba versions 3.3.1 and earlier where - * open could incorrectly fail with invalid parameter. - * If either that or op not supported returned, follow - * the normal lookup. - */ - switch (rc) { - case 0: - /* - * The server may allow us to open things like - * FIFOs, but the client isn't set up to deal - * with that. If it's not a regular file, just - * close it and proceed as if it were a normal - * lookup. - */ - if (newInode && !S_ISREG(newInode->i_mode)) { - CIFSSMBClose(xid, pTcon, fileHandle); - break; - } - case -ENOENT: - posix_open = true; - case -EOPNOTSUPP: - break; - default: - pTcon->broken_posix_open = true; - } - } - if (!posix_open) - rc = cifs_get_inode_info_unix(&newInode, full_path, - parent_dir_inode->i_sb, xid); - } else - rc = cifs_get_inode_info(&newInode, full_path, NULL, - parent_dir_inode->i_sb, xid, NULL); - - if ((rc == 0) && (newInode != NULL)) { - d_add(direntry, newInode); - if (posix_open) { - filp = lookup_instantiate_filp(nd, direntry, - generic_file_open); - if (IS_ERR(filp)) { - rc = PTR_ERR(filp); - CIFSSMBClose(xid, pTcon, fileHandle); - goto lookup_out; - } - - cfile = cifs_new_fileinfo(fileHandle, filp, tlink, - oplock); - if (cfile == NULL) { - fput(filp); - CIFSSMBClose(xid, pTcon, fileHandle); - rc = -ENOMEM; - goto lookup_out; - } - } - /* since paths are not looked up by component - the parent - directories are presumed to be good here */ - renew_parental_timestamps(direntry); - - } else if (rc == -ENOENT) { - rc = 0; - direntry->d_time = jiffies; - d_add(direntry, NULL); - /* if it was once a directory (but how can we tell?) we could do - shrink_dcache_parent(direntry); */ - } else if (rc != -EACCES) { - cERROR(1, "Unexpected lookup error %d", rc); - /* We special case check for Access Denied - since that - is a common return code */ - } - -lookup_out: - kfree(full_path); - cifs_put_tlink(tlink); - FreeXid(xid); - return ERR_PTR(rc); -} - -static int -cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) -{ - if (nd && (nd->flags & LOOKUP_RCU)) - return -ECHILD; - - if (direntry->d_inode) { - if (cifs_revalidate_dentry(direntry)) - return 0; - else { - /* - * If the inode wasn't known to be a dfs entry when - * the dentry was instantiated, such as when created - * via ->readdir(), it needs to be set now since the - * attributes will have been updated by - * cifs_revalidate_dentry(). - */ - if (IS_AUTOMOUNT(direntry->d_inode) && - !(direntry->d_flags & DCACHE_NEED_AUTOMOUNT)) { - spin_lock(&direntry->d_lock); - direntry->d_flags |= DCACHE_NEED_AUTOMOUNT; - spin_unlock(&direntry->d_lock); - } - - return 1; - } - } - - /* - * This may be nfsd (or something), anyway, we can't see the - * intent of this. So, since this can be for creation, drop it. - */ - if (!nd) - return 0; - - /* - * Drop the negative dentry, in order to make sure to use the - * case sensitive name which is specified by user if this is - * for creation. - */ - if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) - return 0; - - if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled) - return 0; - - return 1; -} - -/* static int cifs_d_delete(struct dentry *direntry) -{ - int rc = 0; - - cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name); - - return rc; -} */ - -const struct dentry_operations cifs_dentry_ops = { - .d_revalidate = cifs_d_revalidate, - .d_automount = cifs_dfs_d_automount, -/* d_delete: cifs_d_delete, */ /* not needed except for debugging */ -}; - -static int cifs_ci_hash(const struct dentry *dentry, const struct inode *inode, - struct qstr *q) -{ - struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls; - unsigned long hash; - int i; - - hash = init_name_hash(); - for (i = 0; i < q->len; i++) - hash = partial_name_hash(nls_tolower(codepage, q->name[i]), - hash); - q->hash = end_name_hash(hash); - - return 0; -} - -static int cifs_ci_compare(const struct dentry *parent, - const struct inode *pinode, - const struct dentry *dentry, const struct inode *inode, - unsigned int len, const char *str, const struct qstr *name) -{ - struct nls_table *codepage = CIFS_SB(pinode->i_sb)->local_nls; - - if ((name->len == len) && - (nls_strnicmp(codepage, name->name, str, len) == 0)) - return 0; - return 1; -} - -const struct dentry_operations cifs_ci_dentry_ops = { - .d_revalidate = cifs_d_revalidate, - .d_hash = cifs_ci_hash, - .d_compare = cifs_ci_compare, - .d_automount = cifs_dfs_d_automount, -}; diff --git a/ANDROID_3.4.5/fs/cifs/dns_resolve.c b/ANDROID_3.4.5/fs/cifs/dns_resolve.c deleted file mode 100644 index 1d2d91d9..00000000 --- a/ANDROID_3.4.5/fs/cifs/dns_resolve.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * fs/cifs/dns_resolve.c - * - * Copyright (c) 2007 Igor Mammedov - * Author(s): Igor Mammedov (niallain@gmail.com) - * Steve French (sfrench@us.ibm.com) - * Wang Lei (wang840925@gmail.com) - * David Howells (dhowells@redhat.com) - * - * Contains the CIFS DFS upcall routines used for hostname to - * IP address translation. - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/slab.h> -#include <linux/dns_resolver.h> -#include "dns_resolve.h" -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifs_debug.h" - -/** - * dns_resolve_server_name_to_ip - Resolve UNC server name to ip address. - * @unc: UNC path specifying the server - * @ip_addr: Where to return the IP address. - * - * The IP address will be returned in string form, and the caller is - * responsible for freeing it. - * - * Returns length of result on success, -ve on error. - */ -int -dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) -{ - struct sockaddr_storage ss; - const char *hostname, *sep; - char *name; - int len, rc; - - if (!ip_addr || !unc) - return -EINVAL; - - len = strlen(unc); - if (len < 3) { - cFYI(1, "%s: unc is too short: %s", __func__, unc); - return -EINVAL; - } - - /* Discount leading slashes for cifs */ - len -= 2; - hostname = unc + 2; - - /* Search for server name delimiter */ - sep = memchr(hostname, '\\', len); - if (sep) - len = sep - hostname; - else - cFYI(1, "%s: probably server name is whole unc: %s", - __func__, unc); - - /* Try to interpret hostname as an IPv4 or IPv6 address */ - rc = cifs_convert_address((struct sockaddr *)&ss, hostname, len); - if (rc > 0) - goto name_is_IP_address; - - /* Perform the upcall */ - rc = dns_query(NULL, hostname, len, NULL, ip_addr, NULL); - if (rc < 0) - cFYI(1, "%s: unable to resolve: %*.*s", - __func__, len, len, hostname); - else - cFYI(1, "%s: resolved: %*.*s to %s", - __func__, len, len, hostname, *ip_addr); - return rc; - -name_is_IP_address: - name = kmalloc(len + 1, GFP_KERNEL); - if (!name) - return -ENOMEM; - memcpy(name, hostname, len); - name[len] = 0; - cFYI(1, "%s: unc is IP, skipping dns upcall: %s", __func__, name); - *ip_addr = name; - return 0; -} diff --git a/ANDROID_3.4.5/fs/cifs/dns_resolve.h b/ANDROID_3.4.5/fs/cifs/dns_resolve.h deleted file mode 100644 index d3f5d27f..00000000 --- a/ANDROID_3.4.5/fs/cifs/dns_resolve.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * fs/cifs/dns_resolve.h -- DNS Resolver upcall management for CIFS DFS - * Handles host name to IP address resolution - * - * Copyright (c) International Business Machines Corp., 2008 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _DNS_RESOLVE_H -#define _DNS_RESOLVE_H - -#ifdef __KERNEL__ -extern int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr); -#endif /* KERNEL */ - -#endif /* _DNS_RESOLVE_H */ diff --git a/ANDROID_3.4.5/fs/cifs/export.c b/ANDROID_3.4.5/fs/cifs/export.c deleted file mode 100644 index 9c7ecdcc..00000000 --- a/ANDROID_3.4.5/fs/cifs/export.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * fs/cifs/export.c - * - * Copyright (C) International Business Machines Corp., 2007 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * Common Internet FileSystem (CIFS) client - * - * Operations related to support for exporting files via NFSD - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - /* - * See Documentation/filesystems/nfs/Exporting - * and examples in fs/exportfs - * - * Since cifs is a network file system, an "fsid" must be included for - * any nfs exports file entries which refer to cifs paths. In addition - * the cifs mount must be mounted with the "serverino" option (ie use stable - * server inode numbers instead of locally generated temporary ones). - * Although cifs inodes do not use generation numbers (have generation number - * of zero) - the inode number alone should be good enough for simple cases - * in which users want to export cifs shares with NFS. The decode and encode - * could be improved by using a new routine which expects 64 bit inode numbers - * instead of the default 32 bit routines in fs/exportfs - * - */ - -#include <linux/fs.h> -#include <linux/exportfs.h> -#include "cifsglob.h" -#include "cifs_debug.h" -#include "cifsfs.h" - -#ifdef CONFIG_CIFS_NFSD_EXPORT -static struct dentry *cifs_get_parent(struct dentry *dentry) -{ - /* BB need to add code here eventually to enable export via NFSD */ - cFYI(1, "get parent for %p", dentry); - return ERR_PTR(-EACCES); -} - -const struct export_operations cifs_export_ops = { - .get_parent = cifs_get_parent, -/* Following five export operations are unneeded so far and can default: - .get_dentry = - .get_name = - .find_exported_dentry = - .decode_fh = - .encode_fs = */ -}; - -#endif /* CONFIG_CIFS_NFSD_EXPORT */ - diff --git a/ANDROID_3.4.5/fs/cifs/file.c b/ANDROID_3.4.5/fs/cifs/file.c deleted file mode 100644 index e7ebb5a2..00000000 --- a/ANDROID_3.4.5/fs/cifs/file.c +++ /dev/null @@ -1,3060 +0,0 @@ -/* - * fs/cifs/file.c - * - * vfs operations that deal with files - * - * Copyright (C) International Business Machines Corp., 2002,2010 - * Author(s): Steve French (sfrench@us.ibm.com) - * Jeremy Allison (jra@samba.org) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/fs.h> -#include <linux/backing-dev.h> -#include <linux/stat.h> -#include <linux/fcntl.h> -#include <linux/pagemap.h> -#include <linux/pagevec.h> -#include <linux/writeback.h> -#include <linux/task_io_accounting_ops.h> -#include <linux/delay.h> -#include <linux/mount.h> -#include <linux/slab.h> -#include <linux/swap.h> -#include <asm/div64.h> -#include "cifsfs.h" -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifs_unicode.h" -#include "cifs_debug.h" -#include "cifs_fs_sb.h" -#include "fscache.h" - -static inline int cifs_convert_flags(unsigned int flags) -{ - if ((flags & O_ACCMODE) == O_RDONLY) - return GENERIC_READ; - else if ((flags & O_ACCMODE) == O_WRONLY) - return GENERIC_WRITE; - else if ((flags & O_ACCMODE) == O_RDWR) { - /* GENERIC_ALL is too much permission to request - can cause unnecessary access denied on create */ - /* return GENERIC_ALL; */ - return (GENERIC_READ | GENERIC_WRITE); - } - - return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | - FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | - FILE_READ_DATA); -} - -static u32 cifs_posix_convert_flags(unsigned int flags) -{ - u32 posix_flags = 0; - - if ((flags & O_ACCMODE) == O_RDONLY) - posix_flags = SMB_O_RDONLY; - else if ((flags & O_ACCMODE) == O_WRONLY) - posix_flags = SMB_O_WRONLY; - else if ((flags & O_ACCMODE) == O_RDWR) - posix_flags = SMB_O_RDWR; - - if (flags & O_CREAT) - posix_flags |= SMB_O_CREAT; - if (flags & O_EXCL) - posix_flags |= SMB_O_EXCL; - if (flags & O_TRUNC) - posix_flags |= SMB_O_TRUNC; - /* be safe and imply O_SYNC for O_DSYNC */ - if (flags & O_DSYNC) - posix_flags |= SMB_O_SYNC; - if (flags & O_DIRECTORY) - posix_flags |= SMB_O_DIRECTORY; - if (flags & O_NOFOLLOW) - posix_flags |= SMB_O_NOFOLLOW; - if (flags & O_DIRECT) - posix_flags |= SMB_O_DIRECT; - - return posix_flags; -} - -static inline int cifs_get_disposition(unsigned int flags) -{ - if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) - return FILE_CREATE; - else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) - return FILE_OVERWRITE_IF; - else if ((flags & O_CREAT) == O_CREAT) - return FILE_OPEN_IF; - else if ((flags & O_TRUNC) == O_TRUNC) - return FILE_OVERWRITE; - else - return FILE_OPEN; -} - -int cifs_posix_open(char *full_path, struct inode **pinode, - struct super_block *sb, int mode, unsigned int f_flags, - __u32 *poplock, __u16 *pnetfid, int xid) -{ - int rc; - FILE_UNIX_BASIC_INFO *presp_data; - __u32 posix_flags = 0; - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - struct cifs_fattr fattr; - struct tcon_link *tlink; - struct cifs_tcon *tcon; - - cFYI(1, "posix open %s", full_path); - - presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); - if (presp_data == NULL) - return -ENOMEM; - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) { - rc = PTR_ERR(tlink); - goto posix_open_ret; - } - - tcon = tlink_tcon(tlink); - mode &= ~current_umask(); - - posix_flags = cifs_posix_convert_flags(f_flags); - rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data, - poplock, full_path, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - cifs_put_tlink(tlink); - - if (rc) - goto posix_open_ret; - - if (presp_data->Type == cpu_to_le32(-1)) - goto posix_open_ret; /* open ok, caller does qpathinfo */ - - if (!pinode) - goto posix_open_ret; /* caller does not need info */ - - cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb); - - /* get new inode and set it up */ - if (*pinode == NULL) { - cifs_fill_uniqueid(sb, &fattr); - *pinode = cifs_iget(sb, &fattr); - if (!*pinode) { - rc = -ENOMEM; - goto posix_open_ret; - } - } else { - cifs_fattr_to_inode(*pinode, &fattr); - } - -posix_open_ret: - kfree(presp_data); - return rc; -} - -static int -cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, - struct cifs_tcon *tcon, unsigned int f_flags, __u32 *poplock, - __u16 *pnetfid, int xid) -{ - int rc; - int desiredAccess; - int disposition; - int create_options = CREATE_NOT_DIR; - FILE_ALL_INFO *buf; - - desiredAccess = cifs_convert_flags(f_flags); - -/********************************************************************* - * open flag mapping table: - * - * POSIX Flag CIFS Disposition - * ---------- ---------------- - * O_CREAT FILE_OPEN_IF - * O_CREAT | O_EXCL FILE_CREATE - * O_CREAT | O_TRUNC FILE_OVERWRITE_IF - * O_TRUNC FILE_OVERWRITE - * none of the above FILE_OPEN - * - * Note that there is not a direct match between disposition - * FILE_SUPERSEDE (ie create whether or not file exists although - * O_CREAT | O_TRUNC is similar but truncates the existing - * file rather than creating a new file as FILE_SUPERSEDE does - * (which uses the attributes / metadata passed in on open call) - *? - *? O_SYNC is a reasonable match to CIFS writethrough flag - *? and the read write flags match reasonably. O_LARGEFILE - *? is irrelevant because largefile support is always used - *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY, - * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation - *********************************************************************/ - - disposition = cifs_get_disposition(f_flags); - - /* BB pass O_SYNC flag through on file attributes .. BB */ - - buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - - if (tcon->ses->capabilities & CAP_NT_SMBS) - rc = CIFSSMBOpen(xid, tcon, full_path, disposition, - desiredAccess, create_options, pnetfid, poplock, buf, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags - & CIFS_MOUNT_MAP_SPECIAL_CHR); - else - rc = SMBLegacyOpen(xid, tcon, full_path, disposition, - desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags - & CIFS_MOUNT_MAP_SPECIAL_CHR); - - if (rc) - goto out; - - if (tcon->unix_ext) - rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, - xid); - else - rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, - xid, pnetfid); - -out: - kfree(buf); - return rc; -} - -struct cifsFileInfo * -cifs_new_fileinfo(__u16 fileHandle, struct file *file, - struct tcon_link *tlink, __u32 oplock) -{ - struct dentry *dentry = file->f_path.dentry; - struct inode *inode = dentry->d_inode; - struct cifsInodeInfo *pCifsInode = CIFS_I(inode); - struct cifsFileInfo *pCifsFile; - - pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); - if (pCifsFile == NULL) - return pCifsFile; - - pCifsFile->count = 1; - pCifsFile->netfid = fileHandle; - pCifsFile->pid = current->tgid; - pCifsFile->uid = current_fsuid(); - pCifsFile->dentry = dget(dentry); - pCifsFile->f_flags = file->f_flags; - pCifsFile->invalidHandle = false; - pCifsFile->tlink = cifs_get_tlink(tlink); - mutex_init(&pCifsFile->fh_mutex); - INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break); - - spin_lock(&cifs_file_list_lock); - list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList)); - /* if readable file instance put first in list*/ - if (file->f_mode & FMODE_READ) - list_add(&pCifsFile->flist, &pCifsInode->openFileList); - else - list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList); - spin_unlock(&cifs_file_list_lock); - - cifs_set_oplock_level(pCifsInode, oplock); - pCifsInode->can_cache_brlcks = pCifsInode->clientCanCacheAll; - - file->private_data = pCifsFile; - return pCifsFile; -} - -static void cifs_del_lock_waiters(struct cifsLockInfo *lock); - -/* - * Release a reference on the file private data. This may involve closing - * the filehandle out on the server. Must be called without holding - * cifs_file_list_lock. - */ -void cifsFileInfo_put(struct cifsFileInfo *cifs_file) -{ - struct inode *inode = cifs_file->dentry->d_inode; - struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink); - struct cifsInodeInfo *cifsi = CIFS_I(inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct cifsLockInfo *li, *tmp; - - spin_lock(&cifs_file_list_lock); - if (--cifs_file->count > 0) { - spin_unlock(&cifs_file_list_lock); - return; - } - - /* remove it from the lists */ - list_del(&cifs_file->flist); - list_del(&cifs_file->tlist); - - if (list_empty(&cifsi->openFileList)) { - cFYI(1, "closing last open instance for inode %p", - cifs_file->dentry->d_inode); - - /* in strict cache mode we need invalidate mapping on the last - close because it may cause a error when we open this file - again and get at least level II oplock */ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) - CIFS_I(inode)->invalid_mapping = true; - - cifs_set_oplock_level(cifsi, 0); - } - spin_unlock(&cifs_file_list_lock); - - cancel_work_sync(&cifs_file->oplock_break); - - if (!tcon->need_reconnect && !cifs_file->invalidHandle) { - int xid, rc; - - xid = GetXid(); - rc = CIFSSMBClose(xid, tcon, cifs_file->netfid); - FreeXid(xid); - } - - /* Delete any outstanding lock records. We'll lose them when the file - * is closed anyway. - */ - mutex_lock(&cifsi->lock_mutex); - list_for_each_entry_safe(li, tmp, &cifsi->llist, llist) { - if (li->netfid != cifs_file->netfid) - continue; - list_del(&li->llist); - cifs_del_lock_waiters(li); - kfree(li); - } - mutex_unlock(&cifsi->lock_mutex); - - cifs_put_tlink(cifs_file->tlink); - dput(cifs_file->dentry); - kfree(cifs_file); -} - -int cifs_open(struct inode *inode, struct file *file) -{ - int rc = -EACCES; - int xid; - __u32 oplock; - struct cifs_sb_info *cifs_sb; - struct cifs_tcon *tcon; - struct tcon_link *tlink; - struct cifsFileInfo *pCifsFile = NULL; - char *full_path = NULL; - bool posix_open_ok = false; - __u16 netfid; - - xid = GetXid(); - - cifs_sb = CIFS_SB(inode->i_sb); - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) { - FreeXid(xid); - return PTR_ERR(tlink); - } - tcon = tlink_tcon(tlink); - - full_path = build_path_from_dentry(file->f_path.dentry); - if (full_path == NULL) { - rc = -ENOMEM; - goto out; - } - - cFYI(1, "inode = 0x%p file flags are 0x%x for %s", - inode, file->f_flags, full_path); - - if (tcon->ses->server->oplocks) - oplock = REQ_OPLOCK; - else - oplock = 0; - - if (!tcon->broken_posix_open && tcon->unix_ext && - (tcon->ses->capabilities & CAP_UNIX) && - (CIFS_UNIX_POSIX_PATH_OPS_CAP & - le64_to_cpu(tcon->fsUnixInfo.Capability))) { - /* can not refresh inode info since size could be stale */ - rc = cifs_posix_open(full_path, &inode, inode->i_sb, - cifs_sb->mnt_file_mode /* ignored */, - file->f_flags, &oplock, &netfid, xid); - if (rc == 0) { - cFYI(1, "posix open succeeded"); - posix_open_ok = true; - } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { - if (tcon->ses->serverNOS) - cERROR(1, "server %s of type %s returned" - " unexpected error on SMB posix open" - ", disabling posix open support." - " Check if server update available.", - tcon->ses->serverName, - tcon->ses->serverNOS); - tcon->broken_posix_open = true; - } else if ((rc != -EIO) && (rc != -EREMOTE) && - (rc != -EOPNOTSUPP)) /* path not found or net err */ - goto out; - /* else fallthrough to retry open the old way on network i/o - or DFS errors */ - } - - if (!posix_open_ok) { - rc = cifs_nt_open(full_path, inode, cifs_sb, tcon, - file->f_flags, &oplock, &netfid, xid); - if (rc) - goto out; - } - - pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock); - if (pCifsFile == NULL) { - CIFSSMBClose(xid, tcon, netfid); - rc = -ENOMEM; - goto out; - } - - cifs_fscache_set_inode_cookie(inode, file); - - if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) { - /* time to set mode which we can not set earlier due to - problems creating new read-only files */ - struct cifs_unix_set_info_args args = { - .mode = inode->i_mode, - .uid = NO_CHANGE_64, - .gid = NO_CHANGE_64, - .ctime = NO_CHANGE_64, - .atime = NO_CHANGE_64, - .mtime = NO_CHANGE_64, - .device = 0, - }; - CIFSSMBUnixSetFileInfo(xid, tcon, &args, netfid, - pCifsFile->pid); - } - -out: - kfree(full_path); - FreeXid(xid); - cifs_put_tlink(tlink); - return rc; -} - -/* Try to reacquire byte range locks that were released when session */ -/* to server was lost */ -static int cifs_relock_file(struct cifsFileInfo *cifsFile) -{ - int rc = 0; - -/* BB list all locks open on this file and relock */ - - return rc; -} - -static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush) -{ - int rc = -EACCES; - int xid; - __u32 oplock; - struct cifs_sb_info *cifs_sb; - struct cifs_tcon *tcon; - struct cifsInodeInfo *pCifsInode; - struct inode *inode; - char *full_path = NULL; - int desiredAccess; - int disposition = FILE_OPEN; - int create_options = CREATE_NOT_DIR; - __u16 netfid; - - xid = GetXid(); - mutex_lock(&pCifsFile->fh_mutex); - if (!pCifsFile->invalidHandle) { - mutex_unlock(&pCifsFile->fh_mutex); - rc = 0; - FreeXid(xid); - return rc; - } - - inode = pCifsFile->dentry->d_inode; - cifs_sb = CIFS_SB(inode->i_sb); - tcon = tlink_tcon(pCifsFile->tlink); - -/* can not grab rename sem here because various ops, including - those that already have the rename sem can end up causing writepage - to get called and if the server was down that means we end up here, - and we can never tell if the caller already has the rename_sem */ - full_path = build_path_from_dentry(pCifsFile->dentry); - if (full_path == NULL) { - rc = -ENOMEM; - mutex_unlock(&pCifsFile->fh_mutex); - FreeXid(xid); - return rc; - } - - cFYI(1, "inode = 0x%p file flags 0x%x for %s", - inode, pCifsFile->f_flags, full_path); - - if (tcon->ses->server->oplocks) - oplock = REQ_OPLOCK; - else - oplock = 0; - - if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && - (CIFS_UNIX_POSIX_PATH_OPS_CAP & - le64_to_cpu(tcon->fsUnixInfo.Capability))) { - - /* - * O_CREAT, O_EXCL and O_TRUNC already had their effect on the - * original open. Must mask them off for a reopen. - */ - unsigned int oflags = pCifsFile->f_flags & - ~(O_CREAT | O_EXCL | O_TRUNC); - - rc = cifs_posix_open(full_path, NULL, inode->i_sb, - cifs_sb->mnt_file_mode /* ignored */, - oflags, &oplock, &netfid, xid); - if (rc == 0) { - cFYI(1, "posix reopen succeeded"); - goto reopen_success; - } - /* fallthrough to retry open the old way on errors, especially - in the reconnect path it is important to retry hard */ - } - - desiredAccess = cifs_convert_flags(pCifsFile->f_flags); - - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - - /* Can not refresh inode by passing in file_info buf to be returned - by SMBOpen and then calling get_inode_info with returned buf - since file might have write behind data that needs to be flushed - and server version of file size can be stale. If we knew for sure - that inode was not dirty locally we could do this */ - - rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess, - create_options, &netfid, &oplock, NULL, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc) { - mutex_unlock(&pCifsFile->fh_mutex); - cFYI(1, "cifs_open returned 0x%x", rc); - cFYI(1, "oplock: %d", oplock); - goto reopen_error_exit; - } - -reopen_success: - pCifsFile->netfid = netfid; - pCifsFile->invalidHandle = false; - mutex_unlock(&pCifsFile->fh_mutex); - pCifsInode = CIFS_I(inode); - - if (can_flush) { - rc = filemap_write_and_wait(inode->i_mapping); - mapping_set_error(inode->i_mapping, rc); - - if (tcon->unix_ext) - rc = cifs_get_inode_info_unix(&inode, - full_path, inode->i_sb, xid); - else - rc = cifs_get_inode_info(&inode, - full_path, NULL, inode->i_sb, - xid, NULL); - } /* else we are writing out data to server already - and could deadlock if we tried to flush data, and - since we do not know if we have data that would - invalidate the current end of file on the server - we can not go to the server to get the new inod - info */ - - cifs_set_oplock_level(pCifsInode, oplock); - - cifs_relock_file(pCifsFile); - -reopen_error_exit: - kfree(full_path); - FreeXid(xid); - return rc; -} - -int cifs_close(struct inode *inode, struct file *file) -{ - if (file->private_data != NULL) { - cifsFileInfo_put(file->private_data); - file->private_data = NULL; - } - - /* return code from the ->release op is always ignored */ - return 0; -} - -int cifs_closedir(struct inode *inode, struct file *file) -{ - int rc = 0; - int xid; - struct cifsFileInfo *pCFileStruct = file->private_data; - char *ptmp; - - cFYI(1, "Closedir inode = 0x%p", inode); - - xid = GetXid(); - - if (pCFileStruct) { - struct cifs_tcon *pTcon = tlink_tcon(pCFileStruct->tlink); - - cFYI(1, "Freeing private data in close dir"); - spin_lock(&cifs_file_list_lock); - if (!pCFileStruct->srch_inf.endOfSearch && - !pCFileStruct->invalidHandle) { - pCFileStruct->invalidHandle = true; - spin_unlock(&cifs_file_list_lock); - rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid); - cFYI(1, "Closing uncompleted readdir with rc %d", - rc); - /* not much we can do if it fails anyway, ignore rc */ - rc = 0; - } else - spin_unlock(&cifs_file_list_lock); - ptmp = pCFileStruct->srch_inf.ntwrk_buf_start; - if (ptmp) { - cFYI(1, "closedir free smb buf in srch struct"); - pCFileStruct->srch_inf.ntwrk_buf_start = NULL; - if (pCFileStruct->srch_inf.smallBuf) - cifs_small_buf_release(ptmp); - else - cifs_buf_release(ptmp); - } - cifs_put_tlink(pCFileStruct->tlink); - kfree(file->private_data); - file->private_data = NULL; - } - /* BB can we lock the filestruct while this is going on? */ - FreeXid(xid); - return rc; -} - -static struct cifsLockInfo * -cifs_lock_init(__u64 offset, __u64 length, __u8 type, __u16 netfid) -{ - struct cifsLockInfo *lock = - kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); - if (!lock) - return lock; - lock->offset = offset; - lock->length = length; - lock->type = type; - lock->netfid = netfid; - lock->pid = current->tgid; - INIT_LIST_HEAD(&lock->blist); - init_waitqueue_head(&lock->block_q); - return lock; -} - -static void -cifs_del_lock_waiters(struct cifsLockInfo *lock) -{ - struct cifsLockInfo *li, *tmp; - list_for_each_entry_safe(li, tmp, &lock->blist, blist) { - list_del_init(&li->blist); - wake_up(&li->block_q); - } -} - -static bool -__cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, - __u64 length, __u8 type, __u16 netfid, - struct cifsLockInfo **conf_lock) -{ - struct cifsLockInfo *li, *tmp; - - list_for_each_entry_safe(li, tmp, &cinode->llist, llist) { - if (offset + length <= li->offset || - offset >= li->offset + li->length) - continue; - else if ((type & LOCKING_ANDX_SHARED_LOCK) && - ((netfid == li->netfid && current->tgid == li->pid) || - type == li->type)) - continue; - else { - *conf_lock = li; - return true; - } - } - return false; -} - -static bool -cifs_find_lock_conflict(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, - struct cifsLockInfo **conf_lock) -{ - return __cifs_find_lock_conflict(cinode, lock->offset, lock->length, - lock->type, lock->netfid, conf_lock); -} - -/* - * Check if there is another lock that prevents us to set the lock (mandatory - * style). If such a lock exists, update the flock structure with its - * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks - * or leave it the same if we can't. Returns 0 if we don't need to request to - * the server or 1 otherwise. - */ -static int -cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, - __u8 type, __u16 netfid, struct file_lock *flock) -{ - int rc = 0; - struct cifsLockInfo *conf_lock; - bool exist; - - mutex_lock(&cinode->lock_mutex); - - exist = __cifs_find_lock_conflict(cinode, offset, length, type, netfid, - &conf_lock); - if (exist) { - flock->fl_start = conf_lock->offset; - flock->fl_end = conf_lock->offset + conf_lock->length - 1; - flock->fl_pid = conf_lock->pid; - if (conf_lock->type & LOCKING_ANDX_SHARED_LOCK) - flock->fl_type = F_RDLCK; - else - flock->fl_type = F_WRLCK; - } else if (!cinode->can_cache_brlcks) - rc = 1; - else - flock->fl_type = F_UNLCK; - - mutex_unlock(&cinode->lock_mutex); - return rc; -} - -static void -cifs_lock_add(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock) -{ - mutex_lock(&cinode->lock_mutex); - list_add_tail(&lock->llist, &cinode->llist); - mutex_unlock(&cinode->lock_mutex); -} - -/* - * Set the byte-range lock (mandatory style). Returns: - * 1) 0, if we set the lock and don't need to request to the server; - * 2) 1, if no locks prevent us but we need to request to the server; - * 3) -EACCESS, if there is a lock that prevents us and wait is false. - */ -static int -cifs_lock_add_if(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, - bool wait) -{ - struct cifsLockInfo *conf_lock; - bool exist; - int rc = 0; - -try_again: - exist = false; - mutex_lock(&cinode->lock_mutex); - - exist = cifs_find_lock_conflict(cinode, lock, &conf_lock); - if (!exist && cinode->can_cache_brlcks) { - list_add_tail(&lock->llist, &cinode->llist); - mutex_unlock(&cinode->lock_mutex); - return rc; - } - - if (!exist) - rc = 1; - else if (!wait) - rc = -EACCES; - else { - list_add_tail(&lock->blist, &conf_lock->blist); - mutex_unlock(&cinode->lock_mutex); - rc = wait_event_interruptible(lock->block_q, - (lock->blist.prev == &lock->blist) && - (lock->blist.next == &lock->blist)); - if (!rc) - goto try_again; - mutex_lock(&cinode->lock_mutex); - list_del_init(&lock->blist); - } - - mutex_unlock(&cinode->lock_mutex); - return rc; -} - -/* - * Check if there is another lock that prevents us to set the lock (posix - * style). If such a lock exists, update the flock structure with its - * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks - * or leave it the same if we can't. Returns 0 if we don't need to request to - * the server or 1 otherwise. - */ -static int -cifs_posix_lock_test(struct file *file, struct file_lock *flock) -{ - int rc = 0; - struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode); - unsigned char saved_type = flock->fl_type; - - if ((flock->fl_flags & FL_POSIX) == 0) - return 1; - - mutex_lock(&cinode->lock_mutex); - posix_test_lock(file, flock); - - if (flock->fl_type == F_UNLCK && !cinode->can_cache_brlcks) { - flock->fl_type = saved_type; - rc = 1; - } - - mutex_unlock(&cinode->lock_mutex); - return rc; -} - -/* - * Set the byte-range lock (posix style). Returns: - * 1) 0, if we set the lock and don't need to request to the server; - * 2) 1, if we need to request to the server; - * 3) <0, if the error occurs while setting the lock. - */ -static int -cifs_posix_lock_set(struct file *file, struct file_lock *flock) -{ - struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode); - int rc = 1; - - if ((flock->fl_flags & FL_POSIX) == 0) - return rc; - -try_again: - mutex_lock(&cinode->lock_mutex); - if (!cinode->can_cache_brlcks) { - mutex_unlock(&cinode->lock_mutex); - return rc; - } - - rc = posix_lock_file(file, flock, NULL); - mutex_unlock(&cinode->lock_mutex); - if (rc == FILE_LOCK_DEFERRED) { - rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next); - if (!rc) - goto try_again; - locks_delete_block(flock); - } - return rc; -} - -static int -cifs_push_mandatory_locks(struct cifsFileInfo *cfile) -{ - int xid, rc = 0, stored_rc; - struct cifsLockInfo *li, *tmp; - struct cifs_tcon *tcon; - struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); - unsigned int num, max_num; - LOCKING_ANDX_RANGE *buf, *cur; - int types[] = {LOCKING_ANDX_LARGE_FILES, - LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES}; - int i; - - xid = GetXid(); - tcon = tlink_tcon(cfile->tlink); - - mutex_lock(&cinode->lock_mutex); - if (!cinode->can_cache_brlcks) { - mutex_unlock(&cinode->lock_mutex); - FreeXid(xid); - return rc; - } - - max_num = (tcon->ses->server->maxBuf - sizeof(struct smb_hdr)) / - sizeof(LOCKING_ANDX_RANGE); - buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); - if (!buf) { - mutex_unlock(&cinode->lock_mutex); - FreeXid(xid); - return rc; - } - - for (i = 0; i < 2; i++) { - cur = buf; - num = 0; - list_for_each_entry_safe(li, tmp, &cinode->llist, llist) { - if (li->type != types[i]) - continue; - cur->Pid = cpu_to_le16(li->pid); - cur->LengthLow = cpu_to_le32((u32)li->length); - cur->LengthHigh = cpu_to_le32((u32)(li->length>>32)); - cur->OffsetLow = cpu_to_le32((u32)li->offset); - cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32)); - if (++num == max_num) { - stored_rc = cifs_lockv(xid, tcon, cfile->netfid, - li->type, 0, num, buf); - if (stored_rc) - rc = stored_rc; - cur = buf; - num = 0; - } else - cur++; - } - - if (num) { - stored_rc = cifs_lockv(xid, tcon, cfile->netfid, - types[i], 0, num, buf); - if (stored_rc) - rc = stored_rc; - } - } - - cinode->can_cache_brlcks = false; - mutex_unlock(&cinode->lock_mutex); - - kfree(buf); - FreeXid(xid); - return rc; -} - -/* copied from fs/locks.c with a name change */ -#define cifs_for_each_lock(inode, lockp) \ - for (lockp = &inode->i_flock; *lockp != NULL; \ - lockp = &(*lockp)->fl_next) - -struct lock_to_push { - struct list_head llist; - __u64 offset; - __u64 length; - __u32 pid; - __u16 netfid; - __u8 type; -}; - -static int -cifs_push_posix_locks(struct cifsFileInfo *cfile) -{ - struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); - struct file_lock *flock, **before; - unsigned int count = 0, i = 0; - int rc = 0, xid, type; - struct list_head locks_to_send, *el; - struct lock_to_push *lck, *tmp; - __u64 length; - - xid = GetXid(); - - mutex_lock(&cinode->lock_mutex); - if (!cinode->can_cache_brlcks) { - mutex_unlock(&cinode->lock_mutex); - FreeXid(xid); - return rc; - } - - lock_flocks(); - cifs_for_each_lock(cfile->dentry->d_inode, before) { - if ((*before)->fl_flags & FL_POSIX) - count++; - } - unlock_flocks(); - - INIT_LIST_HEAD(&locks_to_send); - - /* - * Allocating count locks is enough because no FL_POSIX locks can be - * added to the list while we are holding cinode->lock_mutex that - * protects locking operations of this inode. - */ - for (; i < count; i++) { - lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL); - if (!lck) { - rc = -ENOMEM; - goto err_out; - } - list_add_tail(&lck->llist, &locks_to_send); - } - - el = locks_to_send.next; - lock_flocks(); - cifs_for_each_lock(cfile->dentry->d_inode, before) { - flock = *before; - if ((flock->fl_flags & FL_POSIX) == 0) - continue; - if (el == &locks_to_send) { - /* - * The list ended. We don't have enough allocated - * structures - something is really wrong. - */ - cERROR(1, "Can't push all brlocks!"); - break; - } - length = 1 + flock->fl_end - flock->fl_start; - if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK) - type = CIFS_RDLCK; - else - type = CIFS_WRLCK; - lck = list_entry(el, struct lock_to_push, llist); - lck->pid = flock->fl_pid; - lck->netfid = cfile->netfid; - lck->length = length; - lck->type = type; - lck->offset = flock->fl_start; - el = el->next; - } - unlock_flocks(); - - list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) { - struct file_lock tmp_lock; - int stored_rc; - - tmp_lock.fl_start = lck->offset; - stored_rc = CIFSSMBPosixLock(xid, tcon, lck->netfid, lck->pid, - 0, lck->length, &tmp_lock, - lck->type, 0); - if (stored_rc) - rc = stored_rc; - list_del(&lck->llist); - kfree(lck); - } - -out: - cinode->can_cache_brlcks = false; - mutex_unlock(&cinode->lock_mutex); - - FreeXid(xid); - return rc; -err_out: - list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) { - list_del(&lck->llist); - kfree(lck); - } - goto out; -} - -static int -cifs_push_locks(struct cifsFileInfo *cfile) -{ - struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb); - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); - - if ((tcon->ses->capabilities & CAP_UNIX) && - (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && - ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) - return cifs_push_posix_locks(cfile); - - return cifs_push_mandatory_locks(cfile); -} - -static void -cifs_read_flock(struct file_lock *flock, __u8 *type, int *lock, int *unlock, - bool *wait_flag) -{ - if (flock->fl_flags & FL_POSIX) - cFYI(1, "Posix"); - if (flock->fl_flags & FL_FLOCK) - cFYI(1, "Flock"); - if (flock->fl_flags & FL_SLEEP) { - cFYI(1, "Blocking lock"); - *wait_flag = true; - } - if (flock->fl_flags & FL_ACCESS) - cFYI(1, "Process suspended by mandatory locking - " - "not implemented yet"); - if (flock->fl_flags & FL_LEASE) - cFYI(1, "Lease on file - not implemented yet"); - if (flock->fl_flags & - (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE))) - cFYI(1, "Unknown lock flags 0x%x", flock->fl_flags); - - *type = LOCKING_ANDX_LARGE_FILES; - if (flock->fl_type == F_WRLCK) { - cFYI(1, "F_WRLCK "); - *lock = 1; - } else if (flock->fl_type == F_UNLCK) { - cFYI(1, "F_UNLCK"); - *unlock = 1; - /* Check if unlock includes more than one lock range */ - } else if (flock->fl_type == F_RDLCK) { - cFYI(1, "F_RDLCK"); - *type |= LOCKING_ANDX_SHARED_LOCK; - *lock = 1; - } else if (flock->fl_type == F_EXLCK) { - cFYI(1, "F_EXLCK"); - *lock = 1; - } else if (flock->fl_type == F_SHLCK) { - cFYI(1, "F_SHLCK"); - *type |= LOCKING_ANDX_SHARED_LOCK; - *lock = 1; - } else - cFYI(1, "Unknown type of lock"); -} - -static int -cifs_getlk(struct file *file, struct file_lock *flock, __u8 type, - bool wait_flag, bool posix_lck, int xid) -{ - int rc = 0; - __u64 length = 1 + flock->fl_end - flock->fl_start; - struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); - struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); - __u16 netfid = cfile->netfid; - - if (posix_lck) { - int posix_lock_type; - - rc = cifs_posix_lock_test(file, flock); - if (!rc) - return rc; - - if (type & LOCKING_ANDX_SHARED_LOCK) - posix_lock_type = CIFS_RDLCK; - else - posix_lock_type = CIFS_WRLCK; - rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid, - 1 /* get */, length, flock, - posix_lock_type, wait_flag); - return rc; - } - - rc = cifs_lock_test(cinode, flock->fl_start, length, type, netfid, - flock); - if (!rc) - return rc; - - /* BB we could chain these into one lock request BB */ - rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, - flock->fl_start, 0, 1, type, 0, 0); - if (rc == 0) { - rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, - length, flock->fl_start, 1, 0, - type, 0, 0); - flock->fl_type = F_UNLCK; - if (rc != 0) - cERROR(1, "Error unlocking previously locked " - "range %d during test of lock", rc); - return 0; - } - - if (type & LOCKING_ANDX_SHARED_LOCK) { - flock->fl_type = F_WRLCK; - return 0; - } - - rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, - flock->fl_start, 0, 1, - type | LOCKING_ANDX_SHARED_LOCK, 0, 0); - if (rc == 0) { - rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, - length, flock->fl_start, 1, 0, - type | LOCKING_ANDX_SHARED_LOCK, - 0, 0); - flock->fl_type = F_RDLCK; - if (rc != 0) - cERROR(1, "Error unlocking previously locked " - "range %d during test of lock", rc); - } else - flock->fl_type = F_WRLCK; - - return 0; -} - -static void -cifs_move_llist(struct list_head *source, struct list_head *dest) -{ - struct list_head *li, *tmp; - list_for_each_safe(li, tmp, source) - list_move(li, dest); -} - -static void -cifs_free_llist(struct list_head *llist) -{ - struct cifsLockInfo *li, *tmp; - list_for_each_entry_safe(li, tmp, llist, llist) { - cifs_del_lock_waiters(li); - list_del(&li->llist); - kfree(li); - } -} - -static int -cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid) -{ - int rc = 0, stored_rc; - int types[] = {LOCKING_ANDX_LARGE_FILES, - LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES}; - unsigned int i; - unsigned int max_num, num; - LOCKING_ANDX_RANGE *buf, *cur; - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); - struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); - struct cifsLockInfo *li, *tmp; - __u64 length = 1 + flock->fl_end - flock->fl_start; - struct list_head tmp_llist; - - INIT_LIST_HEAD(&tmp_llist); - - max_num = (tcon->ses->server->maxBuf - sizeof(struct smb_hdr)) / - sizeof(LOCKING_ANDX_RANGE); - buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); - if (!buf) - return -ENOMEM; - - mutex_lock(&cinode->lock_mutex); - for (i = 0; i < 2; i++) { - cur = buf; - num = 0; - list_for_each_entry_safe(li, tmp, &cinode->llist, llist) { - if (flock->fl_start > li->offset || - (flock->fl_start + length) < - (li->offset + li->length)) - continue; - if (current->tgid != li->pid) - continue; - if (cfile->netfid != li->netfid) - continue; - if (types[i] != li->type) - continue; - if (!cinode->can_cache_brlcks) { - cur->Pid = cpu_to_le16(li->pid); - cur->LengthLow = cpu_to_le32((u32)li->length); - cur->LengthHigh = - cpu_to_le32((u32)(li->length>>32)); - cur->OffsetLow = cpu_to_le32((u32)li->offset); - cur->OffsetHigh = - cpu_to_le32((u32)(li->offset>>32)); - /* - * We need to save a lock here to let us add - * it again to the inode list if the unlock - * range request fails on the server. - */ - list_move(&li->llist, &tmp_llist); - if (++num == max_num) { - stored_rc = cifs_lockv(xid, tcon, - cfile->netfid, - li->type, num, - 0, buf); - if (stored_rc) { - /* - * We failed on the unlock range - * request - add all locks from - * the tmp list to the head of - * the inode list. - */ - cifs_move_llist(&tmp_llist, - &cinode->llist); - rc = stored_rc; - } else - /* - * The unlock range request - * succeed - free the tmp list. - */ - cifs_free_llist(&tmp_llist); - cur = buf; - num = 0; - } else - cur++; - } else { - /* - * We can cache brlock requests - simply remove - * a lock from the inode list. - */ - list_del(&li->llist); - cifs_del_lock_waiters(li); - kfree(li); - } - } - if (num) { - stored_rc = cifs_lockv(xid, tcon, cfile->netfid, - types[i], num, 0, buf); - if (stored_rc) { - cifs_move_llist(&tmp_llist, &cinode->llist); - rc = stored_rc; - } else - cifs_free_llist(&tmp_llist); - } - } - - mutex_unlock(&cinode->lock_mutex); - kfree(buf); - return rc; -} - -static int -cifs_setlk(struct file *file, struct file_lock *flock, __u8 type, - bool wait_flag, bool posix_lck, int lock, int unlock, int xid) -{ - int rc = 0; - __u64 length = 1 + flock->fl_end - flock->fl_start; - struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); - struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode); - __u16 netfid = cfile->netfid; - - if (posix_lck) { - int posix_lock_type; - - rc = cifs_posix_lock_set(file, flock); - if (!rc || rc < 0) - return rc; - - if (type & LOCKING_ANDX_SHARED_LOCK) - posix_lock_type = CIFS_RDLCK; - else - posix_lock_type = CIFS_WRLCK; - - if (unlock == 1) - posix_lock_type = CIFS_UNLCK; - - rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid, - 0 /* set */, length, flock, - posix_lock_type, wait_flag); - goto out; - } - - if (lock) { - struct cifsLockInfo *lock; - - lock = cifs_lock_init(flock->fl_start, length, type, netfid); - if (!lock) - return -ENOMEM; - - rc = cifs_lock_add_if(cinode, lock, wait_flag); - if (rc < 0) - kfree(lock); - if (rc <= 0) - goto out; - - rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, - flock->fl_start, 0, 1, type, wait_flag, 0); - if (rc) { - kfree(lock); - goto out; - } - - cifs_lock_add(cinode, lock); - } else if (unlock) - rc = cifs_unlock_range(cfile, flock, xid); - -out: - if (flock->fl_flags & FL_POSIX) - posix_lock_file_wait(file, flock); - return rc; -} - -int cifs_lock(struct file *file, int cmd, struct file_lock *flock) -{ - int rc, xid; - int lock = 0, unlock = 0; - bool wait_flag = false; - bool posix_lck = false; - struct cifs_sb_info *cifs_sb; - struct cifs_tcon *tcon; - struct cifsInodeInfo *cinode; - struct cifsFileInfo *cfile; - __u16 netfid; - __u8 type; - - rc = -EACCES; - xid = GetXid(); - - cFYI(1, "Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld " - "end: %lld", cmd, flock->fl_flags, flock->fl_type, - flock->fl_start, flock->fl_end); - - cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag); - - cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - cfile = (struct cifsFileInfo *)file->private_data; - tcon = tlink_tcon(cfile->tlink); - netfid = cfile->netfid; - cinode = CIFS_I(file->f_path.dentry->d_inode); - - if ((tcon->ses->capabilities & CAP_UNIX) && - (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && - ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) - posix_lck = true; - /* - * BB add code here to normalize offset and length to account for - * negative length which we can not accept over the wire. - */ - if (IS_GETLK(cmd)) { - rc = cifs_getlk(file, flock, type, wait_flag, posix_lck, xid); - FreeXid(xid); - return rc; - } - - if (!lock && !unlock) { - /* - * if no lock or unlock then nothing to do since we do not - * know what it is - */ - FreeXid(xid); - return -EOPNOTSUPP; - } - - rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock, - xid); - FreeXid(xid); - return rc; -} - -/* - * update the file size (if needed) after a write. Should be called with - * the inode->i_lock held - */ -void -cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, - unsigned int bytes_written) -{ - loff_t end_of_write = offset + bytes_written; - - if (end_of_write > cifsi->server_eof) - cifsi->server_eof = end_of_write; -} - -static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid, - const char *write_data, size_t write_size, - loff_t *poffset) -{ - int rc = 0; - unsigned int bytes_written = 0; - unsigned int total_written; - struct cifs_sb_info *cifs_sb; - struct cifs_tcon *pTcon; - int xid; - struct dentry *dentry = open_file->dentry; - struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); - struct cifs_io_parms io_parms; - - cifs_sb = CIFS_SB(dentry->d_sb); - - cFYI(1, "write %zd bytes to offset %lld of %s", write_size, - *poffset, dentry->d_name.name); - - pTcon = tlink_tcon(open_file->tlink); - - xid = GetXid(); - - for (total_written = 0; write_size > total_written; - total_written += bytes_written) { - rc = -EAGAIN; - while (rc == -EAGAIN) { - struct kvec iov[2]; - unsigned int len; - - if (open_file->invalidHandle) { - /* we could deadlock if we called - filemap_fdatawait from here so tell - reopen_file not to flush data to - server now */ - rc = cifs_reopen_file(open_file, false); - if (rc != 0) - break; - } - - len = min((size_t)cifs_sb->wsize, - write_size - total_written); - /* iov[0] is reserved for smb header */ - iov[1].iov_base = (char *)write_data + total_written; - iov[1].iov_len = len; - io_parms.netfid = open_file->netfid; - io_parms.pid = pid; - io_parms.tcon = pTcon; - io_parms.offset = *poffset; - io_parms.length = len; - rc = CIFSSMBWrite2(xid, &io_parms, &bytes_written, iov, - 1, 0); - } - if (rc || (bytes_written == 0)) { - if (total_written) - break; - else { - FreeXid(xid); - return rc; - } - } else { - spin_lock(&dentry->d_inode->i_lock); - cifs_update_eof(cifsi, *poffset, bytes_written); - spin_unlock(&dentry->d_inode->i_lock); - *poffset += bytes_written; - } - } - - cifs_stats_bytes_written(pTcon, total_written); - - if (total_written > 0) { - spin_lock(&dentry->d_inode->i_lock); - if (*poffset > dentry->d_inode->i_size) - i_size_write(dentry->d_inode, *poffset); - spin_unlock(&dentry->d_inode->i_lock); - } - mark_inode_dirty_sync(dentry->d_inode); - FreeXid(xid); - return total_written; -} - -struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, - bool fsuid_only) -{ - struct cifsFileInfo *open_file = NULL; - struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb); - - /* only filter by fsuid on multiuser mounts */ - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) - fsuid_only = false; - - spin_lock(&cifs_file_list_lock); - /* we could simply get the first_list_entry since write-only entries - are always at the end of the list but since the first entry might - have a close pending, we go through the whole list */ - list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { - if (fsuid_only && open_file->uid != current_fsuid()) - continue; - if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) { - if (!open_file->invalidHandle) { - /* found a good file */ - /* lock it so it will not be closed on us */ - cifsFileInfo_get(open_file); - spin_unlock(&cifs_file_list_lock); - return open_file; - } /* else might as well continue, and look for - another, or simply have the caller reopen it - again rather than trying to fix this handle */ - } else /* write only file */ - break; /* write only files are last so must be done */ - } - spin_unlock(&cifs_file_list_lock); - return NULL; -} - -struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, - bool fsuid_only) -{ - struct cifsFileInfo *open_file, *inv_file = NULL; - struct cifs_sb_info *cifs_sb; - bool any_available = false; - int rc; - unsigned int refind = 0; - - /* Having a null inode here (because mapping->host was set to zero by - the VFS or MM) should not happen but we had reports of on oops (due to - it being zero) during stress testcases so we need to check for it */ - - if (cifs_inode == NULL) { - cERROR(1, "Null inode passed to cifs_writeable_file"); - dump_stack(); - return NULL; - } - - cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb); - - /* only filter by fsuid on multiuser mounts */ - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) - fsuid_only = false; - - spin_lock(&cifs_file_list_lock); -refind_writable: - if (refind > MAX_REOPEN_ATT) { - spin_unlock(&cifs_file_list_lock); - return NULL; - } - list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { - if (!any_available && open_file->pid != current->tgid) - continue; - if (fsuid_only && open_file->uid != current_fsuid()) - continue; - if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { - if (!open_file->invalidHandle) { - /* found a good writable file */ - cifsFileInfo_get(open_file); - spin_unlock(&cifs_file_list_lock); - return open_file; - } else { - if (!inv_file) - inv_file = open_file; - } - } - } - /* couldn't find useable FH with same pid, try any available */ - if (!any_available) { - any_available = true; - goto refind_writable; - } - - if (inv_file) { - any_available = false; - cifsFileInfo_get(inv_file); - } - - spin_unlock(&cifs_file_list_lock); - - if (inv_file) { - rc = cifs_reopen_file(inv_file, false); - if (!rc) - return inv_file; - else { - spin_lock(&cifs_file_list_lock); - list_move_tail(&inv_file->flist, - &cifs_inode->openFileList); - spin_unlock(&cifs_file_list_lock); - cifsFileInfo_put(inv_file); - spin_lock(&cifs_file_list_lock); - ++refind; - goto refind_writable; - } - } - - return NULL; -} - -static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) -{ - struct address_space *mapping = page->mapping; - loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; - char *write_data; - int rc = -EFAULT; - int bytes_written = 0; - struct inode *inode; - struct cifsFileInfo *open_file; - - if (!mapping || !mapping->host) - return -EFAULT; - - inode = page->mapping->host; - - offset += (loff_t)from; - write_data = kmap(page); - write_data += from; - - if ((to > PAGE_CACHE_SIZE) || (from > to)) { - kunmap(page); - return -EIO; - } - - /* racing with truncate? */ - if (offset > mapping->host->i_size) { - kunmap(page); - return 0; /* don't care */ - } - - /* check to make sure that we are not extending the file */ - if (mapping->host->i_size - offset < (loff_t)to) - to = (unsigned)(mapping->host->i_size - offset); - - open_file = find_writable_file(CIFS_I(mapping->host), false); - if (open_file) { - bytes_written = cifs_write(open_file, open_file->pid, - write_data, to - from, &offset); - cifsFileInfo_put(open_file); - /* Does mm or vfs already set times? */ - inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb); - if ((bytes_written > 0) && (offset)) - rc = 0; - else if (bytes_written < 0) - rc = bytes_written; - } else { - cFYI(1, "No writeable filehandles for inode"); - rc = -EIO; - } - - kunmap(page); - return rc; -} - -/* - * Marshal up the iov array, reserving the first one for the header. Also, - * set wdata->bytes. - */ -static void -cifs_writepages_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata) -{ - int i; - struct inode *inode = wdata->cfile->dentry->d_inode; - loff_t size = i_size_read(inode); - - /* marshal up the pages into iov array */ - wdata->bytes = 0; - for (i = 0; i < wdata->nr_pages; i++) { - iov[i + 1].iov_len = min(size - page_offset(wdata->pages[i]), - (loff_t)PAGE_CACHE_SIZE); - iov[i + 1].iov_base = kmap(wdata->pages[i]); - wdata->bytes += iov[i + 1].iov_len; - } -} - -static int cifs_writepages(struct address_space *mapping, - struct writeback_control *wbc) -{ - struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb); - bool done = false, scanned = false, range_whole = false; - pgoff_t end, index; - struct cifs_writedata *wdata; - struct page *page; - int rc = 0; - - /* - * If wsize is smaller than the page cache size, default to writing - * one page at a time via cifs_writepage - */ - if (cifs_sb->wsize < PAGE_CACHE_SIZE) - return generic_writepages(mapping, wbc); - - if (wbc->range_cyclic) { - index = mapping->writeback_index; /* Start from prev offset */ - end = -1; - } else { - index = wbc->range_start >> PAGE_CACHE_SHIFT; - end = wbc->range_end >> PAGE_CACHE_SHIFT; - if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) - range_whole = true; - scanned = true; - } -retry: - while (!done && index <= end) { - unsigned int i, nr_pages, found_pages; - pgoff_t next = 0, tofind; - struct page **pages; - - tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1, - end - index) + 1; - - wdata = cifs_writedata_alloc((unsigned int)tofind, - cifs_writev_complete); - if (!wdata) { - rc = -ENOMEM; - break; - } - - /* - * find_get_pages_tag seems to return a max of 256 on each - * iteration, so we must call it several times in order to - * fill the array or the wsize is effectively limited to - * 256 * PAGE_CACHE_SIZE. - */ - found_pages = 0; - pages = wdata->pages; - do { - nr_pages = find_get_pages_tag(mapping, &index, - PAGECACHE_TAG_DIRTY, - tofind, pages); - found_pages += nr_pages; - tofind -= nr_pages; - pages += nr_pages; - } while (nr_pages && tofind && index <= end); - - if (found_pages == 0) { - kref_put(&wdata->refcount, cifs_writedata_release); - break; - } - - nr_pages = 0; - for (i = 0; i < found_pages; i++) { - page = wdata->pages[i]; - /* - * At this point we hold neither mapping->tree_lock nor - * lock on the page itself: the page may be truncated or - * invalidated (changing page->mapping to NULL), or even - * swizzled back from swapper_space to tmpfs file - * mapping - */ - - if (nr_pages == 0) - lock_page(page); - else if (!trylock_page(page)) - break; - - if (unlikely(page->mapping != mapping)) { - unlock_page(page); - break; - } - - if (!wbc->range_cyclic && page->index > end) { - done = true; - unlock_page(page); - break; - } - - if (next && (page->index != next)) { - /* Not next consecutive page */ - unlock_page(page); - break; - } - - if (wbc->sync_mode != WB_SYNC_NONE) - wait_on_page_writeback(page); - - if (PageWriteback(page) || - !clear_page_dirty_for_io(page)) { - unlock_page(page); - break; - } - - /* - * This actually clears the dirty bit in the radix tree. - * See cifs_writepage() for more commentary. - */ - set_page_writeback(page); - - if (page_offset(page) >= mapping->host->i_size) { - done = true; - unlock_page(page); - end_page_writeback(page); - break; - } - - wdata->pages[i] = page; - next = page->index + 1; - ++nr_pages; - } - - /* reset index to refind any pages skipped */ - if (nr_pages == 0) - index = wdata->pages[0]->index + 1; - - /* put any pages we aren't going to use */ - for (i = nr_pages; i < found_pages; i++) { - page_cache_release(wdata->pages[i]); - wdata->pages[i] = NULL; - } - - /* nothing to write? */ - if (nr_pages == 0) { - kref_put(&wdata->refcount, cifs_writedata_release); - continue; - } - - wdata->sync_mode = wbc->sync_mode; - wdata->nr_pages = nr_pages; - wdata->offset = page_offset(wdata->pages[0]); - wdata->marshal_iov = cifs_writepages_marshal_iov; - - do { - if (wdata->cfile != NULL) - cifsFileInfo_put(wdata->cfile); - wdata->cfile = find_writable_file(CIFS_I(mapping->host), - false); - if (!wdata->cfile) { - cERROR(1, "No writable handles for inode"); - rc = -EBADF; - break; - } - wdata->pid = wdata->cfile->pid; - rc = cifs_async_writev(wdata); - } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN); - - for (i = 0; i < nr_pages; ++i) - unlock_page(wdata->pages[i]); - - /* send failure -- clean up the mess */ - if (rc != 0) { - for (i = 0; i < nr_pages; ++i) { - if (rc == -EAGAIN) - redirty_page_for_writepage(wbc, - wdata->pages[i]); - else - SetPageError(wdata->pages[i]); - end_page_writeback(wdata->pages[i]); - page_cache_release(wdata->pages[i]); - } - if (rc != -EAGAIN) - mapping_set_error(mapping, rc); - } - kref_put(&wdata->refcount, cifs_writedata_release); - - wbc->nr_to_write -= nr_pages; - if (wbc->nr_to_write <= 0) - done = true; - - index = next; - } - - if (!scanned && !done) { - /* - * We hit the last page and there is more work to be done: wrap - * back to the start of the file - */ - scanned = true; - index = 0; - goto retry; - } - - if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) - mapping->writeback_index = index; - - return rc; -} - -static int -cifs_writepage_locked(struct page *page, struct writeback_control *wbc) -{ - int rc; - int xid; - - xid = GetXid(); -/* BB add check for wbc flags */ - page_cache_get(page); - if (!PageUptodate(page)) - cFYI(1, "ppw - page not up to date"); - - /* - * Set the "writeback" flag, and clear "dirty" in the radix tree. - * - * A writepage() implementation always needs to do either this, - * or re-dirty the page with "redirty_page_for_writepage()" in - * the case of a failure. - * - * Just unlocking the page will cause the radix tree tag-bits - * to fail to update with the state of the page correctly. - */ - set_page_writeback(page); -retry_write: - rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE); - if (rc == -EAGAIN && wbc->sync_mode == WB_SYNC_ALL) - goto retry_write; - else if (rc == -EAGAIN) - redirty_page_for_writepage(wbc, page); - else if (rc != 0) - SetPageError(page); - else - SetPageUptodate(page); - end_page_writeback(page); - page_cache_release(page); - FreeXid(xid); - return rc; -} - -static int cifs_writepage(struct page *page, struct writeback_control *wbc) -{ - int rc = cifs_writepage_locked(page, wbc); - unlock_page(page); - return rc; -} - -static int cifs_write_end(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, unsigned copied, - struct page *page, void *fsdata) -{ - int rc; - struct inode *inode = mapping->host; - struct cifsFileInfo *cfile = file->private_data; - struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb); - __u32 pid; - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) - pid = cfile->pid; - else - pid = current->tgid; - - cFYI(1, "write_end for page %p from pos %lld with %d bytes", - page, pos, copied); - - if (PageChecked(page)) { - if (copied == len) - SetPageUptodate(page); - ClearPageChecked(page); - } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE) - SetPageUptodate(page); - - if (!PageUptodate(page)) { - char *page_data; - unsigned offset = pos & (PAGE_CACHE_SIZE - 1); - int xid; - - xid = GetXid(); - /* this is probably better than directly calling - partialpage_write since in this function the file handle is - known which we might as well leverage */ - /* BB check if anything else missing out of ppw - such as updating last write time */ - page_data = kmap(page); - rc = cifs_write(cfile, pid, page_data + offset, copied, &pos); - /* if (rc < 0) should we set writebehind rc? */ - kunmap(page); - - FreeXid(xid); - } else { - rc = copied; - pos += copied; - set_page_dirty(page); - } - - if (rc > 0) { - spin_lock(&inode->i_lock); - if (pos > inode->i_size) - i_size_write(inode, pos); - spin_unlock(&inode->i_lock); - } - - unlock_page(page); - page_cache_release(page); - - return rc; -} - -int cifs_strict_fsync(struct file *file, loff_t start, loff_t end, - int datasync) -{ - int xid; - int rc = 0; - struct cifs_tcon *tcon; - struct cifsFileInfo *smbfile = file->private_data; - struct inode *inode = file->f_path.dentry->d_inode; - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - - rc = filemap_write_and_wait_range(inode->i_mapping, start, end); - if (rc) - return rc; - mutex_lock(&inode->i_mutex); - - xid = GetXid(); - - cFYI(1, "Sync file - name: %s datasync: 0x%x", - file->f_path.dentry->d_name.name, datasync); - - if (!CIFS_I(inode)->clientCanCacheRead) { - rc = cifs_invalidate_mapping(inode); - if (rc) { - cFYI(1, "rc: %d during invalidate phase", rc); - rc = 0; /* don't care about it in fsync */ - } - } - - tcon = tlink_tcon(smbfile->tlink); - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) - rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); - - FreeXid(xid); - mutex_unlock(&inode->i_mutex); - return rc; -} - -int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync) -{ - int xid; - int rc = 0; - struct cifs_tcon *tcon; - struct cifsFileInfo *smbfile = file->private_data; - struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - struct inode *inode = file->f_mapping->host; - - rc = filemap_write_and_wait_range(inode->i_mapping, start, end); - if (rc) - return rc; - mutex_lock(&inode->i_mutex); - - xid = GetXid(); - - cFYI(1, "Sync file - name: %s datasync: 0x%x", - file->f_path.dentry->d_name.name, datasync); - - tcon = tlink_tcon(smbfile->tlink); - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) - rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); - - FreeXid(xid); - mutex_unlock(&inode->i_mutex); - return rc; -} - -/* - * As file closes, flush all cached write data for this inode checking - * for write behind errors. - */ -int cifs_flush(struct file *file, fl_owner_t id) -{ - struct inode *inode = file->f_path.dentry->d_inode; - int rc = 0; - - if (file->f_mode & FMODE_WRITE) - rc = filemap_write_and_wait(inode->i_mapping); - - cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc); - - return rc; -} - -static int -cifs_write_allocate_pages(struct page **pages, unsigned long num_pages) -{ - int rc = 0; - unsigned long i; - - for (i = 0; i < num_pages; i++) { - pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM); - if (!pages[i]) { - /* - * save number of pages we have already allocated and - * return with ENOMEM error - */ - num_pages = i; - rc = -ENOMEM; - break; - } - } - - if (rc) { - for (i = 0; i < num_pages; i++) - put_page(pages[i]); - } - return rc; -} - -static inline -size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len) -{ - size_t num_pages; - size_t clen; - - clen = min_t(const size_t, len, wsize); - num_pages = DIV_ROUND_UP(clen, PAGE_SIZE); - - if (cur_len) - *cur_len = clen; - - return num_pages; -} - -static void -cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata) -{ - int i; - size_t bytes = wdata->bytes; - - /* marshal up the pages into iov array */ - for (i = 0; i < wdata->nr_pages; i++) { - iov[i + 1].iov_len = min_t(size_t, bytes, PAGE_SIZE); - iov[i + 1].iov_base = kmap(wdata->pages[i]); - bytes -= iov[i + 1].iov_len; - } -} - -static void -cifs_uncached_writev_complete(struct work_struct *work) -{ - int i; - struct cifs_writedata *wdata = container_of(work, - struct cifs_writedata, work); - struct inode *inode = wdata->cfile->dentry->d_inode; - struct cifsInodeInfo *cifsi = CIFS_I(inode); - - spin_lock(&inode->i_lock); - cifs_update_eof(cifsi, wdata->offset, wdata->bytes); - if (cifsi->server_eof > inode->i_size) - i_size_write(inode, cifsi->server_eof); - spin_unlock(&inode->i_lock); - - complete(&wdata->done); - - if (wdata->result != -EAGAIN) { - for (i = 0; i < wdata->nr_pages; i++) - put_page(wdata->pages[i]); - } - - kref_put(&wdata->refcount, cifs_writedata_release); -} - -/* attempt to send write to server, retry on any -EAGAIN errors */ -static int -cifs_uncached_retry_writev(struct cifs_writedata *wdata) -{ - int rc; - - do { - if (wdata->cfile->invalidHandle) { - rc = cifs_reopen_file(wdata->cfile, false); - if (rc != 0) - continue; - } - rc = cifs_async_writev(wdata); - } while (rc == -EAGAIN); - - return rc; -} - -static ssize_t -cifs_iovec_write(struct file *file, const struct iovec *iov, - unsigned long nr_segs, loff_t *poffset) -{ - unsigned long nr_pages, i; - size_t copied, len, cur_len; - ssize_t total_written = 0; - loff_t offset; - struct iov_iter it; - struct cifsFileInfo *open_file; - struct cifs_tcon *tcon; - struct cifs_sb_info *cifs_sb; - struct cifs_writedata *wdata, *tmp; - struct list_head wdata_list; - int rc; - pid_t pid; - - len = iov_length(iov, nr_segs); - if (!len) - return 0; - - rc = generic_write_checks(file, poffset, &len, 0); - if (rc) - return rc; - - INIT_LIST_HEAD(&wdata_list); - cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - open_file = file->private_data; - tcon = tlink_tcon(open_file->tlink); - offset = *poffset; - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) - pid = open_file->pid; - else - pid = current->tgid; - - iov_iter_init(&it, iov, nr_segs, len, 0); - do { - size_t save_len; - - nr_pages = get_numpages(cifs_sb->wsize, len, &cur_len); - wdata = cifs_writedata_alloc(nr_pages, - cifs_uncached_writev_complete); - if (!wdata) { - rc = -ENOMEM; - break; - } - - rc = cifs_write_allocate_pages(wdata->pages, nr_pages); - if (rc) { - kfree(wdata); - break; - } - - save_len = cur_len; - for (i = 0; i < nr_pages; i++) { - copied = min_t(const size_t, cur_len, PAGE_SIZE); - copied = iov_iter_copy_from_user(wdata->pages[i], &it, - 0, copied); - cur_len -= copied; - iov_iter_advance(&it, copied); - } - cur_len = save_len - cur_len; - - wdata->sync_mode = WB_SYNC_ALL; - wdata->nr_pages = nr_pages; - wdata->offset = (__u64)offset; - wdata->cfile = cifsFileInfo_get(open_file); - wdata->pid = pid; - wdata->bytes = cur_len; - wdata->marshal_iov = cifs_uncached_marshal_iov; - rc = cifs_uncached_retry_writev(wdata); - if (rc) { - kref_put(&wdata->refcount, cifs_writedata_release); - break; - } - - list_add_tail(&wdata->list, &wdata_list); - offset += cur_len; - len -= cur_len; - } while (len > 0); - - /* - * If at least one write was successfully sent, then discard any rc - * value from the later writes. If the other write succeeds, then - * we'll end up returning whatever was written. If it fails, then - * we'll get a new rc value from that. - */ - if (!list_empty(&wdata_list)) - rc = 0; - - /* - * Wait for and collect replies for any successful sends in order of - * increasing offset. Once an error is hit or we get a fatal signal - * while waiting, then return without waiting for any more replies. - */ -restart_loop: - list_for_each_entry_safe(wdata, tmp, &wdata_list, list) { - if (!rc) { - /* FIXME: freezable too? */ - rc = wait_for_completion_killable(&wdata->done); - if (rc) - rc = -EINTR; - else if (wdata->result) - rc = wdata->result; - else - total_written += wdata->bytes; - - /* resend call if it's a retryable error */ - if (rc == -EAGAIN) { - rc = cifs_uncached_retry_writev(wdata); - goto restart_loop; - } - } - list_del_init(&wdata->list); - kref_put(&wdata->refcount, cifs_writedata_release); - } - - if (total_written > 0) - *poffset += total_written; - - cifs_stats_bytes_written(tcon, total_written); - return total_written ? total_written : (ssize_t)rc; -} - -ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) -{ - ssize_t written; - struct inode *inode; - - inode = iocb->ki_filp->f_path.dentry->d_inode; - - /* - * BB - optimize the way when signing is disabled. We can drop this - * extra memory-to-memory copying and use iovec buffers for constructing - * write request. - */ - - written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos); - if (written > 0) { - CIFS_I(inode)->invalid_mapping = true; - iocb->ki_pos = pos; - } - - return written; -} - -ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) -{ - struct inode *inode; - - inode = iocb->ki_filp->f_path.dentry->d_inode; - - if (CIFS_I(inode)->clientCanCacheAll) - return generic_file_aio_write(iocb, iov, nr_segs, pos); - - /* - * In strict cache mode we need to write the data to the server exactly - * from the pos to pos+len-1 rather than flush all affected pages - * because it may cause a error with mandatory locks on these pages but - * not on the region from pos to ppos+len-1. - */ - - return cifs_user_writev(iocb, iov, nr_segs, pos); -} - -static ssize_t -cifs_iovec_read(struct file *file, const struct iovec *iov, - unsigned long nr_segs, loff_t *poffset) -{ - int rc; - int xid; - ssize_t total_read; - unsigned int bytes_read = 0; - size_t len, cur_len; - int iov_offset = 0; - struct cifs_sb_info *cifs_sb; - struct cifs_tcon *pTcon; - struct cifsFileInfo *open_file; - struct smb_com_read_rsp *pSMBr; - struct cifs_io_parms io_parms; - char *read_data; - unsigned int rsize; - __u32 pid; - - if (!nr_segs) - return 0; - - len = iov_length(iov, nr_segs); - if (!len) - return 0; - - xid = GetXid(); - cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - - /* FIXME: set up handlers for larger reads and/or convert to async */ - rsize = min_t(unsigned int, cifs_sb->rsize, CIFSMaxBufSize); - - open_file = file->private_data; - pTcon = tlink_tcon(open_file->tlink); - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) - pid = open_file->pid; - else - pid = current->tgid; - - if ((file->f_flags & O_ACCMODE) == O_WRONLY) - cFYI(1, "attempting read on write only file instance"); - - for (total_read = 0; total_read < len; total_read += bytes_read) { - cur_len = min_t(const size_t, len - total_read, rsize); - rc = -EAGAIN; - read_data = NULL; - - while (rc == -EAGAIN) { - int buf_type = CIFS_NO_BUFFER; - if (open_file->invalidHandle) { - rc = cifs_reopen_file(open_file, true); - if (rc != 0) - break; - } - io_parms.netfid = open_file->netfid; - io_parms.pid = pid; - io_parms.tcon = pTcon; - io_parms.offset = *poffset; - io_parms.length = cur_len; - rc = CIFSSMBRead(xid, &io_parms, &bytes_read, - &read_data, &buf_type); - pSMBr = (struct smb_com_read_rsp *)read_data; - if (read_data) { - char *data_offset = read_data + 4 + - le16_to_cpu(pSMBr->DataOffset); - if (memcpy_toiovecend(iov, data_offset, - iov_offset, bytes_read)) - rc = -EFAULT; - if (buf_type == CIFS_SMALL_BUFFER) - cifs_small_buf_release(read_data); - else if (buf_type == CIFS_LARGE_BUFFER) - cifs_buf_release(read_data); - read_data = NULL; - iov_offset += bytes_read; - } - } - - if (rc || (bytes_read == 0)) { - if (total_read) { - break; - } else { - FreeXid(xid); - return rc; - } - } else { - cifs_stats_bytes_read(pTcon, bytes_read); - *poffset += bytes_read; - } - } - - FreeXid(xid); - return total_read; -} - -ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) -{ - ssize_t read; - - read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos); - if (read > 0) - iocb->ki_pos = pos; - - return read; -} - -ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) -{ - struct inode *inode; - - inode = iocb->ki_filp->f_path.dentry->d_inode; - - if (CIFS_I(inode)->clientCanCacheRead) - return generic_file_aio_read(iocb, iov, nr_segs, pos); - - /* - * In strict cache mode we need to read from the server all the time - * if we don't have level II oplock because the server can delay mtime - * change - so we can't make a decision about inode invalidating. - * And we can also fail with pagereading if there are mandatory locks - * on pages affected by this read but not on the region from pos to - * pos+len-1. - */ - - return cifs_user_readv(iocb, iov, nr_segs, pos); -} - -static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, - loff_t *poffset) -{ - int rc = -EACCES; - unsigned int bytes_read = 0; - unsigned int total_read; - unsigned int current_read_size; - unsigned int rsize; - struct cifs_sb_info *cifs_sb; - struct cifs_tcon *pTcon; - int xid; - char *current_offset; - struct cifsFileInfo *open_file; - struct cifs_io_parms io_parms; - int buf_type = CIFS_NO_BUFFER; - __u32 pid; - - xid = GetXid(); - cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - - /* FIXME: set up handlers for larger reads and/or convert to async */ - rsize = min_t(unsigned int, cifs_sb->rsize, CIFSMaxBufSize); - - if (file->private_data == NULL) { - rc = -EBADF; - FreeXid(xid); - return rc; - } - open_file = file->private_data; - pTcon = tlink_tcon(open_file->tlink); - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) - pid = open_file->pid; - else - pid = current->tgid; - - if ((file->f_flags & O_ACCMODE) == O_WRONLY) - cFYI(1, "attempting read on write only file instance"); - - for (total_read = 0, current_offset = read_data; - read_size > total_read; - total_read += bytes_read, current_offset += bytes_read) { - current_read_size = min_t(uint, read_size - total_read, rsize); - - /* For windows me and 9x we do not want to request more - than it negotiated since it will refuse the read then */ - if ((pTcon->ses) && - !(pTcon->ses->capabilities & CAP_LARGE_FILES)) { - current_read_size = min_t(uint, current_read_size, - CIFSMaxBufSize); - } - rc = -EAGAIN; - while (rc == -EAGAIN) { - if (open_file->invalidHandle) { - rc = cifs_reopen_file(open_file, true); - if (rc != 0) - break; - } - io_parms.netfid = open_file->netfid; - io_parms.pid = pid; - io_parms.tcon = pTcon; - io_parms.offset = *poffset; - io_parms.length = current_read_size; - rc = CIFSSMBRead(xid, &io_parms, &bytes_read, - ¤t_offset, &buf_type); - } - if (rc || (bytes_read == 0)) { - if (total_read) { - break; - } else { - FreeXid(xid); - return rc; - } - } else { - cifs_stats_bytes_read(pTcon, total_read); - *poffset += bytes_read; - } - } - FreeXid(xid); - return total_read; -} - -/* - * If the page is mmap'ed into a process' page tables, then we need to make - * sure that it doesn't change while being written back. - */ -static int -cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - struct page *page = vmf->page; - - lock_page(page); - return VM_FAULT_LOCKED; -} - -static struct vm_operations_struct cifs_file_vm_ops = { - .fault = filemap_fault, - .page_mkwrite = cifs_page_mkwrite, -}; - -int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) -{ - int rc, xid; - struct inode *inode = file->f_path.dentry->d_inode; - - xid = GetXid(); - - if (!CIFS_I(inode)->clientCanCacheRead) { - rc = cifs_invalidate_mapping(inode); - if (rc) - return rc; - } - - rc = generic_file_mmap(file, vma); - if (rc == 0) - vma->vm_ops = &cifs_file_vm_ops; - FreeXid(xid); - return rc; -} - -int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) -{ - int rc, xid; - - xid = GetXid(); - rc = cifs_revalidate_file(file); - if (rc) { - cFYI(1, "Validation prior to mmap failed, error=%d", rc); - FreeXid(xid); - return rc; - } - rc = generic_file_mmap(file, vma); - if (rc == 0) - vma->vm_ops = &cifs_file_vm_ops; - FreeXid(xid); - return rc; -} - -static int cifs_readpages(struct file *file, struct address_space *mapping, - struct list_head *page_list, unsigned num_pages) -{ - int rc; - struct list_head tmplist; - struct cifsFileInfo *open_file = file->private_data; - struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - unsigned int rsize = cifs_sb->rsize; - pid_t pid; - - /* - * Give up immediately if rsize is too small to read an entire page. - * The VFS will fall back to readpage. We should never reach this - * point however since we set ra_pages to 0 when the rsize is smaller - * than a cache page. - */ - if (unlikely(rsize < PAGE_CACHE_SIZE)) - return 0; - - /* - * Reads as many pages as possible from fscache. Returns -ENOBUFS - * immediately if the cookie is negative - */ - rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list, - &num_pages); - if (rc == 0) - return rc; - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) - pid = open_file->pid; - else - pid = current->tgid; - - rc = 0; - INIT_LIST_HEAD(&tmplist); - - cFYI(1, "%s: file=%p mapping=%p num_pages=%u", __func__, file, - mapping, num_pages); - - /* - * Start with the page at end of list and move it to private - * list. Do the same with any following pages until we hit - * the rsize limit, hit an index discontinuity, or run out of - * pages. Issue the async read and then start the loop again - * until the list is empty. - * - * Note that list order is important. The page_list is in - * the order of declining indexes. When we put the pages in - * the rdata->pages, then we want them in increasing order. - */ - while (!list_empty(page_list)) { - unsigned int bytes = PAGE_CACHE_SIZE; - unsigned int expected_index; - unsigned int nr_pages = 1; - loff_t offset; - struct page *page, *tpage; - struct cifs_readdata *rdata; - - page = list_entry(page_list->prev, struct page, lru); - - /* - * Lock the page and put it in the cache. Since no one else - * should have access to this page, we're safe to simply set - * PG_locked without checking it first. - */ - __set_page_locked(page); - rc = add_to_page_cache_locked(page, mapping, - page->index, GFP_KERNEL); - - /* give up if we can't stick it in the cache */ - if (rc) { - __clear_page_locked(page); - break; - } - - /* move first page to the tmplist */ - offset = (loff_t)page->index << PAGE_CACHE_SHIFT; - list_move_tail(&page->lru, &tmplist); - - /* now try and add more pages onto the request */ - expected_index = page->index + 1; - list_for_each_entry_safe_reverse(page, tpage, page_list, lru) { - /* discontinuity ? */ - if (page->index != expected_index) - break; - - /* would this page push the read over the rsize? */ - if (bytes + PAGE_CACHE_SIZE > rsize) - break; - - __set_page_locked(page); - if (add_to_page_cache_locked(page, mapping, - page->index, GFP_KERNEL)) { - __clear_page_locked(page); - break; - } - list_move_tail(&page->lru, &tmplist); - bytes += PAGE_CACHE_SIZE; - expected_index++; - nr_pages++; - } - - rdata = cifs_readdata_alloc(nr_pages); - if (!rdata) { - /* best to give up if we're out of mem */ - list_for_each_entry_safe(page, tpage, &tmplist, lru) { - list_del(&page->lru); - lru_cache_add_file(page); - unlock_page(page); - page_cache_release(page); - } - rc = -ENOMEM; - break; - } - - spin_lock(&cifs_file_list_lock); - cifsFileInfo_get(open_file); - spin_unlock(&cifs_file_list_lock); - rdata->cfile = open_file; - rdata->mapping = mapping; - rdata->offset = offset; - rdata->bytes = bytes; - rdata->pid = pid; - list_splice_init(&tmplist, &rdata->pages); - - do { - if (open_file->invalidHandle) { - rc = cifs_reopen_file(open_file, true); - if (rc != 0) - continue; - } - rc = cifs_async_readv(rdata); - } while (rc == -EAGAIN); - - if (rc != 0) { - list_for_each_entry_safe(page, tpage, &rdata->pages, - lru) { - list_del(&page->lru); - lru_cache_add_file(page); - unlock_page(page); - page_cache_release(page); - } - cifs_readdata_free(rdata); - break; - } - } - - return rc; -} - -static int cifs_readpage_worker(struct file *file, struct page *page, - loff_t *poffset) -{ - char *read_data; - int rc; - - /* Is the page cached? */ - rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page); - if (rc == 0) - goto read_complete; - - page_cache_get(page); - read_data = kmap(page); - /* for reads over a certain size could initiate async read ahead */ - - rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset); - - if (rc < 0) - goto io_error; - else - cFYI(1, "Bytes read %d", rc); - - file->f_path.dentry->d_inode->i_atime = - current_fs_time(file->f_path.dentry->d_inode->i_sb); - - if (PAGE_CACHE_SIZE > rc) - memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc); - - flush_dcache_page(page); - SetPageUptodate(page); - - /* send this page to the cache */ - cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page); - - rc = 0; - -io_error: - kunmap(page); - page_cache_release(page); - -read_complete: - return rc; -} - -static int cifs_readpage(struct file *file, struct page *page) -{ - loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; - int rc = -EACCES; - int xid; - - xid = GetXid(); - - if (file->private_data == NULL) { - rc = -EBADF; - FreeXid(xid); - return rc; - } - - cFYI(1, "readpage %p at offset %d 0x%x\n", - page, (int)offset, (int)offset); - - rc = cifs_readpage_worker(file, page, &offset); - - unlock_page(page); - - FreeXid(xid); - return rc; -} - -static int is_inode_writable(struct cifsInodeInfo *cifs_inode) -{ - struct cifsFileInfo *open_file; - - spin_lock(&cifs_file_list_lock); - list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { - if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { - spin_unlock(&cifs_file_list_lock); - return 1; - } - } - spin_unlock(&cifs_file_list_lock); - return 0; -} - -/* We do not want to update the file size from server for inodes - open for write - to avoid races with writepage extending - the file - in the future we could consider allowing - refreshing the inode only on increases in the file size - but this is tricky to do without racing with writebehind - page caching in the current Linux kernel design */ -bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file) -{ - if (!cifsInode) - return true; - - if (is_inode_writable(cifsInode)) { - /* This inode is open for write at least once */ - struct cifs_sb_info *cifs_sb; - - cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { - /* since no page cache to corrupt on directio - we can change size safely */ - return true; - } - - if (i_size_read(&cifsInode->vfs_inode) < end_of_file) - return true; - - return false; - } else - return true; -} - -static int cifs_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, unsigned flags, - struct page **pagep, void **fsdata) -{ - pgoff_t index = pos >> PAGE_CACHE_SHIFT; - loff_t offset = pos & (PAGE_CACHE_SIZE - 1); - loff_t page_start = pos & PAGE_MASK; - loff_t i_size; - struct page *page; - int rc = 0; - - cFYI(1, "write_begin from %lld len %d", (long long)pos, len); - - page = grab_cache_page_write_begin(mapping, index, flags); - if (!page) { - rc = -ENOMEM; - goto out; - } - - if (PageUptodate(page)) - goto out; - - /* - * If we write a full page it will be up to date, no need to read from - * the server. If the write is short, we'll end up doing a sync write - * instead. - */ - if (len == PAGE_CACHE_SIZE) - goto out; - - /* - * optimize away the read when we have an oplock, and we're not - * expecting to use any of the data we'd be reading in. That - * is, when the page lies beyond the EOF, or straddles the EOF - * and the write will cover all of the existing data. - */ - if (CIFS_I(mapping->host)->clientCanCacheRead) { - i_size = i_size_read(mapping->host); - if (page_start >= i_size || - (offset == 0 && (pos + len) >= i_size)) { - zero_user_segments(page, 0, offset, - offset + len, - PAGE_CACHE_SIZE); - /* - * PageChecked means that the parts of the page - * to which we're not writing are considered up - * to date. Once the data is copied to the - * page, it can be set uptodate. - */ - SetPageChecked(page); - goto out; - } - } - - if ((file->f_flags & O_ACCMODE) != O_WRONLY) { - /* - * might as well read a page, it is fast enough. If we get - * an error, we don't need to return it. cifs_write_end will - * do a sync write instead since PG_uptodate isn't set. - */ - cifs_readpage_worker(file, page, &page_start); - } else { - /* we could try using another file handle if there is one - - but how would we lock it to prevent close of that handle - racing with this read? In any case - this will be written out by write_end so is fine */ - } -out: - *pagep = page; - return rc; -} - -static int cifs_release_page(struct page *page, gfp_t gfp) -{ - if (PagePrivate(page)) - return 0; - - return cifs_fscache_release_page(page, gfp); -} - -static void cifs_invalidate_page(struct page *page, unsigned long offset) -{ - struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host); - - if (offset == 0) - cifs_fscache_invalidate_page(page, &cifsi->vfs_inode); -} - -static int cifs_launder_page(struct page *page) -{ - int rc = 0; - loff_t range_start = page_offset(page); - loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); - struct writeback_control wbc = { - .sync_mode = WB_SYNC_ALL, - .nr_to_write = 0, - .range_start = range_start, - .range_end = range_end, - }; - - cFYI(1, "Launder page: %p", page); - - if (clear_page_dirty_for_io(page)) - rc = cifs_writepage_locked(page, &wbc); - - cifs_fscache_invalidate_page(page, page->mapping->host); - return rc; -} - -void cifs_oplock_break(struct work_struct *work) -{ - struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, - oplock_break); - struct inode *inode = cfile->dentry->d_inode; - struct cifsInodeInfo *cinode = CIFS_I(inode); - int rc = 0; - - if (inode && S_ISREG(inode->i_mode)) { - if (cinode->clientCanCacheRead) - break_lease(inode, O_RDONLY); - else - break_lease(inode, O_WRONLY); - rc = filemap_fdatawrite(inode->i_mapping); - if (cinode->clientCanCacheRead == 0) { - rc = filemap_fdatawait(inode->i_mapping); - mapping_set_error(inode->i_mapping, rc); - invalidate_remote_inode(inode); - } - cFYI(1, "Oplock flush inode %p rc %d", inode, rc); - } - - rc = cifs_push_locks(cfile); - if (rc) - cERROR(1, "Push locks rc = %d", rc); - - /* - * releasing stale oplock after recent reconnect of smb session using - * a now incorrect file handle is not a data integrity issue but do - * not bother sending an oplock release if session to server still is - * disconnected since oplock already released by the server - */ - if (!cfile->oplock_break_cancelled) { - rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, - current->tgid, 0, 0, 0, 0, - LOCKING_ANDX_OPLOCK_RELEASE, false, - cinode->clientCanCacheRead ? 1 : 0); - cFYI(1, "Oplock release rc = %d", rc); - } -} - -const struct address_space_operations cifs_addr_ops = { - .readpage = cifs_readpage, - .readpages = cifs_readpages, - .writepage = cifs_writepage, - .writepages = cifs_writepages, - .write_begin = cifs_write_begin, - .write_end = cifs_write_end, - .set_page_dirty = __set_page_dirty_nobuffers, - .releasepage = cifs_release_page, - .invalidatepage = cifs_invalidate_page, - .launder_page = cifs_launder_page, -}; - -/* - * cifs_readpages requires the server to support a buffer large enough to - * contain the header plus one complete page of data. Otherwise, we need - * to leave cifs_readpages out of the address space operations. - */ -const struct address_space_operations cifs_addr_ops_smallbuf = { - .readpage = cifs_readpage, - .writepage = cifs_writepage, - .writepages = cifs_writepages, - .write_begin = cifs_write_begin, - .write_end = cifs_write_end, - .set_page_dirty = __set_page_dirty_nobuffers, - .releasepage = cifs_release_page, - .invalidatepage = cifs_invalidate_page, - .launder_page = cifs_launder_page, -}; diff --git a/ANDROID_3.4.5/fs/cifs/fscache.c b/ANDROID_3.4.5/fs/cifs/fscache.c deleted file mode 100644 index 42e5363b..00000000 --- a/ANDROID_3.4.5/fs/cifs/fscache.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * fs/cifs/fscache.c - CIFS filesystem cache interface - * - * Copyright (c) 2010 Novell, Inc. - * Author(s): Suresh Jayaraman <sjayaraman@suse.de> - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "fscache.h" -#include "cifsglob.h" -#include "cifs_debug.h" -#include "cifs_fs_sb.h" - -void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) -{ - server->fscache = - fscache_acquire_cookie(cifs_fscache_netfs.primary_index, - &cifs_fscache_server_index_def, server); - cFYI(1, "%s: (0x%p/0x%p)", __func__, server, - server->fscache); -} - -void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server) -{ - cFYI(1, "%s: (0x%p/0x%p)", __func__, server, - server->fscache); - fscache_relinquish_cookie(server->fscache, 0); - server->fscache = NULL; -} - -void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) -{ - struct TCP_Server_Info *server = tcon->ses->server; - - tcon->fscache = - fscache_acquire_cookie(server->fscache, - &cifs_fscache_super_index_def, tcon); - cFYI(1, "%s: (0x%p/0x%p)", __func__, server->fscache, - tcon->fscache); -} - -void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) -{ - cFYI(1, "%s: (0x%p)", __func__, tcon->fscache); - fscache_relinquish_cookie(tcon->fscache, 0); - tcon->fscache = NULL; -} - -static void cifs_fscache_enable_inode_cookie(struct inode *inode) -{ - struct cifsInodeInfo *cifsi = CIFS_I(inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); - - if (cifsi->fscache) - return; - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) { - cifsi->fscache = fscache_acquire_cookie(tcon->fscache, - &cifs_fscache_inode_object_def, cifsi); - cFYI(1, "%s: got FH cookie (0x%p/0x%p)", __func__, - tcon->fscache, cifsi->fscache); - } -} - -void cifs_fscache_release_inode_cookie(struct inode *inode) -{ - struct cifsInodeInfo *cifsi = CIFS_I(inode); - - if (cifsi->fscache) { - cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache); - fscache_relinquish_cookie(cifsi->fscache, 0); - cifsi->fscache = NULL; - } -} - -static void cifs_fscache_disable_inode_cookie(struct inode *inode) -{ - struct cifsInodeInfo *cifsi = CIFS_I(inode); - - if (cifsi->fscache) { - cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache); - fscache_uncache_all_inode_pages(cifsi->fscache, inode); - fscache_relinquish_cookie(cifsi->fscache, 1); - cifsi->fscache = NULL; - } -} - -void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp) -{ - if ((filp->f_flags & O_ACCMODE) != O_RDONLY) - cifs_fscache_disable_inode_cookie(inode); - else - cifs_fscache_enable_inode_cookie(inode); -} - -void cifs_fscache_reset_inode_cookie(struct inode *inode) -{ - struct cifsInodeInfo *cifsi = CIFS_I(inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct fscache_cookie *old = cifsi->fscache; - - if (cifsi->fscache) { - /* retire the current fscache cache and get a new one */ - fscache_relinquish_cookie(cifsi->fscache, 1); - - cifsi->fscache = fscache_acquire_cookie( - cifs_sb_master_tcon(cifs_sb)->fscache, - &cifs_fscache_inode_object_def, - cifsi); - cFYI(1, "%s: new cookie 0x%p oldcookie 0x%p", - __func__, cifsi->fscache, old); - } -} - -int cifs_fscache_release_page(struct page *page, gfp_t gfp) -{ - if (PageFsCache(page)) { - struct inode *inode = page->mapping->host; - struct cifsInodeInfo *cifsi = CIFS_I(inode); - - cFYI(1, "%s: (0x%p/0x%p)", __func__, page, - cifsi->fscache); - if (!fscache_maybe_release_page(cifsi->fscache, page, gfp)) - return 0; - } - - return 1; -} - -static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx, - int error) -{ - cFYI(1, "%s: (0x%p/%d)", __func__, page, error); - if (!error) - SetPageUptodate(page); - unlock_page(page); -} - -/* - * Retrieve a page from FS-Cache - */ -int __cifs_readpage_from_fscache(struct inode *inode, struct page *page) -{ - int ret; - - cFYI(1, "%s: (fsc:%p, p:%p, i:0x%p", __func__, - CIFS_I(inode)->fscache, page, inode); - ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page, - cifs_readpage_from_fscache_complete, - NULL, - GFP_KERNEL); - switch (ret) { - - case 0: /* page found in fscache, read submitted */ - cFYI(1, "%s: submitted", __func__); - return ret; - case -ENOBUFS: /* page won't be cached */ - case -ENODATA: /* page not in cache */ - cFYI(1, "%s: %d", __func__, ret); - return 1; - - default: - cERROR(1, "unknown error ret = %d", ret); - } - return ret; -} - -/* - * Retrieve a set of pages from FS-Cache - */ -int __cifs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages) -{ - int ret; - - cFYI(1, "%s: (0x%p/%u/0x%p)", __func__, - CIFS_I(inode)->fscache, *nr_pages, inode); - ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping, - pages, nr_pages, - cifs_readpage_from_fscache_complete, - NULL, - mapping_gfp_mask(mapping)); - switch (ret) { - case 0: /* read submitted to the cache for all pages */ - cFYI(1, "%s: submitted", __func__); - return ret; - - case -ENOBUFS: /* some pages are not cached and can't be */ - case -ENODATA: /* some pages are not cached */ - cFYI(1, "%s: no page", __func__); - return 1; - - default: - cFYI(1, "unknown error ret = %d", ret); - } - - return ret; -} - -void __cifs_readpage_to_fscache(struct inode *inode, struct page *page) -{ - int ret; - - cFYI(1, "%s: (fsc: %p, p: %p, i: %p)", __func__, - CIFS_I(inode)->fscache, page, inode); - ret = fscache_write_page(CIFS_I(inode)->fscache, page, GFP_KERNEL); - if (ret != 0) - fscache_uncache_page(CIFS_I(inode)->fscache, page); -} - -void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode) -{ - struct cifsInodeInfo *cifsi = CIFS_I(inode); - struct fscache_cookie *cookie = cifsi->fscache; - - cFYI(1, "%s: (0x%p/0x%p)", __func__, page, cookie); - fscache_wait_on_page_write(cookie, page); - fscache_uncache_page(cookie, page); -} - diff --git a/ANDROID_3.4.5/fs/cifs/fscache.h b/ANDROID_3.4.5/fs/cifs/fscache.h deleted file mode 100644 index 63539323..00000000 --- a/ANDROID_3.4.5/fs/cifs/fscache.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * fs/cifs/fscache.h - CIFS filesystem cache interface definitions - * - * Copyright (c) 2010 Novell, Inc. - * Authors(s): Suresh Jayaraman (sjayaraman@suse.de> - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _CIFS_FSCACHE_H -#define _CIFS_FSCACHE_H - -#include <linux/fscache.h> - -#include "cifsglob.h" - -#ifdef CONFIG_CIFS_FSCACHE - -extern struct fscache_netfs cifs_fscache_netfs; -extern const struct fscache_cookie_def cifs_fscache_server_index_def; -extern const struct fscache_cookie_def cifs_fscache_super_index_def; -extern const struct fscache_cookie_def cifs_fscache_inode_object_def; - -extern int cifs_fscache_register(void); -extern void cifs_fscache_unregister(void); - -/* - * fscache.c - */ -extern void cifs_fscache_get_client_cookie(struct TCP_Server_Info *); -extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *); -extern void cifs_fscache_get_super_cookie(struct cifs_tcon *); -extern void cifs_fscache_release_super_cookie(struct cifs_tcon *); - -extern void cifs_fscache_release_inode_cookie(struct inode *); -extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *); -extern void cifs_fscache_reset_inode_cookie(struct inode *); - -extern void __cifs_fscache_invalidate_page(struct page *, struct inode *); -extern int cifs_fscache_release_page(struct page *page, gfp_t gfp); -extern int __cifs_readpage_from_fscache(struct inode *, struct page *); -extern int __cifs_readpages_from_fscache(struct inode *, - struct address_space *, - struct list_head *, - unsigned *); - -extern void __cifs_readpage_to_fscache(struct inode *, struct page *); - -static inline void cifs_fscache_invalidate_page(struct page *page, - struct inode *inode) -{ - if (PageFsCache(page)) - __cifs_fscache_invalidate_page(page, inode); -} - -static inline int cifs_readpage_from_fscache(struct inode *inode, - struct page *page) -{ - if (CIFS_I(inode)->fscache) - return __cifs_readpage_from_fscache(inode, page); - - return -ENOBUFS; -} - -static inline int cifs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages) -{ - if (CIFS_I(inode)->fscache) - return __cifs_readpages_from_fscache(inode, mapping, pages, - nr_pages); - return -ENOBUFS; -} - -static inline void cifs_readpage_to_fscache(struct inode *inode, - struct page *page) -{ - if (PageFsCache(page)) - __cifs_readpage_to_fscache(inode, page); -} - -#else /* CONFIG_CIFS_FSCACHE */ -static inline int cifs_fscache_register(void) { return 0; } -static inline void cifs_fscache_unregister(void) {} - -static inline void -cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) {} -static inline void -cifs_fscache_release_client_cookie(struct TCP_Server_Info *server) {} -static inline void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) {} -static inline void -cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) {} - -static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {} -static inline void cifs_fscache_set_inode_cookie(struct inode *inode, - struct file *filp) {} -static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {} -static inline int cifs_fscache_release_page(struct page *page, gfp_t gfp) -{ - return 1; /* May release page */ -} - -static inline void cifs_fscache_invalidate_page(struct page *page, - struct inode *inode) {} -static inline int -cifs_readpage_from_fscache(struct inode *inode, struct page *page) -{ - return -ENOBUFS; -} - -static inline int cifs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages) -{ - return -ENOBUFS; -} - -static inline void cifs_readpage_to_fscache(struct inode *inode, - struct page *page) {} - -#endif /* CONFIG_CIFS_FSCACHE */ - -#endif /* _CIFS_FSCACHE_H */ diff --git a/ANDROID_3.4.5/fs/cifs/inode.c b/ANDROID_3.4.5/fs/cifs/inode.c deleted file mode 100644 index 745da3d0..00000000 --- a/ANDROID_3.4.5/fs/cifs/inode.c +++ /dev/null @@ -1,2293 +0,0 @@ -/* - * fs/cifs/inode.c - * - * Copyright (C) International Business Machines Corp., 2002,2010 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/fs.h> -#include <linux/stat.h> -#include <linux/slab.h> -#include <linux/pagemap.h> -#include <asm/div64.h> -#include "cifsfs.h" -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifs_debug.h" -#include "cifs_fs_sb.h" -#include "fscache.h" - - -static void cifs_set_ops(struct inode *inode) -{ - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - - switch (inode->i_mode & S_IFMT) { - case S_IFREG: - inode->i_op = &cifs_file_inode_ops; - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - inode->i_fop = &cifs_file_direct_nobrl_ops; - else - inode->i_fop = &cifs_file_direct_ops; - } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - inode->i_fop = &cifs_file_strict_nobrl_ops; - else - inode->i_fop = &cifs_file_strict_ops; - } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - inode->i_fop = &cifs_file_nobrl_ops; - else { /* not direct, send byte range locks */ - inode->i_fop = &cifs_file_ops; - } - - /* check if server can support readpages */ - if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf < - PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) - inode->i_data.a_ops = &cifs_addr_ops_smallbuf; - else - inode->i_data.a_ops = &cifs_addr_ops; - break; - case S_IFDIR: -#ifdef CONFIG_CIFS_DFS_UPCALL - if (IS_AUTOMOUNT(inode)) { - inode->i_op = &cifs_dfs_referral_inode_operations; - } else { -#else /* NO DFS support, treat as a directory */ - { -#endif - inode->i_op = &cifs_dir_inode_ops; - inode->i_fop = &cifs_dir_ops; - } - break; - case S_IFLNK: - inode->i_op = &cifs_symlink_inode_ops; - break; - default: - init_special_inode(inode, inode->i_mode, inode->i_rdev); - break; - } -} - -/* check inode attributes against fattr. If they don't match, tag the - * inode for cache invalidation - */ -static void -cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr) -{ - struct cifsInodeInfo *cifs_i = CIFS_I(inode); - - cFYI(1, "%s: revalidating inode %llu", __func__, cifs_i->uniqueid); - - if (inode->i_state & I_NEW) { - cFYI(1, "%s: inode %llu is new", __func__, cifs_i->uniqueid); - return; - } - - /* don't bother with revalidation if we have an oplock */ - if (cifs_i->clientCanCacheRead) { - cFYI(1, "%s: inode %llu is oplocked", __func__, - cifs_i->uniqueid); - return; - } - - /* revalidate if mtime or size have changed */ - if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) && - cifs_i->server_eof == fattr->cf_eof) { - cFYI(1, "%s: inode %llu is unchanged", __func__, - cifs_i->uniqueid); - return; - } - - cFYI(1, "%s: invalidating inode %llu mapping", __func__, - cifs_i->uniqueid); - cifs_i->invalid_mapping = true; -} - -/* populate an inode with info from a cifs_fattr struct */ -void -cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) -{ - struct cifsInodeInfo *cifs_i = CIFS_I(inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - unsigned long oldtime = cifs_i->time; - - cifs_revalidate_cache(inode, fattr); - - inode->i_atime = fattr->cf_atime; - inode->i_mtime = fattr->cf_mtime; - inode->i_ctime = fattr->cf_ctime; - inode->i_rdev = fattr->cf_rdev; - set_nlink(inode, fattr->cf_nlink); - inode->i_uid = fattr->cf_uid; - inode->i_gid = fattr->cf_gid; - - /* if dynperm is set, don't clobber existing mode */ - if (inode->i_state & I_NEW || - !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) - inode->i_mode = fattr->cf_mode; - - cifs_i->cifsAttrs = fattr->cf_cifsattrs; - - if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL) - cifs_i->time = 0; - else - cifs_i->time = jiffies; - - cFYI(1, "inode 0x%p old_time=%ld new_time=%ld", inode, - oldtime, cifs_i->time); - - cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; - - cifs_i->server_eof = fattr->cf_eof; - /* - * Can't safely change the file size here if the client is writing to - * it due to potential races. - */ - spin_lock(&inode->i_lock); - if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { - i_size_write(inode, fattr->cf_eof); - - /* - * i_blocks is not related to (i_size / i_blksize), - * but instead 512 byte (2**9) size is required for - * calculating num blocks. - */ - inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9; - } - spin_unlock(&inode->i_lock); - - if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL) - inode->i_flags |= S_AUTOMOUNT; - cifs_set_ops(inode); -} - -void -cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr) -{ - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) - return; - - fattr->cf_uniqueid = iunique(sb, ROOT_I); -} - -/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */ -void -cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, - struct cifs_sb_info *cifs_sb) -{ - memset(fattr, 0, sizeof(*fattr)); - fattr->cf_uniqueid = le64_to_cpu(info->UniqueId); - fattr->cf_bytes = le64_to_cpu(info->NumOfBytes); - fattr->cf_eof = le64_to_cpu(info->EndOfFile); - - fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); - fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime); - fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange); - fattr->cf_mode = le64_to_cpu(info->Permissions); - - /* - * Since we set the inode type below we need to mask off - * to avoid strange results if bits set above. - */ - fattr->cf_mode &= ~S_IFMT; - switch (le32_to_cpu(info->Type)) { - case UNIX_FILE: - fattr->cf_mode |= S_IFREG; - fattr->cf_dtype = DT_REG; - break; - case UNIX_SYMLINK: - fattr->cf_mode |= S_IFLNK; - fattr->cf_dtype = DT_LNK; - break; - case UNIX_DIR: - fattr->cf_mode |= S_IFDIR; - fattr->cf_dtype = DT_DIR; - break; - case UNIX_CHARDEV: - fattr->cf_mode |= S_IFCHR; - fattr->cf_dtype = DT_CHR; - fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), - le64_to_cpu(info->DevMinor) & MINORMASK); - break; - case UNIX_BLOCKDEV: - fattr->cf_mode |= S_IFBLK; - fattr->cf_dtype = DT_BLK; - fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), - le64_to_cpu(info->DevMinor) & MINORMASK); - break; - case UNIX_FIFO: - fattr->cf_mode |= S_IFIFO; - fattr->cf_dtype = DT_FIFO; - break; - case UNIX_SOCKET: - fattr->cf_mode |= S_IFSOCK; - fattr->cf_dtype = DT_SOCK; - break; - default: - /* safest to call it a file if we do not know */ - fattr->cf_mode |= S_IFREG; - fattr->cf_dtype = DT_REG; - cFYI(1, "unknown type %d", le32_to_cpu(info->Type)); - break; - } - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) - fattr->cf_uid = cifs_sb->mnt_uid; - else - fattr->cf_uid = le64_to_cpu(info->Uid); - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) - fattr->cf_gid = cifs_sb->mnt_gid; - else - fattr->cf_gid = le64_to_cpu(info->Gid); - - fattr->cf_nlink = le64_to_cpu(info->Nlinks); -} - -/* - * Fill a cifs_fattr struct with fake inode info. - * - * Needed to setup cifs_fattr data for the directory which is the - * junction to the new submount (ie to setup the fake directory - * which represents a DFS referral). - */ -static void -cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) -{ - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - - cFYI(1, "creating fake fattr for DFS referral"); - - memset(fattr, 0, sizeof(*fattr)); - fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU; - fattr->cf_uid = cifs_sb->mnt_uid; - fattr->cf_gid = cifs_sb->mnt_gid; - fattr->cf_atime = CURRENT_TIME; - fattr->cf_ctime = CURRENT_TIME; - fattr->cf_mtime = CURRENT_TIME; - fattr->cf_nlink = 2; - fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; -} - -int cifs_get_file_info_unix(struct file *filp) -{ - int rc; - int xid; - FILE_UNIX_BASIC_INFO find_data; - struct cifs_fattr fattr; - struct inode *inode = filp->f_path.dentry->d_inode; - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct cifsFileInfo *cfile = filp->private_data; - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); - - xid = GetXid(); - rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); - if (!rc) { - cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); - } else if (rc == -EREMOTE) { - cifs_create_dfs_fattr(&fattr, inode->i_sb); - rc = 0; - } - - cifs_fattr_to_inode(inode, &fattr); - FreeXid(xid); - return rc; -} - -int cifs_get_inode_info_unix(struct inode **pinode, - const unsigned char *full_path, - struct super_block *sb, int xid) -{ - int rc; - FILE_UNIX_BASIC_INFO find_data; - struct cifs_fattr fattr; - struct cifs_tcon *tcon; - struct tcon_link *tlink; - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - - cFYI(1, "Getting info on %s", full_path); - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - tcon = tlink_tcon(tlink); - - /* could have done a find first instead but this returns more info */ - rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - cifs_put_tlink(tlink); - - if (!rc) { - cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); - } else if (rc == -EREMOTE) { - cifs_create_dfs_fattr(&fattr, sb); - rc = 0; - } else { - return rc; - } - - /* check for Minshall+French symlinks */ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { - int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid); - if (tmprc) - cFYI(1, "CIFSCheckMFSymlink: %d", tmprc); - } - - if (*pinode == NULL) { - /* get new inode */ - cifs_fill_uniqueid(sb, &fattr); - *pinode = cifs_iget(sb, &fattr); - if (!*pinode) - rc = -ENOMEM; - } else { - /* we already have inode, update it */ - cifs_fattr_to_inode(*pinode, &fattr); - } - - return rc; -} - -static int -cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, - struct cifs_sb_info *cifs_sb, int xid) -{ - int rc; - int oplock = 0; - __u16 netfid; - struct tcon_link *tlink; - struct cifs_tcon *tcon; - struct cifs_io_parms io_parms; - char buf[24]; - unsigned int bytes_read; - char *pbuf; - - pbuf = buf; - - fattr->cf_mode &= ~S_IFMT; - - if (fattr->cf_eof == 0) { - fattr->cf_mode |= S_IFIFO; - fattr->cf_dtype = DT_FIFO; - return 0; - } else if (fattr->cf_eof < 8) { - fattr->cf_mode |= S_IFREG; - fattr->cf_dtype = DT_REG; - return -EINVAL; /* EOPNOTSUPP? */ - } - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - tcon = tlink_tcon(tlink); - - rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ, - CREATE_NOT_DIR, &netfid, &oplock, NULL, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc == 0) { - int buf_type = CIFS_NO_BUFFER; - /* Read header */ - io_parms.netfid = netfid; - io_parms.pid = current->tgid; - io_parms.tcon = tcon; - io_parms.offset = 0; - io_parms.length = 24; - rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, - &buf_type); - if ((rc == 0) && (bytes_read >= 8)) { - if (memcmp("IntxBLK", pbuf, 8) == 0) { - cFYI(1, "Block device"); - fattr->cf_mode |= S_IFBLK; - fattr->cf_dtype = DT_BLK; - if (bytes_read == 24) { - /* we have enough to decode dev num */ - __u64 mjr; /* major */ - __u64 mnr; /* minor */ - mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); - mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); - fattr->cf_rdev = MKDEV(mjr, mnr); - } - } else if (memcmp("IntxCHR", pbuf, 8) == 0) { - cFYI(1, "Char device"); - fattr->cf_mode |= S_IFCHR; - fattr->cf_dtype = DT_CHR; - if (bytes_read == 24) { - /* we have enough to decode dev num */ - __u64 mjr; /* major */ - __u64 mnr; /* minor */ - mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); - mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); - fattr->cf_rdev = MKDEV(mjr, mnr); - } - } else if (memcmp("IntxLNK", pbuf, 7) == 0) { - cFYI(1, "Symlink"); - fattr->cf_mode |= S_IFLNK; - fattr->cf_dtype = DT_LNK; - } else { - fattr->cf_mode |= S_IFREG; /* file? */ - fattr->cf_dtype = DT_REG; - rc = -EOPNOTSUPP; - } - } else { - fattr->cf_mode |= S_IFREG; /* then it is a file */ - fattr->cf_dtype = DT_REG; - rc = -EOPNOTSUPP; /* or some unknown SFU type */ - } - CIFSSMBClose(xid, tcon, netfid); - } - cifs_put_tlink(tlink); - return rc; -} - -#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ - -/* - * Fetch mode bits as provided by SFU. - * - * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ? - */ -static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, - struct cifs_sb_info *cifs_sb, int xid) -{ -#ifdef CONFIG_CIFS_XATTR - ssize_t rc; - char ea_value[4]; - __u32 mode; - struct tcon_link *tlink; - struct cifs_tcon *tcon; - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - tcon = tlink_tcon(tlink); - - rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS", - ea_value, 4 /* size of buf */, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - cifs_put_tlink(tlink); - if (rc < 0) - return (int)rc; - else if (rc > 3) { - mode = le32_to_cpu(*((__le32 *)ea_value)); - fattr->cf_mode &= ~SFBITS_MASK; - cFYI(1, "special bits 0%o org mode 0%o", mode, - fattr->cf_mode); - fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode; - cFYI(1, "special mode bits 0%o", mode); - } - - return 0; -#else - return -EOPNOTSUPP; -#endif -} - -/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */ -static void -cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, - struct cifs_sb_info *cifs_sb, bool adjust_tz) -{ - struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); - - memset(fattr, 0, sizeof(*fattr)); - fattr->cf_cifsattrs = le32_to_cpu(info->Attributes); - if (info->DeletePending) - fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING; - - if (info->LastAccessTime) - fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); - else - fattr->cf_atime = CURRENT_TIME; - - fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); - fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); - - if (adjust_tz) { - fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj; - fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj; - } - - fattr->cf_eof = le64_to_cpu(info->EndOfFile); - fattr->cf_bytes = le64_to_cpu(info->AllocationSize); - fattr->cf_createtime = le64_to_cpu(info->CreationTime); - - if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { - fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; - fattr->cf_dtype = DT_DIR; - /* - * Server can return wrong NumberOfLinks value for directories - * when Unix extensions are disabled - fake it. - */ - fattr->cf_nlink = 2; - } else { - fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; - fattr->cf_dtype = DT_REG; - - /* clear write bits if ATTR_READONLY is set */ - if (fattr->cf_cifsattrs & ATTR_READONLY) - fattr->cf_mode &= ~(S_IWUGO); - - fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); - } - - fattr->cf_uid = cifs_sb->mnt_uid; - fattr->cf_gid = cifs_sb->mnt_gid; -} - -int cifs_get_file_info(struct file *filp) -{ - int rc; - int xid; - FILE_ALL_INFO find_data; - struct cifs_fattr fattr; - struct inode *inode = filp->f_path.dentry->d_inode; - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct cifsFileInfo *cfile = filp->private_data; - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); - - xid = GetXid(); - rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); - switch (rc) { - case 0: - cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false); - break; - case -EREMOTE: - cifs_create_dfs_fattr(&fattr, inode->i_sb); - rc = 0; - break; - case -EOPNOTSUPP: - case -EINVAL: - /* - * FIXME: legacy server -- fall back to path-based call? - * for now, just skip revalidating and mark inode for - * immediate reval. - */ - rc = 0; - CIFS_I(inode)->time = 0; - default: - goto cgfi_exit; - } - - /* - * don't bother with SFU junk here -- just mark inode as needing - * revalidation. - */ - fattr.cf_uniqueid = CIFS_I(inode)->uniqueid; - fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; - cifs_fattr_to_inode(inode, &fattr); -cgfi_exit: - FreeXid(xid); - return rc; -} - -int cifs_get_inode_info(struct inode **pinode, - const unsigned char *full_path, FILE_ALL_INFO *pfindData, - struct super_block *sb, int xid, const __u16 *pfid) -{ - int rc = 0, tmprc; - struct cifs_tcon *pTcon; - struct tcon_link *tlink; - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - char *buf = NULL; - bool adjustTZ = false; - struct cifs_fattr fattr; - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - pTcon = tlink_tcon(tlink); - - cFYI(1, "Getting info on %s", full_path); - - if ((pfindData == NULL) && (*pinode != NULL)) { - if (CIFS_I(*pinode)->clientCanCacheRead) { - cFYI(1, "No need to revalidate cached inode sizes"); - goto cgii_exit; - } - } - - /* if file info not passed in then get it from server */ - if (pfindData == NULL) { - buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); - if (buf == NULL) { - rc = -ENOMEM; - goto cgii_exit; - } - pfindData = (FILE_ALL_INFO *)buf; - - /* could do find first instead but this returns more info */ - rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, - 0 /* not legacy */, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - /* BB optimize code so we do not make the above call - when server claims no NT SMB support and the above call - failed at least once - set flag in tcon or mount */ - if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { - rc = SMBQueryInformation(xid, pTcon, full_path, - pfindData, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - adjustTZ = true; - } - } - - if (!rc) { - cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData, - cifs_sb, adjustTZ); - } else if (rc == -EREMOTE) { - cifs_create_dfs_fattr(&fattr, sb); - rc = 0; - } else { - goto cgii_exit; - } - - /* - * If an inode wasn't passed in, then get the inode number - * - * Is an i_ino of zero legal? Can we use that to check if the server - * supports returning inode numbers? Are there other sanity checks we - * can use to ensure that the server is really filling in that field? - * - * We can not use the IndexNumber field by default from Windows or - * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA - * CIFS spec claims that this value is unique within the scope of a - * share, and the windows docs hint that it's actually unique - * per-machine. - * - * There may be higher info levels that work but are there Windows - * server or network appliances for which IndexNumber field is not - * guaranteed unique? - */ - if (*pinode == NULL) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { - int rc1 = 0; - - rc1 = CIFSGetSrvInodeNumber(xid, pTcon, - full_path, &fattr.cf_uniqueid, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc1 || !fattr.cf_uniqueid) { - cFYI(1, "GetSrvInodeNum rc %d", rc1); - fattr.cf_uniqueid = iunique(sb, ROOT_I); - cifs_autodisable_serverino(cifs_sb); - } - } else { - fattr.cf_uniqueid = iunique(sb, ROOT_I); - } - } else { - fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid; - } - - /* query for SFU type info if supported and needed */ - if (fattr.cf_cifsattrs & ATTR_SYSTEM && - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { - tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid); - if (tmprc) - cFYI(1, "cifs_sfu_type failed: %d", tmprc); - } - -#ifdef CONFIG_CIFS_ACL - /* fill in 0777 bits from ACL */ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { - rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, - pfid); - if (rc) { - cFYI(1, "%s: Getting ACL failed with error: %d", - __func__, rc); - goto cgii_exit; - } - } -#endif /* CONFIG_CIFS_ACL */ - - /* fill in remaining high mode bits e.g. SUID, VTX */ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) - cifs_sfu_mode(&fattr, full_path, cifs_sb, xid); - - /* check for Minshall+French symlinks */ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { - tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid); - if (tmprc) - cFYI(1, "CIFSCheckMFSymlink: %d", tmprc); - } - - if (!*pinode) { - *pinode = cifs_iget(sb, &fattr); - if (!*pinode) - rc = -ENOMEM; - } else { - cifs_fattr_to_inode(*pinode, &fattr); - } - -cgii_exit: - kfree(buf); - cifs_put_tlink(tlink); - return rc; -} - -static const struct inode_operations cifs_ipc_inode_ops = { - .lookup = cifs_lookup, -}; - -char *cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, - struct cifs_tcon *tcon) -{ - int pplen = vol->prepath ? strlen(vol->prepath) : 0; - int dfsplen; - char *full_path = NULL; - - /* if no prefix path, simply set path to the root of share to "" */ - if (pplen == 0) { - full_path = kmalloc(1, GFP_KERNEL); - if (full_path) - full_path[0] = 0; - return full_path; - } - - if (tcon->Flags & SMB_SHARE_IS_IN_DFS) - dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1); - else - dfsplen = 0; - - full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL); - if (full_path == NULL) - return full_path; - - if (dfsplen) - strncpy(full_path, tcon->treeName, dfsplen); - strncpy(full_path + dfsplen, vol->prepath, pplen); - convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb)); - full_path[dfsplen + pplen] = 0; /* add trailing null */ - return full_path; -} - -static int -cifs_find_inode(struct inode *inode, void *opaque) -{ - struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; - - /* don't match inode with different uniqueid */ - if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) - return 0; - - /* use createtime like an i_generation field */ - if (CIFS_I(inode)->createtime != fattr->cf_createtime) - return 0; - - /* don't match inode of different type */ - if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT)) - return 0; - - /* if it's not a directory or has no dentries, then flag it */ - if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) - fattr->cf_flags |= CIFS_FATTR_INO_COLLISION; - - return 1; -} - -static int -cifs_init_inode(struct inode *inode, void *opaque) -{ - struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; - - CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; - CIFS_I(inode)->createtime = fattr->cf_createtime; - return 0; -} - -/* - * walk dentry list for an inode and report whether it has aliases that - * are hashed. We use this to determine if a directory inode can actually - * be used. - */ -static bool -inode_has_hashed_dentries(struct inode *inode) -{ - struct dentry *dentry; - - spin_lock(&inode->i_lock); - list_for_each_entry(dentry, &inode->i_dentry, d_alias) { - if (!d_unhashed(dentry) || IS_ROOT(dentry)) { - spin_unlock(&inode->i_lock); - return true; - } - } - spin_unlock(&inode->i_lock); - return false; -} - -/* Given fattrs, get a corresponding inode */ -struct inode * -cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) -{ - unsigned long hash; - struct inode *inode; - -retry_iget5_locked: - cFYI(1, "looking for uniqueid=%llu", fattr->cf_uniqueid); - - /* hash down to 32-bits on 32-bit arch */ - hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); - - inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); - if (inode) { - /* was there a potentially problematic inode collision? */ - if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) { - fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION; - - if (inode_has_hashed_dentries(inode)) { - cifs_autodisable_serverino(CIFS_SB(sb)); - iput(inode); - fattr->cf_uniqueid = iunique(sb, ROOT_I); - goto retry_iget5_locked; - } - } - - cifs_fattr_to_inode(inode, fattr); - if (sb->s_flags & MS_NOATIME) - inode->i_flags |= S_NOATIME | S_NOCMTIME; - if (inode->i_state & I_NEW) { - inode->i_ino = hash; - if (S_ISREG(inode->i_mode)) - inode->i_data.backing_dev_info = sb->s_bdi; -#ifdef CONFIG_CIFS_FSCACHE - /* initialize per-inode cache cookie pointer */ - CIFS_I(inode)->fscache = NULL; -#endif - unlock_new_inode(inode); - } - } - - return inode; -} - -/* gets root inode */ -struct inode *cifs_root_iget(struct super_block *sb) -{ - int xid; - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - struct inode *inode = NULL; - long rc; - struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); - - xid = GetXid(); - if (tcon->unix_ext) - rc = cifs_get_inode_info_unix(&inode, "", sb, xid); - else - rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL); - - if (!inode) { - inode = ERR_PTR(rc); - goto out; - } - -#ifdef CONFIG_CIFS_FSCACHE - /* populate tcon->resource_id */ - tcon->resource_id = CIFS_I(inode)->uniqueid; -#endif - - if (rc && tcon->ipc) { - cFYI(1, "ipc connection - fake read inode"); - inode->i_mode |= S_IFDIR; - set_nlink(inode, 2); - inode->i_op = &cifs_ipc_inode_ops; - inode->i_fop = &simple_dir_operations; - inode->i_uid = cifs_sb->mnt_uid; - inode->i_gid = cifs_sb->mnt_gid; - } else if (rc) { - iget_failed(inode); - inode = ERR_PTR(rc); - } - -out: - /* can not call macro FreeXid here since in a void func - * TODO: This is no longer true - */ - _FreeXid(xid); - return inode; -} - -static int -cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, - char *full_path, __u32 dosattr) -{ - int rc; - int oplock = 0; - __u16 netfid; - __u32 netpid; - bool set_time = false; - struct cifsFileInfo *open_file; - struct cifsInodeInfo *cifsInode = CIFS_I(inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct tcon_link *tlink = NULL; - struct cifs_tcon *pTcon; - FILE_BASIC_INFO info_buf; - - if (attrs == NULL) - return -EINVAL; - - if (attrs->ia_valid & ATTR_ATIME) { - set_time = true; - info_buf.LastAccessTime = - cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime)); - } else - info_buf.LastAccessTime = 0; - - if (attrs->ia_valid & ATTR_MTIME) { - set_time = true; - info_buf.LastWriteTime = - cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime)); - } else - info_buf.LastWriteTime = 0; - - /* - * Samba throws this field away, but windows may actually use it. - * Do not set ctime unless other time stamps are changed explicitly - * (i.e. by utimes()) since we would then have a mix of client and - * server times. - */ - if (set_time && (attrs->ia_valid & ATTR_CTIME)) { - cFYI(1, "CIFS - CTIME changed"); - info_buf.ChangeTime = - cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); - } else - info_buf.ChangeTime = 0; - - info_buf.CreationTime = 0; /* don't change */ - info_buf.Attributes = cpu_to_le32(dosattr); - - /* - * If the file is already open for write, just use that fileid - */ - open_file = find_writable_file(cifsInode, true); - if (open_file) { - netfid = open_file->netfid; - netpid = open_file->pid; - pTcon = tlink_tcon(open_file->tlink); - goto set_via_filehandle; - } - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) { - rc = PTR_ERR(tlink); - tlink = NULL; - goto out; - } - pTcon = tlink_tcon(tlink); - - /* - * NT4 apparently returns success on this call, but it doesn't - * really work. - */ - if (!(pTcon->ses->flags & CIFS_SES_NT4)) { - rc = CIFSSMBSetPathInfo(xid, pTcon, full_path, - &info_buf, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc == 0) { - cifsInode->cifsAttrs = dosattr; - goto out; - } else if (rc != -EOPNOTSUPP && rc != -EINVAL) - goto out; - } - - cFYI(1, "calling SetFileInfo since SetPathInfo for " - "times not supported by this server"); - rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, - SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, - CREATE_NOT_DIR, &netfid, &oplock, - NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - - if (rc != 0) { - if (rc == -EIO) - rc = -EINVAL; - goto out; - } - - netpid = current->tgid; - -set_via_filehandle: - rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid); - if (!rc) - cifsInode->cifsAttrs = dosattr; - - if (open_file == NULL) - CIFSSMBClose(xid, pTcon, netfid); - else - cifsFileInfo_put(open_file); -out: - if (tlink != NULL) - cifs_put_tlink(tlink); - return rc; -} - -/* - * open the given file (if it isn't already), set the DELETE_ON_CLOSE bit - * and rename it to a random name that hopefully won't conflict with - * anything else. - */ -static int -cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid) -{ - int oplock = 0; - int rc; - __u16 netfid; - struct inode *inode = dentry->d_inode; - struct cifsInodeInfo *cifsInode = CIFS_I(inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct tcon_link *tlink; - struct cifs_tcon *tcon; - __u32 dosattr, origattr; - FILE_BASIC_INFO *info_buf = NULL; - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - tcon = tlink_tcon(tlink); - - rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, - DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, - &netfid, &oplock, NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc != 0) - goto out; - - origattr = cifsInode->cifsAttrs; - if (origattr == 0) - origattr |= ATTR_NORMAL; - - dosattr = origattr & ~ATTR_READONLY; - if (dosattr == 0) - dosattr |= ATTR_NORMAL; - dosattr |= ATTR_HIDDEN; - - /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */ - if (dosattr != origattr) { - info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL); - if (info_buf == NULL) { - rc = -ENOMEM; - goto out_close; - } - info_buf->Attributes = cpu_to_le32(dosattr); - rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, - current->tgid); - /* although we would like to mark the file hidden - if that fails we will still try to rename it */ - if (rc != 0) - cifsInode->cifsAttrs = dosattr; - else - dosattr = origattr; /* since not able to change them */ - } - - /* rename the file */ - rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc != 0) { - rc = -ETXTBSY; - goto undo_setattr; - } - - /* try to set DELETE_ON_CLOSE */ - if (!cifsInode->delete_pending) { - rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid, - current->tgid); - /* - * some samba versions return -ENOENT when we try to set the - * file disposition here. Likely a samba bug, but work around - * it for now. This means that some cifsXXX files may hang - * around after they shouldn't. - * - * BB: remove this hack after more servers have the fix - */ - if (rc == -ENOENT) - rc = 0; - else if (rc != 0) { - rc = -ETXTBSY; - goto undo_rename; - } - cifsInode->delete_pending = true; - } - -out_close: - CIFSSMBClose(xid, tcon, netfid); -out: - kfree(info_buf); - cifs_put_tlink(tlink); - return rc; - - /* - * reset everything back to the original state. Don't bother - * dealing with errors here since we can't do anything about - * them anyway. - */ -undo_rename: - CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); -undo_setattr: - if (dosattr != origattr) { - info_buf->Attributes = cpu_to_le32(origattr); - if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, - current->tgid)) - cifsInode->cifsAttrs = origattr; - } - - goto out_close; -} - - -/* - * If dentry->d_inode is null (usually meaning the cached dentry - * is a negative dentry) then we would attempt a standard SMB delete, but - * if that fails we can not attempt the fall back mechanisms on EACCESS - * but will return the EACCESS to the caller. Note that the VFS does not call - * unlink on negative dentries currently. - */ -int cifs_unlink(struct inode *dir, struct dentry *dentry) -{ - int rc = 0; - int xid; - char *full_path = NULL; - struct inode *inode = dentry->d_inode; - struct cifsInodeInfo *cifs_inode; - struct super_block *sb = dir->i_sb; - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - struct tcon_link *tlink; - struct cifs_tcon *tcon; - struct iattr *attrs = NULL; - __u32 dosattr = 0, origattr = 0; - - cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry); - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - tcon = tlink_tcon(tlink); - - xid = GetXid(); - - /* Unlink can be called from rename so we can not take the - * sb->s_vfs_rename_mutex here */ - full_path = build_path_from_dentry(dentry); - if (full_path == NULL) { - rc = -ENOMEM; - goto unlink_out; - } - - if ((tcon->ses->capabilities & CAP_UNIX) && - (CIFS_UNIX_POSIX_PATH_OPS_CAP & - le64_to_cpu(tcon->fsUnixInfo.Capability))) { - rc = CIFSPOSIXDelFile(xid, tcon, full_path, - SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - cFYI(1, "posix del rc %d", rc); - if ((rc == 0) || (rc == -ENOENT)) - goto psx_del_no_retry; - } - -retry_std_delete: - rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - -psx_del_no_retry: - if (!rc) { - if (inode) - drop_nlink(inode); - } else if (rc == -ENOENT) { - d_drop(dentry); - } else if (rc == -ETXTBSY) { - rc = cifs_rename_pending_delete(full_path, dentry, xid); - if (rc == 0) - drop_nlink(inode); - } else if ((rc == -EACCES) && (dosattr == 0) && inode) { - attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); - if (attrs == NULL) { - rc = -ENOMEM; - goto out_reval; - } - - /* try to reset dos attributes */ - cifs_inode = CIFS_I(inode); - origattr = cifs_inode->cifsAttrs; - if (origattr == 0) - origattr |= ATTR_NORMAL; - dosattr = origattr & ~ATTR_READONLY; - if (dosattr == 0) - dosattr |= ATTR_NORMAL; - dosattr |= ATTR_HIDDEN; - - rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr); - if (rc != 0) - goto out_reval; - - goto retry_std_delete; - } - - /* undo the setattr if we errored out and it's needed */ - if (rc != 0 && dosattr != 0) - cifs_set_file_info(inode, attrs, xid, full_path, origattr); - -out_reval: - if (inode) { - cifs_inode = CIFS_I(inode); - cifs_inode->time = 0; /* will force revalidate to get info - when needed */ - inode->i_ctime = current_fs_time(sb); - } - dir->i_ctime = dir->i_mtime = current_fs_time(sb); - cifs_inode = CIFS_I(dir); - CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ -unlink_out: - kfree(full_path); - kfree(attrs); - FreeXid(xid); - cifs_put_tlink(tlink); - return rc; -} - -int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) -{ - int rc = 0, tmprc; - int xid; - struct cifs_sb_info *cifs_sb; - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - char *full_path = NULL; - struct inode *newinode = NULL; - struct cifs_fattr fattr; - - cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode); - - cifs_sb = CIFS_SB(inode->i_sb); - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - pTcon = tlink_tcon(tlink); - - xid = GetXid(); - - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - goto mkdir_out; - } - - if ((pTcon->ses->capabilities & CAP_UNIX) && - (CIFS_UNIX_POSIX_PATH_OPS_CAP & - le64_to_cpu(pTcon->fsUnixInfo.Capability))) { - u32 oplock = 0; - FILE_UNIX_BASIC_INFO *pInfo = - kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); - if (pInfo == NULL) { - rc = -ENOMEM; - goto mkdir_out; - } - - mode &= ~current_umask(); - rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, - mode, NULL /* netfid */, pInfo, &oplock, - full_path, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc == -EOPNOTSUPP) { - kfree(pInfo); - goto mkdir_retry_old; - } else if (rc) { - cFYI(1, "posix mkdir returned 0x%x", rc); - d_drop(direntry); - } else { - if (pInfo->Type == cpu_to_le32(-1)) { - /* no return info, go query for it */ - kfree(pInfo); - goto mkdir_get_info; - } -/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need - to set uid/gid */ - - cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); - cifs_fill_uniqueid(inode->i_sb, &fattr); - newinode = cifs_iget(inode->i_sb, &fattr); - if (!newinode) { - kfree(pInfo); - goto mkdir_get_info; - } - - d_instantiate(direntry, newinode); - -#ifdef CONFIG_CIFS_DEBUG2 - cFYI(1, "instantiated dentry %p %s to inode %p", - direntry, direntry->d_name.name, newinode); - - if (newinode->i_nlink != 2) - cFYI(1, "unexpected number of links %d", - newinode->i_nlink); -#endif - } - kfree(pInfo); - goto mkdir_out; - } -mkdir_retry_old: - /* BB add setting the equivalent of mode via CreateX w/ACLs */ - rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc) { - cFYI(1, "cifs_mkdir returned 0x%x", rc); - d_drop(direntry); - } else { -mkdir_get_info: - if (pTcon->unix_ext) - rc = cifs_get_inode_info_unix(&newinode, full_path, - inode->i_sb, xid); - else - rc = cifs_get_inode_info(&newinode, full_path, NULL, - inode->i_sb, xid, NULL); - - d_instantiate(direntry, newinode); - /* setting nlink not necessary except in cases where we - * failed to get it from the server or was set bogus */ - if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) - set_nlink(direntry->d_inode, 2); - - mode &= ~current_umask(); - /* must turn on setgid bit if parent dir has it */ - if (inode->i_mode & S_ISGID) - mode |= S_ISGID; - - if (pTcon->unix_ext) { - struct cifs_unix_set_info_args args = { - .mode = mode, - .ctime = NO_CHANGE_64, - .atime = NO_CHANGE_64, - .mtime = NO_CHANGE_64, - .device = 0, - }; - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { - args.uid = (__u64)current_fsuid(); - if (inode->i_mode & S_ISGID) - args.gid = (__u64)inode->i_gid; - else - args.gid = (__u64)current_fsgid(); - } else { - args.uid = NO_CHANGE_64; - args.gid = NO_CHANGE_64; - } - CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - } else { - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && - (mode & S_IWUGO) == 0) { - FILE_BASIC_INFO pInfo; - struct cifsInodeInfo *cifsInode; - u32 dosattrs; - - memset(&pInfo, 0, sizeof(pInfo)); - cifsInode = CIFS_I(newinode); - dosattrs = cifsInode->cifsAttrs|ATTR_READONLY; - pInfo.Attributes = cpu_to_le32(dosattrs); - tmprc = CIFSSMBSetPathInfo(xid, pTcon, - full_path, &pInfo, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (tmprc == 0) - cifsInode->cifsAttrs = dosattrs; - } - if (direntry->d_inode) { - if (cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_DYNPERM) - direntry->d_inode->i_mode = - (mode | S_IFDIR); - - if (cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_SET_UID) { - direntry->d_inode->i_uid = - current_fsuid(); - if (inode->i_mode & S_ISGID) - direntry->d_inode->i_gid = - inode->i_gid; - else - direntry->d_inode->i_gid = - current_fsgid(); - } - } - } - } -mkdir_out: - /* - * Force revalidate to get parent dir info when needed since cached - * attributes are invalid now. - */ - CIFS_I(inode)->time = 0; - kfree(full_path); - FreeXid(xid); - cifs_put_tlink(tlink); - return rc; -} - -int cifs_rmdir(struct inode *inode, struct dentry *direntry) -{ - int rc = 0; - int xid; - struct cifs_sb_info *cifs_sb; - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - char *full_path = NULL; - struct cifsInodeInfo *cifsInode; - - cFYI(1, "cifs_rmdir, inode = 0x%p", inode); - - xid = GetXid(); - - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - goto rmdir_exit; - } - - cifs_sb = CIFS_SB(inode->i_sb); - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) { - rc = PTR_ERR(tlink); - goto rmdir_exit; - } - pTcon = tlink_tcon(tlink); - - rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - cifs_put_tlink(tlink); - - if (!rc) { - spin_lock(&direntry->d_inode->i_lock); - i_size_write(direntry->d_inode, 0); - clear_nlink(direntry->d_inode); - spin_unlock(&direntry->d_inode->i_lock); - } - - cifsInode = CIFS_I(direntry->d_inode); - /* force revalidate to go get info when needed */ - cifsInode->time = 0; - - cifsInode = CIFS_I(inode); - /* - * Force revalidate to get parent dir info when needed since cached - * attributes are invalid now. - */ - cifsInode->time = 0; - - direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = - current_fs_time(inode->i_sb); - -rmdir_exit: - kfree(full_path); - FreeXid(xid); - return rc; -} - -static int -cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, - struct dentry *to_dentry, const char *toPath) -{ - struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb); - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - __u16 srcfid; - int oplock, rc; - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - pTcon = tlink_tcon(tlink); - - /* try path-based rename first */ - rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - - /* - * don't bother with rename by filehandle unless file is busy and - * source Note that cross directory moves do not work with - * rename by filehandle to various Windows servers. - */ - if (rc == 0 || rc != -ETXTBSY) - goto do_rename_exit; - - /* open-file renames don't work across directories */ - if (to_dentry->d_parent != from_dentry->d_parent) - goto do_rename_exit; - - /* open the file to be renamed -- we need DELETE perms */ - rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, - CREATE_NOT_DIR, &srcfid, &oplock, NULL, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - - if (rc == 0) { - rc = CIFSSMBRenameOpenFile(xid, pTcon, srcfid, - (const char *) to_dentry->d_name.name, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - - CIFSSMBClose(xid, pTcon, srcfid); - } -do_rename_exit: - cifs_put_tlink(tlink); - return rc; -} - -int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, - struct inode *target_dir, struct dentry *target_dentry) -{ - char *fromName = NULL; - char *toName = NULL; - struct cifs_sb_info *cifs_sb; - struct tcon_link *tlink; - struct cifs_tcon *tcon; - FILE_UNIX_BASIC_INFO *info_buf_source = NULL; - FILE_UNIX_BASIC_INFO *info_buf_target; - int xid, rc, tmprc; - - cifs_sb = CIFS_SB(source_dir->i_sb); - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - tcon = tlink_tcon(tlink); - - xid = GetXid(); - - /* - * we already have the rename sem so we do not need to - * grab it again here to protect the path integrity - */ - fromName = build_path_from_dentry(source_dentry); - if (fromName == NULL) { - rc = -ENOMEM; - goto cifs_rename_exit; - } - - toName = build_path_from_dentry(target_dentry); - if (toName == NULL) { - rc = -ENOMEM; - goto cifs_rename_exit; - } - - rc = cifs_do_rename(xid, source_dentry, fromName, - target_dentry, toName); - - if (rc == -EEXIST && tcon->unix_ext) { - /* - * Are src and dst hardlinks of same inode? We can - * only tell with unix extensions enabled - */ - info_buf_source = - kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), - GFP_KERNEL); - if (info_buf_source == NULL) { - rc = -ENOMEM; - goto cifs_rename_exit; - } - - info_buf_target = info_buf_source + 1; - tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName, - info_buf_source, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (tmprc != 0) - goto unlink_target; - - tmprc = CIFSSMBUnixQPathInfo(xid, tcon, toName, - info_buf_target, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - - if (tmprc == 0 && (info_buf_source->UniqueId == - info_buf_target->UniqueId)) { - /* same file, POSIX says that this is a noop */ - rc = 0; - goto cifs_rename_exit; - } - } /* else ... BB we could add the same check for Windows by - checking the UniqueId via FILE_INTERNAL_INFO */ - -unlink_target: - /* Try unlinking the target dentry if it's not negative */ - if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) { - tmprc = cifs_unlink(target_dir, target_dentry); - if (tmprc) - goto cifs_rename_exit; - - rc = cifs_do_rename(xid, source_dentry, fromName, - target_dentry, toName); - } - -cifs_rename_exit: - kfree(info_buf_source); - kfree(fromName); - kfree(toName); - FreeXid(xid); - cifs_put_tlink(tlink); - return rc; -} - -static bool -cifs_inode_needs_reval(struct inode *inode) -{ - struct cifsInodeInfo *cifs_i = CIFS_I(inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - - if (cifs_i->clientCanCacheRead) - return false; - - if (!lookupCacheEnabled) - return true; - - if (cifs_i->time == 0) - return true; - - if (!time_in_range(jiffies, cifs_i->time, - cifs_i->time + cifs_sb->actimeo)) - return true; - - /* hardlinked files w/ noserverino get "special" treatment */ - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) && - S_ISREG(inode->i_mode) && inode->i_nlink != 1) - return true; - - return false; -} - -/* - * Zap the cache. Called when invalid_mapping flag is set. - */ -int -cifs_invalidate_mapping(struct inode *inode) -{ - int rc = 0; - struct cifsInodeInfo *cifs_i = CIFS_I(inode); - - cifs_i->invalid_mapping = false; - - if (inode->i_mapping && inode->i_mapping->nrpages != 0) { - rc = invalidate_inode_pages2(inode->i_mapping); - if (rc) { - cERROR(1, "%s: could not invalidate inode %p", __func__, - inode); - cifs_i->invalid_mapping = true; - } - } - - cifs_fscache_reset_inode_cookie(inode); - return rc; -} - -int cifs_revalidate_file_attr(struct file *filp) -{ - int rc = 0; - struct inode *inode = filp->f_path.dentry->d_inode; - struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; - - if (!cifs_inode_needs_reval(inode)) - return rc; - - if (tlink_tcon(cfile->tlink)->unix_ext) - rc = cifs_get_file_info_unix(filp); - else - rc = cifs_get_file_info(filp); - - return rc; -} - -int cifs_revalidate_dentry_attr(struct dentry *dentry) -{ - int xid; - int rc = 0; - struct inode *inode = dentry->d_inode; - struct super_block *sb = dentry->d_sb; - char *full_path = NULL; - - if (inode == NULL) - return -ENOENT; - - if (!cifs_inode_needs_reval(inode)) - return rc; - - xid = GetXid(); - - /* can not safely grab the rename sem here if rename calls revalidate - since that would deadlock */ - full_path = build_path_from_dentry(dentry); - if (full_path == NULL) { - rc = -ENOMEM; - goto out; - } - - cFYI(1, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time " - "%ld jiffies %ld", full_path, inode, inode->i_count.counter, - dentry, dentry->d_time, jiffies); - - if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) - rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); - else - rc = cifs_get_inode_info(&inode, full_path, NULL, sb, - xid, NULL); - -out: - kfree(full_path); - FreeXid(xid); - return rc; -} - -int cifs_revalidate_file(struct file *filp) -{ - int rc; - struct inode *inode = filp->f_path.dentry->d_inode; - - rc = cifs_revalidate_file_attr(filp); - if (rc) - return rc; - - if (CIFS_I(inode)->invalid_mapping) - rc = cifs_invalidate_mapping(inode); - return rc; -} - -/* revalidate a dentry's inode attributes */ -int cifs_revalidate_dentry(struct dentry *dentry) -{ - int rc; - struct inode *inode = dentry->d_inode; - - rc = cifs_revalidate_dentry_attr(dentry); - if (rc) - return rc; - - if (CIFS_I(inode)->invalid_mapping) - rc = cifs_invalidate_mapping(inode); - return rc; -} - -int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, - struct kstat *stat) -{ - struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); - struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); - struct inode *inode = dentry->d_inode; - int rc; - - /* - * We need to be sure that all dirty pages are written and the server - * has actual ctime, mtime and file length. - */ - if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping && - inode->i_mapping->nrpages != 0) { - rc = filemap_fdatawait(inode->i_mapping); - if (rc) { - mapping_set_error(inode->i_mapping, rc); - return rc; - } - } - - rc = cifs_revalidate_dentry_attr(dentry); - if (rc) - return rc; - - generic_fillattr(inode, stat); - stat->blksize = CIFS_MAX_MSGSIZE; - stat->ino = CIFS_I(inode)->uniqueid; - - /* - * If on a multiuser mount without unix extensions, and the admin hasn't - * overridden them, set the ownership to the fsuid/fsgid of the current - * process. - */ - if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) && - !tcon->unix_ext) { - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) - stat->uid = current_fsuid(); - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) - stat->gid = current_fsgid(); - } - return rc; -} - -static int cifs_truncate_page(struct address_space *mapping, loff_t from) -{ - pgoff_t index = from >> PAGE_CACHE_SHIFT; - unsigned offset = from & (PAGE_CACHE_SIZE - 1); - struct page *page; - int rc = 0; - - page = grab_cache_page(mapping, index); - if (!page) - return -ENOMEM; - - zero_user_segment(page, offset, PAGE_CACHE_SIZE); - unlock_page(page); - page_cache_release(page); - return rc; -} - -static void cifs_setsize(struct inode *inode, loff_t offset) -{ - loff_t oldsize; - - spin_lock(&inode->i_lock); - oldsize = inode->i_size; - i_size_write(inode, offset); - spin_unlock(&inode->i_lock); - - truncate_pagecache(inode, oldsize, offset); -} - -static int -cifs_set_file_size(struct inode *inode, struct iattr *attrs, - int xid, char *full_path) -{ - int rc; - struct cifsFileInfo *open_file; - struct cifsInodeInfo *cifsInode = CIFS_I(inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct tcon_link *tlink = NULL; - struct cifs_tcon *pTcon = NULL; - struct cifs_io_parms io_parms; - - /* - * To avoid spurious oplock breaks from server, in the case of - * inodes that we already have open, avoid doing path based - * setting of file size if we can do it by handle. - * This keeps our caching token (oplock) and avoids timeouts - * when the local oplock break takes longer to flush - * writebehind data than the SMB timeout for the SetPathInfo - * request would allow - */ - open_file = find_writable_file(cifsInode, true); - if (open_file) { - __u16 nfid = open_file->netfid; - __u32 npid = open_file->pid; - pTcon = tlink_tcon(open_file->tlink); - rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid, - npid, false); - cifsFileInfo_put(open_file); - cFYI(1, "SetFSize for attrs rc = %d", rc); - if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { - unsigned int bytes_written; - - io_parms.netfid = nfid; - io_parms.pid = npid; - io_parms.tcon = pTcon; - io_parms.offset = 0; - io_parms.length = attrs->ia_size; - rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, - NULL, NULL, 1); - cFYI(1, "Wrt seteof rc %d", rc); - } - } else - rc = -EINVAL; - - if (rc != 0) { - if (pTcon == NULL) { - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - pTcon = tlink_tcon(tlink); - } - - /* Set file size by pathname rather than by handle - either because no valid, writeable file handle for - it was found or because there was an error setting - it by handle */ - rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, - false, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - cFYI(1, "SetEOF by path (setattrs) rc = %d", rc); - if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { - __u16 netfid; - int oplock = 0; - - rc = SMBLegacyOpen(xid, pTcon, full_path, - FILE_OPEN, GENERIC_WRITE, - CREATE_NOT_DIR, &netfid, &oplock, NULL, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc == 0) { - unsigned int bytes_written; - - io_parms.netfid = netfid; - io_parms.pid = current->tgid; - io_parms.tcon = pTcon; - io_parms.offset = 0; - io_parms.length = attrs->ia_size; - rc = CIFSSMBWrite(xid, &io_parms, - &bytes_written, - NULL, NULL, 1); - cFYI(1, "wrt seteof rc %d", rc); - CIFSSMBClose(xid, pTcon, netfid); - } - } - if (tlink) - cifs_put_tlink(tlink); - } - - if (rc == 0) { - cifsInode->server_eof = attrs->ia_size; - cifs_setsize(inode, attrs->ia_size); - cifs_truncate_page(inode->i_mapping, inode->i_size); - } - - return rc; -} - -static int -cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) -{ - int rc; - int xid; - char *full_path = NULL; - struct inode *inode = direntry->d_inode; - struct cifsInodeInfo *cifsInode = CIFS_I(inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - struct cifs_unix_set_info_args *args = NULL; - struct cifsFileInfo *open_file; - - cFYI(1, "setattr_unix on file %s attrs->ia_valid=0x%x", - direntry->d_name.name, attrs->ia_valid); - - xid = GetXid(); - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) - attrs->ia_valid |= ATTR_FORCE; - - rc = inode_change_ok(inode, attrs); - if (rc < 0) - goto out; - - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - goto out; - } - - /* - * Attempt to flush data before changing attributes. We need to do - * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the - * ownership or mode then we may also need to do this. Here, we take - * the safe way out and just do the flush on all setattr requests. If - * the flush returns error, store it to report later and continue. - * - * BB: This should be smarter. Why bother flushing pages that - * will be truncated anyway? Also, should we error out here if - * the flush returns error? - */ - rc = filemap_write_and_wait(inode->i_mapping); - mapping_set_error(inode->i_mapping, rc); - rc = 0; - - if (attrs->ia_valid & ATTR_SIZE) { - rc = cifs_set_file_size(inode, attrs, xid, full_path); - if (rc != 0) - goto out; - } - - /* skip mode change if it's just for clearing setuid/setgid */ - if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) - attrs->ia_valid &= ~ATTR_MODE; - - args = kmalloc(sizeof(*args), GFP_KERNEL); - if (args == NULL) { - rc = -ENOMEM; - goto out; - } - - /* set up the struct */ - if (attrs->ia_valid & ATTR_MODE) - args->mode = attrs->ia_mode; - else - args->mode = NO_CHANGE_64; - - if (attrs->ia_valid & ATTR_UID) - args->uid = attrs->ia_uid; - else - args->uid = NO_CHANGE_64; - - if (attrs->ia_valid & ATTR_GID) - args->gid = attrs->ia_gid; - else - args->gid = NO_CHANGE_64; - - if (attrs->ia_valid & ATTR_ATIME) - args->atime = cifs_UnixTimeToNT(attrs->ia_atime); - else - args->atime = NO_CHANGE_64; - - if (attrs->ia_valid & ATTR_MTIME) - args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime); - else - args->mtime = NO_CHANGE_64; - - if (attrs->ia_valid & ATTR_CTIME) - args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime); - else - args->ctime = NO_CHANGE_64; - - args->device = 0; - open_file = find_writable_file(cifsInode, true); - if (open_file) { - u16 nfid = open_file->netfid; - u32 npid = open_file->pid; - pTcon = tlink_tcon(open_file->tlink); - rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); - cifsFileInfo_put(open_file); - } else { - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) { - rc = PTR_ERR(tlink); - goto out; - } - pTcon = tlink_tcon(tlink); - rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - cifs_put_tlink(tlink); - } - - if (rc) - goto out; - - if ((attrs->ia_valid & ATTR_SIZE) && - attrs->ia_size != i_size_read(inode)) - truncate_setsize(inode, attrs->ia_size); - - setattr_copy(inode, attrs); - mark_inode_dirty(inode); - - /* force revalidate when any of these times are set since some - of the fs types (eg ext3, fat) do not have fine enough - time granularity to match protocol, and we do not have a - a way (yet) to query the server fs's time granularity (and - whether it rounds times down). - */ - if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME)) - cifsInode->time = 0; -out: - kfree(args); - kfree(full_path); - FreeXid(xid); - return rc; -} - -static int -cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) -{ - int xid; - uid_t uid = NO_CHANGE_32; - gid_t gid = NO_CHANGE_32; - struct inode *inode = direntry->d_inode; - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct cifsInodeInfo *cifsInode = CIFS_I(inode); - char *full_path = NULL; - int rc = -EACCES; - __u32 dosattr = 0; - __u64 mode = NO_CHANGE_64; - - xid = GetXid(); - - cFYI(1, "setattr on file %s attrs->iavalid 0x%x", - direntry->d_name.name, attrs->ia_valid); - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) - attrs->ia_valid |= ATTR_FORCE; - - rc = inode_change_ok(inode, attrs); - if (rc < 0) { - FreeXid(xid); - return rc; - } - - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - FreeXid(xid); - return rc; - } - - /* - * Attempt to flush data before changing attributes. We need to do - * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the - * ownership or mode then we may also need to do this. Here, we take - * the safe way out and just do the flush on all setattr requests. If - * the flush returns error, store it to report later and continue. - * - * BB: This should be smarter. Why bother flushing pages that - * will be truncated anyway? Also, should we error out here if - * the flush returns error? - */ - rc = filemap_write_and_wait(inode->i_mapping); - mapping_set_error(inode->i_mapping, rc); - rc = 0; - - if (attrs->ia_valid & ATTR_SIZE) { - rc = cifs_set_file_size(inode, attrs, xid, full_path); - if (rc != 0) - goto cifs_setattr_exit; - } - - if (attrs->ia_valid & ATTR_UID) - uid = attrs->ia_uid; - - if (attrs->ia_valid & ATTR_GID) - gid = attrs->ia_gid; - -#ifdef CONFIG_CIFS_ACL - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { - if (uid != NO_CHANGE_32 || gid != NO_CHANGE_32) { - rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64, - uid, gid); - if (rc) { - cFYI(1, "%s: Setting id failed with error: %d", - __func__, rc); - goto cifs_setattr_exit; - } - } - } else -#endif /* CONFIG_CIFS_ACL */ - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) - attrs->ia_valid &= ~(ATTR_UID | ATTR_GID); - - /* skip mode change if it's just for clearing setuid/setgid */ - if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) - attrs->ia_valid &= ~ATTR_MODE; - - if (attrs->ia_valid & ATTR_MODE) { - mode = attrs->ia_mode; - rc = 0; -#ifdef CONFIG_CIFS_ACL - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { - rc = id_mode_to_cifs_acl(inode, full_path, mode, - NO_CHANGE_32, NO_CHANGE_32); - if (rc) { - cFYI(1, "%s: Setting ACL failed with error: %d", - __func__, rc); - goto cifs_setattr_exit; - } - } else -#endif /* CONFIG_CIFS_ACL */ - if (((mode & S_IWUGO) == 0) && - (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { - - dosattr = cifsInode->cifsAttrs | ATTR_READONLY; - - /* fix up mode if we're not using dynperm */ - if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) - attrs->ia_mode = inode->i_mode & ~S_IWUGO; - } else if ((mode & S_IWUGO) && - (cifsInode->cifsAttrs & ATTR_READONLY)) { - - dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY; - /* Attributes of 0 are ignored */ - if (dosattr == 0) - dosattr |= ATTR_NORMAL; - - /* reset local inode permissions to normal */ - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { - attrs->ia_mode &= ~(S_IALLUGO); - if (S_ISDIR(inode->i_mode)) - attrs->ia_mode |= - cifs_sb->mnt_dir_mode; - else - attrs->ia_mode |= - cifs_sb->mnt_file_mode; - } - } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { - /* ignore mode change - ATTR_READONLY hasn't changed */ - attrs->ia_valid &= ~ATTR_MODE; - } - } - - if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) || - ((attrs->ia_valid & ATTR_MODE) && dosattr)) { - rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr); - /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */ - - /* Even if error on time set, no sense failing the call if - the server would set the time to a reasonable value anyway, - and this check ensures that we are not being called from - sys_utimes in which case we ought to fail the call back to - the user when the server rejects the call */ - if ((rc) && (attrs->ia_valid & - (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE))) - rc = 0; - } - - /* do not need local check to inode_check_ok since the server does - that */ - if (rc) - goto cifs_setattr_exit; - - if ((attrs->ia_valid & ATTR_SIZE) && - attrs->ia_size != i_size_read(inode)) - truncate_setsize(inode, attrs->ia_size); - - setattr_copy(inode, attrs); - mark_inode_dirty(inode); - -cifs_setattr_exit: - kfree(full_path); - FreeXid(xid); - return rc; -} - -int -cifs_setattr(struct dentry *direntry, struct iattr *attrs) -{ - struct inode *inode = direntry->d_inode; - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb); - - if (pTcon->unix_ext) - return cifs_setattr_unix(direntry, attrs); - - return cifs_setattr_nounix(direntry, attrs); - - /* BB: add cifs_setattr_legacy for really old servers */ -} - -#if 0 -void cifs_delete_inode(struct inode *inode) -{ - cFYI(1, "In cifs_delete_inode, inode = 0x%p", inode); - /* may have to add back in if and when safe distributed caching of - directories added e.g. via FindNotify */ -} -#endif diff --git a/ANDROID_3.4.5/fs/cifs/ioctl.c b/ANDROID_3.4.5/fs/cifs/ioctl.c deleted file mode 100644 index 4221b5e4..00000000 --- a/ANDROID_3.4.5/fs/cifs/ioctl.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * fs/cifs/ioctl.c - * - * vfs operations that deal with io control - * - * Copyright (C) International Business Machines Corp., 2005,2007 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/fs.h> -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifs_debug.h" -#include "cifsfs.h" - -#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2) - -long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) -{ - struct inode *inode = filep->f_dentry->d_inode; - int rc = -ENOTTY; /* strange error - but the precedent */ - int xid; - struct cifs_sb_info *cifs_sb; -#ifdef CONFIG_CIFS_POSIX - struct cifsFileInfo *pSMBFile = filep->private_data; - struct cifs_tcon *tcon; - __u64 ExtAttrBits = 0; - __u64 ExtAttrMask = 0; - __u64 caps; -#endif /* CONFIG_CIFS_POSIX */ - - xid = GetXid(); - - cFYI(1, "ioctl file %p cmd %u arg %lu", filep, command, arg); - - cifs_sb = CIFS_SB(inode->i_sb); - - switch (command) { - case CIFS_IOC_CHECKUMOUNT: - cFYI(1, "User unmount attempted"); - if (cifs_sb->mnt_uid == current_uid()) - rc = 0; - else { - rc = -EACCES; - cFYI(1, "uids do not match"); - } - break; -#ifdef CONFIG_CIFS_POSIX - case FS_IOC_GETFLAGS: - if (pSMBFile == NULL) - break; - tcon = tlink_tcon(pSMBFile->tlink); - caps = le64_to_cpu(tcon->fsUnixInfo.Capability); - if (CIFS_UNIX_EXTATTR_CAP & caps) { - rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid, - &ExtAttrBits, &ExtAttrMask); - if (rc == 0) - rc = put_user(ExtAttrBits & - FS_FL_USER_VISIBLE, - (int __user *)arg); - } - break; - - case FS_IOC_SETFLAGS: - if (pSMBFile == NULL) - break; - tcon = tlink_tcon(pSMBFile->tlink); - caps = le64_to_cpu(tcon->fsUnixInfo.Capability); - if (CIFS_UNIX_EXTATTR_CAP & caps) { - if (get_user(ExtAttrBits, (int __user *)arg)) { - rc = -EFAULT; - break; - } - /* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid, - extAttrBits, &ExtAttrMask);*/ - } - cFYI(1, "set flags not implemented yet"); - break; -#endif /* CONFIG_CIFS_POSIX */ - default: - cFYI(1, "unsupported ioctl"); - break; - } - - FreeXid(xid); - return rc; -} diff --git a/ANDROID_3.4.5/fs/cifs/link.c b/ANDROID_3.4.5/fs/cifs/link.c deleted file mode 100644 index 6b0e0643..00000000 --- a/ANDROID_3.4.5/fs/cifs/link.c +++ /dev/null @@ -1,606 +0,0 @@ -/* - * fs/cifs/link.c - * - * Copyright (C) International Business Machines Corp., 2002,2008 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/fs.h> -#include <linux/stat.h> -#include <linux/slab.h> -#include <linux/namei.h> -#include "cifsfs.h" -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifs_debug.h" -#include "cifs_fs_sb.h" - -#define CIFS_MF_SYMLINK_LEN_OFFSET (4+1) -#define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1)) -#define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1)) -#define CIFS_MF_SYMLINK_LINK_MAXLEN (1024) -#define CIFS_MF_SYMLINK_FILE_SIZE \ - (CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN) - -#define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n" -#define CIFS_MF_SYMLINK_MD5_FORMAT \ - "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n" -#define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) \ - md5_hash[0], md5_hash[1], md5_hash[2], md5_hash[3], \ - md5_hash[4], md5_hash[5], md5_hash[6], md5_hash[7], \ - md5_hash[8], md5_hash[9], md5_hash[10], md5_hash[11],\ - md5_hash[12], md5_hash[13], md5_hash[14], md5_hash[15] - -static int -symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash) -{ - int rc; - unsigned int size; - struct crypto_shash *md5; - struct sdesc *sdescmd5; - - md5 = crypto_alloc_shash("md5", 0, 0); - if (IS_ERR(md5)) { - rc = PTR_ERR(md5); - cERROR(1, "%s: Crypto md5 allocation error %d\n", __func__, rc); - return rc; - } - size = sizeof(struct shash_desc) + crypto_shash_descsize(md5); - sdescmd5 = kmalloc(size, GFP_KERNEL); - if (!sdescmd5) { - rc = -ENOMEM; - cERROR(1, "%s: Memory allocation failure\n", __func__); - goto symlink_hash_err; - } - sdescmd5->shash.tfm = md5; - sdescmd5->shash.flags = 0x0; - - rc = crypto_shash_init(&sdescmd5->shash); - if (rc) { - cERROR(1, "%s: Could not init md5 shash\n", __func__); - goto symlink_hash_err; - } - rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len); - if (rc) { - cERROR(1, "%s: Could not update iwth link_str\n", __func__); - goto symlink_hash_err; - } - rc = crypto_shash_final(&sdescmd5->shash, md5_hash); - if (rc) - cERROR(1, "%s: Could not generate md5 hash\n", __func__); - -symlink_hash_err: - crypto_free_shash(md5); - kfree(sdescmd5); - - return rc; -} - -static int -CIFSParseMFSymlink(const u8 *buf, - unsigned int buf_len, - unsigned int *_link_len, - char **_link_str) -{ - int rc; - unsigned int link_len; - const char *md5_str1; - const char *link_str; - u8 md5_hash[16]; - char md5_str2[34]; - - if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE) - return -EINVAL; - - md5_str1 = (const char *)&buf[CIFS_MF_SYMLINK_MD5_OFFSET]; - link_str = (const char *)&buf[CIFS_MF_SYMLINK_LINK_OFFSET]; - - rc = sscanf(buf, CIFS_MF_SYMLINK_LEN_FORMAT, &link_len); - if (rc != 1) - return -EINVAL; - - rc = symlink_hash(link_len, link_str, md5_hash); - if (rc) { - cFYI(1, "%s: MD5 hash failure: %d\n", __func__, rc); - return rc; - } - - snprintf(md5_str2, sizeof(md5_str2), - CIFS_MF_SYMLINK_MD5_FORMAT, - CIFS_MF_SYMLINK_MD5_ARGS(md5_hash)); - - if (strncmp(md5_str1, md5_str2, 17) != 0) - return -EINVAL; - - if (_link_str) { - *_link_str = kstrndup(link_str, link_len, GFP_KERNEL); - if (!*_link_str) - return -ENOMEM; - } - - *_link_len = link_len; - return 0; -} - -static int -CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) -{ - int rc; - unsigned int link_len; - unsigned int ofs; - u8 md5_hash[16]; - - if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE) - return -EINVAL; - - link_len = strlen(link_str); - - if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN) - return -ENAMETOOLONG; - - rc = symlink_hash(link_len, link_str, md5_hash); - if (rc) { - cFYI(1, "%s: MD5 hash failure: %d\n", __func__, rc); - return rc; - } - - snprintf(buf, buf_len, - CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT, - link_len, - CIFS_MF_SYMLINK_MD5_ARGS(md5_hash)); - - ofs = CIFS_MF_SYMLINK_LINK_OFFSET; - memcpy(buf + ofs, link_str, link_len); - - ofs += link_len; - if (ofs < CIFS_MF_SYMLINK_FILE_SIZE) { - buf[ofs] = '\n'; - ofs++; - } - - while (ofs < CIFS_MF_SYMLINK_FILE_SIZE) { - buf[ofs] = ' '; - ofs++; - } - - return 0; -} - -static int -CIFSCreateMFSymLink(const int xid, struct cifs_tcon *tcon, - const char *fromName, const char *toName, - struct cifs_sb_info *cifs_sb) -{ - int rc; - int oplock = 0; - int remap; - int create_options = CREATE_NOT_DIR; - __u16 netfid = 0; - u8 *buf; - unsigned int bytes_written = 0; - struct cifs_io_parms io_parms; - struct nls_table *nls_codepage; - - nls_codepage = cifs_sb->local_nls; - remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; - - buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - rc = CIFSFormatMFSymlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName); - if (rc != 0) { - kfree(buf); - return rc; - } - - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - - rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE, - create_options, &netfid, &oplock, NULL, - nls_codepage, remap); - if (rc != 0) { - kfree(buf); - return rc; - } - - io_parms.netfid = netfid; - io_parms.pid = current->tgid; - io_parms.tcon = tcon; - io_parms.offset = 0; - io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; - - rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, buf, NULL, 0); - CIFSSMBClose(xid, tcon, netfid); - kfree(buf); - if (rc != 0) - return rc; - - if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE) - return -EIO; - - return 0; -} - -static int -CIFSQueryMFSymLink(const int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, char **symlinkinfo, - const struct nls_table *nls_codepage, int remap) -{ - int rc; - int oplock = 0; - __u16 netfid = 0; - u8 *buf; - char *pbuf; - unsigned int bytes_read = 0; - int buf_type = CIFS_NO_BUFFER; - unsigned int link_len = 0; - struct cifs_io_parms io_parms; - FILE_ALL_INFO file_info; - - rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ, - CREATE_NOT_DIR, &netfid, &oplock, &file_info, - nls_codepage, remap); - if (rc != 0) - return rc; - - if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { - CIFSSMBClose(xid, tcon, netfid); - /* it's not a symlink */ - return -EINVAL; - } - - buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - pbuf = buf; - io_parms.netfid = netfid; - io_parms.pid = current->tgid; - io_parms.tcon = tcon; - io_parms.offset = 0; - io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; - - rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type); - CIFSSMBClose(xid, tcon, netfid); - if (rc != 0) { - kfree(buf); - return rc; - } - - rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, symlinkinfo); - kfree(buf); - if (rc != 0) - return rc; - - return 0; -} - -bool -CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr) -{ - if (!(fattr->cf_mode & S_IFREG)) - /* it's not a symlink */ - return false; - - if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE) - /* it's not a symlink */ - return false; - - return true; -} - -int -CIFSCheckMFSymlink(struct cifs_fattr *fattr, - const unsigned char *path, - struct cifs_sb_info *cifs_sb, int xid) -{ - int rc; - int oplock = 0; - __u16 netfid = 0; - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - struct cifs_io_parms io_parms; - u8 *buf; - char *pbuf; - unsigned int bytes_read = 0; - int buf_type = CIFS_NO_BUFFER; - unsigned int link_len = 0; - FILE_ALL_INFO file_info; - - if (!CIFSCouldBeMFSymlink(fattr)) - /* it's not a symlink */ - return 0; - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - pTcon = tlink_tcon(tlink); - - rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ, - CREATE_NOT_DIR, &netfid, &oplock, &file_info, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc != 0) - goto out; - - if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { - CIFSSMBClose(xid, pTcon, netfid); - /* it's not a symlink */ - goto out; - } - - buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); - if (!buf) { - rc = -ENOMEM; - goto out; - } - pbuf = buf; - io_parms.netfid = netfid; - io_parms.pid = current->tgid; - io_parms.tcon = pTcon; - io_parms.offset = 0; - io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; - - rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type); - CIFSSMBClose(xid, pTcon, netfid); - if (rc != 0) { - kfree(buf); - goto out; - } - - rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL); - kfree(buf); - if (rc == -EINVAL) { - /* it's not a symlink */ - rc = 0; - goto out; - } - - if (rc != 0) - goto out; - - /* it is a symlink */ - fattr->cf_eof = link_len; - fattr->cf_mode &= ~S_IFMT; - fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; - fattr->cf_dtype = DT_LNK; -out: - cifs_put_tlink(tlink); - return rc; -} - -int -cifs_hardlink(struct dentry *old_file, struct inode *inode, - struct dentry *direntry) -{ - int rc = -EACCES; - int xid; - char *fromName = NULL; - char *toName = NULL; - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - struct cifsInodeInfo *cifsInode; - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - pTcon = tlink_tcon(tlink); - - xid = GetXid(); - - fromName = build_path_from_dentry(old_file); - toName = build_path_from_dentry(direntry); - if ((fromName == NULL) || (toName == NULL)) { - rc = -ENOMEM; - goto cifs_hl_exit; - } - - if (pTcon->unix_ext) - rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - else { - rc = CIFSCreateHardLink(xid, pTcon, fromName, toName, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if ((rc == -EIO) || (rc == -EINVAL)) - rc = -EOPNOTSUPP; - } - - d_drop(direntry); /* force new lookup from server of target */ - - /* if source file is cached (oplocked) revalidate will not go to server - until the file is closed or oplock broken so update nlinks locally */ - if (old_file->d_inode) { - cifsInode = CIFS_I(old_file->d_inode); - if (rc == 0) { - inc_nlink(old_file->d_inode); -/* BB should we make this contingent on superblock flag NOATIME? */ -/* old_file->d_inode->i_ctime = CURRENT_TIME;*/ - /* parent dir timestamps will update from srv - within a second, would it really be worth it - to set the parent dir cifs inode time to zero - to force revalidate (faster) for it too? */ - } - /* if not oplocked will force revalidate to get info - on source file from srv */ - cifsInode->time = 0; - - /* Will update parent dir timestamps from srv within a second. - Would it really be worth it to set the parent dir (cifs - inode) time field to zero to force revalidate on parent - directory faster ie - CIFS_I(inode)->time = 0; */ - } - -cifs_hl_exit: - kfree(fromName); - kfree(toName); - FreeXid(xid); - cifs_put_tlink(tlink); - return rc; -} - -void * -cifs_follow_link(struct dentry *direntry, struct nameidata *nd) -{ - struct inode *inode = direntry->d_inode; - int rc = -ENOMEM; - int xid; - char *full_path = NULL; - char *target_path = NULL; - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct tcon_link *tlink = NULL; - struct cifs_tcon *tcon; - - xid = GetXid(); - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) { - rc = PTR_ERR(tlink); - tlink = NULL; - goto out; - } - tcon = tlink_tcon(tlink); - - /* - * For now, we just handle symlinks with unix extensions enabled. - * Eventually we should handle NTFS reparse points, and MacOS - * symlink support. For instance... - * - * rc = CIFSSMBQueryReparseLinkInfo(...) - * - * For now, just return -EACCES when the server doesn't support posix - * extensions. Note that we still allow querying symlinks when posix - * extensions are manually disabled. We could disable these as well - * but there doesn't seem to be any harm in allowing the client to - * read them. - */ - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) - && !(tcon->ses->capabilities & CAP_UNIX)) { - rc = -EACCES; - goto out; - } - - full_path = build_path_from_dentry(direntry); - if (!full_path) - goto out; - - cFYI(1, "Full path: %s inode = 0x%p", full_path, inode); - - rc = -EACCES; - /* - * First try Minshall+French Symlinks, if configured - * and fallback to UNIX Extensions Symlinks. - */ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) - rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - - if ((rc != 0) && (tcon->ses->capabilities & CAP_UNIX)) - rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path, - cifs_sb->local_nls); - - kfree(full_path); -out: - if (rc != 0) { - kfree(target_path); - target_path = ERR_PTR(rc); - } - - FreeXid(xid); - if (tlink) - cifs_put_tlink(tlink); - nd_set_link(nd, target_path); - return NULL; -} - -int -cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) -{ - int rc = -EOPNOTSUPP; - int xid; - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - char *full_path = NULL; - struct inode *newinode = NULL; - - xid = GetXid(); - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) { - rc = PTR_ERR(tlink); - goto symlink_exit; - } - pTcon = tlink_tcon(tlink); - - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - goto symlink_exit; - } - - cFYI(1, "Full path: %s", full_path); - cFYI(1, "symname is %s", symname); - - /* BB what if DFS and this volume is on different share? BB */ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) - rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname, - cifs_sb); - else if (pTcon->unix_ext) - rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, - cifs_sb->local_nls); - /* else - rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName, - cifs_sb_target->local_nls); */ - - if (rc == 0) { - if (pTcon->unix_ext) - rc = cifs_get_inode_info_unix(&newinode, full_path, - inode->i_sb, xid); - else - rc = cifs_get_inode_info(&newinode, full_path, NULL, - inode->i_sb, xid, NULL); - - if (rc != 0) { - cFYI(1, "Create symlink ok, getinodeinfo fail rc = %d", - rc); - } else { - d_instantiate(direntry, newinode); - } - } -symlink_exit: - kfree(full_path); - cifs_put_tlink(tlink); - FreeXid(xid); - return rc; -} - -void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie) -{ - char *p = nd_get_link(nd); - if (!IS_ERR(p)) - kfree(p); -} diff --git a/ANDROID_3.4.5/fs/cifs/misc.c b/ANDROID_3.4.5/fs/cifs/misc.c deleted file mode 100644 index c29d1aa2..00000000 --- a/ANDROID_3.4.5/fs/cifs/misc.c +++ /dev/null @@ -1,721 +0,0 @@ -/* - * fs/cifs/misc.c - * - * Copyright (C) International Business Machines Corp., 2002,2008 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/slab.h> -#include <linux/ctype.h> -#include <linux/mempool.h> -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifs_debug.h" -#include "smberr.h" -#include "nterr.h" -#include "cifs_unicode.h" - -extern mempool_t *cifs_sm_req_poolp; -extern mempool_t *cifs_req_poolp; - -/* The xid serves as a useful identifier for each incoming vfs request, - in a similar way to the mid which is useful to track each sent smb, - and CurrentXid can also provide a running counter (although it - will eventually wrap past zero) of the total vfs operations handled - since the cifs fs was mounted */ - -unsigned int -_GetXid(void) -{ - unsigned int xid; - - spin_lock(&GlobalMid_Lock); - GlobalTotalActiveXid++; - - /* keep high water mark for number of simultaneous ops in filesystem */ - if (GlobalTotalActiveXid > GlobalMaxActiveXid) - GlobalMaxActiveXid = GlobalTotalActiveXid; - if (GlobalTotalActiveXid > 65000) - cFYI(1, "warning: more than 65000 requests active"); - xid = GlobalCurrentXid++; - spin_unlock(&GlobalMid_Lock); - return xid; -} - -void -_FreeXid(unsigned int xid) -{ - spin_lock(&GlobalMid_Lock); - /* if (GlobalTotalActiveXid == 0) - BUG(); */ - GlobalTotalActiveXid--; - spin_unlock(&GlobalMid_Lock); -} - -struct cifs_ses * -sesInfoAlloc(void) -{ - struct cifs_ses *ret_buf; - - ret_buf = kzalloc(sizeof(struct cifs_ses), GFP_KERNEL); - if (ret_buf) { - atomic_inc(&sesInfoAllocCount); - ret_buf->status = CifsNew; - ++ret_buf->ses_count; - INIT_LIST_HEAD(&ret_buf->smb_ses_list); - INIT_LIST_HEAD(&ret_buf->tcon_list); - mutex_init(&ret_buf->session_mutex); - } - return ret_buf; -} - -void -sesInfoFree(struct cifs_ses *buf_to_free) -{ - if (buf_to_free == NULL) { - cFYI(1, "Null buffer passed to sesInfoFree"); - return; - } - - atomic_dec(&sesInfoAllocCount); - kfree(buf_to_free->serverOS); - kfree(buf_to_free->serverDomain); - kfree(buf_to_free->serverNOS); - if (buf_to_free->password) { - memset(buf_to_free->password, 0, strlen(buf_to_free->password)); - kfree(buf_to_free->password); - } - kfree(buf_to_free->user_name); - kfree(buf_to_free->domainName); - kfree(buf_to_free); -} - -struct cifs_tcon * -tconInfoAlloc(void) -{ - struct cifs_tcon *ret_buf; - ret_buf = kzalloc(sizeof(struct cifs_tcon), GFP_KERNEL); - if (ret_buf) { - atomic_inc(&tconInfoAllocCount); - ret_buf->tidStatus = CifsNew; - ++ret_buf->tc_count; - INIT_LIST_HEAD(&ret_buf->openFileList); - INIT_LIST_HEAD(&ret_buf->tcon_list); -#ifdef CONFIG_CIFS_STATS - spin_lock_init(&ret_buf->stat_lock); -#endif - } - return ret_buf; -} - -void -tconInfoFree(struct cifs_tcon *buf_to_free) -{ - if (buf_to_free == NULL) { - cFYI(1, "Null buffer passed to tconInfoFree"); - return; - } - atomic_dec(&tconInfoAllocCount); - kfree(buf_to_free->nativeFileSystem); - if (buf_to_free->password) { - memset(buf_to_free->password, 0, strlen(buf_to_free->password)); - kfree(buf_to_free->password); - } - kfree(buf_to_free); -} - -struct smb_hdr * -cifs_buf_get(void) -{ - struct smb_hdr *ret_buf = NULL; - -/* We could use negotiated size instead of max_msgsize - - but it may be more efficient to always alloc same size - albeit slightly larger than necessary and maxbuffersize - defaults to this and can not be bigger */ - ret_buf = mempool_alloc(cifs_req_poolp, GFP_NOFS); - - /* clear the first few header bytes */ - /* for most paths, more is cleared in header_assemble */ - if (ret_buf) { - memset(ret_buf, 0, sizeof(struct smb_hdr) + 3); - atomic_inc(&bufAllocCount); -#ifdef CONFIG_CIFS_STATS2 - atomic_inc(&totBufAllocCount); -#endif /* CONFIG_CIFS_STATS2 */ - } - - return ret_buf; -} - -void -cifs_buf_release(void *buf_to_free) -{ - if (buf_to_free == NULL) { - /* cFYI(1, "Null buffer passed to cifs_buf_release");*/ - return; - } - mempool_free(buf_to_free, cifs_req_poolp); - - atomic_dec(&bufAllocCount); - return; -} - -struct smb_hdr * -cifs_small_buf_get(void) -{ - struct smb_hdr *ret_buf = NULL; - -/* We could use negotiated size instead of max_msgsize - - but it may be more efficient to always alloc same size - albeit slightly larger than necessary and maxbuffersize - defaults to this and can not be bigger */ - ret_buf = mempool_alloc(cifs_sm_req_poolp, GFP_NOFS); - if (ret_buf) { - /* No need to clear memory here, cleared in header assemble */ - /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/ - atomic_inc(&smBufAllocCount); -#ifdef CONFIG_CIFS_STATS2 - atomic_inc(&totSmBufAllocCount); -#endif /* CONFIG_CIFS_STATS2 */ - - } - return ret_buf; -} - -void -cifs_small_buf_release(void *buf_to_free) -{ - - if (buf_to_free == NULL) { - cFYI(1, "Null buffer passed to cifs_small_buf_release"); - return; - } - mempool_free(buf_to_free, cifs_sm_req_poolp); - - atomic_dec(&smBufAllocCount); - return; -} - -/* - * Find a free multiplex id (SMB mid). Otherwise there could be - * mid collisions which might cause problems, demultiplexing the - * wrong response to this request. Multiplex ids could collide if - * one of a series requests takes much longer than the others, or - * if a very large number of long lived requests (byte range - * locks or FindNotify requests) are pending. No more than - * 64K-1 requests can be outstanding at one time. If no - * mids are available, return zero. A future optimization - * could make the combination of mids and uid the key we use - * to demultiplex on (rather than mid alone). - * In addition to the above check, the cifs demultiplex - * code already used the command code as a secondary - * check of the frame and if signing is negotiated the - * response would be discarded if the mid were the same - * but the signature was wrong. Since the mid is not put in the - * pending queue until later (when it is about to be dispatched) - * we do have to limit the number of outstanding requests - * to somewhat less than 64K-1 although it is hard to imagine - * so many threads being in the vfs at one time. - */ -__u64 GetNextMid(struct TCP_Server_Info *server) -{ - __u64 mid = 0; - __u16 last_mid, cur_mid; - bool collision; - - spin_lock(&GlobalMid_Lock); - - /* mid is 16 bit only for CIFS/SMB */ - cur_mid = (__u16)((server->CurrentMid) & 0xffff); - /* we do not want to loop forever */ - last_mid = cur_mid; - cur_mid++; - - /* - * This nested loop looks more expensive than it is. - * In practice the list of pending requests is short, - * fewer than 50, and the mids are likely to be unique - * on the first pass through the loop unless some request - * takes longer than the 64 thousand requests before it - * (and it would also have to have been a request that - * did not time out). - */ - while (cur_mid != last_mid) { - struct mid_q_entry *mid_entry; - unsigned int num_mids; - - collision = false; - if (cur_mid == 0) - cur_mid++; - - num_mids = 0; - list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { - ++num_mids; - if (mid_entry->mid == cur_mid && - mid_entry->mid_state == MID_REQUEST_SUBMITTED) { - /* This mid is in use, try a different one */ - collision = true; - break; - } - } - - /* - * if we have more than 32k mids in the list, then something - * is very wrong. Possibly a local user is trying to DoS the - * box by issuing long-running calls and SIGKILL'ing them. If - * we get to 2^16 mids then we're in big trouble as this - * function could loop forever. - * - * Go ahead and assign out the mid in this situation, but force - * an eventual reconnect to clean out the pending_mid_q. - */ - if (num_mids > 32768) - server->tcpStatus = CifsNeedReconnect; - - if (!collision) { - mid = (__u64)cur_mid; - server->CurrentMid = mid; - break; - } - cur_mid++; - } - spin_unlock(&GlobalMid_Lock); - return mid; -} - -/* NB: MID can not be set if treeCon not passed in, in that - case it is responsbility of caller to set the mid */ -void -header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , - const struct cifs_tcon *treeCon, int word_count - /* length of fixed section (word count) in two byte units */) -{ - struct list_head *temp_item; - struct cifs_ses *ses; - char *temp = (char *) buffer; - - memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */ - - buffer->smb_buf_length = cpu_to_be32( - (2 * word_count) + sizeof(struct smb_hdr) - - 4 /* RFC 1001 length field does not count */ + - 2 /* for bcc field itself */) ; - - buffer->Protocol[0] = 0xFF; - buffer->Protocol[1] = 'S'; - buffer->Protocol[2] = 'M'; - buffer->Protocol[3] = 'B'; - buffer->Command = smb_command; - buffer->Flags = 0x00; /* case sensitive */ - buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES; - buffer->Pid = cpu_to_le16((__u16)current->tgid); - buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16)); - if (treeCon) { - buffer->Tid = treeCon->tid; - if (treeCon->ses) { - if (treeCon->ses->capabilities & CAP_UNICODE) - buffer->Flags2 |= SMBFLG2_UNICODE; - if (treeCon->ses->capabilities & CAP_STATUS32) - buffer->Flags2 |= SMBFLG2_ERR_STATUS; - - /* Uid is not converted */ - buffer->Uid = treeCon->ses->Suid; - buffer->Mid = GetNextMid(treeCon->ses->server); - if (multiuser_mount != 0) { - /* For the multiuser case, there are few obvious technically */ - /* possible mechanisms to match the local linux user (uid) */ - /* to a valid remote smb user (smb_uid): */ - /* 1) Query Winbind (or other local pam/nss daemon */ - /* for userid/password/logon_domain or credential */ - /* 2) Query Winbind for uid to sid to username mapping */ - /* and see if we have a matching password for existing*/ - /* session for that user perhas getting password by */ - /* adding a new pam_cifs module that stores passwords */ - /* so that the cifs vfs can get at that for all logged*/ - /* on users */ - /* 3) (Which is the mechanism we have chosen) */ - /* Search through sessions to the same server for a */ - /* a match on the uid that was passed in on mount */ - /* with the current processes uid (or euid?) and use */ - /* that smb uid. If no existing smb session for */ - /* that uid found, use the default smb session ie */ - /* the smb session for the volume mounted which is */ - /* the same as would be used if the multiuser mount */ - /* flag were disabled. */ - - /* BB Add support for establishing new tCon and SMB Session */ - /* with userid/password pairs found on the smb session */ - /* for other target tcp/ip addresses BB */ - if (current_fsuid() != treeCon->ses->linux_uid) { - cFYI(1, "Multiuser mode and UID " - "did not match tcon uid"); - spin_lock(&cifs_tcp_ses_lock); - list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) { - ses = list_entry(temp_item, struct cifs_ses, smb_ses_list); - if (ses->linux_uid == current_fsuid()) { - if (ses->server == treeCon->ses->server) { - cFYI(1, "found matching uid substitute right smb_uid"); - buffer->Uid = ses->Suid; - break; - } else { - /* BB eventually call cifs_setup_session here */ - cFYI(1, "local UID found but no smb sess with this server exists"); - } - } - } - spin_unlock(&cifs_tcp_ses_lock); - } - } - } - if (treeCon->Flags & SMB_SHARE_IS_IN_DFS) - buffer->Flags2 |= SMBFLG2_DFS; - if (treeCon->nocase) - buffer->Flags |= SMBFLG_CASELESS; - if ((treeCon->ses) && (treeCon->ses->server)) - if (treeCon->ses->server->sec_mode & - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) - buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - } - -/* endian conversion of flags is now done just before sending */ - buffer->WordCount = (char) word_count; - return; -} - -static int -check_smb_hdr(struct smb_hdr *smb, __u16 mid) -{ - /* does it have the right SMB "signature" ? */ - if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) { - cERROR(1, "Bad protocol string signature header 0x%x", - *(unsigned int *)smb->Protocol); - return 1; - } - - /* Make sure that message ids match */ - if (mid != smb->Mid) { - cERROR(1, "Mids do not match. received=%u expected=%u", - smb->Mid, mid); - return 1; - } - - /* if it's a response then accept */ - if (smb->Flags & SMBFLG_RESPONSE) - return 0; - - /* only one valid case where server sends us request */ - if (smb->Command == SMB_COM_LOCKING_ANDX) - return 0; - - cERROR(1, "Server sent request, not response. mid=%u", smb->Mid); - return 1; -} - -int -checkSMB(char *buf, unsigned int total_read) -{ - struct smb_hdr *smb = (struct smb_hdr *)buf; - __u16 mid = smb->Mid; - __u32 rfclen = be32_to_cpu(smb->smb_buf_length); - __u32 clc_len; /* calculated length */ - cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", - total_read, rfclen); - - /* is this frame too small to even get to a BCC? */ - if (total_read < 2 + sizeof(struct smb_hdr)) { - if ((total_read >= sizeof(struct smb_hdr) - 1) - && (smb->Status.CifsError != 0)) { - /* it's an error return */ - smb->WordCount = 0; - /* some error cases do not return wct and bcc */ - return 0; - } else if ((total_read == sizeof(struct smb_hdr) + 1) && - (smb->WordCount == 0)) { - char *tmp = (char *)smb; - /* Need to work around a bug in two servers here */ - /* First, check if the part of bcc they sent was zero */ - if (tmp[sizeof(struct smb_hdr)] == 0) { - /* some servers return only half of bcc - * on simple responses (wct, bcc both zero) - * in particular have seen this on - * ulogoffX and FindClose. This leaves - * one byte of bcc potentially unitialized - */ - /* zero rest of bcc */ - tmp[sizeof(struct smb_hdr)+1] = 0; - return 0; - } - cERROR(1, "rcvd invalid byte count (bcc)"); - } else { - cERROR(1, "Length less than smb header size"); - } - return -EIO; - } - - /* otherwise, there is enough to get to the BCC */ - if (check_smb_hdr(smb, mid)) - return -EIO; - clc_len = smbCalcSize(smb); - - if (4 + rfclen != total_read) { - cERROR(1, "Length read does not match RFC1001 length %d", - rfclen); - return -EIO; - } - - if (4 + rfclen != clc_len) { - /* check if bcc wrapped around for large read responses */ - if ((rfclen > 64 * 1024) && (rfclen > clc_len)) { - /* check if lengths match mod 64K */ - if (((4 + rfclen) & 0xFFFF) == (clc_len & 0xFFFF)) - return 0; /* bcc wrapped */ - } - cFYI(1, "Calculated size %u vs length %u mismatch for mid=%u", - clc_len, 4 + rfclen, smb->Mid); - - if (4 + rfclen < clc_len) { - cERROR(1, "RFC1001 size %u smaller than SMB for mid=%u", - rfclen, smb->Mid); - return -EIO; - } else if (rfclen > clc_len + 512) { - /* - * Some servers (Windows XP in particular) send more - * data than the lengths in the SMB packet would - * indicate on certain calls (byte range locks and - * trans2 find first calls in particular). While the - * client can handle such a frame by ignoring the - * trailing data, we choose limit the amount of extra - * data to 512 bytes. - */ - cERROR(1, "RFC1001 size %u more than 512 bytes larger " - "than SMB for mid=%u", rfclen, smb->Mid); - return -EIO; - } - } - return 0; -} - -bool -is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) -{ - struct smb_hdr *buf = (struct smb_hdr *)buffer; - struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf; - struct list_head *tmp, *tmp1, *tmp2; - struct cifs_ses *ses; - struct cifs_tcon *tcon; - struct cifsInodeInfo *pCifsInode; - struct cifsFileInfo *netfile; - - cFYI(1, "Checking for oplock break or dnotify response"); - if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) && - (pSMB->hdr.Flags & SMBFLG_RESPONSE)) { - struct smb_com_transaction_change_notify_rsp *pSMBr = - (struct smb_com_transaction_change_notify_rsp *)buf; - struct file_notify_information *pnotify; - __u32 data_offset = 0; - if (get_bcc(buf) > sizeof(struct file_notify_information)) { - data_offset = le32_to_cpu(pSMBr->DataOffset); - - pnotify = (struct file_notify_information *) - ((char *)&pSMBr->hdr.Protocol + data_offset); - cFYI(1, "dnotify on %s Action: 0x%x", - pnotify->FileName, pnotify->Action); - /* cifs_dump_mem("Rcvd notify Data: ",buf, - sizeof(struct smb_hdr)+60); */ - return true; - } - if (pSMBr->hdr.Status.CifsError) { - cFYI(1, "notify err 0x%d", - pSMBr->hdr.Status.CifsError); - return true; - } - return false; - } - if (pSMB->hdr.Command != SMB_COM_LOCKING_ANDX) - return false; - if (pSMB->hdr.Flags & SMBFLG_RESPONSE) { - /* no sense logging error on invalid handle on oplock - break - harmless race between close request and oplock - break response is expected from time to time writing out - large dirty files cached on the client */ - if ((NT_STATUS_INVALID_HANDLE) == - le32_to_cpu(pSMB->hdr.Status.CifsError)) { - cFYI(1, "invalid handle on oplock break"); - return true; - } else if (ERRbadfid == - le16_to_cpu(pSMB->hdr.Status.DosError.Error)) { - return true; - } else { - return false; /* on valid oplock brk we get "request" */ - } - } - if (pSMB->hdr.WordCount != 8) - return false; - - cFYI(1, "oplock type 0x%d level 0x%d", - pSMB->LockType, pSMB->OplockLevel); - if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)) - return false; - - /* look up tcon based on tid & uid */ - spin_lock(&cifs_tcp_ses_lock); - list_for_each(tmp, &srv->smb_ses_list) { - ses = list_entry(tmp, struct cifs_ses, smb_ses_list); - list_for_each(tmp1, &ses->tcon_list) { - tcon = list_entry(tmp1, struct cifs_tcon, tcon_list); - if (tcon->tid != buf->Tid) - continue; - - cifs_stats_inc(&tcon->num_oplock_brks); - spin_lock(&cifs_file_list_lock); - list_for_each(tmp2, &tcon->openFileList) { - netfile = list_entry(tmp2, struct cifsFileInfo, - tlist); - if (pSMB->Fid != netfile->netfid) - continue; - - cFYI(1, "file id match, oplock break"); - pCifsInode = CIFS_I(netfile->dentry->d_inode); - - cifs_set_oplock_level(pCifsInode, - pSMB->OplockLevel ? OPLOCK_READ : 0); - queue_work(cifsiod_wq, - &netfile->oplock_break); - netfile->oplock_break_cancelled = false; - - spin_unlock(&cifs_file_list_lock); - spin_unlock(&cifs_tcp_ses_lock); - return true; - } - spin_unlock(&cifs_file_list_lock); - spin_unlock(&cifs_tcp_ses_lock); - cFYI(1, "No matching file for oplock break"); - return true; - } - } - spin_unlock(&cifs_tcp_ses_lock); - cFYI(1, "Can not process oplock break for non-existent connection"); - return true; -} - -void -dump_smb(void *buf, int smb_buf_length) -{ - int i, j; - char debug_line[17]; - unsigned char *buffer = buf; - - if (traceSMB == 0) - return; - - for (i = 0, j = 0; i < smb_buf_length; i++, j++) { - if (i % 8 == 0) { - /* have reached the beginning of line */ - printk(KERN_DEBUG "| "); - j = 0; - } - printk("%0#4x ", buffer[i]); - debug_line[2 * j] = ' '; - if (isprint(buffer[i])) - debug_line[1 + (2 * j)] = buffer[i]; - else - debug_line[1 + (2 * j)] = '_'; - - if (i % 8 == 7) { - /* reached end of line, time to print ascii */ - debug_line[16] = 0; - printk(" | %s\n", debug_line); - } - } - for (; j < 8; j++) { - printk(" "); - debug_line[2 * j] = ' '; - debug_line[1 + (2 * j)] = ' '; - } - printk(" | %s\n", debug_line); - return; -} - -void -cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) -{ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { - cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; - cERROR(1, "Autodisabling the use of server inode numbers on " - "%s. This server doesn't seem to support them " - "properly. Hardlinks will not be recognized on this " - "mount. Consider mounting with the \"noserverino\" " - "option to silence this message.", - cifs_sb_master_tcon(cifs_sb)->treeName); - } -} - -void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) -{ - oplock &= 0xF; - - if (oplock == OPLOCK_EXCLUSIVE) { - cinode->clientCanCacheAll = true; - cinode->clientCanCacheRead = true; - cFYI(1, "Exclusive Oplock granted on inode %p", - &cinode->vfs_inode); - } else if (oplock == OPLOCK_READ) { - cinode->clientCanCacheAll = false; - cinode->clientCanCacheRead = true; - cFYI(1, "Level II Oplock granted on inode %p", - &cinode->vfs_inode); - } else { - cinode->clientCanCacheAll = false; - cinode->clientCanCacheRead = false; - } -} - -bool -backup_cred(struct cifs_sb_info *cifs_sb) -{ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) { - if (cifs_sb->mnt_backupuid == current_fsuid()) - return true; - } - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) { - if (in_group_p(cifs_sb->mnt_backupgid)) - return true; - } - - return false; -} - -void -cifs_add_credits(struct TCP_Server_Info *server, const unsigned int add) -{ - spin_lock(&server->req_lock); - server->credits += add; - server->in_flight--; - spin_unlock(&server->req_lock); - wake_up(&server->request_q); -} - -void -cifs_set_credits(struct TCP_Server_Info *server, const int val) -{ - spin_lock(&server->req_lock); - server->credits = val; - server->oplocks = val > 1 ? enable_oplocks : false; - spin_unlock(&server->req_lock); -} diff --git a/ANDROID_3.4.5/fs/cifs/netmisc.c b/ANDROID_3.4.5/fs/cifs/netmisc.c deleted file mode 100644 index 581c225f..00000000 --- a/ANDROID_3.4.5/fs/cifs/netmisc.c +++ /dev/null @@ -1,1008 +0,0 @@ -/* - * fs/cifs/netmisc.c - * - * Copyright (c) International Business Machines Corp., 2002,2008 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * Error mapping routines from Samba libsmb/errormap.c - * Copyright (C) Andrew Tridgell 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/net.h> -#include <linux/string.h> -#include <linux/in.h> -#include <linux/ctype.h> -#include <linux/fs.h> -#include <asm/div64.h> -#include <asm/byteorder.h> -#include <linux/inet.h> -#include "cifsfs.h" -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsproto.h" -#include "smberr.h" -#include "cifs_debug.h" -#include "nterr.h" - -struct smb_to_posix_error { - __u16 smb_err; - int posix_code; -}; - -static const struct smb_to_posix_error mapping_table_ERRDOS[] = { - {ERRbadfunc, -EINVAL}, - {ERRbadfile, -ENOENT}, - {ERRbadpath, -ENOTDIR}, - {ERRnofids, -EMFILE}, - {ERRnoaccess, -EACCES}, - {ERRbadfid, -EBADF}, - {ERRbadmcb, -EIO}, - {ERRnomem, -ENOMEM}, - {ERRbadmem, -EFAULT}, - {ERRbadenv, -EFAULT}, - {ERRbadformat, -EINVAL}, - {ERRbadaccess, -EACCES}, - {ERRbaddata, -EIO}, - {ERRbaddrive, -ENXIO}, - {ERRremcd, -EACCES}, - {ERRdiffdevice, -EXDEV}, - {ERRnofiles, -ENOENT}, - {ERRwriteprot, -EROFS}, - {ERRbadshare, -ETXTBSY}, - {ERRlock, -EACCES}, - {ERRunsup, -EINVAL}, - {ERRnosuchshare, -ENXIO}, - {ERRfilexists, -EEXIST}, - {ERRinvparm, -EINVAL}, - {ERRdiskfull, -ENOSPC}, - {ERRinvname, -ENOENT}, - {ERRinvlevel, -EOPNOTSUPP}, - {ERRdirnotempty, -ENOTEMPTY}, - {ERRnotlocked, -ENOLCK}, - {ERRcancelviolation, -ENOLCK}, - {ERRalreadyexists, -EEXIST}, - {ERRmoredata, -EOVERFLOW}, - {ERReasnotsupported, -EOPNOTSUPP}, - {ErrQuota, -EDQUOT}, - {ErrNotALink, -ENOLINK}, - {ERRnetlogonNotStarted, -ENOPROTOOPT}, - {ERRsymlink, -EOPNOTSUPP}, - {ErrTooManyLinks, -EMLINK}, - {0, 0} -}; - -static const struct smb_to_posix_error mapping_table_ERRSRV[] = { - {ERRerror, -EIO}, - {ERRbadpw, -EACCES}, /* was EPERM */ - {ERRbadtype, -EREMOTE}, - {ERRaccess, -EACCES}, - {ERRinvtid, -ENXIO}, - {ERRinvnetname, -ENXIO}, - {ERRinvdevice, -ENXIO}, - {ERRqfull, -ENOSPC}, - {ERRqtoobig, -ENOSPC}, - {ERRqeof, -EIO}, - {ERRinvpfid, -EBADF}, - {ERRsmbcmd, -EBADRQC}, - {ERRsrverror, -EIO}, - {ERRbadBID, -EIO}, - {ERRfilespecs, -EINVAL}, - {ERRbadLink, -EIO}, - {ERRbadpermits, -EINVAL}, - {ERRbadPID, -ESRCH}, - {ERRsetattrmode, -EINVAL}, - {ERRpaused, -EHOSTDOWN}, - {ERRmsgoff, -EHOSTDOWN}, - {ERRnoroom, -ENOSPC}, - {ERRrmuns, -EUSERS}, - {ERRtimeout, -ETIME}, - {ERRnoresource, -ENOBUFS}, - {ERRtoomanyuids, -EUSERS}, - {ERRbaduid, -EACCES}, - {ERRusempx, -EIO}, - {ERRusestd, -EIO}, - {ERR_NOTIFY_ENUM_DIR, -ENOBUFS}, - {ERRnoSuchUser, -EACCES}, -/* {ERRaccountexpired, -EACCES}, - {ERRbadclient, -EACCES}, - {ERRbadLogonTime, -EACCES}, - {ERRpasswordExpired, -EACCES},*/ - {ERRaccountexpired, -EKEYEXPIRED}, - {ERRbadclient, -EACCES}, - {ERRbadLogonTime, -EACCES}, - {ERRpasswordExpired, -EKEYEXPIRED}, - - {ERRnosupport, -EINVAL}, - {0, 0} -}; - -static const struct smb_to_posix_error mapping_table_ERRHRD[] = { - {0, 0} -}; - -/* - * Convert a string containing text IPv4 or IPv6 address to binary form. - * - * Returns 0 on failure. - */ -static int -cifs_inet_pton(const int address_family, const char *cp, int len, void *dst) -{ - int ret = 0; - - /* calculate length by finding first slash or NULL */ - if (address_family == AF_INET) - ret = in4_pton(cp, len, dst, '\\', NULL); - else if (address_family == AF_INET6) - ret = in6_pton(cp, len, dst , '\\', NULL); - - cFYI(DBG2, "address conversion returned %d for %*.*s", - ret, len, len, cp); - if (ret > 0) - ret = 1; - return ret; -} - -/* - * Try to convert a string to an IPv4 address and then attempt to convert - * it to an IPv6 address if that fails. Set the family field if either - * succeeds. If it's an IPv6 address and it has a '%' sign in it, try to - * treat the part following it as a numeric sin6_scope_id. - * - * Returns 0 on failure. - */ -int -cifs_convert_address(struct sockaddr *dst, const char *src, int len) -{ - int rc, alen, slen; - const char *pct; - char scope_id[13]; - struct sockaddr_in *s4 = (struct sockaddr_in *) dst; - struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst; - - /* IPv4 address */ - if (cifs_inet_pton(AF_INET, src, len, &s4->sin_addr.s_addr)) { - s4->sin_family = AF_INET; - return 1; - } - - /* attempt to exclude the scope ID from the address part */ - pct = memchr(src, '%', len); - alen = pct ? pct - src : len; - - rc = cifs_inet_pton(AF_INET6, src, alen, &s6->sin6_addr.s6_addr); - if (!rc) - return rc; - - s6->sin6_family = AF_INET6; - if (pct) { - /* grab the scope ID */ - slen = len - (alen + 1); - if (slen <= 0 || slen > 12) - return 0; - memcpy(scope_id, pct + 1, slen); - scope_id[slen] = '\0'; - - rc = kstrtouint(scope_id, 0, &s6->sin6_scope_id); - rc = (rc == 0) ? 1 : 0; - } - - return rc; -} - -int -cifs_set_port(struct sockaddr *addr, const unsigned short int port) -{ - switch (addr->sa_family) { - case AF_INET: - ((struct sockaddr_in *)addr)->sin_port = htons(port); - break; - case AF_INET6: - ((struct sockaddr_in6 *)addr)->sin6_port = htons(port); - break; - default: - return 0; - } - return 1; -} - -int -cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, - const unsigned short int port) -{ - if (!cifs_convert_address(dst, src, len)) - return 0; - return cifs_set_port(dst, port); -} - -/***************************************************************************** -convert a NT status code to a dos class/code - *****************************************************************************/ -/* NT status -> dos error map */ -static const struct { - __u8 dos_class; - __u16 dos_code; - __u32 ntstatus; -} ntstatus_to_dos_map[] = { - { - ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, { - ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, { - ERRDOS, ERRinvlevel, NT_STATUS_INVALID_INFO_CLASS}, { - ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, { - ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, { - ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, { - ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA}, { - ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE}, { - ERRHRD, ERRgeneral, NT_STATUS_BAD_INITIAL_STACK}, { - ERRDOS, 193, NT_STATUS_BAD_INITIAL_PC}, { - ERRDOS, 87, NT_STATUS_INVALID_CID}, { - ERRHRD, ERRgeneral, NT_STATUS_TIMER_NOT_CANCELED}, { - ERRDOS, 87, NT_STATUS_INVALID_PARAMETER}, { - ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_DEVICE}, { - ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE}, { - ERRDOS, ERRbadfunc, NT_STATUS_INVALID_DEVICE_REQUEST}, { - ERRDOS, 38, NT_STATUS_END_OF_FILE}, { - ERRDOS, 34, NT_STATUS_WRONG_VOLUME}, { - ERRDOS, 21, NT_STATUS_NO_MEDIA_IN_DEVICE}, { - ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, { - ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR}, -/* { This NT error code was 'sqashed' - from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK - during the session setup } */ - { - ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, { - ERRDOS, 487, NT_STATUS_CONFLICTING_ADDRESSES}, { - ERRDOS, 487, NT_STATUS_NOT_MAPPED_VIEW}, { - ERRDOS, 87, NT_STATUS_UNABLE_TO_FREE_VM}, { - ERRDOS, 87, NT_STATUS_UNABLE_TO_DELETE_SECTION}, { - ERRDOS, 2142, NT_STATUS_INVALID_SYSTEM_SERVICE}, { - ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_INSTRUCTION}, { - ERRDOS, ERRnoaccess, NT_STATUS_INVALID_LOCK_SEQUENCE}, { - ERRDOS, ERRnoaccess, NT_STATUS_INVALID_VIEW_SIZE}, { - ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, { - ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED}, -/* { This NT error code was 'sqashed' - from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE - during the session setup } */ - { - ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, { - ERRDOS, 111, NT_STATUS_BUFFER_TOO_SMALL}, { - ERRDOS, ERRbadfid, NT_STATUS_OBJECT_TYPE_MISMATCH}, { - ERRHRD, ERRgeneral, NT_STATUS_NONCONTINUABLE_EXCEPTION}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_DISPOSITION}, { - ERRHRD, ERRgeneral, NT_STATUS_UNWIND}, { - ERRHRD, ERRgeneral, NT_STATUS_BAD_STACK}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_UNWIND_TARGET}, { - ERRDOS, 158, NT_STATUS_NOT_LOCKED}, { - ERRHRD, ERRgeneral, NT_STATUS_PARITY_ERROR}, { - ERRDOS, 487, NT_STATUS_UNABLE_TO_DECOMMIT_VM}, { - ERRDOS, 487, NT_STATUS_NOT_COMMITTED}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_PORT_ATTRIBUTES}, { - ERRHRD, ERRgeneral, NT_STATUS_PORT_MESSAGE_TOO_LONG}, { - ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_MIX}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_QUOTA_LOWER}, { - ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, { - /* mapping changed since shell does lookup on * expects FileNotFound */ - ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, { - ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, { - ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, { - ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, { - ERRDOS, ERRbadfid, NT_STATUS_PORT_DISCONNECTED}, { - ERRHRD, ERRgeneral, NT_STATUS_DEVICE_ALREADY_ATTACHED}, { - ERRDOS, 161, NT_STATUS_OBJECT_PATH_INVALID}, { - ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND}, { - ERRDOS, 161, NT_STATUS_OBJECT_PATH_SYNTAX_BAD}, { - ERRHRD, ERRgeneral, NT_STATUS_DATA_OVERRUN}, { - ERRHRD, ERRgeneral, NT_STATUS_DATA_LATE_ERROR}, { - ERRDOS, 23, NT_STATUS_DATA_ERROR}, { - ERRDOS, 23, NT_STATUS_CRC_ERROR}, { - ERRDOS, ERRnomem, NT_STATUS_SECTION_TOO_BIG}, { - ERRDOS, ERRnoaccess, NT_STATUS_PORT_CONNECTION_REFUSED}, { - ERRDOS, ERRbadfid, NT_STATUS_INVALID_PORT_HANDLE}, { - ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION}, { - ERRHRD, ERRgeneral, NT_STATUS_QUOTA_EXCEEDED}, { - ERRDOS, 87, NT_STATUS_INVALID_PAGE_PROTECTION}, { - ERRDOS, 288, NT_STATUS_MUTANT_NOT_OWNED}, { - ERRDOS, 298, NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED}, { - ERRDOS, 87, NT_STATUS_PORT_ALREADY_SET}, { - ERRDOS, 87, NT_STATUS_SECTION_NOT_IMAGE}, { - ERRDOS, 156, NT_STATUS_SUSPEND_COUNT_EXCEEDED}, { - ERRDOS, ERRnoaccess, NT_STATUS_THREAD_IS_TERMINATING}, { - ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT}, { - ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP}, { - ERRDOS, 87, NT_STATUS_SECTION_PROTECTION}, { - ERRDOS, ERReasnotsupported, NT_STATUS_EAS_NOT_SUPPORTED}, { - ERRDOS, 255, NT_STATUS_EA_TOO_LARGE}, { - ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE}, { - ERRHRD, ERRgeneral, NT_STATUS_EA_CORRUPT_ERROR}, { - ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, { - ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED}, { - ERRDOS, ERRbadfile, NT_STATUS_DELETE_PENDING}, { - ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, { - ERRHRD, ERRgeneral, NT_STATUS_UNKNOWN_REVISION}, { - ERRHRD, ERRgeneral, NT_STATUS_REVISION_MISMATCH}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_OWNER}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_PRIMARY_GROUP}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_IMPERSONATION_TOKEN}, { - ERRHRD, ERRgeneral, NT_STATUS_CANT_DISABLE_MANDATORY}, { - ERRDOS, 2215, NT_STATUS_NO_LOGON_SERVERS}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_LOGON_SESSION}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PRIVILEGE}, { - ERRDOS, ERRnoaccess, NT_STATUS_PRIVILEGE_NOT_HELD}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, { - ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS}, -/* { This NT error code was 'sqashed' - from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE - during the session setup } */ - { - ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { /* could map to 2238 */ - ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, { - ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, { - ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, { - ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN}, -/* { This NT error code was 'sqashed' - from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE - during the session setup } */ - { - ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, { - ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_PASSWORD}, { - ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, { - ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, { - ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, { - ERRSRV, ERRbadLogonTime, NT_STATUS_INVALID_LOGON_HOURS}, { - ERRSRV, ERRbadclient, NT_STATUS_INVALID_WORKSTATION}, { - ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, { - ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_DISABLED}, { - ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, { - ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, { - ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_SUB_AUTHORITY}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACL}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_SID}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_SECURITY_DESCR}, { - ERRDOS, 127, NT_STATUS_PROCEDURE_NOT_FOUND}, { - ERRDOS, 193, NT_STATUS_INVALID_IMAGE_FORMAT}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_TOKEN}, { - ERRHRD, ERRgeneral, NT_STATUS_BAD_INHERITANCE_ACL}, { - ERRDOS, 158, NT_STATUS_RANGE_NOT_LOCKED}, { - ERRDOS, 112, NT_STATUS_DISK_FULL}, { - ERRHRD, ERRgeneral, NT_STATUS_SERVER_DISABLED}, { - ERRHRD, ERRgeneral, NT_STATUS_SERVER_NOT_DISABLED}, { - ERRDOS, 68, NT_STATUS_TOO_MANY_GUIDS_REQUESTED}, { - ERRDOS, 259, NT_STATUS_GUIDS_EXHAUSTED}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_ID_AUTHORITY}, { - ERRDOS, 259, NT_STATUS_AGENTS_EXHAUSTED}, { - ERRDOS, 154, NT_STATUS_INVALID_VOLUME_LABEL}, { - ERRDOS, 14, NT_STATUS_SECTION_NOT_EXTENDED}, { - ERRDOS, 487, NT_STATUS_NOT_MAPPED_DATA}, { - ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_DATA_NOT_FOUND}, { - ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_TYPE_NOT_FOUND}, { - ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_NAME_NOT_FOUND}, { - ERRHRD, ERRgeneral, NT_STATUS_ARRAY_BOUNDS_EXCEEDED}, { - ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DENORMAL_OPERAND}, { - ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DIVIDE_BY_ZERO}, { - ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INEXACT_RESULT}, { - ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INVALID_OPERATION}, { - ERRHRD, ERRgeneral, NT_STATUS_FLOAT_OVERFLOW}, { - ERRHRD, ERRgeneral, NT_STATUS_FLOAT_STACK_CHECK}, { - ERRHRD, ERRgeneral, NT_STATUS_FLOAT_UNDERFLOW}, { - ERRHRD, ERRgeneral, NT_STATUS_INTEGER_DIVIDE_BY_ZERO}, { - ERRDOS, 534, NT_STATUS_INTEGER_OVERFLOW}, { - ERRHRD, ERRgeneral, NT_STATUS_PRIVILEGED_INSTRUCTION}, { - ERRDOS, ERRnomem, NT_STATUS_TOO_MANY_PAGING_FILES}, { - ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, { - ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED}, -/* { This NT error code was 'sqashed' - from NT_STATUS_INSUFFICIENT_RESOURCES to - NT_STATUS_INSUFF_SERVER_RESOURCES during the session setup } */ - { - ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, { - ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, { - ERRDOS, 23, NT_STATUS_DEVICE_DATA_ERROR}, { - ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_CONNECTED}, { - ERRDOS, 21, NT_STATUS_DEVICE_POWER_FAILURE}, { - ERRDOS, 487, NT_STATUS_FREE_VM_NOT_AT_BASE}, { - ERRDOS, 487, NT_STATUS_MEMORY_NOT_ALLOCATED}, { - ERRHRD, ERRgeneral, NT_STATUS_WORKING_SET_QUOTA}, { - ERRDOS, 19, NT_STATUS_MEDIA_WRITE_PROTECTED}, { - ERRDOS, 21, NT_STATUS_DEVICE_NOT_READY}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_GROUP_ATTRIBUTES}, { - ERRHRD, ERRgeneral, NT_STATUS_BAD_IMPERSONATION_LEVEL}, { - ERRHRD, ERRgeneral, NT_STATUS_CANT_OPEN_ANONYMOUS}, { - ERRHRD, ERRgeneral, NT_STATUS_BAD_VALIDATION_CLASS}, { - ERRHRD, ERRgeneral, NT_STATUS_BAD_TOKEN_TYPE}, { - ERRDOS, 87, NT_STATUS_BAD_MASTER_BOOT_RECORD}, { - ERRHRD, ERRgeneral, NT_STATUS_INSTRUCTION_MISALIGNMENT}, { - ERRDOS, ERRpipebusy, NT_STATUS_INSTANCE_NOT_AVAILABLE}, { - ERRDOS, ERRpipebusy, NT_STATUS_PIPE_NOT_AVAILABLE}, { - ERRDOS, ERRbadpipe, NT_STATUS_INVALID_PIPE_STATE}, { - ERRDOS, ERRpipebusy, NT_STATUS_PIPE_BUSY}, { - ERRDOS, ERRbadfunc, NT_STATUS_ILLEGAL_FUNCTION}, { - ERRDOS, ERRnotconnected, NT_STATUS_PIPE_DISCONNECTED}, { - ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_CLOSING}, { - ERRHRD, ERRgeneral, NT_STATUS_PIPE_CONNECTED}, { - ERRHRD, ERRgeneral, NT_STATUS_PIPE_LISTENING}, { - ERRDOS, ERRbadpipe, NT_STATUS_INVALID_READ_MODE}, { - ERRDOS, 121, NT_STATUS_IO_TIMEOUT}, { - ERRDOS, 38, NT_STATUS_FILE_FORCED_CLOSED}, { - ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STARTED}, { - ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STOPPED}, { - ERRHRD, ERRgeneral, NT_STATUS_COULD_NOT_INTERPRET}, { - ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, { - ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED}, { - ERRDOS, 51, NT_STATUS_REMOTE_NOT_LISTENING}, { - ERRDOS, 52, NT_STATUS_DUPLICATE_NAME}, { - ERRDOS, 53, NT_STATUS_BAD_NETWORK_PATH}, { - ERRDOS, 54, NT_STATUS_NETWORK_BUSY}, { - ERRDOS, 55, NT_STATUS_DEVICE_DOES_NOT_EXIST}, { - ERRDOS, 56, NT_STATUS_TOO_MANY_COMMANDS}, { - ERRDOS, 57, NT_STATUS_ADAPTER_HARDWARE_ERROR}, { - ERRDOS, 58, NT_STATUS_INVALID_NETWORK_RESPONSE}, { - ERRDOS, 59, NT_STATUS_UNEXPECTED_NETWORK_ERROR}, { - ERRDOS, 60, NT_STATUS_BAD_REMOTE_ADAPTER}, { - ERRDOS, 61, NT_STATUS_PRINT_QUEUE_FULL}, { - ERRDOS, 62, NT_STATUS_NO_SPOOL_SPACE}, { - ERRDOS, 63, NT_STATUS_PRINT_CANCELLED}, { - ERRDOS, 64, NT_STATUS_NETWORK_NAME_DELETED}, { - ERRDOS, 65, NT_STATUS_NETWORK_ACCESS_DENIED}, { - ERRDOS, 66, NT_STATUS_BAD_DEVICE_TYPE}, { - ERRDOS, ERRnosuchshare, NT_STATUS_BAD_NETWORK_NAME}, { - ERRDOS, 68, NT_STATUS_TOO_MANY_NAMES}, { - ERRDOS, 69, NT_STATUS_TOO_MANY_SESSIONS}, { - ERRDOS, 70, NT_STATUS_SHARING_PAUSED}, { - ERRDOS, 71, NT_STATUS_REQUEST_NOT_ACCEPTED}, { - ERRDOS, 72, NT_STATUS_REDIRECTOR_PAUSED}, { - ERRDOS, 88, NT_STATUS_NET_WRITE_FAULT}, { - ERRHRD, ERRgeneral, NT_STATUS_PROFILING_AT_LIMIT}, { - ERRDOS, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE}, { - ERRDOS, ERRnoaccess, NT_STATUS_FILE_RENAMED}, { - ERRDOS, 240, NT_STATUS_VIRTUAL_CIRCUIT_CLOSED}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_SECURITY_ON_OBJECT}, { - ERRHRD, ERRgeneral, NT_STATUS_CANT_WAIT}, { - ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_EMPTY}, { - ERRHRD, ERRgeneral, NT_STATUS_CANT_ACCESS_DOMAIN_INFO}, { - ERRHRD, ERRgeneral, NT_STATUS_CANT_TERMINATE_SELF}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_SERVER_STATE}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_STATE}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_ROLE}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_DOMAIN}, { - ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_EXISTS}, { - ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_LIMIT_EXCEEDED}, { - ERRDOS, 300, NT_STATUS_OPLOCK_NOT_GRANTED}, { - ERRDOS, 301, NT_STATUS_INVALID_OPLOCK_PROTOCOL}, { - ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_CORRUPTION}, { - ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_ERROR}, { - ERRHRD, ERRgeneral, NT_STATUS_GENERIC_NOT_MAPPED}, { - ERRHRD, ERRgeneral, NT_STATUS_BAD_DESCRIPTOR_FORMAT}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_USER_BUFFER}, { - ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_IO_ERROR}, { - ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_CREATE_ERR}, { - ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_MAP_ERROR}, { - ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_EXTEND_ERR}, { - ERRHRD, ERRgeneral, NT_STATUS_NOT_LOGON_PROCESS}, { - ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_EXISTS}, { - ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_1}, { - ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_2}, { - ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_3}, { - ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_4}, { - ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_5}, { - ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_6}, { - ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_7}, { - ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_8}, { - ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_9}, { - ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_10}, { - ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_11}, { - ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_12}, { - ERRDOS, ERRbadpath, NT_STATUS_REDIRECTOR_NOT_STARTED}, { - ERRHRD, ERRgeneral, NT_STATUS_REDIRECTOR_STARTED}, { - ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PACKAGE}, { - ERRHRD, ERRgeneral, NT_STATUS_BAD_FUNCTION_TABLE}, { - ERRDOS, 203, 0xc0000100}, { - ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY}, { - ERRHRD, ERRgeneral, NT_STATUS_FILE_CORRUPT_ERROR}, { - ERRDOS, 267, NT_STATUS_NOT_A_DIRECTORY}, { - ERRHRD, ERRgeneral, NT_STATUS_BAD_LOGON_SESSION_STATE}, { - ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_COLLISION}, { - ERRDOS, 206, NT_STATUS_NAME_TOO_LONG}, { - ERRDOS, 2401, NT_STATUS_FILES_OPEN}, { - ERRDOS, 2404, NT_STATUS_CONNECTION_IN_USE}, { - ERRHRD, ERRgeneral, NT_STATUS_MESSAGE_NOT_FOUND}, { - ERRDOS, ERRnoaccess, NT_STATUS_PROCESS_IS_TERMINATING}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_LOGON_TYPE}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_GUID_TRANSLATION}, { - ERRHRD, ERRgeneral, NT_STATUS_CANNOT_IMPERSONATE}, { - ERRHRD, ERRgeneral, NT_STATUS_IMAGE_ALREADY_LOADED}, { - ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_PRESENT}, { - ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_NOT_EXIST}, { - ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_ALREADY_OWNED}, { - ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_LID_OWNER}, { - ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_COMMAND}, { - ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_LID}, { - ERRHRD, ERRgeneral, NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE}, { - ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_SELECTOR}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_LDT}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_SIZE}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_OFFSET}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_DESCRIPTOR}, { - ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NE_FORMAT}, { - ERRHRD, ERRgeneral, NT_STATUS_RXACT_INVALID_STATE}, { - ERRHRD, ERRgeneral, NT_STATUS_RXACT_COMMIT_FAILURE}, { - ERRHRD, ERRgeneral, NT_STATUS_MAPPED_FILE_SIZE_ZERO}, { - ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES}, { - ERRHRD, ERRgeneral, NT_STATUS_CANCELLED}, { - ERRDOS, ERRnoaccess, NT_STATUS_CANNOT_DELETE}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_COMPUTER_NAME}, { - ERRDOS, ERRnoaccess, NT_STATUS_FILE_DELETED}, { - ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_ACCOUNT}, { - ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_GROUP}, { - ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_USER}, { - ERRHRD, ERRgeneral, NT_STATUS_MEMBERS_PRIMARY_GROUP}, { - ERRDOS, ERRbadfid, NT_STATUS_FILE_CLOSED}, { - ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_THREADS}, { - ERRHRD, ERRgeneral, NT_STATUS_THREAD_NOT_IN_PROCESS}, { - ERRHRD, ERRgeneral, NT_STATUS_TOKEN_ALREADY_IN_USE}, { - ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA_EXCEEDED}, { - ERRHRD, ERRgeneral, NT_STATUS_COMMITMENT_LIMIT}, { - ERRDOS, 193, NT_STATUS_INVALID_IMAGE_LE_FORMAT}, { - ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NOT_MZ}, { - ERRDOS, 193, NT_STATUS_INVALID_IMAGE_PROTECT}, { - ERRDOS, 193, NT_STATUS_INVALID_IMAGE_WIN_16}, { - ERRHRD, ERRgeneral, NT_STATUS_LOGON_SERVER_CONFLICT}, { - ERRHRD, ERRgeneral, NT_STATUS_TIME_DIFFERENCE_AT_DC}, { - ERRHRD, ERRgeneral, NT_STATUS_SYNCHRONIZATION_REQUIRED}, { - ERRDOS, 126, NT_STATUS_DLL_NOT_FOUND}, { - ERRHRD, ERRgeneral, NT_STATUS_OPEN_FAILED}, { - ERRHRD, ERRgeneral, NT_STATUS_IO_PRIVILEGE_FAILED}, { - ERRDOS, 182, NT_STATUS_ORDINAL_NOT_FOUND}, { - ERRDOS, 127, NT_STATUS_ENTRYPOINT_NOT_FOUND}, { - ERRHRD, ERRgeneral, NT_STATUS_CONTROL_C_EXIT}, { - ERRDOS, 64, NT_STATUS_LOCAL_DISCONNECT}, { - ERRDOS, 64, NT_STATUS_REMOTE_DISCONNECT}, { - ERRDOS, 51, NT_STATUS_REMOTE_RESOURCES}, { - ERRDOS, 59, NT_STATUS_LINK_FAILED}, { - ERRDOS, 59, NT_STATUS_LINK_TIMEOUT}, { - ERRDOS, 59, NT_STATUS_INVALID_CONNECTION}, { - ERRDOS, 59, NT_STATUS_INVALID_ADDRESS}, { - ERRHRD, ERRgeneral, NT_STATUS_DLL_INIT_FAILED}, { - ERRHRD, ERRgeneral, NT_STATUS_MISSING_SYSTEMFILE}, { - ERRHRD, ERRgeneral, NT_STATUS_UNHANDLED_EXCEPTION}, { - ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE}, { - ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE}, { - ERRDOS, 124, NT_STATUS_INVALID_LEVEL}, { - ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE}, { - ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT}, { - ERRDOS, 109, NT_STATUS_PIPE_BROKEN}, { - ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_CORRUPT}, { - ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_IO_FAILED}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_EVENT_PAIR}, { - ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_VOLUME}, { - ERRHRD, ERRgeneral, NT_STATUS_SERIAL_NO_DEVICE_INITED}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_ALIAS}, { - ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_ALIAS}, { - ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_ALIAS}, { - ERRHRD, ERRgeneral, NT_STATUS_ALIAS_EXISTS}, { - ERRHRD, ERRgeneral, NT_STATUS_LOGON_NOT_GRANTED}, { - ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SECRETS}, { - ERRHRD, ERRgeneral, NT_STATUS_SECRET_TOO_LONG}, { - ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_ERROR}, { - ERRHRD, ERRgeneral, NT_STATUS_FULLSCREEN_MODE}, { - ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_CONTEXT_IDS}, { - ERRDOS, ERRnoaccess, NT_STATUS_LOGON_TYPE_NOT_GRANTED}, { - ERRHRD, ERRgeneral, NT_STATUS_NOT_REGISTRY_FILE}, { - ERRHRD, ERRgeneral, NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED}, { - ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR}, { - ERRHRD, ERRgeneral, NT_STATUS_FT_MISSING_MEMBER}, { - ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_SERVICE_ENTRY}, { - ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_CHARACTER}, { - ERRHRD, ERRgeneral, NT_STATUS_UNMAPPABLE_CHARACTER}, { - ERRHRD, ERRgeneral, NT_STATUS_UNDEFINED_CHARACTER}, { - ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_VOLUME}, { - ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND}, { - ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_WRONG_CYLINDER}, { - ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_UNKNOWN_ERROR}, { - ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_BAD_REGISTERS}, { - ERRHRD, ERRgeneral, NT_STATUS_DISK_RECALIBRATE_FAILED}, { - ERRHRD, ERRgeneral, NT_STATUS_DISK_OPERATION_FAILED}, { - ERRHRD, ERRgeneral, NT_STATUS_DISK_RESET_FAILED}, { - ERRHRD, ERRgeneral, NT_STATUS_SHARED_IRQ_BUSY}, { - ERRHRD, ERRgeneral, NT_STATUS_FT_ORPHANING}, { - ERRHRD, ERRgeneral, 0xc000016e}, { - ERRHRD, ERRgeneral, 0xc000016f}, { - ERRHRD, ERRgeneral, 0xc0000170}, { - ERRHRD, ERRgeneral, 0xc0000171}, { - ERRHRD, ERRgeneral, NT_STATUS_PARTITION_FAILURE}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_BLOCK_LENGTH}, { - ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_PARTITIONED}, { - ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_LOCK_MEDIA}, { - ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_UNLOAD_MEDIA}, { - ERRHRD, ERRgeneral, NT_STATUS_EOM_OVERFLOW}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_MEDIA}, { - ERRHRD, ERRgeneral, 0xc0000179}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_MEMBER}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_MEMBER}, { - ERRHRD, ERRgeneral, NT_STATUS_KEY_DELETED}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_LOG_SPACE}, { - ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SIDS}, { - ERRHRD, ERRgeneral, NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED}, { - ERRHRD, ERRgeneral, NT_STATUS_KEY_HAS_CHILDREN}, { - ERRHRD, ERRgeneral, NT_STATUS_CHILD_MUST_BE_VOLATILE}, { - ERRDOS, 87, NT_STATUS_DEVICE_CONFIGURATION_ERROR}, { - ERRHRD, ERRgeneral, NT_STATUS_DRIVER_INTERNAL_ERROR}, { - ERRDOS, 22, NT_STATUS_INVALID_DEVICE_STATE}, { - ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR}, { - ERRHRD, ERRgeneral, NT_STATUS_DEVICE_PROTOCOL_ERROR}, { - ERRHRD, ERRgeneral, NT_STATUS_BACKUP_CONTROLLER}, { - ERRHRD, ERRgeneral, NT_STATUS_LOG_FILE_FULL}, { - ERRDOS, 19, NT_STATUS_TOO_LATE}, { - ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET}, -/* { This NT error code was 'sqashed' - from NT_STATUS_NO_TRUST_SAM_ACCOUNT to - NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE during the session setup } */ - { - ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, { - ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, { - ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE}, { - ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CORRUPT}, { - ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_CANT_START}, { - ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, { - ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, { - ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, { - ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_EXPIRED}, { - ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, { - ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, { - ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, { - ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CHANGED}, { - ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT}, { - ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, { - ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT}, -/* { This NT error code was 'sqashed' - from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE - during the session setup } */ - { - ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, { - ERRHRD, ERRgeneral, NT_STATUS_FS_DRIVER_REQUIRED}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_USER_SESSION_KEY}, { - ERRDOS, 59, NT_STATUS_USER_SESSION_DELETED}, { - ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_LANG_NOT_FOUND}, { - ERRDOS, ERRnomem, NT_STATUS_INSUFF_SERVER_RESOURCES}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_BUFFER_SIZE}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_COMPONENT}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_WILDCARD}, { - ERRDOS, 68, NT_STATUS_TOO_MANY_ADDRESSES}, { - ERRDOS, 52, NT_STATUS_ADDRESS_ALREADY_EXISTS}, { - ERRDOS, 64, NT_STATUS_ADDRESS_CLOSED}, { - ERRDOS, 64, NT_STATUS_CONNECTION_DISCONNECTED}, { - ERRDOS, 64, NT_STATUS_CONNECTION_RESET}, { - ERRDOS, 68, NT_STATUS_TOO_MANY_NODES}, { - ERRDOS, 59, NT_STATUS_TRANSACTION_ABORTED}, { - ERRDOS, 59, NT_STATUS_TRANSACTION_TIMED_OUT}, { - ERRDOS, 59, NT_STATUS_TRANSACTION_NO_RELEASE}, { - ERRDOS, 59, NT_STATUS_TRANSACTION_NO_MATCH}, { - ERRDOS, 59, NT_STATUS_TRANSACTION_RESPONDED}, { - ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_ID}, { - ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_TYPE}, { - ERRDOS, ERRunsup, NT_STATUS_NOT_SERVER_SESSION}, { - ERRDOS, ERRunsup, NT_STATUS_NOT_CLIENT_SESSION}, { - ERRHRD, ERRgeneral, NT_STATUS_CANNOT_LOAD_REGISTRY_FILE}, { - ERRHRD, ERRgeneral, NT_STATUS_DEBUG_ATTACH_FAILED}, { - ERRHRD, ERRgeneral, NT_STATUS_SYSTEM_PROCESS_TERMINATED}, { - ERRHRD, ERRgeneral, NT_STATUS_DATA_NOT_ACCEPTED}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_BROWSER_SERVERS_FOUND}, { - ERRHRD, ERRgeneral, NT_STATUS_VDM_HARD_ERROR}, { - ERRHRD, ERRgeneral, NT_STATUS_DRIVER_CANCEL_TIMEOUT}, { - ERRHRD, ERRgeneral, NT_STATUS_REPLY_MESSAGE_MISMATCH}, { - ERRHRD, ERRgeneral, NT_STATUS_MAPPED_ALIGNMENT}, { - ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, { - ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, { - ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, { - ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_MUST_CHANGE}, { - ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, { - ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, { - ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, { - ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW_READ}, { - ERRHRD, ERRgeneral, NT_STATUS_FAIL_CHECK}, { - ERRHRD, ERRgeneral, NT_STATUS_DUPLICATE_OBJECTID}, { - ERRHRD, ERRgeneral, NT_STATUS_OBJECTID_EXISTS}, { - ERRHRD, ERRgeneral, NT_STATUS_CONVERT_TO_LARGE}, { - ERRHRD, ERRgeneral, NT_STATUS_RETRY}, { - ERRHRD, ERRgeneral, NT_STATUS_FOUND_OUT_OF_SCOPE}, { - ERRHRD, ERRgeneral, NT_STATUS_ALLOCATE_BUCKET}, { - ERRHRD, ERRgeneral, NT_STATUS_PROPSET_NOT_FOUND}, { - ERRHRD, ERRgeneral, NT_STATUS_MARSHALL_OVERFLOW}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_VARIANT}, { - ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND}, { - ERRDOS, ERRnoaccess, NT_STATUS_ACCOUNT_LOCKED_OUT}, { - ERRDOS, ERRbadfid, NT_STATUS_HANDLE_NOT_CLOSABLE}, { - ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_REFUSED}, { - ERRHRD, ERRgeneral, NT_STATUS_GRACEFUL_DISCONNECT}, { - ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_ALREADY_ASSOCIATED}, { - ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_NOT_ASSOCIATED}, { - ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_INVALID}, { - ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ACTIVE}, { - ERRHRD, ERRgeneral, NT_STATUS_NETWORK_UNREACHABLE}, { - ERRHRD, ERRgeneral, NT_STATUS_HOST_UNREACHABLE}, { - ERRHRD, ERRgeneral, NT_STATUS_PROTOCOL_UNREACHABLE}, { - ERRHRD, ERRgeneral, NT_STATUS_PORT_UNREACHABLE}, { - ERRHRD, ERRgeneral, NT_STATUS_REQUEST_ABORTED}, { - ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ABORTED}, { - ERRHRD, ERRgeneral, NT_STATUS_BAD_COMPRESSION_BUFFER}, { - ERRHRD, ERRgeneral, NT_STATUS_USER_MAPPED_FILE}, { - ERRHRD, ERRgeneral, NT_STATUS_AUDIT_FAILED}, { - ERRHRD, ERRgeneral, NT_STATUS_TIMER_RESOLUTION_NOT_SET}, { - ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_COUNT_LIMIT}, { - ERRHRD, ERRgeneral, NT_STATUS_LOGIN_TIME_RESTRICTION}, { - ERRHRD, ERRgeneral, NT_STATUS_LOGIN_WKSTA_RESTRICTION}, { - ERRDOS, 193, NT_STATUS_IMAGE_MP_UP_MISMATCH}, { - ERRHRD, ERRgeneral, 0xc000024a}, { - ERRHRD, ERRgeneral, 0xc000024b}, { - ERRHRD, ERRgeneral, 0xc000024c}, { - ERRHRD, ERRgeneral, 0xc000024d}, { - ERRHRD, ERRgeneral, 0xc000024e}, { - ERRHRD, ERRgeneral, 0xc000024f}, { - ERRHRD, ERRgeneral, NT_STATUS_INSUFFICIENT_LOGON_INFO}, { - ERRHRD, ERRgeneral, NT_STATUS_BAD_DLL_ENTRYPOINT}, { - ERRHRD, ERRgeneral, NT_STATUS_BAD_SERVICE_ENTRYPOINT}, { - ERRHRD, ERRgeneral, NT_STATUS_LPC_REPLY_LOST}, { - ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT1}, { - ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT2}, { - ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_QUOTA_LIMIT}, { - ERRSRV, 3, NT_STATUS_PATH_NOT_COVERED}, { - ERRHRD, ERRgeneral, NT_STATUS_NO_CALLBACK_ACTIVE}, { - ERRHRD, ERRgeneral, NT_STATUS_LICENSE_QUOTA_EXCEEDED}, { - ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_SHORT}, { - ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_RECENT}, { - ERRHRD, ERRgeneral, NT_STATUS_PWD_HISTORY_CONFLICT}, { - ERRHRD, ERRgeneral, 0xc000025d}, { - ERRHRD, ERRgeneral, NT_STATUS_PLUGPLAY_NO_DEVICE}, { - ERRHRD, ERRgeneral, NT_STATUS_UNSUPPORTED_COMPRESSION}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_HW_PROFILE}, { - ERRHRD, ERRgeneral, NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH}, { - ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, { - ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, { - ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, { - ERRDOS, ErrTooManyLinks, NT_STATUS_TOO_MANY_LINKS}, { - ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, { - ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, { - ERRDOS, 21, 0xc000026e}, { - ERRDOS, 161, 0xc0000281}, { - ERRDOS, ERRnoaccess, 0xc000028a}, { - ERRDOS, ERRnoaccess, 0xc000028b}, { - ERRHRD, ERRgeneral, 0xc000028c}, { - ERRDOS, ERRnoaccess, 0xc000028d}, { - ERRDOS, ERRnoaccess, 0xc000028e}, { - ERRDOS, ERRnoaccess, 0xc000028f}, { - ERRDOS, ERRnoaccess, 0xc0000290}, { - ERRDOS, ERRbadfunc, 0xc000029c}, { - ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, { - ERRDOS, ERRinvlevel, 0x007c0001}, }; - -/***************************************************************************** - Print an error message from the status code - *****************************************************************************/ -static void -cifs_print_status(__u32 status_code) -{ - int idx = 0; - - while (nt_errs[idx].nt_errstr != NULL) { - if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) == - (status_code & 0xFFFFFF)) { - printk(KERN_NOTICE "Status code returned 0x%08x %s\n", - status_code, nt_errs[idx].nt_errstr); - } - idx++; - } - return; -} - - -static void -ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode) -{ - int i; - if (ntstatus == 0) { - *eclass = 0; - *ecode = 0; - return; - } - for (i = 0; ntstatus_to_dos_map[i].ntstatus; i++) { - if (ntstatus == ntstatus_to_dos_map[i].ntstatus) { - *eclass = ntstatus_to_dos_map[i].dos_class; - *ecode = ntstatus_to_dos_map[i].dos_code; - return; - } - } - *eclass = ERRHRD; - *ecode = ERRgeneral; -} - -int -map_smb_to_linux_error(char *buf, bool logErr) -{ - struct smb_hdr *smb = (struct smb_hdr *)buf; - unsigned int i; - int rc = -EIO; /* if transport error smb error may not be set */ - __u8 smberrclass; - __u16 smberrcode; - - /* BB if NT Status codes - map NT BB */ - - /* old style smb error codes */ - if (smb->Status.CifsError == 0) - return 0; - - if (smb->Flags2 & SMBFLG2_ERR_STATUS) { - /* translate the newer STATUS codes to old style SMB errors - * and then to POSIX errors */ - __u32 err = le32_to_cpu(smb->Status.CifsError); - if (logErr && (err != (NT_STATUS_MORE_PROCESSING_REQUIRED))) - cifs_print_status(err); - else if (cifsFYI & CIFS_RC) - cifs_print_status(err); - ntstatus_to_dos(err, &smberrclass, &smberrcode); - } else { - smberrclass = smb->Status.DosError.ErrorClass; - smberrcode = le16_to_cpu(smb->Status.DosError.Error); - } - - /* old style errors */ - - /* DOS class smb error codes - map DOS */ - if (smberrclass == ERRDOS) { - /* 1 byte field no need to byte reverse */ - for (i = 0; - i < - sizeof(mapping_table_ERRDOS) / - sizeof(struct smb_to_posix_error); i++) { - if (mapping_table_ERRDOS[i].smb_err == 0) - break; - else if (mapping_table_ERRDOS[i].smb_err == - smberrcode) { - rc = mapping_table_ERRDOS[i].posix_code; - break; - } - /* else try next error mapping one to see if match */ - } - } else if (smberrclass == ERRSRV) { - /* server class of error codes */ - for (i = 0; - i < - sizeof(mapping_table_ERRSRV) / - sizeof(struct smb_to_posix_error); i++) { - if (mapping_table_ERRSRV[i].smb_err == 0) - break; - else if (mapping_table_ERRSRV[i].smb_err == - smberrcode) { - rc = mapping_table_ERRSRV[i].posix_code; - break; - } - /* else try next error mapping to see if match */ - } - } - /* else ERRHRD class errors or junk - return EIO */ - - cFYI(1, "Mapping smb error code 0x%x to POSIX err %d", - le32_to_cpu(smb->Status.CifsError), rc); - - /* generic corrective action e.g. reconnect SMB session on - * ERRbaduid could be added */ - - return rc; -} - -/* - * calculate the size of the SMB message based on the fixed header - * portion, the number of word parameters and the data portion of the message - */ -unsigned int -smbCalcSize(struct smb_hdr *ptr) -{ - return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + - 2 /* size of the bcc field */ + get_bcc(ptr)); -} - -/* The following are taken from fs/ntfs/util.c */ - -#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000) - -/* - * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units) - * into Unix UTC (based 1970-01-01, in seconds). - */ -struct timespec -cifs_NTtimeToUnix(__le64 ntutc) -{ - struct timespec ts; - /* BB what about the timezone? BB */ - - /* Subtract the NTFS time offset, then convert to 1s intervals. */ - u64 t; - - t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET; - ts.tv_nsec = do_div(t, 10000000) * 100; - ts.tv_sec = t; - return ts; -} - -/* Convert the Unix UTC into NT UTC. */ -u64 -cifs_UnixTimeToNT(struct timespec t) -{ - /* Convert to 100ns intervals and then add the NTFS time offset. */ - return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET; -} - -static int total_days_of_prev_months[] = -{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; - -struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset) -{ - struct timespec ts; - int sec, min, days, month, year; - u16 date = le16_to_cpu(le_date); - u16 time = le16_to_cpu(le_time); - SMB_TIME *st = (SMB_TIME *)&time; - SMB_DATE *sd = (SMB_DATE *)&date; - - cFYI(1, "date %d time %d", date, time); - - sec = 2 * st->TwoSeconds; - min = st->Minutes; - if ((sec > 59) || (min > 59)) - cERROR(1, "illegal time min %d sec %d", min, sec); - sec += (min * 60); - sec += 60 * 60 * st->Hours; - if (st->Hours > 24) - cERROR(1, "illegal hours %d", st->Hours); - days = sd->Day; - month = sd->Month; - if ((days > 31) || (month > 12)) { - cERROR(1, "illegal date, month %d day: %d", month, days); - if (month > 12) - month = 12; - } - month -= 1; - days += total_days_of_prev_months[month]; - days += 3652; /* account for difference in days between 1980 and 1970 */ - year = sd->Year; - days += year * 365; - days += (year/4); /* leap year */ - /* generalized leap year calculation is more complex, ie no leap year - for years/100 except for years/400, but since the maximum number for DOS - year is 2**7, the last year is 1980+127, which means we need only - consider 2 special case years, ie the years 2000 and 2100, and only - adjust for the lack of leap year for the year 2100, as 2000 was a - leap year (divisable by 400) */ - if (year >= 120) /* the year 2100 */ - days = days - 1; /* do not count leap year for the year 2100 */ - - /* adjust for leap year where we are still before leap day */ - if (year != 120) - days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0); - sec += 24 * 60 * 60 * days; - - ts.tv_sec = sec + offset; - - /* cFYI(1, "sec after cnvrt dos to unix time %d",sec); */ - - ts.tv_nsec = 0; - return ts; -} diff --git a/ANDROID_3.4.5/fs/cifs/nterr.c b/ANDROID_3.4.5/fs/cifs/nterr.c deleted file mode 100644 index 819fd994..00000000 --- a/ANDROID_3.4.5/fs/cifs/nterr.c +++ /dev/null @@ -1,687 +0,0 @@ -/* - * Unix SMB/Netbios implementation. - * Version 1.9. - * RPC Pipe client / server routines - * Copyright (C) Luke Kenneth Casson Leighton 1997-2001. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* NT error codes - see nterr.h */ -#include <linux/types.h> -#include <linux/fs.h> -#include "nterr.h" - -const struct nt_err_code_struct nt_errs[] = { - {"NT_STATUS_OK", NT_STATUS_OK}, - {"NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL}, - {"NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED}, - {"NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS}, - {"NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH}, - {"NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION}, - {"STATUS_BUFFER_OVERFLOW", STATUS_BUFFER_OVERFLOW}, - {"NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR}, - {"NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA}, - {"NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE}, - {"NT_STATUS_BAD_INITIAL_STACK", NT_STATUS_BAD_INITIAL_STACK}, - {"NT_STATUS_BAD_INITIAL_PC", NT_STATUS_BAD_INITIAL_PC}, - {"NT_STATUS_INVALID_CID", NT_STATUS_INVALID_CID}, - {"NT_STATUS_TIMER_NOT_CANCELED", NT_STATUS_TIMER_NOT_CANCELED}, - {"NT_STATUS_INVALID_PARAMETER", NT_STATUS_INVALID_PARAMETER}, - {"NT_STATUS_NO_SUCH_DEVICE", NT_STATUS_NO_SUCH_DEVICE}, - {"NT_STATUS_NO_SUCH_FILE", NT_STATUS_NO_SUCH_FILE}, - {"NT_STATUS_INVALID_DEVICE_REQUEST", - NT_STATUS_INVALID_DEVICE_REQUEST}, - {"NT_STATUS_END_OF_FILE", NT_STATUS_END_OF_FILE}, - {"NT_STATUS_WRONG_VOLUME", NT_STATUS_WRONG_VOLUME}, - {"NT_STATUS_NO_MEDIA_IN_DEVICE", NT_STATUS_NO_MEDIA_IN_DEVICE}, - {"NT_STATUS_UNRECOGNIZED_MEDIA", NT_STATUS_UNRECOGNIZED_MEDIA}, - {"NT_STATUS_NONEXISTENT_SECTOR", NT_STATUS_NONEXISTENT_SECTOR}, - {"NT_STATUS_MORE_PROCESSING_REQUIRED", - NT_STATUS_MORE_PROCESSING_REQUIRED}, - {"NT_STATUS_NO_MEMORY", NT_STATUS_NO_MEMORY}, - {"NT_STATUS_CONFLICTING_ADDRESSES", - NT_STATUS_CONFLICTING_ADDRESSES}, - {"NT_STATUS_NOT_MAPPED_VIEW", NT_STATUS_NOT_MAPPED_VIEW}, - {"NT_STATUS_UNABLE_TO_FREE_VM", NT_STATUS_UNABLE_TO_FREE_VM}, - {"NT_STATUS_UNABLE_TO_DELETE_SECTION", - NT_STATUS_UNABLE_TO_DELETE_SECTION}, - {"NT_STATUS_INVALID_SYSTEM_SERVICE", - NT_STATUS_INVALID_SYSTEM_SERVICE}, - {"NT_STATUS_ILLEGAL_INSTRUCTION", NT_STATUS_ILLEGAL_INSTRUCTION}, - {"NT_STATUS_INVALID_LOCK_SEQUENCE", - NT_STATUS_INVALID_LOCK_SEQUENCE}, - {"NT_STATUS_INVALID_VIEW_SIZE", NT_STATUS_INVALID_VIEW_SIZE}, - {"NT_STATUS_INVALID_FILE_FOR_SECTION", - NT_STATUS_INVALID_FILE_FOR_SECTION}, - {"NT_STATUS_ALREADY_COMMITTED", NT_STATUS_ALREADY_COMMITTED}, - {"NT_STATUS_ACCESS_DENIED", NT_STATUS_ACCESS_DENIED}, - {"NT_STATUS_BUFFER_TOO_SMALL", NT_STATUS_BUFFER_TOO_SMALL}, - {"NT_STATUS_OBJECT_TYPE_MISMATCH", NT_STATUS_OBJECT_TYPE_MISMATCH}, - {"NT_STATUS_NONCONTINUABLE_EXCEPTION", - NT_STATUS_NONCONTINUABLE_EXCEPTION}, - {"NT_STATUS_INVALID_DISPOSITION", NT_STATUS_INVALID_DISPOSITION}, - {"NT_STATUS_UNWIND", NT_STATUS_UNWIND}, - {"NT_STATUS_BAD_STACK", NT_STATUS_BAD_STACK}, - {"NT_STATUS_INVALID_UNWIND_TARGET", - NT_STATUS_INVALID_UNWIND_TARGET}, - {"NT_STATUS_NOT_LOCKED", NT_STATUS_NOT_LOCKED}, - {"NT_STATUS_PARITY_ERROR", NT_STATUS_PARITY_ERROR}, - {"NT_STATUS_UNABLE_TO_DECOMMIT_VM", - NT_STATUS_UNABLE_TO_DECOMMIT_VM}, - {"NT_STATUS_NOT_COMMITTED", NT_STATUS_NOT_COMMITTED}, - {"NT_STATUS_INVALID_PORT_ATTRIBUTES", - NT_STATUS_INVALID_PORT_ATTRIBUTES}, - {"NT_STATUS_PORT_MESSAGE_TOO_LONG", - NT_STATUS_PORT_MESSAGE_TOO_LONG}, - {"NT_STATUS_INVALID_PARAMETER_MIX", - NT_STATUS_INVALID_PARAMETER_MIX}, - {"NT_STATUS_INVALID_QUOTA_LOWER", NT_STATUS_INVALID_QUOTA_LOWER}, - {"NT_STATUS_DISK_CORRUPT_ERROR", NT_STATUS_DISK_CORRUPT_ERROR}, - {"NT_STATUS_OBJECT_NAME_INVALID", NT_STATUS_OBJECT_NAME_INVALID}, - {"NT_STATUS_OBJECT_NAME_NOT_FOUND", - NT_STATUS_OBJECT_NAME_NOT_FOUND}, - {"NT_STATUS_OBJECT_NAME_COLLISION", - NT_STATUS_OBJECT_NAME_COLLISION}, - {"NT_STATUS_HANDLE_NOT_WAITABLE", NT_STATUS_HANDLE_NOT_WAITABLE}, - {"NT_STATUS_PORT_DISCONNECTED", NT_STATUS_PORT_DISCONNECTED}, - {"NT_STATUS_DEVICE_ALREADY_ATTACHED", - NT_STATUS_DEVICE_ALREADY_ATTACHED}, - {"NT_STATUS_OBJECT_PATH_INVALID", NT_STATUS_OBJECT_PATH_INVALID}, - {"NT_STATUS_OBJECT_PATH_NOT_FOUND", - NT_STATUS_OBJECT_PATH_NOT_FOUND}, - {"NT_STATUS_OBJECT_PATH_SYNTAX_BAD", - NT_STATUS_OBJECT_PATH_SYNTAX_BAD}, - {"NT_STATUS_DATA_OVERRUN", NT_STATUS_DATA_OVERRUN}, - {"NT_STATUS_DATA_LATE_ERROR", NT_STATUS_DATA_LATE_ERROR}, - {"NT_STATUS_DATA_ERROR", NT_STATUS_DATA_ERROR}, - {"NT_STATUS_CRC_ERROR", NT_STATUS_CRC_ERROR}, - {"NT_STATUS_SECTION_TOO_BIG", NT_STATUS_SECTION_TOO_BIG}, - {"NT_STATUS_PORT_CONNECTION_REFUSED", - NT_STATUS_PORT_CONNECTION_REFUSED}, - {"NT_STATUS_INVALID_PORT_HANDLE", NT_STATUS_INVALID_PORT_HANDLE}, - {"NT_STATUS_SHARING_VIOLATION", NT_STATUS_SHARING_VIOLATION}, - {"NT_STATUS_QUOTA_EXCEEDED", NT_STATUS_QUOTA_EXCEEDED}, - {"NT_STATUS_INVALID_PAGE_PROTECTION", - NT_STATUS_INVALID_PAGE_PROTECTION}, - {"NT_STATUS_MUTANT_NOT_OWNED", NT_STATUS_MUTANT_NOT_OWNED}, - {"NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED", - NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED}, - {"NT_STATUS_PORT_ALREADY_SET", NT_STATUS_PORT_ALREADY_SET}, - {"NT_STATUS_SECTION_NOT_IMAGE", NT_STATUS_SECTION_NOT_IMAGE}, - {"NT_STATUS_SUSPEND_COUNT_EXCEEDED", - NT_STATUS_SUSPEND_COUNT_EXCEEDED}, - {"NT_STATUS_THREAD_IS_TERMINATING", - NT_STATUS_THREAD_IS_TERMINATING}, - {"NT_STATUS_BAD_WORKING_SET_LIMIT", - NT_STATUS_BAD_WORKING_SET_LIMIT}, - {"NT_STATUS_INCOMPATIBLE_FILE_MAP", - NT_STATUS_INCOMPATIBLE_FILE_MAP}, - {"NT_STATUS_SECTION_PROTECTION", NT_STATUS_SECTION_PROTECTION}, - {"NT_STATUS_EAS_NOT_SUPPORTED", NT_STATUS_EAS_NOT_SUPPORTED}, - {"NT_STATUS_EA_TOO_LARGE", NT_STATUS_EA_TOO_LARGE}, - {"NT_STATUS_NONEXISTENT_EA_ENTRY", NT_STATUS_NONEXISTENT_EA_ENTRY}, - {"NT_STATUS_NO_EAS_ON_FILE", NT_STATUS_NO_EAS_ON_FILE}, - {"NT_STATUS_EA_CORRUPT_ERROR", NT_STATUS_EA_CORRUPT_ERROR}, - {"NT_STATUS_FILE_LOCK_CONFLICT", NT_STATUS_FILE_LOCK_CONFLICT}, - {"NT_STATUS_LOCK_NOT_GRANTED", NT_STATUS_LOCK_NOT_GRANTED}, - {"NT_STATUS_DELETE_PENDING", NT_STATUS_DELETE_PENDING}, - {"NT_STATUS_CTL_FILE_NOT_SUPPORTED", - NT_STATUS_CTL_FILE_NOT_SUPPORTED}, - {"NT_STATUS_UNKNOWN_REVISION", NT_STATUS_UNKNOWN_REVISION}, - {"NT_STATUS_REVISION_MISMATCH", NT_STATUS_REVISION_MISMATCH}, - {"NT_STATUS_INVALID_OWNER", NT_STATUS_INVALID_OWNER}, - {"NT_STATUS_INVALID_PRIMARY_GROUP", - NT_STATUS_INVALID_PRIMARY_GROUP}, - {"NT_STATUS_NO_IMPERSONATION_TOKEN", - NT_STATUS_NO_IMPERSONATION_TOKEN}, - {"NT_STATUS_CANT_DISABLE_MANDATORY", - NT_STATUS_CANT_DISABLE_MANDATORY}, - {"NT_STATUS_NO_LOGON_SERVERS", NT_STATUS_NO_LOGON_SERVERS}, - {"NT_STATUS_NO_SUCH_LOGON_SESSION", - NT_STATUS_NO_SUCH_LOGON_SESSION}, - {"NT_STATUS_NO_SUCH_PRIVILEGE", NT_STATUS_NO_SUCH_PRIVILEGE}, - {"NT_STATUS_PRIVILEGE_NOT_HELD", NT_STATUS_PRIVILEGE_NOT_HELD}, - {"NT_STATUS_INVALID_ACCOUNT_NAME", NT_STATUS_INVALID_ACCOUNT_NAME}, - {"NT_STATUS_USER_EXISTS", NT_STATUS_USER_EXISTS}, - {"NT_STATUS_NO_SUCH_USER", NT_STATUS_NO_SUCH_USER}, - {"NT_STATUS_GROUP_EXISTS", NT_STATUS_GROUP_EXISTS}, - {"NT_STATUS_NO_SUCH_GROUP", NT_STATUS_NO_SUCH_GROUP}, - {"NT_STATUS_MEMBER_IN_GROUP", NT_STATUS_MEMBER_IN_GROUP}, - {"NT_STATUS_MEMBER_NOT_IN_GROUP", NT_STATUS_MEMBER_NOT_IN_GROUP}, - {"NT_STATUS_LAST_ADMIN", NT_STATUS_LAST_ADMIN}, - {"NT_STATUS_WRONG_PASSWORD", NT_STATUS_WRONG_PASSWORD}, - {"NT_STATUS_ILL_FORMED_PASSWORD", NT_STATUS_ILL_FORMED_PASSWORD}, - {"NT_STATUS_PASSWORD_RESTRICTION", NT_STATUS_PASSWORD_RESTRICTION}, - {"NT_STATUS_LOGON_FAILURE", NT_STATUS_LOGON_FAILURE}, - {"NT_STATUS_ACCOUNT_RESTRICTION", NT_STATUS_ACCOUNT_RESTRICTION}, - {"NT_STATUS_INVALID_LOGON_HOURS", NT_STATUS_INVALID_LOGON_HOURS}, - {"NT_STATUS_INVALID_WORKSTATION", NT_STATUS_INVALID_WORKSTATION}, - {"NT_STATUS_PASSWORD_EXPIRED", NT_STATUS_PASSWORD_EXPIRED}, - {"NT_STATUS_ACCOUNT_DISABLED", NT_STATUS_ACCOUNT_DISABLED}, - {"NT_STATUS_NONE_MAPPED", NT_STATUS_NONE_MAPPED}, - {"NT_STATUS_TOO_MANY_LUIDS_REQUESTED", - NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, - {"NT_STATUS_LUIDS_EXHAUSTED", NT_STATUS_LUIDS_EXHAUSTED}, - {"NT_STATUS_INVALID_SUB_AUTHORITY", - NT_STATUS_INVALID_SUB_AUTHORITY}, - {"NT_STATUS_INVALID_ACL", NT_STATUS_INVALID_ACL}, - {"NT_STATUS_INVALID_SID", NT_STATUS_INVALID_SID}, - {"NT_STATUS_INVALID_SECURITY_DESCR", - NT_STATUS_INVALID_SECURITY_DESCR}, - {"NT_STATUS_PROCEDURE_NOT_FOUND", NT_STATUS_PROCEDURE_NOT_FOUND}, - {"NT_STATUS_INVALID_IMAGE_FORMAT", NT_STATUS_INVALID_IMAGE_FORMAT}, - {"NT_STATUS_NO_TOKEN", NT_STATUS_NO_TOKEN}, - {"NT_STATUS_BAD_INHERITANCE_ACL", NT_STATUS_BAD_INHERITANCE_ACL}, - {"NT_STATUS_RANGE_NOT_LOCKED", NT_STATUS_RANGE_NOT_LOCKED}, - {"NT_STATUS_DISK_FULL", NT_STATUS_DISK_FULL}, - {"NT_STATUS_SERVER_DISABLED", NT_STATUS_SERVER_DISABLED}, - {"NT_STATUS_SERVER_NOT_DISABLED", NT_STATUS_SERVER_NOT_DISABLED}, - {"NT_STATUS_TOO_MANY_GUIDS_REQUESTED", - NT_STATUS_TOO_MANY_GUIDS_REQUESTED}, - {"NT_STATUS_GUIDS_EXHAUSTED", NT_STATUS_GUIDS_EXHAUSTED}, - {"NT_STATUS_INVALID_ID_AUTHORITY", NT_STATUS_INVALID_ID_AUTHORITY}, - {"NT_STATUS_AGENTS_EXHAUSTED", NT_STATUS_AGENTS_EXHAUSTED}, - {"NT_STATUS_INVALID_VOLUME_LABEL", NT_STATUS_INVALID_VOLUME_LABEL}, - {"NT_STATUS_SECTION_NOT_EXTENDED", NT_STATUS_SECTION_NOT_EXTENDED}, - {"NT_STATUS_NOT_MAPPED_DATA", NT_STATUS_NOT_MAPPED_DATA}, - {"NT_STATUS_RESOURCE_DATA_NOT_FOUND", - NT_STATUS_RESOURCE_DATA_NOT_FOUND}, - {"NT_STATUS_RESOURCE_TYPE_NOT_FOUND", - NT_STATUS_RESOURCE_TYPE_NOT_FOUND}, - {"NT_STATUS_RESOURCE_NAME_NOT_FOUND", - NT_STATUS_RESOURCE_NAME_NOT_FOUND}, - {"NT_STATUS_ARRAY_BOUNDS_EXCEEDED", - NT_STATUS_ARRAY_BOUNDS_EXCEEDED}, - {"NT_STATUS_FLOAT_DENORMAL_OPERAND", - NT_STATUS_FLOAT_DENORMAL_OPERAND}, - {"NT_STATUS_FLOAT_DIVIDE_BY_ZERO", NT_STATUS_FLOAT_DIVIDE_BY_ZERO}, - {"NT_STATUS_FLOAT_INEXACT_RESULT", NT_STATUS_FLOAT_INEXACT_RESULT}, - {"NT_STATUS_FLOAT_INVALID_OPERATION", - NT_STATUS_FLOAT_INVALID_OPERATION}, - {"NT_STATUS_FLOAT_OVERFLOW", NT_STATUS_FLOAT_OVERFLOW}, - {"NT_STATUS_FLOAT_STACK_CHECK", NT_STATUS_FLOAT_STACK_CHECK}, - {"NT_STATUS_FLOAT_UNDERFLOW", NT_STATUS_FLOAT_UNDERFLOW}, - {"NT_STATUS_INTEGER_DIVIDE_BY_ZERO", - NT_STATUS_INTEGER_DIVIDE_BY_ZERO}, - {"NT_STATUS_INTEGER_OVERFLOW", NT_STATUS_INTEGER_OVERFLOW}, - {"NT_STATUS_PRIVILEGED_INSTRUCTION", - NT_STATUS_PRIVILEGED_INSTRUCTION}, - {"NT_STATUS_TOO_MANY_PAGING_FILES", - NT_STATUS_TOO_MANY_PAGING_FILES}, - {"NT_STATUS_FILE_INVALID", NT_STATUS_FILE_INVALID}, - {"NT_STATUS_ALLOTTED_SPACE_EXCEEDED", - NT_STATUS_ALLOTTED_SPACE_EXCEEDED}, - {"NT_STATUS_INSUFFICIENT_RESOURCES", - NT_STATUS_INSUFFICIENT_RESOURCES}, - {"NT_STATUS_DFS_EXIT_PATH_FOUND", NT_STATUS_DFS_EXIT_PATH_FOUND}, - {"NT_STATUS_DEVICE_DATA_ERROR", NT_STATUS_DEVICE_DATA_ERROR}, - {"NT_STATUS_DEVICE_NOT_CONNECTED", NT_STATUS_DEVICE_NOT_CONNECTED}, - {"NT_STATUS_DEVICE_POWER_FAILURE", NT_STATUS_DEVICE_POWER_FAILURE}, - {"NT_STATUS_FREE_VM_NOT_AT_BASE", NT_STATUS_FREE_VM_NOT_AT_BASE}, - {"NT_STATUS_MEMORY_NOT_ALLOCATED", NT_STATUS_MEMORY_NOT_ALLOCATED}, - {"NT_STATUS_WORKING_SET_QUOTA", NT_STATUS_WORKING_SET_QUOTA}, - {"NT_STATUS_MEDIA_WRITE_PROTECTED", - NT_STATUS_MEDIA_WRITE_PROTECTED}, - {"NT_STATUS_DEVICE_NOT_READY", NT_STATUS_DEVICE_NOT_READY}, - {"NT_STATUS_INVALID_GROUP_ATTRIBUTES", - NT_STATUS_INVALID_GROUP_ATTRIBUTES}, - {"NT_STATUS_BAD_IMPERSONATION_LEVEL", - NT_STATUS_BAD_IMPERSONATION_LEVEL}, - {"NT_STATUS_CANT_OPEN_ANONYMOUS", NT_STATUS_CANT_OPEN_ANONYMOUS}, - {"NT_STATUS_BAD_VALIDATION_CLASS", NT_STATUS_BAD_VALIDATION_CLASS}, - {"NT_STATUS_BAD_TOKEN_TYPE", NT_STATUS_BAD_TOKEN_TYPE}, - {"NT_STATUS_BAD_MASTER_BOOT_RECORD", - NT_STATUS_BAD_MASTER_BOOT_RECORD}, - {"NT_STATUS_INSTRUCTION_MISALIGNMENT", - NT_STATUS_INSTRUCTION_MISALIGNMENT}, - {"NT_STATUS_INSTANCE_NOT_AVAILABLE", - NT_STATUS_INSTANCE_NOT_AVAILABLE}, - {"NT_STATUS_PIPE_NOT_AVAILABLE", NT_STATUS_PIPE_NOT_AVAILABLE}, - {"NT_STATUS_INVALID_PIPE_STATE", NT_STATUS_INVALID_PIPE_STATE}, - {"NT_STATUS_PIPE_BUSY", NT_STATUS_PIPE_BUSY}, - {"NT_STATUS_ILLEGAL_FUNCTION", NT_STATUS_ILLEGAL_FUNCTION}, - {"NT_STATUS_PIPE_DISCONNECTED", NT_STATUS_PIPE_DISCONNECTED}, - {"NT_STATUS_PIPE_CLOSING", NT_STATUS_PIPE_CLOSING}, - {"NT_STATUS_PIPE_CONNECTED", NT_STATUS_PIPE_CONNECTED}, - {"NT_STATUS_PIPE_LISTENING", NT_STATUS_PIPE_LISTENING}, - {"NT_STATUS_INVALID_READ_MODE", NT_STATUS_INVALID_READ_MODE}, - {"NT_STATUS_IO_TIMEOUT", NT_STATUS_IO_TIMEOUT}, - {"NT_STATUS_FILE_FORCED_CLOSED", NT_STATUS_FILE_FORCED_CLOSED}, - {"NT_STATUS_PROFILING_NOT_STARTED", - NT_STATUS_PROFILING_NOT_STARTED}, - {"NT_STATUS_PROFILING_NOT_STOPPED", - NT_STATUS_PROFILING_NOT_STOPPED}, - {"NT_STATUS_COULD_NOT_INTERPRET", NT_STATUS_COULD_NOT_INTERPRET}, - {"NT_STATUS_FILE_IS_A_DIRECTORY", NT_STATUS_FILE_IS_A_DIRECTORY}, - {"NT_STATUS_NOT_SUPPORTED", NT_STATUS_NOT_SUPPORTED}, - {"NT_STATUS_REMOTE_NOT_LISTENING", NT_STATUS_REMOTE_NOT_LISTENING}, - {"NT_STATUS_DUPLICATE_NAME", NT_STATUS_DUPLICATE_NAME}, - {"NT_STATUS_BAD_NETWORK_PATH", NT_STATUS_BAD_NETWORK_PATH}, - {"NT_STATUS_NETWORK_BUSY", NT_STATUS_NETWORK_BUSY}, - {"NT_STATUS_DEVICE_DOES_NOT_EXIST", - NT_STATUS_DEVICE_DOES_NOT_EXIST}, - {"NT_STATUS_TOO_MANY_COMMANDS", NT_STATUS_TOO_MANY_COMMANDS}, - {"NT_STATUS_ADAPTER_HARDWARE_ERROR", - NT_STATUS_ADAPTER_HARDWARE_ERROR}, - {"NT_STATUS_INVALID_NETWORK_RESPONSE", - NT_STATUS_INVALID_NETWORK_RESPONSE}, - {"NT_STATUS_UNEXPECTED_NETWORK_ERROR", - NT_STATUS_UNEXPECTED_NETWORK_ERROR}, - {"NT_STATUS_BAD_REMOTE_ADAPTER", NT_STATUS_BAD_REMOTE_ADAPTER}, - {"NT_STATUS_PRINT_QUEUE_FULL", NT_STATUS_PRINT_QUEUE_FULL}, - {"NT_STATUS_NO_SPOOL_SPACE", NT_STATUS_NO_SPOOL_SPACE}, - {"NT_STATUS_PRINT_CANCELLED", NT_STATUS_PRINT_CANCELLED}, - {"NT_STATUS_NETWORK_NAME_DELETED", NT_STATUS_NETWORK_NAME_DELETED}, - {"NT_STATUS_NETWORK_ACCESS_DENIED", - NT_STATUS_NETWORK_ACCESS_DENIED}, - {"NT_STATUS_BAD_DEVICE_TYPE", NT_STATUS_BAD_DEVICE_TYPE}, - {"NT_STATUS_BAD_NETWORK_NAME", NT_STATUS_BAD_NETWORK_NAME}, - {"NT_STATUS_TOO_MANY_NAMES", NT_STATUS_TOO_MANY_NAMES}, - {"NT_STATUS_TOO_MANY_SESSIONS", NT_STATUS_TOO_MANY_SESSIONS}, - {"NT_STATUS_SHARING_PAUSED", NT_STATUS_SHARING_PAUSED}, - {"NT_STATUS_REQUEST_NOT_ACCEPTED", NT_STATUS_REQUEST_NOT_ACCEPTED}, - {"NT_STATUS_REDIRECTOR_PAUSED", NT_STATUS_REDIRECTOR_PAUSED}, - {"NT_STATUS_NET_WRITE_FAULT", NT_STATUS_NET_WRITE_FAULT}, - {"NT_STATUS_PROFILING_AT_LIMIT", NT_STATUS_PROFILING_AT_LIMIT}, - {"NT_STATUS_NOT_SAME_DEVICE", NT_STATUS_NOT_SAME_DEVICE}, - {"NT_STATUS_FILE_RENAMED", NT_STATUS_FILE_RENAMED}, - {"NT_STATUS_VIRTUAL_CIRCUIT_CLOSED", - NT_STATUS_VIRTUAL_CIRCUIT_CLOSED}, - {"NT_STATUS_NO_SECURITY_ON_OBJECT", - NT_STATUS_NO_SECURITY_ON_OBJECT}, - {"NT_STATUS_CANT_WAIT", NT_STATUS_CANT_WAIT}, - {"NT_STATUS_PIPE_EMPTY", NT_STATUS_PIPE_EMPTY}, - {"NT_STATUS_CANT_ACCESS_DOMAIN_INFO", - NT_STATUS_CANT_ACCESS_DOMAIN_INFO}, - {"NT_STATUS_CANT_TERMINATE_SELF", NT_STATUS_CANT_TERMINATE_SELF}, - {"NT_STATUS_INVALID_SERVER_STATE", NT_STATUS_INVALID_SERVER_STATE}, - {"NT_STATUS_INVALID_DOMAIN_STATE", NT_STATUS_INVALID_DOMAIN_STATE}, - {"NT_STATUS_INVALID_DOMAIN_ROLE", NT_STATUS_INVALID_DOMAIN_ROLE}, - {"NT_STATUS_NO_SUCH_DOMAIN", NT_STATUS_NO_SUCH_DOMAIN}, - {"NT_STATUS_DOMAIN_EXISTS", NT_STATUS_DOMAIN_EXISTS}, - {"NT_STATUS_DOMAIN_LIMIT_EXCEEDED", - NT_STATUS_DOMAIN_LIMIT_EXCEEDED}, - {"NT_STATUS_OPLOCK_NOT_GRANTED", NT_STATUS_OPLOCK_NOT_GRANTED}, - {"NT_STATUS_INVALID_OPLOCK_PROTOCOL", - NT_STATUS_INVALID_OPLOCK_PROTOCOL}, - {"NT_STATUS_INTERNAL_DB_CORRUPTION", - NT_STATUS_INTERNAL_DB_CORRUPTION}, - {"NT_STATUS_INTERNAL_ERROR", NT_STATUS_INTERNAL_ERROR}, - {"NT_STATUS_GENERIC_NOT_MAPPED", NT_STATUS_GENERIC_NOT_MAPPED}, - {"NT_STATUS_BAD_DESCRIPTOR_FORMAT", - NT_STATUS_BAD_DESCRIPTOR_FORMAT}, - {"NT_STATUS_INVALID_USER_BUFFER", NT_STATUS_INVALID_USER_BUFFER}, - {"NT_STATUS_UNEXPECTED_IO_ERROR", NT_STATUS_UNEXPECTED_IO_ERROR}, - {"NT_STATUS_UNEXPECTED_MM_CREATE_ERR", - NT_STATUS_UNEXPECTED_MM_CREATE_ERR}, - {"NT_STATUS_UNEXPECTED_MM_MAP_ERROR", - NT_STATUS_UNEXPECTED_MM_MAP_ERROR}, - {"NT_STATUS_UNEXPECTED_MM_EXTEND_ERR", - NT_STATUS_UNEXPECTED_MM_EXTEND_ERR}, - {"NT_STATUS_NOT_LOGON_PROCESS", NT_STATUS_NOT_LOGON_PROCESS}, - {"NT_STATUS_LOGON_SESSION_EXISTS", NT_STATUS_LOGON_SESSION_EXISTS}, - {"NT_STATUS_INVALID_PARAMETER_1", NT_STATUS_INVALID_PARAMETER_1}, - {"NT_STATUS_INVALID_PARAMETER_2", NT_STATUS_INVALID_PARAMETER_2}, - {"NT_STATUS_INVALID_PARAMETER_3", NT_STATUS_INVALID_PARAMETER_3}, - {"NT_STATUS_INVALID_PARAMETER_4", NT_STATUS_INVALID_PARAMETER_4}, - {"NT_STATUS_INVALID_PARAMETER_5", NT_STATUS_INVALID_PARAMETER_5}, - {"NT_STATUS_INVALID_PARAMETER_6", NT_STATUS_INVALID_PARAMETER_6}, - {"NT_STATUS_INVALID_PARAMETER_7", NT_STATUS_INVALID_PARAMETER_7}, - {"NT_STATUS_INVALID_PARAMETER_8", NT_STATUS_INVALID_PARAMETER_8}, - {"NT_STATUS_INVALID_PARAMETER_9", NT_STATUS_INVALID_PARAMETER_9}, - {"NT_STATUS_INVALID_PARAMETER_10", NT_STATUS_INVALID_PARAMETER_10}, - {"NT_STATUS_INVALID_PARAMETER_11", NT_STATUS_INVALID_PARAMETER_11}, - {"NT_STATUS_INVALID_PARAMETER_12", NT_STATUS_INVALID_PARAMETER_12}, - {"NT_STATUS_REDIRECTOR_NOT_STARTED", - NT_STATUS_REDIRECTOR_NOT_STARTED}, - {"NT_STATUS_REDIRECTOR_STARTED", NT_STATUS_REDIRECTOR_STARTED}, - {"NT_STATUS_STACK_OVERFLOW", NT_STATUS_STACK_OVERFLOW}, - {"NT_STATUS_NO_SUCH_PACKAGE", NT_STATUS_NO_SUCH_PACKAGE}, - {"NT_STATUS_BAD_FUNCTION_TABLE", NT_STATUS_BAD_FUNCTION_TABLE}, - {"NT_STATUS_DIRECTORY_NOT_EMPTY", NT_STATUS_DIRECTORY_NOT_EMPTY}, - {"NT_STATUS_FILE_CORRUPT_ERROR", NT_STATUS_FILE_CORRUPT_ERROR}, - {"NT_STATUS_NOT_A_DIRECTORY", NT_STATUS_NOT_A_DIRECTORY}, - {"NT_STATUS_BAD_LOGON_SESSION_STATE", - NT_STATUS_BAD_LOGON_SESSION_STATE}, - {"NT_STATUS_LOGON_SESSION_COLLISION", - NT_STATUS_LOGON_SESSION_COLLISION}, - {"NT_STATUS_NAME_TOO_LONG", NT_STATUS_NAME_TOO_LONG}, - {"NT_STATUS_FILES_OPEN", NT_STATUS_FILES_OPEN}, - {"NT_STATUS_CONNECTION_IN_USE", NT_STATUS_CONNECTION_IN_USE}, - {"NT_STATUS_MESSAGE_NOT_FOUND", NT_STATUS_MESSAGE_NOT_FOUND}, - {"NT_STATUS_PROCESS_IS_TERMINATING", - NT_STATUS_PROCESS_IS_TERMINATING}, - {"NT_STATUS_INVALID_LOGON_TYPE", NT_STATUS_INVALID_LOGON_TYPE}, - {"NT_STATUS_NO_GUID_TRANSLATION", NT_STATUS_NO_GUID_TRANSLATION}, - {"NT_STATUS_CANNOT_IMPERSONATE", NT_STATUS_CANNOT_IMPERSONATE}, - {"NT_STATUS_IMAGE_ALREADY_LOADED", NT_STATUS_IMAGE_ALREADY_LOADED}, - {"NT_STATUS_ABIOS_NOT_PRESENT", NT_STATUS_ABIOS_NOT_PRESENT}, - {"NT_STATUS_ABIOS_LID_NOT_EXIST", NT_STATUS_ABIOS_LID_NOT_EXIST}, - {"NT_STATUS_ABIOS_LID_ALREADY_OWNED", - NT_STATUS_ABIOS_LID_ALREADY_OWNED}, - {"NT_STATUS_ABIOS_NOT_LID_OWNER", NT_STATUS_ABIOS_NOT_LID_OWNER}, - {"NT_STATUS_ABIOS_INVALID_COMMAND", - NT_STATUS_ABIOS_INVALID_COMMAND}, - {"NT_STATUS_ABIOS_INVALID_LID", NT_STATUS_ABIOS_INVALID_LID}, - {"NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE", - NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE}, - {"NT_STATUS_ABIOS_INVALID_SELECTOR", - NT_STATUS_ABIOS_INVALID_SELECTOR}, - {"NT_STATUS_NO_LDT", NT_STATUS_NO_LDT}, - {"NT_STATUS_INVALID_LDT_SIZE", NT_STATUS_INVALID_LDT_SIZE}, - {"NT_STATUS_INVALID_LDT_OFFSET", NT_STATUS_INVALID_LDT_OFFSET}, - {"NT_STATUS_INVALID_LDT_DESCRIPTOR", - NT_STATUS_INVALID_LDT_DESCRIPTOR}, - {"NT_STATUS_INVALID_IMAGE_NE_FORMAT", - NT_STATUS_INVALID_IMAGE_NE_FORMAT}, - {"NT_STATUS_RXACT_INVALID_STATE", NT_STATUS_RXACT_INVALID_STATE}, - {"NT_STATUS_RXACT_COMMIT_FAILURE", NT_STATUS_RXACT_COMMIT_FAILURE}, - {"NT_STATUS_MAPPED_FILE_SIZE_ZERO", - NT_STATUS_MAPPED_FILE_SIZE_ZERO}, - {"NT_STATUS_TOO_MANY_OPENED_FILES", - NT_STATUS_TOO_MANY_OPENED_FILES}, - {"NT_STATUS_CANCELLED", NT_STATUS_CANCELLED}, - {"NT_STATUS_CANNOT_DELETE", NT_STATUS_CANNOT_DELETE}, - {"NT_STATUS_INVALID_COMPUTER_NAME", - NT_STATUS_INVALID_COMPUTER_NAME}, - {"NT_STATUS_FILE_DELETED", NT_STATUS_FILE_DELETED}, - {"NT_STATUS_SPECIAL_ACCOUNT", NT_STATUS_SPECIAL_ACCOUNT}, - {"NT_STATUS_SPECIAL_GROUP", NT_STATUS_SPECIAL_GROUP}, - {"NT_STATUS_SPECIAL_USER", NT_STATUS_SPECIAL_USER}, - {"NT_STATUS_MEMBERS_PRIMARY_GROUP", - NT_STATUS_MEMBERS_PRIMARY_GROUP}, - {"NT_STATUS_FILE_CLOSED", NT_STATUS_FILE_CLOSED}, - {"NT_STATUS_TOO_MANY_THREADS", NT_STATUS_TOO_MANY_THREADS}, - {"NT_STATUS_THREAD_NOT_IN_PROCESS", - NT_STATUS_THREAD_NOT_IN_PROCESS}, - {"NT_STATUS_TOKEN_ALREADY_IN_USE", NT_STATUS_TOKEN_ALREADY_IN_USE}, - {"NT_STATUS_PAGEFILE_QUOTA_EXCEEDED", - NT_STATUS_PAGEFILE_QUOTA_EXCEEDED}, - {"NT_STATUS_COMMITMENT_LIMIT", NT_STATUS_COMMITMENT_LIMIT}, - {"NT_STATUS_INVALID_IMAGE_LE_FORMAT", - NT_STATUS_INVALID_IMAGE_LE_FORMAT}, - {"NT_STATUS_INVALID_IMAGE_NOT_MZ", NT_STATUS_INVALID_IMAGE_NOT_MZ}, - {"NT_STATUS_INVALID_IMAGE_PROTECT", - NT_STATUS_INVALID_IMAGE_PROTECT}, - {"NT_STATUS_INVALID_IMAGE_WIN_16", NT_STATUS_INVALID_IMAGE_WIN_16}, - {"NT_STATUS_LOGON_SERVER_CONFLICT", - NT_STATUS_LOGON_SERVER_CONFLICT}, - {"NT_STATUS_TIME_DIFFERENCE_AT_DC", - NT_STATUS_TIME_DIFFERENCE_AT_DC}, - {"NT_STATUS_SYNCHRONIZATION_REQUIRED", - NT_STATUS_SYNCHRONIZATION_REQUIRED}, - {"NT_STATUS_DLL_NOT_FOUND", NT_STATUS_DLL_NOT_FOUND}, - {"NT_STATUS_OPEN_FAILED", NT_STATUS_OPEN_FAILED}, - {"NT_STATUS_IO_PRIVILEGE_FAILED", NT_STATUS_IO_PRIVILEGE_FAILED}, - {"NT_STATUS_ORDINAL_NOT_FOUND", NT_STATUS_ORDINAL_NOT_FOUND}, - {"NT_STATUS_ENTRYPOINT_NOT_FOUND", NT_STATUS_ENTRYPOINT_NOT_FOUND}, - {"NT_STATUS_CONTROL_C_EXIT", NT_STATUS_CONTROL_C_EXIT}, - {"NT_STATUS_LOCAL_DISCONNECT", NT_STATUS_LOCAL_DISCONNECT}, - {"NT_STATUS_REMOTE_DISCONNECT", NT_STATUS_REMOTE_DISCONNECT}, - {"NT_STATUS_REMOTE_RESOURCES", NT_STATUS_REMOTE_RESOURCES}, - {"NT_STATUS_LINK_FAILED", NT_STATUS_LINK_FAILED}, - {"NT_STATUS_LINK_TIMEOUT", NT_STATUS_LINK_TIMEOUT}, - {"NT_STATUS_INVALID_CONNECTION", NT_STATUS_INVALID_CONNECTION}, - {"NT_STATUS_INVALID_ADDRESS", NT_STATUS_INVALID_ADDRESS}, - {"NT_STATUS_DLL_INIT_FAILED", NT_STATUS_DLL_INIT_FAILED}, - {"NT_STATUS_MISSING_SYSTEMFILE", NT_STATUS_MISSING_SYSTEMFILE}, - {"NT_STATUS_UNHANDLED_EXCEPTION", NT_STATUS_UNHANDLED_EXCEPTION}, - {"NT_STATUS_APP_INIT_FAILURE", NT_STATUS_APP_INIT_FAILURE}, - {"NT_STATUS_PAGEFILE_CREATE_FAILED", - NT_STATUS_PAGEFILE_CREATE_FAILED}, - {"NT_STATUS_NO_PAGEFILE", NT_STATUS_NO_PAGEFILE}, - {"NT_STATUS_INVALID_LEVEL", NT_STATUS_INVALID_LEVEL}, - {"NT_STATUS_WRONG_PASSWORD_CORE", NT_STATUS_WRONG_PASSWORD_CORE}, - {"NT_STATUS_ILLEGAL_FLOAT_CONTEXT", - NT_STATUS_ILLEGAL_FLOAT_CONTEXT}, - {"NT_STATUS_PIPE_BROKEN", NT_STATUS_PIPE_BROKEN}, - {"NT_STATUS_REGISTRY_CORRUPT", NT_STATUS_REGISTRY_CORRUPT}, - {"NT_STATUS_REGISTRY_IO_FAILED", NT_STATUS_REGISTRY_IO_FAILED}, - {"NT_STATUS_NO_EVENT_PAIR", NT_STATUS_NO_EVENT_PAIR}, - {"NT_STATUS_UNRECOGNIZED_VOLUME", NT_STATUS_UNRECOGNIZED_VOLUME}, - {"NT_STATUS_SERIAL_NO_DEVICE_INITED", - NT_STATUS_SERIAL_NO_DEVICE_INITED}, - {"NT_STATUS_NO_SUCH_ALIAS", NT_STATUS_NO_SUCH_ALIAS}, - {"NT_STATUS_MEMBER_NOT_IN_ALIAS", NT_STATUS_MEMBER_NOT_IN_ALIAS}, - {"NT_STATUS_MEMBER_IN_ALIAS", NT_STATUS_MEMBER_IN_ALIAS}, - {"NT_STATUS_ALIAS_EXISTS", NT_STATUS_ALIAS_EXISTS}, - {"NT_STATUS_LOGON_NOT_GRANTED", NT_STATUS_LOGON_NOT_GRANTED}, - {"NT_STATUS_TOO_MANY_SECRETS", NT_STATUS_TOO_MANY_SECRETS}, - {"NT_STATUS_SECRET_TOO_LONG", NT_STATUS_SECRET_TOO_LONG}, - {"NT_STATUS_INTERNAL_DB_ERROR", NT_STATUS_INTERNAL_DB_ERROR}, - {"NT_STATUS_FULLSCREEN_MODE", NT_STATUS_FULLSCREEN_MODE}, - {"NT_STATUS_TOO_MANY_CONTEXT_IDS", NT_STATUS_TOO_MANY_CONTEXT_IDS}, - {"NT_STATUS_LOGON_TYPE_NOT_GRANTED", - NT_STATUS_LOGON_TYPE_NOT_GRANTED}, - {"NT_STATUS_NOT_REGISTRY_FILE", NT_STATUS_NOT_REGISTRY_FILE}, - {"NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED", - NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED}, - {"NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR", - NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR}, - {"NT_STATUS_FT_MISSING_MEMBER", NT_STATUS_FT_MISSING_MEMBER}, - {"NT_STATUS_ILL_FORMED_SERVICE_ENTRY", - NT_STATUS_ILL_FORMED_SERVICE_ENTRY}, - {"NT_STATUS_ILLEGAL_CHARACTER", NT_STATUS_ILLEGAL_CHARACTER}, - {"NT_STATUS_UNMAPPABLE_CHARACTER", NT_STATUS_UNMAPPABLE_CHARACTER}, - {"NT_STATUS_UNDEFINED_CHARACTER", NT_STATUS_UNDEFINED_CHARACTER}, - {"NT_STATUS_FLOPPY_VOLUME", NT_STATUS_FLOPPY_VOLUME}, - {"NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND", - NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND}, - {"NT_STATUS_FLOPPY_WRONG_CYLINDER", - NT_STATUS_FLOPPY_WRONG_CYLINDER}, - {"NT_STATUS_FLOPPY_UNKNOWN_ERROR", NT_STATUS_FLOPPY_UNKNOWN_ERROR}, - {"NT_STATUS_FLOPPY_BAD_REGISTERS", NT_STATUS_FLOPPY_BAD_REGISTERS}, - {"NT_STATUS_DISK_RECALIBRATE_FAILED", - NT_STATUS_DISK_RECALIBRATE_FAILED}, - {"NT_STATUS_DISK_OPERATION_FAILED", - NT_STATUS_DISK_OPERATION_FAILED}, - {"NT_STATUS_DISK_RESET_FAILED", NT_STATUS_DISK_RESET_FAILED}, - {"NT_STATUS_SHARED_IRQ_BUSY", NT_STATUS_SHARED_IRQ_BUSY}, - {"NT_STATUS_FT_ORPHANING", NT_STATUS_FT_ORPHANING}, - {"NT_STATUS_PARTITION_FAILURE", NT_STATUS_PARTITION_FAILURE}, - {"NT_STATUS_INVALID_BLOCK_LENGTH", NT_STATUS_INVALID_BLOCK_LENGTH}, - {"NT_STATUS_DEVICE_NOT_PARTITIONED", - NT_STATUS_DEVICE_NOT_PARTITIONED}, - {"NT_STATUS_UNABLE_TO_LOCK_MEDIA", NT_STATUS_UNABLE_TO_LOCK_MEDIA}, - {"NT_STATUS_UNABLE_TO_UNLOAD_MEDIA", - NT_STATUS_UNABLE_TO_UNLOAD_MEDIA}, - {"NT_STATUS_EOM_OVERFLOW", NT_STATUS_EOM_OVERFLOW}, - {"NT_STATUS_NO_MEDIA", NT_STATUS_NO_MEDIA}, - {"NT_STATUS_NO_SUCH_MEMBER", NT_STATUS_NO_SUCH_MEMBER}, - {"NT_STATUS_INVALID_MEMBER", NT_STATUS_INVALID_MEMBER}, - {"NT_STATUS_KEY_DELETED", NT_STATUS_KEY_DELETED}, - {"NT_STATUS_NO_LOG_SPACE", NT_STATUS_NO_LOG_SPACE}, - {"NT_STATUS_TOO_MANY_SIDS", NT_STATUS_TOO_MANY_SIDS}, - {"NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED", - NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED}, - {"NT_STATUS_KEY_HAS_CHILDREN", NT_STATUS_KEY_HAS_CHILDREN}, - {"NT_STATUS_CHILD_MUST_BE_VOLATILE", - NT_STATUS_CHILD_MUST_BE_VOLATILE}, - {"NT_STATUS_DEVICE_CONFIGURATION_ERROR", - NT_STATUS_DEVICE_CONFIGURATION_ERROR}, - {"NT_STATUS_DRIVER_INTERNAL_ERROR", - NT_STATUS_DRIVER_INTERNAL_ERROR}, - {"NT_STATUS_INVALID_DEVICE_STATE", NT_STATUS_INVALID_DEVICE_STATE}, - {"NT_STATUS_IO_DEVICE_ERROR", NT_STATUS_IO_DEVICE_ERROR}, - {"NT_STATUS_DEVICE_PROTOCOL_ERROR", - NT_STATUS_DEVICE_PROTOCOL_ERROR}, - {"NT_STATUS_BACKUP_CONTROLLER", NT_STATUS_BACKUP_CONTROLLER}, - {"NT_STATUS_LOG_FILE_FULL", NT_STATUS_LOG_FILE_FULL}, - {"NT_STATUS_TOO_LATE", NT_STATUS_TOO_LATE}, - {"NT_STATUS_NO_TRUST_LSA_SECRET", NT_STATUS_NO_TRUST_LSA_SECRET}, - {"NT_STATUS_NO_TRUST_SAM_ACCOUNT", NT_STATUS_NO_TRUST_SAM_ACCOUNT}, - {"NT_STATUS_TRUSTED_DOMAIN_FAILURE", - NT_STATUS_TRUSTED_DOMAIN_FAILURE}, - {"NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE", - NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE}, - {"NT_STATUS_EVENTLOG_FILE_CORRUPT", - NT_STATUS_EVENTLOG_FILE_CORRUPT}, - {"NT_STATUS_EVENTLOG_CANT_START", NT_STATUS_EVENTLOG_CANT_START}, - {"NT_STATUS_TRUST_FAILURE", NT_STATUS_TRUST_FAILURE}, - {"NT_STATUS_MUTANT_LIMIT_EXCEEDED", - NT_STATUS_MUTANT_LIMIT_EXCEEDED}, - {"NT_STATUS_NETLOGON_NOT_STARTED", NT_STATUS_NETLOGON_NOT_STARTED}, - {"NT_STATUS_ACCOUNT_EXPIRED", NT_STATUS_ACCOUNT_EXPIRED}, - {"NT_STATUS_POSSIBLE_DEADLOCK", NT_STATUS_POSSIBLE_DEADLOCK}, - {"NT_STATUS_NETWORK_CREDENTIAL_CONFLICT", - NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, - {"NT_STATUS_REMOTE_SESSION_LIMIT", NT_STATUS_REMOTE_SESSION_LIMIT}, - {"NT_STATUS_EVENTLOG_FILE_CHANGED", - NT_STATUS_EVENTLOG_FILE_CHANGED}, - {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT", - NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT}, - {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT", - NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, - {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT", - NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT}, - {"NT_STATUS_DOMAIN_TRUST_INCONSISTENT", - NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, - {"NT_STATUS_FS_DRIVER_REQUIRED", NT_STATUS_FS_DRIVER_REQUIRED}, - {"NT_STATUS_NO_USER_SESSION_KEY", NT_STATUS_NO_USER_SESSION_KEY}, - {"NT_STATUS_USER_SESSION_DELETED", NT_STATUS_USER_SESSION_DELETED}, - {"NT_STATUS_RESOURCE_LANG_NOT_FOUND", - NT_STATUS_RESOURCE_LANG_NOT_FOUND}, - {"NT_STATUS_INSUFF_SERVER_RESOURCES", - NT_STATUS_INSUFF_SERVER_RESOURCES}, - {"NT_STATUS_INVALID_BUFFER_SIZE", NT_STATUS_INVALID_BUFFER_SIZE}, - {"NT_STATUS_INVALID_ADDRESS_COMPONENT", - NT_STATUS_INVALID_ADDRESS_COMPONENT}, - {"NT_STATUS_INVALID_ADDRESS_WILDCARD", - NT_STATUS_INVALID_ADDRESS_WILDCARD}, - {"NT_STATUS_TOO_MANY_ADDRESSES", NT_STATUS_TOO_MANY_ADDRESSES}, - {"NT_STATUS_ADDRESS_ALREADY_EXISTS", - NT_STATUS_ADDRESS_ALREADY_EXISTS}, - {"NT_STATUS_ADDRESS_CLOSED", NT_STATUS_ADDRESS_CLOSED}, - {"NT_STATUS_CONNECTION_DISCONNECTED", - NT_STATUS_CONNECTION_DISCONNECTED}, - {"NT_STATUS_CONNECTION_RESET", NT_STATUS_CONNECTION_RESET}, - {"NT_STATUS_TOO_MANY_NODES", NT_STATUS_TOO_MANY_NODES}, - {"NT_STATUS_TRANSACTION_ABORTED", NT_STATUS_TRANSACTION_ABORTED}, - {"NT_STATUS_TRANSACTION_TIMED_OUT", - NT_STATUS_TRANSACTION_TIMED_OUT}, - {"NT_STATUS_TRANSACTION_NO_RELEASE", - NT_STATUS_TRANSACTION_NO_RELEASE}, - {"NT_STATUS_TRANSACTION_NO_MATCH", NT_STATUS_TRANSACTION_NO_MATCH}, - {"NT_STATUS_TRANSACTION_RESPONDED", - NT_STATUS_TRANSACTION_RESPONDED}, - {"NT_STATUS_TRANSACTION_INVALID_ID", - NT_STATUS_TRANSACTION_INVALID_ID}, - {"NT_STATUS_TRANSACTION_INVALID_TYPE", - NT_STATUS_TRANSACTION_INVALID_TYPE}, - {"NT_STATUS_NOT_SERVER_SESSION", NT_STATUS_NOT_SERVER_SESSION}, - {"NT_STATUS_NOT_CLIENT_SESSION", NT_STATUS_NOT_CLIENT_SESSION}, - {"NT_STATUS_CANNOT_LOAD_REGISTRY_FILE", - NT_STATUS_CANNOT_LOAD_REGISTRY_FILE}, - {"NT_STATUS_DEBUG_ATTACH_FAILED", NT_STATUS_DEBUG_ATTACH_FAILED}, - {"NT_STATUS_SYSTEM_PROCESS_TERMINATED", - NT_STATUS_SYSTEM_PROCESS_TERMINATED}, - {"NT_STATUS_DATA_NOT_ACCEPTED", NT_STATUS_DATA_NOT_ACCEPTED}, - {"NT_STATUS_NO_BROWSER_SERVERS_FOUND", - NT_STATUS_NO_BROWSER_SERVERS_FOUND}, - {"NT_STATUS_VDM_HARD_ERROR", NT_STATUS_VDM_HARD_ERROR}, - {"NT_STATUS_DRIVER_CANCEL_TIMEOUT", - NT_STATUS_DRIVER_CANCEL_TIMEOUT}, - {"NT_STATUS_REPLY_MESSAGE_MISMATCH", - NT_STATUS_REPLY_MESSAGE_MISMATCH}, - {"NT_STATUS_MAPPED_ALIGNMENT", NT_STATUS_MAPPED_ALIGNMENT}, - {"NT_STATUS_IMAGE_CHECKSUM_MISMATCH", - NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, - {"NT_STATUS_LOST_WRITEBEHIND_DATA", - NT_STATUS_LOST_WRITEBEHIND_DATA}, - {"NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID", - NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, - {"NT_STATUS_PASSWORD_MUST_CHANGE", NT_STATUS_PASSWORD_MUST_CHANGE}, - {"NT_STATUS_NOT_FOUND", NT_STATUS_NOT_FOUND}, - {"NT_STATUS_NOT_TINY_STREAM", NT_STATUS_NOT_TINY_STREAM}, - {"NT_STATUS_RECOVERY_FAILURE", NT_STATUS_RECOVERY_FAILURE}, - {"NT_STATUS_STACK_OVERFLOW_READ", NT_STATUS_STACK_OVERFLOW_READ}, - {"NT_STATUS_FAIL_CHECK", NT_STATUS_FAIL_CHECK}, - {"NT_STATUS_DUPLICATE_OBJECTID", NT_STATUS_DUPLICATE_OBJECTID}, - {"NT_STATUS_OBJECTID_EXISTS", NT_STATUS_OBJECTID_EXISTS}, - {"NT_STATUS_CONVERT_TO_LARGE", NT_STATUS_CONVERT_TO_LARGE}, - {"NT_STATUS_RETRY", NT_STATUS_RETRY}, - {"NT_STATUS_FOUND_OUT_OF_SCOPE", NT_STATUS_FOUND_OUT_OF_SCOPE}, - {"NT_STATUS_ALLOCATE_BUCKET", NT_STATUS_ALLOCATE_BUCKET}, - {"NT_STATUS_PROPSET_NOT_FOUND", NT_STATUS_PROPSET_NOT_FOUND}, - {"NT_STATUS_MARSHALL_OVERFLOW", NT_STATUS_MARSHALL_OVERFLOW}, - {"NT_STATUS_INVALID_VARIANT", NT_STATUS_INVALID_VARIANT}, - {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", - NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND}, - {"NT_STATUS_ACCOUNT_LOCKED_OUT", NT_STATUS_ACCOUNT_LOCKED_OUT}, - {"NT_STATUS_HANDLE_NOT_CLOSABLE", NT_STATUS_HANDLE_NOT_CLOSABLE}, - {"NT_STATUS_CONNECTION_REFUSED", NT_STATUS_CONNECTION_REFUSED}, - {"NT_STATUS_GRACEFUL_DISCONNECT", NT_STATUS_GRACEFUL_DISCONNECT}, - {"NT_STATUS_ADDRESS_ALREADY_ASSOCIATED", - NT_STATUS_ADDRESS_ALREADY_ASSOCIATED}, - {"NT_STATUS_ADDRESS_NOT_ASSOCIATED", - NT_STATUS_ADDRESS_NOT_ASSOCIATED}, - {"NT_STATUS_CONNECTION_INVALID", NT_STATUS_CONNECTION_INVALID}, - {"NT_STATUS_CONNECTION_ACTIVE", NT_STATUS_CONNECTION_ACTIVE}, - {"NT_STATUS_NETWORK_UNREACHABLE", NT_STATUS_NETWORK_UNREACHABLE}, - {"NT_STATUS_HOST_UNREACHABLE", NT_STATUS_HOST_UNREACHABLE}, - {"NT_STATUS_PROTOCOL_UNREACHABLE", NT_STATUS_PROTOCOL_UNREACHABLE}, - {"NT_STATUS_PORT_UNREACHABLE", NT_STATUS_PORT_UNREACHABLE}, - {"NT_STATUS_REQUEST_ABORTED", NT_STATUS_REQUEST_ABORTED}, - {"NT_STATUS_CONNECTION_ABORTED", NT_STATUS_CONNECTION_ABORTED}, - {"NT_STATUS_BAD_COMPRESSION_BUFFER", - NT_STATUS_BAD_COMPRESSION_BUFFER}, - {"NT_STATUS_USER_MAPPED_FILE", NT_STATUS_USER_MAPPED_FILE}, - {"NT_STATUS_AUDIT_FAILED", NT_STATUS_AUDIT_FAILED}, - {"NT_STATUS_TIMER_RESOLUTION_NOT_SET", - NT_STATUS_TIMER_RESOLUTION_NOT_SET}, - {"NT_STATUS_CONNECTION_COUNT_LIMIT", - NT_STATUS_CONNECTION_COUNT_LIMIT}, - {"NT_STATUS_LOGIN_TIME_RESTRICTION", - NT_STATUS_LOGIN_TIME_RESTRICTION}, - {"NT_STATUS_LOGIN_WKSTA_RESTRICTION", - NT_STATUS_LOGIN_WKSTA_RESTRICTION}, - {"NT_STATUS_IMAGE_MP_UP_MISMATCH", NT_STATUS_IMAGE_MP_UP_MISMATCH}, - {"NT_STATUS_INSUFFICIENT_LOGON_INFO", - NT_STATUS_INSUFFICIENT_LOGON_INFO}, - {"NT_STATUS_BAD_DLL_ENTRYPOINT", NT_STATUS_BAD_DLL_ENTRYPOINT}, - {"NT_STATUS_BAD_SERVICE_ENTRYPOINT", - NT_STATUS_BAD_SERVICE_ENTRYPOINT}, - {"NT_STATUS_LPC_REPLY_LOST", NT_STATUS_LPC_REPLY_LOST}, - {"NT_STATUS_IP_ADDRESS_CONFLICT1", NT_STATUS_IP_ADDRESS_CONFLICT1}, - {"NT_STATUS_IP_ADDRESS_CONFLICT2", NT_STATUS_IP_ADDRESS_CONFLICT2}, - {"NT_STATUS_REGISTRY_QUOTA_LIMIT", NT_STATUS_REGISTRY_QUOTA_LIMIT}, - {"NT_STATUS_PATH_NOT_COVERED", NT_STATUS_PATH_NOT_COVERED}, - {"NT_STATUS_NO_CALLBACK_ACTIVE", NT_STATUS_NO_CALLBACK_ACTIVE}, - {"NT_STATUS_LICENSE_QUOTA_EXCEEDED", - NT_STATUS_LICENSE_QUOTA_EXCEEDED}, - {"NT_STATUS_PWD_TOO_SHORT", NT_STATUS_PWD_TOO_SHORT}, - {"NT_STATUS_PWD_TOO_RECENT", NT_STATUS_PWD_TOO_RECENT}, - {"NT_STATUS_PWD_HISTORY_CONFLICT", NT_STATUS_PWD_HISTORY_CONFLICT}, - {"NT_STATUS_PLUGPLAY_NO_DEVICE", NT_STATUS_PLUGPLAY_NO_DEVICE}, - {"NT_STATUS_UNSUPPORTED_COMPRESSION", - NT_STATUS_UNSUPPORTED_COMPRESSION}, - {"NT_STATUS_INVALID_HW_PROFILE", NT_STATUS_INVALID_HW_PROFILE}, - {"NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH", - NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH}, - {"NT_STATUS_DRIVER_ORDINAL_NOT_FOUND", - NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, - {"NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND", - NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, - {"NT_STATUS_RESOURCE_NOT_OWNED", NT_STATUS_RESOURCE_NOT_OWNED}, - {"NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS}, - {"NT_STATUS_QUOTA_LIST_INCONSISTENT", - NT_STATUS_QUOTA_LIST_INCONSISTENT}, - {"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE}, - {"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES}, - {"STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES}, - {"STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED}, - {NULL, 0} -}; diff --git a/ANDROID_3.4.5/fs/cifs/nterr.h b/ANDROID_3.4.5/fs/cifs/nterr.h deleted file mode 100644 index 25726736..00000000 --- a/ANDROID_3.4.5/fs/cifs/nterr.h +++ /dev/null @@ -1,561 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NT error code constants - Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) John H Terpstra 1996-2000 - Copyright (C) Luke Kenneth Casson Leighton 1996-2000 - Copyright (C) Paul Ashton 1998-2000 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - - - -#ifndef _NTERR_H -#define _NTERR_H - -struct nt_err_code_struct { - char *nt_errstr; - __u32 nt_errcode; -}; - -extern const struct nt_err_code_struct nt_errs[]; - -/* Win32 Status codes. */ -#define STATUS_MORE_ENTRIES 0x0105 -#define ERROR_INVALID_PARAMETER 0x0057 -#define ERROR_INSUFFICIENT_BUFFER 0x007a -#define STATUS_1804 0x070c -#define STATUS_NOTIFY_ENUM_DIR 0x010c - -/* Win32 Error codes extracted using a loop in smbclient then printing a - netmon sniff to a file. */ - -#define NT_STATUS_OK 0x0000 -#define STATUS_SOME_UNMAPPED 0x0107 -#define STATUS_BUFFER_OVERFLOW 0x80000005 -#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a -#define NT_STATUS_MEDIA_CHANGED 0x8000001c -#define NT_STATUS_END_OF_MEDIA 0x8000001e -#define NT_STATUS_MEDIA_CHECK 0x80000020 -#define NT_STATUS_NO_DATA_DETECTED 0x8000001c -#define NT_STATUS_STOPPED_ON_SYMLINK 0x8000002d -#define NT_STATUS_DEVICE_REQUIRES_CLEANING 0x80000288 -#define NT_STATUS_DEVICE_DOOR_OPEN 0x80000288 -#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001 -#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002 -#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003 -#define NT_STATUS_INFO_LENGTH_MISMATCH 0xC0000000 | 0x0004 -#define NT_STATUS_ACCESS_VIOLATION 0xC0000000 | 0x0005 -#define NT_STATUS_IN_PAGE_ERROR 0xC0000000 | 0x0006 -#define NT_STATUS_PAGEFILE_QUOTA 0xC0000000 | 0x0007 -#define NT_STATUS_INVALID_HANDLE 0xC0000000 | 0x0008 -#define NT_STATUS_BAD_INITIAL_STACK 0xC0000000 | 0x0009 -#define NT_STATUS_BAD_INITIAL_PC 0xC0000000 | 0x000a -#define NT_STATUS_INVALID_CID 0xC0000000 | 0x000b -#define NT_STATUS_TIMER_NOT_CANCELED 0xC0000000 | 0x000c -#define NT_STATUS_INVALID_PARAMETER 0xC0000000 | 0x000d -#define NT_STATUS_NO_SUCH_DEVICE 0xC0000000 | 0x000e -#define NT_STATUS_NO_SUCH_FILE 0xC0000000 | 0x000f -#define NT_STATUS_INVALID_DEVICE_REQUEST 0xC0000000 | 0x0010 -#define NT_STATUS_END_OF_FILE 0xC0000000 | 0x0011 -#define NT_STATUS_WRONG_VOLUME 0xC0000000 | 0x0012 -#define NT_STATUS_NO_MEDIA_IN_DEVICE 0xC0000000 | 0x0013 -#define NT_STATUS_UNRECOGNIZED_MEDIA 0xC0000000 | 0x0014 -#define NT_STATUS_NONEXISTENT_SECTOR 0xC0000000 | 0x0015 -#define NT_STATUS_MORE_PROCESSING_REQUIRED 0xC0000000 | 0x0016 -#define NT_STATUS_NO_MEMORY 0xC0000000 | 0x0017 -#define NT_STATUS_CONFLICTING_ADDRESSES 0xC0000000 | 0x0018 -#define NT_STATUS_NOT_MAPPED_VIEW 0xC0000000 | 0x0019 -#define NT_STATUS_UNABLE_TO_FREE_VM 0x80000000 | 0x001a -#define NT_STATUS_UNABLE_TO_DELETE_SECTION 0xC0000000 | 0x001b -#define NT_STATUS_INVALID_SYSTEM_SERVICE 0xC0000000 | 0x001c -#define NT_STATUS_ILLEGAL_INSTRUCTION 0xC0000000 | 0x001d -#define NT_STATUS_INVALID_LOCK_SEQUENCE 0xC0000000 | 0x001e -#define NT_STATUS_INVALID_VIEW_SIZE 0xC0000000 | 0x001f -#define NT_STATUS_INVALID_FILE_FOR_SECTION 0xC0000000 | 0x0020 -#define NT_STATUS_ALREADY_COMMITTED 0xC0000000 | 0x0021 -#define NT_STATUS_ACCESS_DENIED 0xC0000000 | 0x0022 -#define NT_STATUS_BUFFER_TOO_SMALL 0xC0000000 | 0x0023 -#define NT_STATUS_OBJECT_TYPE_MISMATCH 0xC0000000 | 0x0024 -#define NT_STATUS_NONCONTINUABLE_EXCEPTION 0xC0000000 | 0x0025 -#define NT_STATUS_INVALID_DISPOSITION 0xC0000000 | 0x0026 -#define NT_STATUS_UNWIND 0xC0000000 | 0x0027 -#define NT_STATUS_BAD_STACK 0xC0000000 | 0x0028 -#define NT_STATUS_INVALID_UNWIND_TARGET 0xC0000000 | 0x0029 -#define NT_STATUS_NOT_LOCKED 0xC0000000 | 0x002a -#define NT_STATUS_PARITY_ERROR 0xC0000000 | 0x002b -#define NT_STATUS_UNABLE_TO_DECOMMIT_VM 0xC0000000 | 0x002c -#define NT_STATUS_NOT_COMMITTED 0xC0000000 | 0x002d -#define NT_STATUS_INVALID_PORT_ATTRIBUTES 0xC0000000 | 0x002e -#define NT_STATUS_PORT_MESSAGE_TOO_LONG 0xC0000000 | 0x002f -#define NT_STATUS_INVALID_PARAMETER_MIX 0xC0000000 | 0x0030 -#define NT_STATUS_INVALID_QUOTA_LOWER 0xC0000000 | 0x0031 -#define NT_STATUS_DISK_CORRUPT_ERROR 0xC0000000 | 0x0032 -#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000000 | 0x0033 -#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000000 | 0x0034 -#define NT_STATUS_OBJECT_NAME_COLLISION 0xC0000000 | 0x0035 -#define NT_STATUS_HANDLE_NOT_WAITABLE 0xC0000000 | 0x0036 -#define NT_STATUS_PORT_DISCONNECTED 0xC0000000 | 0x0037 -#define NT_STATUS_DEVICE_ALREADY_ATTACHED 0xC0000000 | 0x0038 -#define NT_STATUS_OBJECT_PATH_INVALID 0xC0000000 | 0x0039 -#define NT_STATUS_OBJECT_PATH_NOT_FOUND 0xC0000000 | 0x003a -#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD 0xC0000000 | 0x003b -#define NT_STATUS_DATA_OVERRUN 0xC0000000 | 0x003c -#define NT_STATUS_DATA_LATE_ERROR 0xC0000000 | 0x003d -#define NT_STATUS_DATA_ERROR 0xC0000000 | 0x003e -#define NT_STATUS_CRC_ERROR 0xC0000000 | 0x003f -#define NT_STATUS_SECTION_TOO_BIG 0xC0000000 | 0x0040 -#define NT_STATUS_PORT_CONNECTION_REFUSED 0xC0000000 | 0x0041 -#define NT_STATUS_INVALID_PORT_HANDLE 0xC0000000 | 0x0042 -#define NT_STATUS_SHARING_VIOLATION 0xC0000000 | 0x0043 -#define NT_STATUS_QUOTA_EXCEEDED 0xC0000000 | 0x0044 -#define NT_STATUS_INVALID_PAGE_PROTECTION 0xC0000000 | 0x0045 -#define NT_STATUS_MUTANT_NOT_OWNED 0xC0000000 | 0x0046 -#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000000 | 0x0047 -#define NT_STATUS_PORT_ALREADY_SET 0xC0000000 | 0x0048 -#define NT_STATUS_SECTION_NOT_IMAGE 0xC0000000 | 0x0049 -#define NT_STATUS_SUSPEND_COUNT_EXCEEDED 0xC0000000 | 0x004a -#define NT_STATUS_THREAD_IS_TERMINATING 0xC0000000 | 0x004b -#define NT_STATUS_BAD_WORKING_SET_LIMIT 0xC0000000 | 0x004c -#define NT_STATUS_INCOMPATIBLE_FILE_MAP 0xC0000000 | 0x004d -#define NT_STATUS_SECTION_PROTECTION 0xC0000000 | 0x004e -#define NT_STATUS_EAS_NOT_SUPPORTED 0xC0000000 | 0x004f -#define NT_STATUS_EA_TOO_LARGE 0xC0000000 | 0x0050 -#define NT_STATUS_NONEXISTENT_EA_ENTRY 0xC0000000 | 0x0051 -#define NT_STATUS_NO_EAS_ON_FILE 0xC0000000 | 0x0052 -#define NT_STATUS_EA_CORRUPT_ERROR 0xC0000000 | 0x0053 -#define NT_STATUS_FILE_LOCK_CONFLICT 0xC0000000 | 0x0054 -#define NT_STATUS_LOCK_NOT_GRANTED 0xC0000000 | 0x0055 -#define NT_STATUS_DELETE_PENDING 0xC0000000 | 0x0056 -#define NT_STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000000 | 0x0057 -#define NT_STATUS_UNKNOWN_REVISION 0xC0000000 | 0x0058 -#define NT_STATUS_REVISION_MISMATCH 0xC0000000 | 0x0059 -#define NT_STATUS_INVALID_OWNER 0xC0000000 | 0x005a -#define NT_STATUS_INVALID_PRIMARY_GROUP 0xC0000000 | 0x005b -#define NT_STATUS_NO_IMPERSONATION_TOKEN 0xC0000000 | 0x005c -#define NT_STATUS_CANT_DISABLE_MANDATORY 0xC0000000 | 0x005d -#define NT_STATUS_NO_LOGON_SERVERS 0xC0000000 | 0x005e -#define NT_STATUS_NO_SUCH_LOGON_SESSION 0xC0000000 | 0x005f -#define NT_STATUS_NO_SUCH_PRIVILEGE 0xC0000000 | 0x0060 -#define NT_STATUS_PRIVILEGE_NOT_HELD 0xC0000000 | 0x0061 -#define NT_STATUS_INVALID_ACCOUNT_NAME 0xC0000000 | 0x0062 -#define NT_STATUS_USER_EXISTS 0xC0000000 | 0x0063 -#define NT_STATUS_NO_SUCH_USER 0xC0000000 | 0x0064 -#define NT_STATUS_GROUP_EXISTS 0xC0000000 | 0x0065 -#define NT_STATUS_NO_SUCH_GROUP 0xC0000000 | 0x0066 -#define NT_STATUS_MEMBER_IN_GROUP 0xC0000000 | 0x0067 -#define NT_STATUS_MEMBER_NOT_IN_GROUP 0xC0000000 | 0x0068 -#define NT_STATUS_LAST_ADMIN 0xC0000000 | 0x0069 -#define NT_STATUS_WRONG_PASSWORD 0xC0000000 | 0x006a -#define NT_STATUS_ILL_FORMED_PASSWORD 0xC0000000 | 0x006b -#define NT_STATUS_PASSWORD_RESTRICTION 0xC0000000 | 0x006c -#define NT_STATUS_LOGON_FAILURE 0xC0000000 | 0x006d -#define NT_STATUS_ACCOUNT_RESTRICTION 0xC0000000 | 0x006e -#define NT_STATUS_INVALID_LOGON_HOURS 0xC0000000 | 0x006f -#define NT_STATUS_INVALID_WORKSTATION 0xC0000000 | 0x0070 -#define NT_STATUS_PASSWORD_EXPIRED 0xC0000000 | 0x0071 -#define NT_STATUS_ACCOUNT_DISABLED 0xC0000000 | 0x0072 -#define NT_STATUS_NONE_MAPPED 0xC0000000 | 0x0073 -#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000000 | 0x0074 -#define NT_STATUS_LUIDS_EXHAUSTED 0xC0000000 | 0x0075 -#define NT_STATUS_INVALID_SUB_AUTHORITY 0xC0000000 | 0x0076 -#define NT_STATUS_INVALID_ACL 0xC0000000 | 0x0077 -#define NT_STATUS_INVALID_SID 0xC0000000 | 0x0078 -#define NT_STATUS_INVALID_SECURITY_DESCR 0xC0000000 | 0x0079 -#define NT_STATUS_PROCEDURE_NOT_FOUND 0xC0000000 | 0x007a -#define NT_STATUS_INVALID_IMAGE_FORMAT 0xC0000000 | 0x007b -#define NT_STATUS_NO_TOKEN 0xC0000000 | 0x007c -#define NT_STATUS_BAD_INHERITANCE_ACL 0xC0000000 | 0x007d -#define NT_STATUS_RANGE_NOT_LOCKED 0xC0000000 | 0x007e -#define NT_STATUS_DISK_FULL 0xC0000000 | 0x007f -#define NT_STATUS_SERVER_DISABLED 0xC0000000 | 0x0080 -#define NT_STATUS_SERVER_NOT_DISABLED 0xC0000000 | 0x0081 -#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000000 | 0x0082 -#define NT_STATUS_GUIDS_EXHAUSTED 0xC0000000 | 0x0083 -#define NT_STATUS_INVALID_ID_AUTHORITY 0xC0000000 | 0x0084 -#define NT_STATUS_AGENTS_EXHAUSTED 0xC0000000 | 0x0085 -#define NT_STATUS_INVALID_VOLUME_LABEL 0xC0000000 | 0x0086 -#define NT_STATUS_SECTION_NOT_EXTENDED 0xC0000000 | 0x0087 -#define NT_STATUS_NOT_MAPPED_DATA 0xC0000000 | 0x0088 -#define NT_STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000000 | 0x0089 -#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND 0xC0000000 | 0x008a -#define NT_STATUS_RESOURCE_NAME_NOT_FOUND 0xC0000000 | 0x008b -#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED 0xC0000000 | 0x008c -#define NT_STATUS_FLOAT_DENORMAL_OPERAND 0xC0000000 | 0x008d -#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO 0xC0000000 | 0x008e -#define NT_STATUS_FLOAT_INEXACT_RESULT 0xC0000000 | 0x008f -#define NT_STATUS_FLOAT_INVALID_OPERATION 0xC0000000 | 0x0090 -#define NT_STATUS_FLOAT_OVERFLOW 0xC0000000 | 0x0091 -#define NT_STATUS_FLOAT_STACK_CHECK 0xC0000000 | 0x0092 -#define NT_STATUS_FLOAT_UNDERFLOW 0xC0000000 | 0x0093 -#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000000 | 0x0094 -#define NT_STATUS_INTEGER_OVERFLOW 0xC0000000 | 0x0095 -#define NT_STATUS_PRIVILEGED_INSTRUCTION 0xC0000000 | 0x0096 -#define NT_STATUS_TOO_MANY_PAGING_FILES 0xC0000000 | 0x0097 -#define NT_STATUS_FILE_INVALID 0xC0000000 | 0x0098 -#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000000 | 0x0099 -#define NT_STATUS_INSUFFICIENT_RESOURCES 0xC0000000 | 0x009a -#define NT_STATUS_DFS_EXIT_PATH_FOUND 0xC0000000 | 0x009b -#define NT_STATUS_DEVICE_DATA_ERROR 0xC0000000 | 0x009c -#define NT_STATUS_DEVICE_NOT_CONNECTED 0xC0000000 | 0x009d -#define NT_STATUS_DEVICE_POWER_FAILURE 0xC0000000 | 0x009e -#define NT_STATUS_FREE_VM_NOT_AT_BASE 0xC0000000 | 0x009f -#define NT_STATUS_MEMORY_NOT_ALLOCATED 0xC0000000 | 0x00a0 -#define NT_STATUS_WORKING_SET_QUOTA 0xC0000000 | 0x00a1 -#define NT_STATUS_MEDIA_WRITE_PROTECTED 0xC0000000 | 0x00a2 -#define NT_STATUS_DEVICE_NOT_READY 0xC0000000 | 0x00a3 -#define NT_STATUS_INVALID_GROUP_ATTRIBUTES 0xC0000000 | 0x00a4 -#define NT_STATUS_BAD_IMPERSONATION_LEVEL 0xC0000000 | 0x00a5 -#define NT_STATUS_CANT_OPEN_ANONYMOUS 0xC0000000 | 0x00a6 -#define NT_STATUS_BAD_VALIDATION_CLASS 0xC0000000 | 0x00a7 -#define NT_STATUS_BAD_TOKEN_TYPE 0xC0000000 | 0x00a8 -#define NT_STATUS_BAD_MASTER_BOOT_RECORD 0xC0000000 | 0x00a9 -#define NT_STATUS_INSTRUCTION_MISALIGNMENT 0xC0000000 | 0x00aa -#define NT_STATUS_INSTANCE_NOT_AVAILABLE 0xC0000000 | 0x00ab -#define NT_STATUS_PIPE_NOT_AVAILABLE 0xC0000000 | 0x00ac -#define NT_STATUS_INVALID_PIPE_STATE 0xC0000000 | 0x00ad -#define NT_STATUS_PIPE_BUSY 0xC0000000 | 0x00ae -#define NT_STATUS_ILLEGAL_FUNCTION 0xC0000000 | 0x00af -#define NT_STATUS_PIPE_DISCONNECTED 0xC0000000 | 0x00b0 -#define NT_STATUS_PIPE_CLOSING 0xC0000000 | 0x00b1 -#define NT_STATUS_PIPE_CONNECTED 0xC0000000 | 0x00b2 -#define NT_STATUS_PIPE_LISTENING 0xC0000000 | 0x00b3 -#define NT_STATUS_INVALID_READ_MODE 0xC0000000 | 0x00b4 -#define NT_STATUS_IO_TIMEOUT 0xC0000000 | 0x00b5 -#define NT_STATUS_FILE_FORCED_CLOSED 0xC0000000 | 0x00b6 -#define NT_STATUS_PROFILING_NOT_STARTED 0xC0000000 | 0x00b7 -#define NT_STATUS_PROFILING_NOT_STOPPED 0xC0000000 | 0x00b8 -#define NT_STATUS_COULD_NOT_INTERPRET 0xC0000000 | 0x00b9 -#define NT_STATUS_FILE_IS_A_DIRECTORY 0xC0000000 | 0x00ba -#define NT_STATUS_NOT_SUPPORTED 0xC0000000 | 0x00bb -#define NT_STATUS_REMOTE_NOT_LISTENING 0xC0000000 | 0x00bc -#define NT_STATUS_DUPLICATE_NAME 0xC0000000 | 0x00bd -#define NT_STATUS_BAD_NETWORK_PATH 0xC0000000 | 0x00be -#define NT_STATUS_NETWORK_BUSY 0xC0000000 | 0x00bf -#define NT_STATUS_DEVICE_DOES_NOT_EXIST 0xC0000000 | 0x00c0 -#define NT_STATUS_TOO_MANY_COMMANDS 0xC0000000 | 0x00c1 -#define NT_STATUS_ADAPTER_HARDWARE_ERROR 0xC0000000 | 0x00c2 -#define NT_STATUS_INVALID_NETWORK_RESPONSE 0xC0000000 | 0x00c3 -#define NT_STATUS_UNEXPECTED_NETWORK_ERROR 0xC0000000 | 0x00c4 -#define NT_STATUS_BAD_REMOTE_ADAPTER 0xC0000000 | 0x00c5 -#define NT_STATUS_PRINT_QUEUE_FULL 0xC0000000 | 0x00c6 -#define NT_STATUS_NO_SPOOL_SPACE 0xC0000000 | 0x00c7 -#define NT_STATUS_PRINT_CANCELLED 0xC0000000 | 0x00c8 -#define NT_STATUS_NETWORK_NAME_DELETED 0xC0000000 | 0x00c9 -#define NT_STATUS_NETWORK_ACCESS_DENIED 0xC0000000 | 0x00ca -#define NT_STATUS_BAD_DEVICE_TYPE 0xC0000000 | 0x00cb -#define NT_STATUS_BAD_NETWORK_NAME 0xC0000000 | 0x00cc -#define NT_STATUS_TOO_MANY_NAMES 0xC0000000 | 0x00cd -#define NT_STATUS_TOO_MANY_SESSIONS 0xC0000000 | 0x00ce -#define NT_STATUS_SHARING_PAUSED 0xC0000000 | 0x00cf -#define NT_STATUS_REQUEST_NOT_ACCEPTED 0xC0000000 | 0x00d0 -#define NT_STATUS_REDIRECTOR_PAUSED 0xC0000000 | 0x00d1 -#define NT_STATUS_NET_WRITE_FAULT 0xC0000000 | 0x00d2 -#define NT_STATUS_PROFILING_AT_LIMIT 0xC0000000 | 0x00d3 -#define NT_STATUS_NOT_SAME_DEVICE 0xC0000000 | 0x00d4 -#define NT_STATUS_FILE_RENAMED 0xC0000000 | 0x00d5 -#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC0000000 | 0x00d6 -#define NT_STATUS_NO_SECURITY_ON_OBJECT 0xC0000000 | 0x00d7 -#define NT_STATUS_CANT_WAIT 0xC0000000 | 0x00d8 -#define NT_STATUS_PIPE_EMPTY 0xC0000000 | 0x00d9 -#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO 0xC0000000 | 0x00da -#define NT_STATUS_CANT_TERMINATE_SELF 0xC0000000 | 0x00db -#define NT_STATUS_INVALID_SERVER_STATE 0xC0000000 | 0x00dc -#define NT_STATUS_INVALID_DOMAIN_STATE 0xC0000000 | 0x00dd -#define NT_STATUS_INVALID_DOMAIN_ROLE 0xC0000000 | 0x00de -#define NT_STATUS_NO_SUCH_DOMAIN 0xC0000000 | 0x00df -#define NT_STATUS_DOMAIN_EXISTS 0xC0000000 | 0x00e0 -#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED 0xC0000000 | 0x00e1 -#define NT_STATUS_OPLOCK_NOT_GRANTED 0xC0000000 | 0x00e2 -#define NT_STATUS_INVALID_OPLOCK_PROTOCOL 0xC0000000 | 0x00e3 -#define NT_STATUS_INTERNAL_DB_CORRUPTION 0xC0000000 | 0x00e4 -#define NT_STATUS_INTERNAL_ERROR 0xC0000000 | 0x00e5 -#define NT_STATUS_GENERIC_NOT_MAPPED 0xC0000000 | 0x00e6 -#define NT_STATUS_BAD_DESCRIPTOR_FORMAT 0xC0000000 | 0x00e7 -#define NT_STATUS_INVALID_USER_BUFFER 0xC0000000 | 0x00e8 -#define NT_STATUS_UNEXPECTED_IO_ERROR 0xC0000000 | 0x00e9 -#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR 0xC0000000 | 0x00ea -#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR 0xC0000000 | 0x00eb -#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC0000000 | 0x00ec -#define NT_STATUS_NOT_LOGON_PROCESS 0xC0000000 | 0x00ed -#define NT_STATUS_LOGON_SESSION_EXISTS 0xC0000000 | 0x00ee -#define NT_STATUS_INVALID_PARAMETER_1 0xC0000000 | 0x00ef -#define NT_STATUS_INVALID_PARAMETER_2 0xC0000000 | 0x00f0 -#define NT_STATUS_INVALID_PARAMETER_3 0xC0000000 | 0x00f1 -#define NT_STATUS_INVALID_PARAMETER_4 0xC0000000 | 0x00f2 -#define NT_STATUS_INVALID_PARAMETER_5 0xC0000000 | 0x00f3 -#define NT_STATUS_INVALID_PARAMETER_6 0xC0000000 | 0x00f4 -#define NT_STATUS_INVALID_PARAMETER_7 0xC0000000 | 0x00f5 -#define NT_STATUS_INVALID_PARAMETER_8 0xC0000000 | 0x00f6 -#define NT_STATUS_INVALID_PARAMETER_9 0xC0000000 | 0x00f7 -#define NT_STATUS_INVALID_PARAMETER_10 0xC0000000 | 0x00f8 -#define NT_STATUS_INVALID_PARAMETER_11 0xC0000000 | 0x00f9 -#define NT_STATUS_INVALID_PARAMETER_12 0xC0000000 | 0x00fa -#define NT_STATUS_REDIRECTOR_NOT_STARTED 0xC0000000 | 0x00fb -#define NT_STATUS_REDIRECTOR_STARTED 0xC0000000 | 0x00fc -#define NT_STATUS_STACK_OVERFLOW 0xC0000000 | 0x00fd -#define NT_STATUS_NO_SUCH_PACKAGE 0xC0000000 | 0x00fe -#define NT_STATUS_BAD_FUNCTION_TABLE 0xC0000000 | 0x00ff -#define NT_STATUS_DIRECTORY_NOT_EMPTY 0xC0000000 | 0x0101 -#define NT_STATUS_FILE_CORRUPT_ERROR 0xC0000000 | 0x0102 -#define NT_STATUS_NOT_A_DIRECTORY 0xC0000000 | 0x0103 -#define NT_STATUS_BAD_LOGON_SESSION_STATE 0xC0000000 | 0x0104 -#define NT_STATUS_LOGON_SESSION_COLLISION 0xC0000000 | 0x0105 -#define NT_STATUS_NAME_TOO_LONG 0xC0000000 | 0x0106 -#define NT_STATUS_FILES_OPEN 0xC0000000 | 0x0107 -#define NT_STATUS_CONNECTION_IN_USE 0xC0000000 | 0x0108 -#define NT_STATUS_MESSAGE_NOT_FOUND 0xC0000000 | 0x0109 -#define NT_STATUS_PROCESS_IS_TERMINATING 0xC0000000 | 0x010a -#define NT_STATUS_INVALID_LOGON_TYPE 0xC0000000 | 0x010b -#define NT_STATUS_NO_GUID_TRANSLATION 0xC0000000 | 0x010c -#define NT_STATUS_CANNOT_IMPERSONATE 0xC0000000 | 0x010d -#define NT_STATUS_IMAGE_ALREADY_LOADED 0xC0000000 | 0x010e -#define NT_STATUS_ABIOS_NOT_PRESENT 0xC0000000 | 0x010f -#define NT_STATUS_ABIOS_LID_NOT_EXIST 0xC0000000 | 0x0110 -#define NT_STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000000 | 0x0111 -#define NT_STATUS_ABIOS_NOT_LID_OWNER 0xC0000000 | 0x0112 -#define NT_STATUS_ABIOS_INVALID_COMMAND 0xC0000000 | 0x0113 -#define NT_STATUS_ABIOS_INVALID_LID 0xC0000000 | 0x0114 -#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000000 | 0x0115 -#define NT_STATUS_ABIOS_INVALID_SELECTOR 0xC0000000 | 0x0116 -#define NT_STATUS_NO_LDT 0xC0000000 | 0x0117 -#define NT_STATUS_INVALID_LDT_SIZE 0xC0000000 | 0x0118 -#define NT_STATUS_INVALID_LDT_OFFSET 0xC0000000 | 0x0119 -#define NT_STATUS_INVALID_LDT_DESCRIPTOR 0xC0000000 | 0x011a -#define NT_STATUS_INVALID_IMAGE_NE_FORMAT 0xC0000000 | 0x011b -#define NT_STATUS_RXACT_INVALID_STATE 0xC0000000 | 0x011c -#define NT_STATUS_RXACT_COMMIT_FAILURE 0xC0000000 | 0x011d -#define NT_STATUS_MAPPED_FILE_SIZE_ZERO 0xC0000000 | 0x011e -#define NT_STATUS_TOO_MANY_OPENED_FILES 0xC0000000 | 0x011f -#define NT_STATUS_CANCELLED 0xC0000000 | 0x0120 -#define NT_STATUS_CANNOT_DELETE 0xC0000000 | 0x0121 -#define NT_STATUS_INVALID_COMPUTER_NAME 0xC0000000 | 0x0122 -#define NT_STATUS_FILE_DELETED 0xC0000000 | 0x0123 -#define NT_STATUS_SPECIAL_ACCOUNT 0xC0000000 | 0x0124 -#define NT_STATUS_SPECIAL_GROUP 0xC0000000 | 0x0125 -#define NT_STATUS_SPECIAL_USER 0xC0000000 | 0x0126 -#define NT_STATUS_MEMBERS_PRIMARY_GROUP 0xC0000000 | 0x0127 -#define NT_STATUS_FILE_CLOSED 0xC0000000 | 0x0128 -#define NT_STATUS_TOO_MANY_THREADS 0xC0000000 | 0x0129 -#define NT_STATUS_THREAD_NOT_IN_PROCESS 0xC0000000 | 0x012a -#define NT_STATUS_TOKEN_ALREADY_IN_USE 0xC0000000 | 0x012b -#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC0000000 | 0x012c -#define NT_STATUS_COMMITMENT_LIMIT 0xC0000000 | 0x012d -#define NT_STATUS_INVALID_IMAGE_LE_FORMAT 0xC0000000 | 0x012e -#define NT_STATUS_INVALID_IMAGE_NOT_MZ 0xC0000000 | 0x012f -#define NT_STATUS_INVALID_IMAGE_PROTECT 0xC0000000 | 0x0130 -#define NT_STATUS_INVALID_IMAGE_WIN_16 0xC0000000 | 0x0131 -#define NT_STATUS_LOGON_SERVER_CONFLICT 0xC0000000 | 0x0132 -#define NT_STATUS_TIME_DIFFERENCE_AT_DC 0xC0000000 | 0x0133 -#define NT_STATUS_SYNCHRONIZATION_REQUIRED 0xC0000000 | 0x0134 -#define NT_STATUS_DLL_NOT_FOUND 0xC0000000 | 0x0135 -#define NT_STATUS_OPEN_FAILED 0xC0000000 | 0x0136 -#define NT_STATUS_IO_PRIVILEGE_FAILED 0xC0000000 | 0x0137 -#define NT_STATUS_ORDINAL_NOT_FOUND 0xC0000000 | 0x0138 -#define NT_STATUS_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0139 -#define NT_STATUS_CONTROL_C_EXIT 0xC0000000 | 0x013a -#define NT_STATUS_LOCAL_DISCONNECT 0xC0000000 | 0x013b -#define NT_STATUS_REMOTE_DISCONNECT 0xC0000000 | 0x013c -#define NT_STATUS_REMOTE_RESOURCES 0xC0000000 | 0x013d -#define NT_STATUS_LINK_FAILED 0xC0000000 | 0x013e -#define NT_STATUS_LINK_TIMEOUT 0xC0000000 | 0x013f -#define NT_STATUS_INVALID_CONNECTION 0xC0000000 | 0x0140 -#define NT_STATUS_INVALID_ADDRESS 0xC0000000 | 0x0141 -#define NT_STATUS_DLL_INIT_FAILED 0xC0000000 | 0x0142 -#define NT_STATUS_MISSING_SYSTEMFILE 0xC0000000 | 0x0143 -#define NT_STATUS_UNHANDLED_EXCEPTION 0xC0000000 | 0x0144 -#define NT_STATUS_APP_INIT_FAILURE 0xC0000000 | 0x0145 -#define NT_STATUS_PAGEFILE_CREATE_FAILED 0xC0000000 | 0x0146 -#define NT_STATUS_NO_PAGEFILE 0xC0000000 | 0x0147 -#define NT_STATUS_INVALID_LEVEL 0xC0000000 | 0x0148 -#define NT_STATUS_WRONG_PASSWORD_CORE 0xC0000000 | 0x0149 -#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT 0xC0000000 | 0x014a -#define NT_STATUS_PIPE_BROKEN 0xC0000000 | 0x014b -#define NT_STATUS_REGISTRY_CORRUPT 0xC0000000 | 0x014c -#define NT_STATUS_REGISTRY_IO_FAILED 0xC0000000 | 0x014d -#define NT_STATUS_NO_EVENT_PAIR 0xC0000000 | 0x014e -#define NT_STATUS_UNRECOGNIZED_VOLUME 0xC0000000 | 0x014f -#define NT_STATUS_SERIAL_NO_DEVICE_INITED 0xC0000000 | 0x0150 -#define NT_STATUS_NO_SUCH_ALIAS 0xC0000000 | 0x0151 -#define NT_STATUS_MEMBER_NOT_IN_ALIAS 0xC0000000 | 0x0152 -#define NT_STATUS_MEMBER_IN_ALIAS 0xC0000000 | 0x0153 -#define NT_STATUS_ALIAS_EXISTS 0xC0000000 | 0x0154 -#define NT_STATUS_LOGON_NOT_GRANTED 0xC0000000 | 0x0155 -#define NT_STATUS_TOO_MANY_SECRETS 0xC0000000 | 0x0156 -#define NT_STATUS_SECRET_TOO_LONG 0xC0000000 | 0x0157 -#define NT_STATUS_INTERNAL_DB_ERROR 0xC0000000 | 0x0158 -#define NT_STATUS_FULLSCREEN_MODE 0xC0000000 | 0x0159 -#define NT_STATUS_TOO_MANY_CONTEXT_IDS 0xC0000000 | 0x015a -#define NT_STATUS_LOGON_TYPE_NOT_GRANTED 0xC0000000 | 0x015b -#define NT_STATUS_NOT_REGISTRY_FILE 0xC0000000 | 0x015c -#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x015d -#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC0000000 | 0x015e -#define NT_STATUS_FT_MISSING_MEMBER 0xC0000000 | 0x015f -#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000000 | 0x0160 -#define NT_STATUS_ILLEGAL_CHARACTER 0xC0000000 | 0x0161 -#define NT_STATUS_UNMAPPABLE_CHARACTER 0xC0000000 | 0x0162 -#define NT_STATUS_UNDEFINED_CHARACTER 0xC0000000 | 0x0163 -#define NT_STATUS_FLOPPY_VOLUME 0xC0000000 | 0x0164 -#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000000 | 0x0165 -#define NT_STATUS_FLOPPY_WRONG_CYLINDER 0xC0000000 | 0x0166 -#define NT_STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000000 | 0x0167 -#define NT_STATUS_FLOPPY_BAD_REGISTERS 0xC0000000 | 0x0168 -#define NT_STATUS_DISK_RECALIBRATE_FAILED 0xC0000000 | 0x0169 -#define NT_STATUS_DISK_OPERATION_FAILED 0xC0000000 | 0x016a -#define NT_STATUS_DISK_RESET_FAILED 0xC0000000 | 0x016b -#define NT_STATUS_SHARED_IRQ_BUSY 0xC0000000 | 0x016c -#define NT_STATUS_FT_ORPHANING 0xC0000000 | 0x016d -#define NT_STATUS_PARTITION_FAILURE 0xC0000000 | 0x0172 -#define NT_STATUS_INVALID_BLOCK_LENGTH 0xC0000000 | 0x0173 -#define NT_STATUS_DEVICE_NOT_PARTITIONED 0xC0000000 | 0x0174 -#define NT_STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000000 | 0x0175 -#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000000 | 0x0176 -#define NT_STATUS_EOM_OVERFLOW 0xC0000000 | 0x0177 -#define NT_STATUS_NO_MEDIA 0xC0000000 | 0x0178 -#define NT_STATUS_NO_SUCH_MEMBER 0xC0000000 | 0x017a -#define NT_STATUS_INVALID_MEMBER 0xC0000000 | 0x017b -#define NT_STATUS_KEY_DELETED 0xC0000000 | 0x017c -#define NT_STATUS_NO_LOG_SPACE 0xC0000000 | 0x017d -#define NT_STATUS_TOO_MANY_SIDS 0xC0000000 | 0x017e -#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x017f -#define NT_STATUS_KEY_HAS_CHILDREN 0xC0000000 | 0x0180 -#define NT_STATUS_CHILD_MUST_BE_VOLATILE 0xC0000000 | 0x0181 -#define NT_STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000000 | 0x0182 -#define NT_STATUS_DRIVER_INTERNAL_ERROR 0xC0000000 | 0x0183 -#define NT_STATUS_INVALID_DEVICE_STATE 0xC0000000 | 0x0184 -#define NT_STATUS_IO_DEVICE_ERROR 0xC0000000 | 0x0185 -#define NT_STATUS_DEVICE_PROTOCOL_ERROR 0xC0000000 | 0x0186 -#define NT_STATUS_BACKUP_CONTROLLER 0xC0000000 | 0x0187 -#define NT_STATUS_LOG_FILE_FULL 0xC0000000 | 0x0188 -#define NT_STATUS_TOO_LATE 0xC0000000 | 0x0189 -#define NT_STATUS_NO_TRUST_LSA_SECRET 0xC0000000 | 0x018a -#define NT_STATUS_NO_TRUST_SAM_ACCOUNT 0xC0000000 | 0x018b -#define NT_STATUS_TRUSTED_DOMAIN_FAILURE 0xC0000000 | 0x018c -#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC0000000 | 0x018d -#define NT_STATUS_EVENTLOG_FILE_CORRUPT 0xC0000000 | 0x018e -#define NT_STATUS_EVENTLOG_CANT_START 0xC0000000 | 0x018f -#define NT_STATUS_TRUST_FAILURE 0xC0000000 | 0x0190 -#define NT_STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000000 | 0x0191 -#define NT_STATUS_NETLOGON_NOT_STARTED 0xC0000000 | 0x0192 -#define NT_STATUS_ACCOUNT_EXPIRED 0xC0000000 | 0x0193 -#define NT_STATUS_POSSIBLE_DEADLOCK 0xC0000000 | 0x0194 -#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000000 | 0x0195 -#define NT_STATUS_REMOTE_SESSION_LIMIT 0xC0000000 | 0x0196 -#define NT_STATUS_EVENTLOG_FILE_CHANGED 0xC0000000 | 0x0197 -#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000000 | 0x0198 -#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000000 | 0x0199 -#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC0000000 | 0x019a -#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT 0xC0000000 | 0x019b -#define NT_STATUS_FS_DRIVER_REQUIRED 0xC0000000 | 0x019c -#define NT_STATUS_NO_USER_SESSION_KEY 0xC0000000 | 0x0202 -#define NT_STATUS_USER_SESSION_DELETED 0xC0000000 | 0x0203 -#define NT_STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000000 | 0x0204 -#define NT_STATUS_INSUFF_SERVER_RESOURCES 0xC0000000 | 0x0205 -#define NT_STATUS_INVALID_BUFFER_SIZE 0xC0000000 | 0x0206 -#define NT_STATUS_INVALID_ADDRESS_COMPONENT 0xC0000000 | 0x0207 -#define NT_STATUS_INVALID_ADDRESS_WILDCARD 0xC0000000 | 0x0208 -#define NT_STATUS_TOO_MANY_ADDRESSES 0xC0000000 | 0x0209 -#define NT_STATUS_ADDRESS_ALREADY_EXISTS 0xC0000000 | 0x020a -#define NT_STATUS_ADDRESS_CLOSED 0xC0000000 | 0x020b -#define NT_STATUS_CONNECTION_DISCONNECTED 0xC0000000 | 0x020c -#define NT_STATUS_CONNECTION_RESET 0xC0000000 | 0x020d -#define NT_STATUS_TOO_MANY_NODES 0xC0000000 | 0x020e -#define NT_STATUS_TRANSACTION_ABORTED 0xC0000000 | 0x020f -#define NT_STATUS_TRANSACTION_TIMED_OUT 0xC0000000 | 0x0210 -#define NT_STATUS_TRANSACTION_NO_RELEASE 0xC0000000 | 0x0211 -#define NT_STATUS_TRANSACTION_NO_MATCH 0xC0000000 | 0x0212 -#define NT_STATUS_TRANSACTION_RESPONDED 0xC0000000 | 0x0213 -#define NT_STATUS_TRANSACTION_INVALID_ID 0xC0000000 | 0x0214 -#define NT_STATUS_TRANSACTION_INVALID_TYPE 0xC0000000 | 0x0215 -#define NT_STATUS_NOT_SERVER_SESSION 0xC0000000 | 0x0216 -#define NT_STATUS_NOT_CLIENT_SESSION 0xC0000000 | 0x0217 -#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000000 | 0x0218 -#define NT_STATUS_DEBUG_ATTACH_FAILED 0xC0000000 | 0x0219 -#define NT_STATUS_SYSTEM_PROCESS_TERMINATED 0xC0000000 | 0x021a -#define NT_STATUS_DATA_NOT_ACCEPTED 0xC0000000 | 0x021b -#define NT_STATUS_NO_BROWSER_SERVERS_FOUND 0xC0000000 | 0x021c -#define NT_STATUS_VDM_HARD_ERROR 0xC0000000 | 0x021d -#define NT_STATUS_DRIVER_CANCEL_TIMEOUT 0xC0000000 | 0x021e -#define NT_STATUS_REPLY_MESSAGE_MISMATCH 0xC0000000 | 0x021f -#define NT_STATUS_MAPPED_ALIGNMENT 0xC0000000 | 0x0220 -#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000000 | 0x0221 -#define NT_STATUS_LOST_WRITEBEHIND_DATA 0xC0000000 | 0x0222 -#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000000 | 0x0223 -#define NT_STATUS_PASSWORD_MUST_CHANGE 0xC0000000 | 0x0224 -#define NT_STATUS_NOT_FOUND 0xC0000000 | 0x0225 -#define NT_STATUS_NOT_TINY_STREAM 0xC0000000 | 0x0226 -#define NT_STATUS_RECOVERY_FAILURE 0xC0000000 | 0x0227 -#define NT_STATUS_STACK_OVERFLOW_READ 0xC0000000 | 0x0228 -#define NT_STATUS_FAIL_CHECK 0xC0000000 | 0x0229 -#define NT_STATUS_DUPLICATE_OBJECTID 0xC0000000 | 0x022a -#define NT_STATUS_OBJECTID_EXISTS 0xC0000000 | 0x022b -#define NT_STATUS_CONVERT_TO_LARGE 0xC0000000 | 0x022c -#define NT_STATUS_RETRY 0xC0000000 | 0x022d -#define NT_STATUS_FOUND_OUT_OF_SCOPE 0xC0000000 | 0x022e -#define NT_STATUS_ALLOCATE_BUCKET 0xC0000000 | 0x022f -#define NT_STATUS_PROPSET_NOT_FOUND 0xC0000000 | 0x0230 -#define NT_STATUS_MARSHALL_OVERFLOW 0xC0000000 | 0x0231 -#define NT_STATUS_INVALID_VARIANT 0xC0000000 | 0x0232 -#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000000 | 0x0233 -#define NT_STATUS_ACCOUNT_LOCKED_OUT 0xC0000000 | 0x0234 -#define NT_STATUS_HANDLE_NOT_CLOSABLE 0xC0000000 | 0x0235 -#define NT_STATUS_CONNECTION_REFUSED 0xC0000000 | 0x0236 -#define NT_STATUS_GRACEFUL_DISCONNECT 0xC0000000 | 0x0237 -#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000000 | 0x0238 -#define NT_STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000000 | 0x0239 -#define NT_STATUS_CONNECTION_INVALID 0xC0000000 | 0x023a -#define NT_STATUS_CONNECTION_ACTIVE 0xC0000000 | 0x023b -#define NT_STATUS_NETWORK_UNREACHABLE 0xC0000000 | 0x023c -#define NT_STATUS_HOST_UNREACHABLE 0xC0000000 | 0x023d -#define NT_STATUS_PROTOCOL_UNREACHABLE 0xC0000000 | 0x023e -#define NT_STATUS_PORT_UNREACHABLE 0xC0000000 | 0x023f -#define NT_STATUS_REQUEST_ABORTED 0xC0000000 | 0x0240 -#define NT_STATUS_CONNECTION_ABORTED 0xC0000000 | 0x0241 -#define NT_STATUS_BAD_COMPRESSION_BUFFER 0xC0000000 | 0x0242 -#define NT_STATUS_USER_MAPPED_FILE 0xC0000000 | 0x0243 -#define NT_STATUS_AUDIT_FAILED 0xC0000000 | 0x0244 -#define NT_STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000000 | 0x0245 -#define NT_STATUS_CONNECTION_COUNT_LIMIT 0xC0000000 | 0x0246 -#define NT_STATUS_LOGIN_TIME_RESTRICTION 0xC0000000 | 0x0247 -#define NT_STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000000 | 0x0248 -#define NT_STATUS_IMAGE_MP_UP_MISMATCH 0xC0000000 | 0x0249 -#define NT_STATUS_INSUFFICIENT_LOGON_INFO 0xC0000000 | 0x0250 -#define NT_STATUS_BAD_DLL_ENTRYPOINT 0xC0000000 | 0x0251 -#define NT_STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000000 | 0x0252 -#define NT_STATUS_LPC_REPLY_LOST 0xC0000000 | 0x0253 -#define NT_STATUS_IP_ADDRESS_CONFLICT1 0xC0000000 | 0x0254 -#define NT_STATUS_IP_ADDRESS_CONFLICT2 0xC0000000 | 0x0255 -#define NT_STATUS_REGISTRY_QUOTA_LIMIT 0xC0000000 | 0x0256 -#define NT_STATUS_PATH_NOT_COVERED 0xC0000000 | 0x0257 -#define NT_STATUS_NO_CALLBACK_ACTIVE 0xC0000000 | 0x0258 -#define NT_STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000000 | 0x0259 -#define NT_STATUS_PWD_TOO_SHORT 0xC0000000 | 0x025a -#define NT_STATUS_PWD_TOO_RECENT 0xC0000000 | 0x025b -#define NT_STATUS_PWD_HISTORY_CONFLICT 0xC0000000 | 0x025c -#define NT_STATUS_PLUGPLAY_NO_DEVICE 0xC0000000 | 0x025e -#define NT_STATUS_UNSUPPORTED_COMPRESSION 0xC0000000 | 0x025f -#define NT_STATUS_INVALID_HW_PROFILE 0xC0000000 | 0x0260 -#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000000 | 0x0261 -#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000000 | 0x0262 -#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0263 -#define NT_STATUS_RESOURCE_NOT_OWNED 0xC0000000 | 0x0264 -#define NT_STATUS_TOO_MANY_LINKS 0xC0000000 | 0x0265 -#define NT_STATUS_QUOTA_LIST_INCONSISTENT 0xC0000000 | 0x0266 -#define NT_STATUS_FILE_IS_OFFLINE 0xC0000000 | 0x0267 -#define NT_STATUS_NO_SUCH_JOB 0xC0000000 | 0xEDE /* scheduler */ - -#endif /* _NTERR_H */ diff --git a/ANDROID_3.4.5/fs/cifs/ntlmssp.h b/ANDROID_3.4.5/fs/cifs/ntlmssp.h deleted file mode 100644 index 5d52e4a3..00000000 --- a/ANDROID_3.4.5/fs/cifs/ntlmssp.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * fs/cifs/ntlmssp.h - * - * Copyright (c) International Business Machines Corp., 2002,2007 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define NTLMSSP_SIGNATURE "NTLMSSP" -/* Message Types */ -#define NtLmNegotiate cpu_to_le32(1) -#define NtLmChallenge cpu_to_le32(2) -#define NtLmAuthenticate cpu_to_le32(3) -#define UnknownMessage cpu_to_le32(8) - -/* Negotiate Flags */ -#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are unicode */ -#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */ -#define NTLMSSP_REQUEST_TARGET 0x04 /* Srv returns its auth realm */ -/* define reserved9 0x08 */ -#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signing capability */ -#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */ -#define NTLMSSP_NEGOTIATE_DGRAM 0x0040 -#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Use LM session key */ -/* defined reserved 8 0x0100 */ -#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */ -#define NTLMSSP_NEGOTIATE_NT_ONLY 0x0400 /* Lanman not allowed */ -#define NTLMSSP_ANONYMOUS 0x0800 -#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 /* reserved6 */ -#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000 -#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server same machine */ -#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign. All security levels */ -#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000 -#define NTLMSSP_TARGET_TYPE_SERVER 0x20000 -#define NTLMSSP_TARGET_TYPE_SHARE 0x40000 -#define NTLMSSP_NEGOTIATE_EXTENDED_SEC 0x80000 /* NB:not related to NTLMv2 pwd*/ -/* #define NTLMSSP_REQUEST_INIT_RESP 0x100000 */ -#define NTLMSSP_NEGOTIATE_IDENTIFY 0x100000 -#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000 /* reserved5 */ -#define NTLMSSP_REQUEST_NON_NT_KEY 0x400000 -#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000 -/* #define reserved4 0x1000000 */ -#define NTLMSSP_NEGOTIATE_VERSION 0x2000000 /* we do not set */ -/* #define reserved3 0x4000000 */ -/* #define reserved2 0x8000000 */ -/* #define reserved1 0x10000000 */ -#define NTLMSSP_NEGOTIATE_128 0x20000000 -#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 -#define NTLMSSP_NEGOTIATE_56 0x80000000 - -/* Define AV Pair Field IDs */ -enum av_field_type { - NTLMSSP_AV_EOL = 0, - NTLMSSP_AV_NB_COMPUTER_NAME, - NTLMSSP_AV_NB_DOMAIN_NAME, - NTLMSSP_AV_DNS_COMPUTER_NAME, - NTLMSSP_AV_DNS_DOMAIN_NAME, - NTLMSSP_AV_DNS_TREE_NAME, - NTLMSSP_AV_FLAGS, - NTLMSSP_AV_TIMESTAMP, - NTLMSSP_AV_RESTRICTION, - NTLMSSP_AV_TARGET_NAME, - NTLMSSP_AV_CHANNEL_BINDINGS -}; - -/* Although typedefs are not commonly used for structure definitions */ -/* in the Linux kernel, in this particular case they are useful */ -/* to more closely match the standards document for NTLMSSP from */ -/* OpenGroup and to make the code more closely match the standard in */ -/* appearance */ - -typedef struct _SECURITY_BUFFER { - __le16 Length; - __le16 MaximumLength; - __le32 BufferOffset; /* offset to buffer */ -} __attribute__((packed)) SECURITY_BUFFER; - -typedef struct _NEGOTIATE_MESSAGE { - __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; - __le32 MessageType; /* NtLmNegotiate = 1 */ - __le32 NegotiateFlags; - SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */ - SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */ - /* SECURITY_BUFFER for version info not present since we - do not set the version is present flag */ - char DomainString[0]; - /* followed by WorkstationString */ -} __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE; - -typedef struct _CHALLENGE_MESSAGE { - __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; - __le32 MessageType; /* NtLmChallenge = 2 */ - SECURITY_BUFFER TargetName; - __le32 NegotiateFlags; - __u8 Challenge[CIFS_CRYPTO_KEY_SIZE]; - __u8 Reserved[8]; - SECURITY_BUFFER TargetInfoArray; - /* SECURITY_BUFFER for version info not present since we - do not set the version is present flag */ -} __attribute__((packed)) CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE; - -typedef struct _AUTHENTICATE_MESSAGE { - __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; - __le32 MessageType; /* NtLmsAuthenticate = 3 */ - SECURITY_BUFFER LmChallengeResponse; - SECURITY_BUFFER NtChallengeResponse; - SECURITY_BUFFER DomainName; - SECURITY_BUFFER UserName; - SECURITY_BUFFER WorkstationName; - SECURITY_BUFFER SessionKey; - __le32 NegotiateFlags; - /* SECURITY_BUFFER for version info not present since we - do not set the version is present flag */ - char UserString[0]; -} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE; diff --git a/ANDROID_3.4.5/fs/cifs/readdir.c b/ANDROID_3.4.5/fs/cifs/readdir.c deleted file mode 100644 index 0a8224d1..00000000 --- a/ANDROID_3.4.5/fs/cifs/readdir.c +++ /dev/null @@ -1,842 +0,0 @@ -/* - * fs/cifs/readdir.c - * - * Directory search handling - * - * Copyright (C) International Business Machines Corp., 2004, 2008 - * Copyright (C) Red Hat, Inc., 2011 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/fs.h> -#include <linux/pagemap.h> -#include <linux/slab.h> -#include <linux/stat.h> -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifs_unicode.h" -#include "cifs_debug.h" -#include "cifs_fs_sb.h" -#include "cifsfs.h" - -/* - * To be safe - for UCS to UTF-8 with strings loaded with the rare long - * characters alloc more to account for such multibyte target UTF-8 - * characters. - */ -#define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2) - -#ifdef CONFIG_CIFS_DEBUG2 -static void dump_cifs_file_struct(struct file *file, char *label) -{ - struct cifsFileInfo *cf; - - if (file) { - cf = file->private_data; - if (cf == NULL) { - cFYI(1, "empty cifs private file data"); - return; - } - if (cf->invalidHandle) - cFYI(1, "invalid handle"); - if (cf->srch_inf.endOfSearch) - cFYI(1, "end of search"); - if (cf->srch_inf.emptyDir) - cFYI(1, "empty dir"); - } -} -#else -static inline void dump_cifs_file_struct(struct file *file, char *label) -{ -} -#endif /* DEBUG2 */ - -/* - * Find the dentry that matches "name". If there isn't one, create one. If it's - * a negative dentry or the uniqueid changed, then drop it and recreate it. - */ -static struct dentry * -cifs_readdir_lookup(struct dentry *parent, struct qstr *name, - struct cifs_fattr *fattr) -{ - struct dentry *dentry, *alias; - struct inode *inode; - struct super_block *sb = parent->d_inode->i_sb; - - cFYI(1, "For %s", name->name); - - if (parent->d_op && parent->d_op->d_hash) - parent->d_op->d_hash(parent, parent->d_inode, name); - else - name->hash = full_name_hash(name->name, name->len); - - dentry = d_lookup(parent, name); - if (dentry) { - /* FIXME: check for inode number changes? */ - if (dentry->d_inode != NULL) - return dentry; - d_drop(dentry); - dput(dentry); - } - - dentry = d_alloc(parent, name); - if (dentry == NULL) - return NULL; - - inode = cifs_iget(sb, fattr); - if (!inode) { - dput(dentry); - return NULL; - } - - alias = d_materialise_unique(dentry, inode); - if (alias != NULL) { - dput(dentry); - if (IS_ERR(alias)) - return NULL; - dentry = alias; - } - - return dentry; -} - -static void -cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) -{ - fattr->cf_uid = cifs_sb->mnt_uid; - fattr->cf_gid = cifs_sb->mnt_gid; - - if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { - fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; - fattr->cf_dtype = DT_DIR; - } else { - fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; - fattr->cf_dtype = DT_REG; - } - - if (fattr->cf_cifsattrs & ATTR_READONLY) - fattr->cf_mode &= ~S_IWUGO; - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL && - fattr->cf_cifsattrs & ATTR_SYSTEM) { - if (fattr->cf_eof == 0) { - fattr->cf_mode &= ~S_IFMT; - fattr->cf_mode |= S_IFIFO; - fattr->cf_dtype = DT_FIFO; - } else { - /* - * trying to get the type and mode via SFU can be slow, - * so just call those regular files for now, and mark - * for reval - */ - fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; - } - } -} - -static void -cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, - struct cifs_sb_info *cifs_sb) -{ - memset(fattr, 0, sizeof(*fattr)); - fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes); - fattr->cf_eof = le64_to_cpu(info->EndOfFile); - fattr->cf_bytes = le64_to_cpu(info->AllocationSize); - fattr->cf_createtime = le64_to_cpu(info->CreationTime); - fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); - fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); - fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); - - cifs_fill_common_info(fattr, cifs_sb); -} - -static void -cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info, - struct cifs_sb_info *cifs_sb) -{ - int offset = cifs_sb_master_tcon(cifs_sb)->ses->server->timeAdj; - - memset(fattr, 0, sizeof(*fattr)); - fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate, - info->LastAccessTime, offset); - fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate, - info->LastWriteTime, offset); - fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate, - info->LastWriteTime, offset); - - fattr->cf_cifsattrs = le16_to_cpu(info->Attributes); - fattr->cf_bytes = le32_to_cpu(info->AllocationSize); - fattr->cf_eof = le32_to_cpu(info->DataSize); - - cifs_fill_common_info(fattr, cifs_sb); -} - -/* BB eventually need to add the following helper function to - resolve NT_STATUS_STOPPED_ON_SYMLINK return code when - we try to do FindFirst on (NTFS) directory symlinks */ -/* -int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, - int xid) -{ - __u16 fid; - int len; - int oplock = 0; - int rc; - struct cifs_tcon *ptcon = cifs_sb_tcon(cifs_sb); - char *tmpbuffer; - - rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ, - OPEN_REPARSE_POINT, &fid, &oplock, NULL, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (!rc) { - tmpbuffer = kmalloc(maxpath); - rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path, - tmpbuffer, - maxpath -1, - fid, - cifs_sb->local_nls); - if (CIFSSMBClose(xid, ptcon, fid)) { - cFYI(1, "Error closing temporary reparsepoint open"); - } - } -} - */ - -static int initiate_cifs_search(const int xid, struct file *file) -{ - __u16 search_flags; - int rc = 0; - char *full_path = NULL; - struct cifsFileInfo *cifsFile; - struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - struct tcon_link *tlink = NULL; - struct cifs_tcon *pTcon; - - if (file->private_data == NULL) { - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - - cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); - if (cifsFile == NULL) { - rc = -ENOMEM; - goto error_exit; - } - file->private_data = cifsFile; - cifsFile->tlink = cifs_get_tlink(tlink); - pTcon = tlink_tcon(tlink); - } else { - cifsFile = file->private_data; - pTcon = tlink_tcon(cifsFile->tlink); - } - - cifsFile->invalidHandle = true; - cifsFile->srch_inf.endOfSearch = false; - - full_path = build_path_from_dentry(file->f_path.dentry); - if (full_path == NULL) { - rc = -ENOMEM; - goto error_exit; - } - - cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos); - -ffirst_retry: - /* test for Unix extensions */ - /* but now check for them on the share/mount not on the SMB session */ -/* if (pTcon->ses->capabilities & CAP_UNIX) { */ - if (pTcon->unix_ext) - cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; - else if ((pTcon->ses->capabilities & - (CAP_NT_SMBS | CAP_NT_FIND)) == 0) { - cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD; - } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { - cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO; - } else /* not srvinos - BB fixme add check for backlevel? */ { - cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; - } - - search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME; - if (backup_cred(cifs_sb)) - search_flags |= CIFS_SEARCH_BACKUP_SEARCH; - - rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls, - &cifsFile->netfid, search_flags, &cifsFile->srch_inf, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); - if (rc == 0) - cifsFile->invalidHandle = false; - /* BB add following call to handle readdir on new NTFS symlink errors - else if STATUS_STOPPED_ON_SYMLINK - call get_symlink_reparse_path and retry with new path */ - else if ((rc == -EOPNOTSUPP) && - (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { - cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; - goto ffirst_retry; - } -error_exit: - kfree(full_path); - cifs_put_tlink(tlink); - return rc; -} - -/* return length of unicode string in bytes */ -static int cifs_unicode_bytelen(const char *str) -{ - int len; - const __le16 *ustr = (const __le16 *)str; - - for (len = 0; len <= PATH_MAX; len++) { - if (ustr[len] == 0) - return len << 1; - } - cFYI(1, "Unicode string longer than PATH_MAX found"); - return len << 1; -} - -static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level) -{ - char *new_entry; - FILE_DIRECTORY_INFO *pDirInfo = (FILE_DIRECTORY_INFO *)old_entry; - - if (level == SMB_FIND_FILE_INFO_STANDARD) { - FIND_FILE_STANDARD_INFO *pfData; - pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo; - - new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) + - pfData->FileNameLength; - } else - new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset); - cFYI(1, "new entry %p old entry %p", new_entry, old_entry); - /* validate that new_entry is not past end of SMB */ - if (new_entry >= end_of_smb) { - cERROR(1, "search entry %p began after end of SMB %p old entry %p", - new_entry, end_of_smb, old_entry); - return NULL; - } else if (((level == SMB_FIND_FILE_INFO_STANDARD) && - (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb)) - || ((level != SMB_FIND_FILE_INFO_STANDARD) && - (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) { - cERROR(1, "search entry %p extends after end of SMB %p", - new_entry, end_of_smb); - return NULL; - } else - return new_entry; - -} - -struct cifs_dirent { - const char *name; - size_t namelen; - u32 resume_key; - u64 ino; -}; - -static void cifs_fill_dirent_unix(struct cifs_dirent *de, - const FILE_UNIX_INFO *info, bool is_unicode) -{ - de->name = &info->FileName[0]; - if (is_unicode) - de->namelen = cifs_unicode_bytelen(de->name); - else - de->namelen = strnlen(de->name, PATH_MAX); - de->resume_key = info->ResumeKey; - de->ino = le64_to_cpu(info->basic.UniqueId); -} - -static void cifs_fill_dirent_dir(struct cifs_dirent *de, - const FILE_DIRECTORY_INFO *info) -{ - de->name = &info->FileName[0]; - de->namelen = le32_to_cpu(info->FileNameLength); - de->resume_key = info->FileIndex; -} - -static void cifs_fill_dirent_full(struct cifs_dirent *de, - const FILE_FULL_DIRECTORY_INFO *info) -{ - de->name = &info->FileName[0]; - de->namelen = le32_to_cpu(info->FileNameLength); - de->resume_key = info->FileIndex; -} - -static void cifs_fill_dirent_search(struct cifs_dirent *de, - const SEARCH_ID_FULL_DIR_INFO *info) -{ - de->name = &info->FileName[0]; - de->namelen = le32_to_cpu(info->FileNameLength); - de->resume_key = info->FileIndex; - de->ino = le64_to_cpu(info->UniqueId); -} - -static void cifs_fill_dirent_both(struct cifs_dirent *de, - const FILE_BOTH_DIRECTORY_INFO *info) -{ - de->name = &info->FileName[0]; - de->namelen = le32_to_cpu(info->FileNameLength); - de->resume_key = info->FileIndex; -} - -static void cifs_fill_dirent_std(struct cifs_dirent *de, - const FIND_FILE_STANDARD_INFO *info) -{ - de->name = &info->FileName[0]; - /* one byte length, no endianess conversion */ - de->namelen = info->FileNameLength; - de->resume_key = info->ResumeKey; -} - -static int cifs_fill_dirent(struct cifs_dirent *de, const void *info, - u16 level, bool is_unicode) -{ - memset(de, 0, sizeof(*de)); - - switch (level) { - case SMB_FIND_FILE_UNIX: - cifs_fill_dirent_unix(de, info, is_unicode); - break; - case SMB_FIND_FILE_DIRECTORY_INFO: - cifs_fill_dirent_dir(de, info); - break; - case SMB_FIND_FILE_FULL_DIRECTORY_INFO: - cifs_fill_dirent_full(de, info); - break; - case SMB_FIND_FILE_ID_FULL_DIR_INFO: - cifs_fill_dirent_search(de, info); - break; - case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - cifs_fill_dirent_both(de, info); - break; - case SMB_FIND_FILE_INFO_STANDARD: - cifs_fill_dirent_std(de, info); - break; - default: - cFYI(1, "Unknown findfirst level %d", level); - return -EINVAL; - } - - return 0; -} - -#define UNICODE_DOT cpu_to_le16(0x2e) - -/* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */ -static int cifs_entry_is_dot(struct cifs_dirent *de, bool is_unicode) -{ - int rc = 0; - - if (!de->name) - return 0; - - if (is_unicode) { - __le16 *ufilename = (__le16 *)de->name; - if (de->namelen == 2) { - /* check for . */ - if (ufilename[0] == UNICODE_DOT) - rc = 1; - } else if (de->namelen == 4) { - /* check for .. */ - if (ufilename[0] == UNICODE_DOT && - ufilename[1] == UNICODE_DOT) - rc = 2; - } - } else /* ASCII */ { - if (de->namelen == 1) { - if (de->name[0] == '.') - rc = 1; - } else if (de->namelen == 2) { - if (de->name[0] == '.' && de->name[1] == '.') - rc = 2; - } - } - - return rc; -} - -/* Check if directory that we are searching has changed so we can decide - whether we can use the cached search results from the previous search */ -static int is_dir_changed(struct file *file) -{ - struct inode *inode = file->f_path.dentry->d_inode; - struct cifsInodeInfo *cifsInfo = CIFS_I(inode); - - if (cifsInfo->time == 0) - return 1; /* directory was changed, perhaps due to unlink */ - else - return 0; - -} - -static int cifs_save_resume_key(const char *current_entry, - struct cifsFileInfo *file_info) -{ - struct cifs_dirent de; - int rc; - - rc = cifs_fill_dirent(&de, current_entry, file_info->srch_inf.info_level, - file_info->srch_inf.unicode); - if (!rc) { - file_info->srch_inf.presume_name = de.name; - file_info->srch_inf.resume_name_len = de.namelen; - file_info->srch_inf.resume_key = de.resume_key; - } - return rc; -} - -/* find the corresponding entry in the search */ -/* Note that the SMB server returns search entries for . and .. which - complicates logic here if we choose to parse for them and we do not - assume that they are located in the findfirst return buffer.*/ -/* We start counting in the buffer with entry 2 and increment for every - entry (do not increment for . or .. entry) */ -static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, - struct file *file, char **ppCurrentEntry, int *num_to_ret) -{ - __u16 search_flags; - int rc = 0; - int pos_in_buf = 0; - loff_t first_entry_in_buffer; - loff_t index_to_find = file->f_pos; - struct cifsFileInfo *cifsFile = file->private_data; - struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - /* check if index in the buffer */ - - if ((cifsFile == NULL) || (ppCurrentEntry == NULL) || - (num_to_ret == NULL)) - return -ENOENT; - - *ppCurrentEntry = NULL; - first_entry_in_buffer = - cifsFile->srch_inf.index_of_last_entry - - cifsFile->srch_inf.entries_in_buffer; - - /* if first entry in buf is zero then is first buffer - in search response data which means it is likely . and .. - will be in this buffer, although some servers do not return - . and .. for the root of a drive and for those we need - to start two entries earlier */ - - dump_cifs_file_struct(file, "In fce "); - if (((index_to_find < cifsFile->srch_inf.index_of_last_entry) && - is_dir_changed(file)) || - (index_to_find < first_entry_in_buffer)) { - /* close and restart search */ - cFYI(1, "search backing up - close and restart search"); - spin_lock(&cifs_file_list_lock); - if (!cifsFile->srch_inf.endOfSearch && - !cifsFile->invalidHandle) { - cifsFile->invalidHandle = true; - spin_unlock(&cifs_file_list_lock); - CIFSFindClose(xid, pTcon, cifsFile->netfid); - } else - spin_unlock(&cifs_file_list_lock); - if (cifsFile->srch_inf.ntwrk_buf_start) { - cFYI(1, "freeing SMB ff cache buf on search rewind"); - if (cifsFile->srch_inf.smallBuf) - cifs_small_buf_release(cifsFile->srch_inf. - ntwrk_buf_start); - else - cifs_buf_release(cifsFile->srch_inf. - ntwrk_buf_start); - cifsFile->srch_inf.ntwrk_buf_start = NULL; - } - rc = initiate_cifs_search(xid, file); - if (rc) { - cFYI(1, "error %d reinitiating a search on rewind", - rc); - return rc; - } - /* FindFirst/Next set last_entry to NULL on malformed reply */ - if (cifsFile->srch_inf.last_entry) - cifs_save_resume_key(cifsFile->srch_inf.last_entry, - cifsFile); - } - - search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME; - if (backup_cred(cifs_sb)) - search_flags |= CIFS_SEARCH_BACKUP_SEARCH; - - while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && - (rc == 0) && !cifsFile->srch_inf.endOfSearch) { - cFYI(1, "calling findnext2"); - rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, search_flags, - &cifsFile->srch_inf); - /* FindFirst/Next set last_entry to NULL on malformed reply */ - if (cifsFile->srch_inf.last_entry) - cifs_save_resume_key(cifsFile->srch_inf.last_entry, - cifsFile); - if (rc) - return -ENOENT; - } - if (index_to_find < cifsFile->srch_inf.index_of_last_entry) { - /* we found the buffer that contains the entry */ - /* scan and find it */ - int i; - char *current_entry; - char *end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + - smbCalcSize((struct smb_hdr *) - cifsFile->srch_inf.ntwrk_buf_start); - - current_entry = cifsFile->srch_inf.srch_entries_start; - first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry - - cifsFile->srch_inf.entries_in_buffer; - pos_in_buf = index_to_find - first_entry_in_buffer; - cFYI(1, "found entry - pos_in_buf %d", pos_in_buf); - - for (i = 0; (i < (pos_in_buf)) && (current_entry != NULL); i++) { - /* go entry by entry figuring out which is first */ - current_entry = nxt_dir_entry(current_entry, end_of_smb, - cifsFile->srch_inf.info_level); - } - if ((current_entry == NULL) && (i < pos_in_buf)) { - /* BB fixme - check if we should flag this error */ - cERROR(1, "reached end of buf searching for pos in buf" - " %d index to find %lld rc %d", - pos_in_buf, index_to_find, rc); - } - rc = 0; - *ppCurrentEntry = current_entry; - } else { - cFYI(1, "index not in buffer - could not findnext into it"); - return 0; - } - - if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) { - cFYI(1, "can not return entries pos_in_buf beyond last"); - *num_to_ret = 0; - } else - *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf; - - return rc; -} - -static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, - void *dirent, char *scratch_buf, unsigned int max_len) -{ - struct cifsFileInfo *file_info = file->private_data; - struct super_block *sb = file->f_path.dentry->d_sb; - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - struct cifs_dirent de = { NULL, }; - struct cifs_fattr fattr; - struct dentry *dentry; - struct qstr name; - int rc = 0; - ino_t ino; - - rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level, - file_info->srch_inf.unicode); - if (rc) - return rc; - - if (de.namelen > max_len) { - cERROR(1, "bad search response length %zd past smb end", - de.namelen); - return -EINVAL; - } - - /* skip . and .. since we added them first */ - if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode)) - return 0; - - if (file_info->srch_inf.unicode) { - struct nls_table *nlt = cifs_sb->local_nls; - - name.name = scratch_buf; - name.len = - cifs_from_utf16((char *)name.name, (__le16 *)de.name, - UNICODE_NAME_MAX, - min_t(size_t, de.namelen, - (size_t)max_len), nlt, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - name.len -= nls_nullsize(nlt); - } else { - name.name = de.name; - name.len = de.namelen; - } - - switch (file_info->srch_inf.info_level) { - case SMB_FIND_FILE_UNIX: - cifs_unix_basic_to_fattr(&fattr, - &((FILE_UNIX_INFO *)find_entry)->basic, - cifs_sb); - break; - case SMB_FIND_FILE_INFO_STANDARD: - cifs_std_info_to_fattr(&fattr, - (FIND_FILE_STANDARD_INFO *)find_entry, - cifs_sb); - break; - default: - cifs_dir_info_to_fattr(&fattr, - (FILE_DIRECTORY_INFO *)find_entry, - cifs_sb); - break; - } - - if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { - fattr.cf_uniqueid = de.ino; - } else { - fattr.cf_uniqueid = iunique(sb, ROOT_I); - cifs_autodisable_serverino(cifs_sb); - } - - if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) && - CIFSCouldBeMFSymlink(&fattr)) - /* - * trying to get the type and mode can be slow, - * so just call those regular files for now, and mark - * for reval - */ - fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; - - ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); - dentry = cifs_readdir_lookup(file->f_dentry, &name, &fattr); - - rc = filldir(dirent, name.name, name.len, file->f_pos, ino, - fattr.cf_dtype); - - dput(dentry); - return rc; -} - - -int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) -{ - int rc = 0; - int xid, i; - struct cifs_tcon *pTcon; - struct cifsFileInfo *cifsFile = NULL; - char *current_entry; - int num_to_fill = 0; - char *tmp_buf = NULL; - char *end_of_smb; - unsigned int max_len; - - xid = GetXid(); - - /* - * Ensure FindFirst doesn't fail before doing filldir() for '.' and - * '..'. Otherwise we won't be able to notify VFS in case of failure. - */ - if (file->private_data == NULL) { - rc = initiate_cifs_search(xid, file); - cFYI(1, "initiate cifs search rc %d", rc); - if (rc) - goto rddir2_exit; - } - - switch ((int) file->f_pos) { - case 0: - if (filldir(direntry, ".", 1, file->f_pos, - file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) { - cERROR(1, "Filldir for current dir failed"); - rc = -ENOMEM; - break; - } - file->f_pos++; - case 1: - if (filldir(direntry, "..", 2, file->f_pos, - parent_ino(file->f_path.dentry), DT_DIR) < 0) { - cERROR(1, "Filldir for parent dir failed"); - rc = -ENOMEM; - break; - } - file->f_pos++; - default: - /* 1) If search is active, - is in current search buffer? - if it before then restart search - if after then keep searching till find it */ - - if (file->private_data == NULL) { - rc = -EINVAL; - FreeXid(xid); - return rc; - } - cifsFile = file->private_data; - if (cifsFile->srch_inf.endOfSearch) { - if (cifsFile->srch_inf.emptyDir) { - cFYI(1, "End of search, empty dir"); - rc = 0; - break; - } - } /* else { - cifsFile->invalidHandle = true; - CIFSFindClose(xid, pTcon, cifsFile->netfid); - } */ - - pTcon = tlink_tcon(cifsFile->tlink); - rc = find_cifs_entry(xid, pTcon, file, - ¤t_entry, &num_to_fill); - if (rc) { - cFYI(1, "fce error %d", rc); - goto rddir2_exit; - } else if (current_entry != NULL) { - cFYI(1, "entry %lld found", file->f_pos); - } else { - cFYI(1, "could not find entry"); - goto rddir2_exit; - } - cFYI(1, "loop through %d times filling dir for net buf %p", - num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); - max_len = smbCalcSize((struct smb_hdr *) - cifsFile->srch_inf.ntwrk_buf_start); - end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; - - tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); - if (tmp_buf == NULL) { - rc = -ENOMEM; - break; - } - - for (i = 0; (i < num_to_fill) && (rc == 0); i++) { - if (current_entry == NULL) { - /* evaluate whether this case is an error */ - cERROR(1, "past SMB end, num to fill %d i %d", - num_to_fill, i); - break; - } - /* if buggy server returns . and .. late do - we want to check for that here? */ - rc = cifs_filldir(current_entry, file, - filldir, direntry, tmp_buf, max_len); - if (rc == -EOVERFLOW) { - rc = 0; - break; - } - - file->f_pos++; - if (file->f_pos == - cifsFile->srch_inf.index_of_last_entry) { - cFYI(1, "last entry in buf at pos %lld %s", - file->f_pos, tmp_buf); - cifs_save_resume_key(current_entry, cifsFile); - break; - } else - current_entry = - nxt_dir_entry(current_entry, end_of_smb, - cifsFile->srch_inf.info_level); - } - kfree(tmp_buf); - break; - } /* end switch */ - -rddir2_exit: - FreeXid(xid); - return rc; -} diff --git a/ANDROID_3.4.5/fs/cifs/rfc1002pdu.h b/ANDROID_3.4.5/fs/cifs/rfc1002pdu.h deleted file mode 100644 index 8b69fcce..00000000 --- a/ANDROID_3.4.5/fs/cifs/rfc1002pdu.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * fs/cifs/rfc1002pdu.h - * - * Protocol Data Unit definitions for RFC 1001/1002 support - * - * Copyright (c) International Business Machines Corp., 2004 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */ - - /* RFC 1002 session packet types */ -#define RFC1002_SESSION_MESSAGE 0x00 -#define RFC1002_SESSION_REQUEST 0x81 -#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82 -#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83 -#define RFC1002_RETARGET_SESSION_RESPONSE 0x84 -#define RFC1002_SESSION_KEEP_ALIVE 0x85 - - /* RFC 1002 flags (only one defined */ -#define RFC1002_LENGTH_EXTEND 0x80 /* high order bit of length (ie +64K) */ - -struct rfc1002_session_packet { - __u8 type; - __u8 flags; - __u16 length; - union { - struct { - __u8 called_len; - __u8 called_name[32]; - __u8 scope1; /* null */ - __u8 calling_len; - __u8 calling_name[32]; - __u8 scope2; /* null */ - } __attribute__((packed)) session_req; - struct { - __u32 retarget_ip_addr; - __u16 port; - } __attribute__((packed)) retarget_resp; - __u8 neg_ses_resp_error_code; - /* POSITIVE_SESSION_RESPONSE packet does not include trailer. - SESSION_KEEP_ALIVE packet also does not include a trailer. - Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */ - } __attribute__((packed)) trailer; -} __attribute__((packed)); - -/* Negative Session Response error codes */ -#define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */ -#define RFC1002_NOT_LISTENING_CALLING 0x81 /* not listening on calling name */ -#define RFC1002_NOT_PRESENT 0x82 /* called name not present */ -#define RFC1002_INSUFFICIENT_RESOURCE 0x83 -#define RFC1002_UNSPECIFIED_ERROR 0x8F - -/* RFC 1002 Datagram service packets are not defined here as they -are not needed for the network filesystem client unless we plan on -implementing broadcast resolution of the server ip address (from -server netbios name). Currently server names are resolved only via DNS -(tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/ - -#define DEFAULT_CIFS_CALLED_NAME "*SMBSERVER " diff --git a/ANDROID_3.4.5/fs/cifs/sess.c b/ANDROID_3.4.5/fs/cifs/sess.c deleted file mode 100644 index 551d0c2b..00000000 --- a/ANDROID_3.4.5/fs/cifs/sess.c +++ /dev/null @@ -1,958 +0,0 @@ -/* - * fs/cifs/sess.c - * - * SMB/CIFS session setup handling routines - * - * Copyright (c) International Business Machines Corp., 2006, 2009 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifs_unicode.h" -#include "cifs_debug.h" -#include "ntlmssp.h" -#include "nterr.h" -#include <linux/utsname.h> -#include <linux/slab.h> -#include "cifs_spnego.h" - -/* - * Checks if this is the first smb session to be reconnected after - * the socket has been reestablished (so we know whether to use vc 0). - * Called while holding the cifs_tcp_ses_lock, so do not block - */ -static bool is_first_ses_reconnect(struct cifs_ses *ses) -{ - struct list_head *tmp; - struct cifs_ses *tmp_ses; - - list_for_each(tmp, &ses->server->smb_ses_list) { - tmp_ses = list_entry(tmp, struct cifs_ses, - smb_ses_list); - if (tmp_ses->need_reconnect == false) - return false; - } - /* could not find a session that was already connected, - this must be the first one we are reconnecting */ - return true; -} - -/* - * vc number 0 is treated specially by some servers, and should be the - * first one we request. After that we can use vcnumbers up to maxvcs, - * one for each smb session (some Windows versions set maxvcs incorrectly - * so maxvc=1 can be ignored). If we have too many vcs, we can reuse - * any vc but zero (some servers reset the connection on vcnum zero) - * - */ -static __le16 get_next_vcnum(struct cifs_ses *ses) -{ - __u16 vcnum = 0; - struct list_head *tmp; - struct cifs_ses *tmp_ses; - __u16 max_vcs = ses->server->max_vcs; - __u16 i; - int free_vc_found = 0; - - /* Quoting the MS-SMB specification: "Windows-based SMB servers set this - field to one but do not enforce this limit, which allows an SMB client - to establish more virtual circuits than allowed by this value ... but - other server implementations can enforce this limit." */ - if (max_vcs < 2) - max_vcs = 0xFFFF; - - spin_lock(&cifs_tcp_ses_lock); - if ((ses->need_reconnect) && is_first_ses_reconnect(ses)) - goto get_vc_num_exit; /* vcnum will be zero */ - for (i = ses->server->srv_count - 1; i < max_vcs; i++) { - if (i == 0) /* this is the only connection, use vc 0 */ - break; - - free_vc_found = 1; - - list_for_each(tmp, &ses->server->smb_ses_list) { - tmp_ses = list_entry(tmp, struct cifs_ses, - smb_ses_list); - if (tmp_ses->vcnum == i) { - free_vc_found = 0; - break; /* found duplicate, try next vcnum */ - } - } - if (free_vc_found) - break; /* we found a vcnumber that will work - use it */ - } - - if (i == 0) - vcnum = 0; /* for most common case, ie if one smb session, use - vc zero. Also for case when no free vcnum, zero - is safest to send (some clients only send zero) */ - else if (free_vc_found == 0) - vcnum = 1; /* we can not reuse vc=0 safely, since some servers - reset all uids on that, but 1 is ok. */ - else - vcnum = i; - ses->vcnum = vcnum; -get_vc_num_exit: - spin_unlock(&cifs_tcp_ses_lock); - - return cpu_to_le16(vcnum); -} - -static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB) -{ - __u32 capabilities = 0; - - /* init fields common to all four types of SessSetup */ - /* Note that offsets for first seven fields in req struct are same */ - /* in CIFS Specs so does not matter which of 3 forms of struct */ - /* that we use in next few lines */ - /* Note that header is initialized to zero in header_assemble */ - pSMB->req.AndXCommand = 0xFF; - pSMB->req.MaxBufferSize = cpu_to_le16(min_t(u32, - CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4, - USHRT_MAX)); - pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); - pSMB->req.VcNumber = get_next_vcnum(ses); - - /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ - - /* BB verify whether signing required on neg or just on auth frame - (and NTLM case) */ - - capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | - CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; - - if (ses->server->sec_mode & - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) - pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - - if (ses->capabilities & CAP_UNICODE) { - pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE; - capabilities |= CAP_UNICODE; - } - if (ses->capabilities & CAP_STATUS32) { - pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS; - capabilities |= CAP_STATUS32; - } - if (ses->capabilities & CAP_DFS) { - pSMB->req.hdr.Flags2 |= SMBFLG2_DFS; - capabilities |= CAP_DFS; - } - if (ses->capabilities & CAP_UNIX) - capabilities |= CAP_UNIX; - - return capabilities; -} - -static void -unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp) -{ - char *bcc_ptr = *pbcc_area; - int bytes_ret = 0; - - /* Copy OS version */ - bytes_ret = cifs_strtoUTF16((__le16 *)bcc_ptr, "Linux version ", 32, - nls_cp); - bcc_ptr += 2 * bytes_ret; - bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, init_utsname()->release, - 32, nls_cp); - bcc_ptr += 2 * bytes_ret; - bcc_ptr += 2; /* trailing null */ - - bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, - 32, nls_cp); - bcc_ptr += 2 * bytes_ret; - bcc_ptr += 2; /* trailing null */ - - *pbcc_area = bcc_ptr; -} - -static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses, - const struct nls_table *nls_cp) -{ - char *bcc_ptr = *pbcc_area; - int bytes_ret = 0; - - /* copy domain */ - if (ses->domainName == NULL) { - /* Sending null domain better than using a bogus domain name (as - we did briefly in 2.6.18) since server will use its default */ - *bcc_ptr = 0; - *(bcc_ptr+1) = 0; - bytes_ret = 0; - } else - bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName, - 256, nls_cp); - bcc_ptr += 2 * bytes_ret; - bcc_ptr += 2; /* account for null terminator */ - - *pbcc_area = bcc_ptr; -} - - -static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, - const struct nls_table *nls_cp) -{ - char *bcc_ptr = *pbcc_area; - int bytes_ret = 0; - - /* BB FIXME add check that strings total less - than 335 or will need to send them as arrays */ - - /* unicode strings, must be word aligned before the call */ -/* if ((long) bcc_ptr % 2) { - *bcc_ptr = 0; - bcc_ptr++; - } */ - /* copy user */ - if (ses->user_name == NULL) { - /* null user mount */ - *bcc_ptr = 0; - *(bcc_ptr+1) = 0; - } else { - bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name, - MAX_USERNAME_SIZE, nls_cp); - } - bcc_ptr += 2 * bytes_ret; - bcc_ptr += 2; /* account for null termination */ - - unicode_domain_string(&bcc_ptr, ses, nls_cp); - unicode_oslm_strings(&bcc_ptr, nls_cp); - - *pbcc_area = bcc_ptr; -} - -static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, - const struct nls_table *nls_cp) -{ - char *bcc_ptr = *pbcc_area; - - /* copy user */ - /* BB what about null user mounts - check that we do this BB */ - /* copy user */ - if (ses->user_name != NULL) { - strncpy(bcc_ptr, ses->user_name, MAX_USERNAME_SIZE); - bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE); - } - /* else null user mount */ - *bcc_ptr = 0; - bcc_ptr++; /* account for null termination */ - - /* copy domain */ - if (ses->domainName != NULL) { - strncpy(bcc_ptr, ses->domainName, 256); - bcc_ptr += strnlen(ses->domainName, 256); - } /* else we will send a null domain name - so the server will default to its own domain */ - *bcc_ptr = 0; - bcc_ptr++; - - /* BB check for overflow here */ - - strcpy(bcc_ptr, "Linux version "); - bcc_ptr += strlen("Linux version "); - strcpy(bcc_ptr, init_utsname()->release); - bcc_ptr += strlen(init_utsname()->release) + 1; - - strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); - bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; - - *pbcc_area = bcc_ptr; -} - -static void -decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses, - const struct nls_table *nls_cp) -{ - int len; - char *data = *pbcc_area; - - cFYI(1, "bleft %d", bleft); - - kfree(ses->serverOS); - ses->serverOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp); - cFYI(1, "serverOS=%s", ses->serverOS); - len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2; - data += len; - bleft -= len; - if (bleft <= 0) - return; - - kfree(ses->serverNOS); - ses->serverNOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp); - cFYI(1, "serverNOS=%s", ses->serverNOS); - len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2; - data += len; - bleft -= len; - if (bleft <= 0) - return; - - kfree(ses->serverDomain); - ses->serverDomain = cifs_strndup_from_utf16(data, bleft, true, nls_cp); - cFYI(1, "serverDomain=%s", ses->serverDomain); - - return; -} - -static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft, - struct cifs_ses *ses, - const struct nls_table *nls_cp) -{ - int rc = 0; - int len; - char *bcc_ptr = *pbcc_area; - - cFYI(1, "decode sessetup ascii. bleft %d", bleft); - - len = strnlen(bcc_ptr, bleft); - if (len >= bleft) - return rc; - - kfree(ses->serverOS); - - ses->serverOS = kzalloc(len + 1, GFP_KERNEL); - if (ses->serverOS) - strncpy(ses->serverOS, bcc_ptr, len); - if (strncmp(ses->serverOS, "OS/2", 4) == 0) { - cFYI(1, "OS/2 server"); - ses->flags |= CIFS_SES_OS2; - } - - bcc_ptr += len + 1; - bleft -= len + 1; - - len = strnlen(bcc_ptr, bleft); - if (len >= bleft) - return rc; - - kfree(ses->serverNOS); - - ses->serverNOS = kzalloc(len + 1, GFP_KERNEL); - if (ses->serverNOS) - strncpy(ses->serverNOS, bcc_ptr, len); - - bcc_ptr += len + 1; - bleft -= len + 1; - - len = strnlen(bcc_ptr, bleft); - if (len > bleft) - return rc; - - /* No domain field in LANMAN case. Domain is - returned by old servers in the SMB negprot response */ - /* BB For newer servers which do not support Unicode, - but thus do return domain here we could add parsing - for it later, but it is not very important */ - cFYI(1, "ascii: bytes left %d", bleft); - - return rc; -} - -static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, - struct cifs_ses *ses) -{ - unsigned int tioffset; /* challenge message target info area */ - unsigned int tilen; /* challenge message target info area length */ - - CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; - - if (blob_len < sizeof(CHALLENGE_MESSAGE)) { - cERROR(1, "challenge blob len %d too small", blob_len); - return -EINVAL; - } - - if (memcmp(pblob->Signature, "NTLMSSP", 8)) { - cERROR(1, "blob signature incorrect %s", pblob->Signature); - return -EINVAL; - } - if (pblob->MessageType != NtLmChallenge) { - cERROR(1, "Incorrect message type %d", pblob->MessageType); - return -EINVAL; - } - - memcpy(ses->ntlmssp->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE); - /* BB we could decode pblob->NegotiateFlags; some may be useful */ - /* In particular we can examine sign flags */ - /* BB spec says that if AvId field of MsvAvTimestamp is populated then - we must set the MIC field of the AUTHENTICATE_MESSAGE */ - ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags); - tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset); - tilen = le16_to_cpu(pblob->TargetInfoArray.Length); - if (tioffset > blob_len || tioffset + tilen > blob_len) { - cERROR(1, "tioffset + tilen too high %u + %u", tioffset, tilen); - return -EINVAL; - } - if (tilen) { - ses->auth_key.response = kmalloc(tilen, GFP_KERNEL); - if (!ses->auth_key.response) { - cERROR(1, "Challenge target info allocation failure"); - return -ENOMEM; - } - memcpy(ses->auth_key.response, bcc_ptr + tioffset, tilen); - ses->auth_key.len = tilen; - } - - return 0; -} - -/* BB Move to ntlmssp.c eventually */ - -/* We do not malloc the blob, it is passed in pbuffer, because - it is fixed size, and small, making this approach cleaner */ -static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, - struct cifs_ses *ses) -{ - NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer; - __u32 flags; - - memset(pbuffer, 0, sizeof(NEGOTIATE_MESSAGE)); - memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); - sec_blob->MessageType = NtLmNegotiate; - - /* BB is NTLMV2 session security format easier to use here? */ - flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | - NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | - NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; - if (ses->server->sec_mode & - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { - flags |= NTLMSSP_NEGOTIATE_SIGN; - if (!ses->server->session_estab) - flags |= NTLMSSP_NEGOTIATE_KEY_XCH; - } - - sec_blob->NegotiateFlags = cpu_to_le32(flags); - - sec_blob->WorkstationName.BufferOffset = 0; - sec_blob->WorkstationName.Length = 0; - sec_blob->WorkstationName.MaximumLength = 0; - - /* Domain name is sent on the Challenge not Negotiate NTLMSSP request */ - sec_blob->DomainName.BufferOffset = 0; - sec_blob->DomainName.Length = 0; - sec_blob->DomainName.MaximumLength = 0; -} - -/* We do not malloc the blob, it is passed in pbuffer, because its - maximum possible size is fixed and small, making this approach cleaner. - This function returns the length of the data in the blob */ -static int build_ntlmssp_auth_blob(unsigned char *pbuffer, - u16 *buflen, - struct cifs_ses *ses, - const struct nls_table *nls_cp) -{ - int rc; - AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; - __u32 flags; - unsigned char *tmp; - - memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); - sec_blob->MessageType = NtLmAuthenticate; - - flags = NTLMSSP_NEGOTIATE_56 | - NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | - NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | - NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; - if (ses->server->sec_mode & - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { - flags |= NTLMSSP_NEGOTIATE_SIGN; - if (!ses->server->session_estab) - flags |= NTLMSSP_NEGOTIATE_KEY_XCH; - } - - tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE); - sec_blob->NegotiateFlags = cpu_to_le32(flags); - - sec_blob->LmChallengeResponse.BufferOffset = - cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE)); - sec_blob->LmChallengeResponse.Length = 0; - sec_blob->LmChallengeResponse.MaximumLength = 0; - - sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); - rc = setup_ntlmv2_rsp(ses, nls_cp); - if (rc) { - cERROR(1, "Error %d during NTLMSSP authentication", rc); - goto setup_ntlmv2_ret; - } - memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE, - ses->auth_key.len - CIFS_SESS_KEY_SIZE); - tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE; - - sec_blob->NtChallengeResponse.Length = - cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE); - sec_blob->NtChallengeResponse.MaximumLength = - cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE); - - if (ses->domainName == NULL) { - sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); - sec_blob->DomainName.Length = 0; - sec_blob->DomainName.MaximumLength = 0; - tmp += 2; - } else { - int len; - len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName, - MAX_USERNAME_SIZE, nls_cp); - len *= 2; /* unicode is 2 bytes each */ - sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); - sec_blob->DomainName.Length = cpu_to_le16(len); - sec_blob->DomainName.MaximumLength = cpu_to_le16(len); - tmp += len; - } - - if (ses->user_name == NULL) { - sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); - sec_blob->UserName.Length = 0; - sec_blob->UserName.MaximumLength = 0; - tmp += 2; - } else { - int len; - len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name, - MAX_USERNAME_SIZE, nls_cp); - len *= 2; /* unicode is 2 bytes each */ - sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); - sec_blob->UserName.Length = cpu_to_le16(len); - sec_blob->UserName.MaximumLength = cpu_to_le16(len); - tmp += len; - } - - sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - pbuffer); - sec_blob->WorkstationName.Length = 0; - sec_blob->WorkstationName.MaximumLength = 0; - tmp += 2; - - if (((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) || - (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) - && !calc_seckey(ses)) { - memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); - sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); - sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); - sec_blob->SessionKey.MaximumLength = - cpu_to_le16(CIFS_CPHTXT_SIZE); - tmp += CIFS_CPHTXT_SIZE; - } else { - sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); - sec_blob->SessionKey.Length = 0; - sec_blob->SessionKey.MaximumLength = 0; - } - -setup_ntlmv2_ret: - *buflen = tmp - pbuffer; - return rc; -} - -int -CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses, - const struct nls_table *nls_cp) -{ - int rc = 0; - int wct; - struct smb_hdr *smb_buf; - char *bcc_ptr; - char *str_area; - SESSION_SETUP_ANDX *pSMB; - __u32 capabilities; - __u16 count; - int resp_buf_type; - struct kvec iov[3]; - enum securityEnum type; - __u16 action, bytes_remaining; - struct key *spnego_key = NULL; - __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ - u16 blob_len; - char *ntlmsspblob = NULL; - - if (ses == NULL) - return -EINVAL; - - type = ses->server->secType; - cFYI(1, "sess setup type %d", type); - if (type == RawNTLMSSP) { - /* if memory allocation is successful, caller of this function - * frees it. - */ - ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL); - if (!ses->ntlmssp) - return -ENOMEM; - } - -ssetup_ntlmssp_authenticate: - if (phase == NtLmChallenge) - phase = NtLmAuthenticate; /* if ntlmssp, now final phase */ - - if (type == LANMAN) { -#ifndef CONFIG_CIFS_WEAK_PW_HASH - /* LANMAN and plaintext are less secure and off by default. - So we make this explicitly be turned on in kconfig (in the - build) and turned on at runtime (changed from the default) - in proc/fs/cifs or via mount parm. Unfortunately this is - needed for old Win (e.g. Win95), some obscure NAS and OS/2 */ - return -EOPNOTSUPP; -#endif - wct = 10; /* lanman 2 style sessionsetup */ - } else if ((type == NTLM) || (type == NTLMv2)) { - /* For NTLMv2 failures eventually may need to retry NTLM */ - wct = 13; /* old style NTLM sessionsetup */ - } else /* same size: negotiate or auth, NTLMSSP or extended security */ - wct = 12; - - rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses, - (void **)&smb_buf); - if (rc) - return rc; - - pSMB = (SESSION_SETUP_ANDX *)smb_buf; - - capabilities = cifs_ssetup_hdr(ses, pSMB); - - /* we will send the SMB in three pieces: - a fixed length beginning part, an optional - SPNEGO blob (which can be zero length), and a - last part which will include the strings - and rest of bcc area. This allows us to avoid - a large buffer 17K allocation */ - iov[0].iov_base = (char *)pSMB; - iov[0].iov_len = be32_to_cpu(smb_buf->smb_buf_length) + 4; - - /* setting this here allows the code at the end of the function - to free the request buffer if there's an error */ - resp_buf_type = CIFS_SMALL_BUFFER; - - /* 2000 big enough to fit max user, domain, NOS name etc. */ - str_area = kmalloc(2000, GFP_KERNEL); - if (str_area == NULL) { - rc = -ENOMEM; - goto ssetup_exit; - } - bcc_ptr = str_area; - - ses->flags &= ~CIFS_SES_LANMAN; - - iov[1].iov_base = NULL; - iov[1].iov_len = 0; - - if (type == LANMAN) { -#ifdef CONFIG_CIFS_WEAK_PW_HASH - char lnm_session_key[CIFS_AUTH_RESP_SIZE]; - - pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE; - - /* no capabilities flags in old lanman negotiation */ - - pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE); - - /* Calculate hash with password and copy into bcc_ptr. - * Encryption Key (stored as in cryptkey) gets used if the - * security mode bit in Negottiate Protocol response states - * to use challenge/response method (i.e. Password bit is 1). - */ - - rc = calc_lanman_hash(ses->password, ses->server->cryptkey, - ses->server->sec_mode & SECMODE_PW_ENCRYPT ? - true : false, lnm_session_key); - - ses->flags |= CIFS_SES_LANMAN; - memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE); - bcc_ptr += CIFS_AUTH_RESP_SIZE; - - /* can not sign if LANMAN negotiated so no need - to calculate signing key? but what if server - changed to do higher than lanman dialect and - we reconnected would we ever calc signing_key? */ - - cFYI(1, "Negotiating LANMAN setting up strings"); - /* Unicode not allowed for LANMAN dialects */ - ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); -#endif - } else if (type == NTLM) { - pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); - pSMB->req_no_secext.CaseInsensitivePasswordLength = - cpu_to_le16(CIFS_AUTH_RESP_SIZE); - pSMB->req_no_secext.CaseSensitivePasswordLength = - cpu_to_le16(CIFS_AUTH_RESP_SIZE); - - /* calculate ntlm response and session key */ - rc = setup_ntlm_response(ses, nls_cp); - if (rc) { - cERROR(1, "Error %d during NTLM authentication", rc); - goto ssetup_exit; - } - - /* copy ntlm response */ - memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, - CIFS_AUTH_RESP_SIZE); - bcc_ptr += CIFS_AUTH_RESP_SIZE; - memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, - CIFS_AUTH_RESP_SIZE); - bcc_ptr += CIFS_AUTH_RESP_SIZE; - - if (ses->capabilities & CAP_UNICODE) { - /* unicode strings must be word aligned */ - if (iov[0].iov_len % 2) { - *bcc_ptr = 0; - bcc_ptr++; - } - unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); - } else - ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); - } else if (type == NTLMv2) { - pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); - - /* LM2 password would be here if we supported it */ - pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; - - /* calculate nlmv2 response and session key */ - rc = setup_ntlmv2_rsp(ses, nls_cp); - if (rc) { - cERROR(1, "Error %d during NTLMv2 authentication", rc); - goto ssetup_exit; - } - memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, - ses->auth_key.len - CIFS_SESS_KEY_SIZE); - bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE; - - /* set case sensitive password length after tilen may get - * assigned, tilen is 0 otherwise. - */ - pSMB->req_no_secext.CaseSensitivePasswordLength = - cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE); - - if (ses->capabilities & CAP_UNICODE) { - if (iov[0].iov_len % 2) { - *bcc_ptr = 0; - bcc_ptr++; - } - unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); - } else - ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); - } else if (type == Kerberos) { -#ifdef CONFIG_CIFS_UPCALL - struct cifs_spnego_msg *msg; - - spnego_key = cifs_get_spnego_key(ses); - if (IS_ERR(spnego_key)) { - rc = PTR_ERR(spnego_key); - spnego_key = NULL; - goto ssetup_exit; - } - - msg = spnego_key->payload.data; - /* check version field to make sure that cifs.upcall is - sending us a response in an expected form */ - if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) { - cERROR(1, "incorrect version of cifs.upcall (expected" - " %d but got %d)", - CIFS_SPNEGO_UPCALL_VERSION, msg->version); - rc = -EKEYREJECTED; - goto ssetup_exit; - } - - ses->auth_key.response = kmalloc(msg->sesskey_len, GFP_KERNEL); - if (!ses->auth_key.response) { - cERROR(1, "Kerberos can't allocate (%u bytes) memory", - msg->sesskey_len); - rc = -ENOMEM; - goto ssetup_exit; - } - memcpy(ses->auth_key.response, msg->data, msg->sesskey_len); - ses->auth_key.len = msg->sesskey_len; - - pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; - capabilities |= CAP_EXTENDED_SECURITY; - pSMB->req.Capabilities = cpu_to_le32(capabilities); - iov[1].iov_base = msg->data + msg->sesskey_len; - iov[1].iov_len = msg->secblob_len; - pSMB->req.SecurityBlobLength = cpu_to_le16(iov[1].iov_len); - - if (ses->capabilities & CAP_UNICODE) { - /* unicode strings must be word aligned */ - if ((iov[0].iov_len + iov[1].iov_len) % 2) { - *bcc_ptr = 0; - bcc_ptr++; - } - unicode_oslm_strings(&bcc_ptr, nls_cp); - unicode_domain_string(&bcc_ptr, ses, nls_cp); - } else - /* BB: is this right? */ - ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); -#else /* ! CONFIG_CIFS_UPCALL */ - cERROR(1, "Kerberos negotiated but upcall support disabled!"); - rc = -ENOSYS; - goto ssetup_exit; -#endif /* CONFIG_CIFS_UPCALL */ - } else if (type == RawNTLMSSP) { - if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) { - cERROR(1, "NTLMSSP requires Unicode support"); - rc = -ENOSYS; - goto ssetup_exit; - } - - cFYI(1, "ntlmssp session setup phase %d", phase); - pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; - capabilities |= CAP_EXTENDED_SECURITY; - pSMB->req.Capabilities |= cpu_to_le32(capabilities); - switch(phase) { - case NtLmNegotiate: - build_ntlmssp_negotiate_blob( - pSMB->req.SecurityBlob, ses); - iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); - iov[1].iov_base = pSMB->req.SecurityBlob; - pSMB->req.SecurityBlobLength = - cpu_to_le16(sizeof(NEGOTIATE_MESSAGE)); - break; - case NtLmAuthenticate: - /* - * 5 is an empirical value, large enough to hold - * authenticate message plus max 10 of av paris, - * domain, user, workstation names, flags, etc. - */ - ntlmsspblob = kzalloc( - 5*sizeof(struct _AUTHENTICATE_MESSAGE), - GFP_KERNEL); - if (!ntlmsspblob) { - cERROR(1, "Can't allocate NTLMSSP blob"); - rc = -ENOMEM; - goto ssetup_exit; - } - - rc = build_ntlmssp_auth_blob(ntlmsspblob, - &blob_len, ses, nls_cp); - if (rc) - goto ssetup_exit; - iov[1].iov_len = blob_len; - iov[1].iov_base = ntlmsspblob; - pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len); - /* - * Make sure that we tell the server that we are using - * the uid that it just gave us back on the response - * (challenge) - */ - smb_buf->Uid = ses->Suid; - break; - default: - cERROR(1, "invalid phase %d", phase); - rc = -ENOSYS; - goto ssetup_exit; - } - /* unicode strings must be word aligned */ - if ((iov[0].iov_len + iov[1].iov_len) % 2) { - *bcc_ptr = 0; - bcc_ptr++; - } - unicode_oslm_strings(&bcc_ptr, nls_cp); - } else { - cERROR(1, "secType %d not supported!", type); - rc = -ENOSYS; - goto ssetup_exit; - } - - iov[2].iov_base = str_area; - iov[2].iov_len = (long) bcc_ptr - (long) str_area; - - count = iov[1].iov_len + iov[2].iov_len; - smb_buf->smb_buf_length = - cpu_to_be32(be32_to_cpu(smb_buf->smb_buf_length) + count); - - put_bcc(count, smb_buf); - - rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, - CIFS_LOG_ERROR); - /* SMB request buf freed in SendReceive2 */ - - pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base; - smb_buf = (struct smb_hdr *)iov[0].iov_base; - - if ((type == RawNTLMSSP) && (smb_buf->Status.CifsError == - cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))) { - if (phase != NtLmNegotiate) { - cERROR(1, "Unexpected more processing error"); - goto ssetup_exit; - } - /* NTLMSSP Negotiate sent now processing challenge (response) */ - phase = NtLmChallenge; /* process ntlmssp challenge */ - rc = 0; /* MORE_PROC rc is not an error here, but expected */ - } - if (rc) - goto ssetup_exit; - - if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) { - rc = -EIO; - cERROR(1, "bad word count %d", smb_buf->WordCount); - goto ssetup_exit; - } - action = le16_to_cpu(pSMB->resp.Action); - if (action & GUEST_LOGIN) - cFYI(1, "Guest login"); /* BB mark SesInfo struct? */ - ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */ - cFYI(1, "UID = %d ", ses->Suid); - /* response can have either 3 or 4 word count - Samba sends 3 */ - /* and lanman response is 3 */ - bytes_remaining = get_bcc(smb_buf); - bcc_ptr = pByteArea(smb_buf); - - if (smb_buf->WordCount == 4) { - blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength); - if (blob_len > bytes_remaining) { - cERROR(1, "bad security blob length %d", blob_len); - rc = -EINVAL; - goto ssetup_exit; - } - if (phase == NtLmChallenge) { - rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses); - /* now goto beginning for ntlmssp authenticate phase */ - if (rc) - goto ssetup_exit; - } - bcc_ptr += blob_len; - bytes_remaining -= blob_len; - } - - /* BB check if Unicode and decode strings */ - if (bytes_remaining == 0) { - /* no string area to decode, do nothing */ - } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) { - /* unicode string area must be word-aligned */ - if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { - ++bcc_ptr; - --bytes_remaining; - } - decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp); - } else { - rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, - ses, nls_cp); - } - -ssetup_exit: - if (spnego_key) { - key_revoke(spnego_key); - key_put(spnego_key); - } - kfree(str_area); - kfree(ntlmsspblob); - ntlmsspblob = NULL; - if (resp_buf_type == CIFS_SMALL_BUFFER) { - cFYI(1, "ssetup freeing small buf %p", iov[0].iov_base); - cifs_small_buf_release(iov[0].iov_base); - } else if (resp_buf_type == CIFS_LARGE_BUFFER) - cifs_buf_release(iov[0].iov_base); - - /* if ntlmssp, and negotiate succeeded, proceed to authenticate phase */ - if ((phase == NtLmChallenge) && (rc == 0)) - goto ssetup_ntlmssp_authenticate; - - return rc; -} diff --git a/ANDROID_3.4.5/fs/cifs/smbencrypt.c b/ANDROID_3.4.5/fs/cifs/smbencrypt.c deleted file mode 100644 index d5cd9aa7..00000000 --- a/ANDROID_3.4.5/fs/cifs/smbencrypt.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - SMB parameters and setup - Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Luke Kenneth Casson Leighton 1996-2000 - Modified by Jeremy Allison 1995. - Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003 - Modified by Steve French (sfrench@us.ibm.com) 2002-2003 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/fs.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/random.h> -#include "cifs_unicode.h" -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifs_debug.h" -#include "cifsproto.h" - -#ifndef false -#define false 0 -#endif -#ifndef true -#define true 1 -#endif - -/* following came from the other byteorder.h to avoid include conflicts */ -#define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) -#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) -#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val))) - -static void -str_to_key(unsigned char *str, unsigned char *key) -{ - int i; - - key[0] = str[0] >> 1; - key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2); - key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3); - key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4); - key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5); - key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6); - key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7); - key[7] = str[6] & 0x7F; - for (i = 0; i < 8; i++) - key[i] = (key[i] << 1); -} - -static int -smbhash(unsigned char *out, const unsigned char *in, unsigned char *key) -{ - int rc; - unsigned char key2[8]; - struct crypto_blkcipher *tfm_des; - struct scatterlist sgin, sgout; - struct blkcipher_desc desc; - - str_to_key(key, key2); - - tfm_des = crypto_alloc_blkcipher("ecb(des)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm_des)) { - rc = PTR_ERR(tfm_des); - cERROR(1, "could not allocate des crypto API\n"); - goto smbhash_err; - } - - desc.tfm = tfm_des; - - crypto_blkcipher_setkey(tfm_des, key2, 8); - - sg_init_one(&sgin, in, 8); - sg_init_one(&sgout, out, 8); - - rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, 8); - if (rc) - cERROR(1, "could not encrypt crypt key rc: %d\n", rc); - - crypto_free_blkcipher(tfm_des); -smbhash_err: - return rc; -} - -static int -E_P16(unsigned char *p14, unsigned char *p16) -{ - int rc; - unsigned char sp8[8] = - { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; - - rc = smbhash(p16, sp8, p14); - if (rc) - return rc; - rc = smbhash(p16 + 8, sp8, p14 + 7); - return rc; -} - -static int -E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24) -{ - int rc; - - rc = smbhash(p24, c8, p21); - if (rc) - return rc; - rc = smbhash(p24 + 8, c8, p21 + 7); - if (rc) - return rc; - rc = smbhash(p24 + 16, c8, p21 + 14); - return rc; -} - -/* produce a md4 message digest from data of length n bytes */ -int -mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len) -{ - int rc; - unsigned int size; - struct crypto_shash *md4; - struct sdesc *sdescmd4; - - md4 = crypto_alloc_shash("md4", 0, 0); - if (IS_ERR(md4)) { - rc = PTR_ERR(md4); - cERROR(1, "%s: Crypto md4 allocation error %d\n", __func__, rc); - return rc; - } - size = sizeof(struct shash_desc) + crypto_shash_descsize(md4); - sdescmd4 = kmalloc(size, GFP_KERNEL); - if (!sdescmd4) { - rc = -ENOMEM; - cERROR(1, "%s: Memory allocation failure\n", __func__); - goto mdfour_err; - } - sdescmd4->shash.tfm = md4; - sdescmd4->shash.flags = 0x0; - - rc = crypto_shash_init(&sdescmd4->shash); - if (rc) { - cERROR(1, "%s: Could not init md4 shash\n", __func__); - goto mdfour_err; - } - rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len); - if (rc) { - cERROR(1, "%s: Could not update with link_str\n", __func__); - goto mdfour_err; - } - rc = crypto_shash_final(&sdescmd4->shash, md4_hash); - if (rc) - cERROR(1, "%s: Could not genereate md4 hash\n", __func__); - -mdfour_err: - crypto_free_shash(md4); - kfree(sdescmd4); - - return rc; -} - -/* - This implements the X/Open SMB password encryption - It takes a password, a 8 byte "crypt key" and puts 24 bytes of - encrypted password into p24 */ -/* Note that password must be uppercased and null terminated */ -int -SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24) -{ - int rc; - unsigned char p14[14], p16[16], p21[21]; - - memset(p14, '\0', 14); - memset(p16, '\0', 16); - memset(p21, '\0', 21); - - memcpy(p14, passwd, 14); - rc = E_P16(p14, p16); - if (rc) - return rc; - - memcpy(p21, p16, 16); - rc = E_P24(p21, c8, p24); - - return rc; -} - -/* - * Creates the MD4 Hash of the users password in NT UNICODE. - */ - -int -E_md4hash(const unsigned char *passwd, unsigned char *p16, - const struct nls_table *codepage) -{ - int rc; - int len; - __le16 wpwd[129]; - - /* Password cannot be longer than 128 characters */ - if (passwd) /* Password must be converted to NT unicode */ - len = cifs_strtoUTF16(wpwd, passwd, 128, codepage); - else { - len = 0; - *wpwd = 0; /* Ensure string is null terminated */ - } - - rc = mdfour(p16, (unsigned char *) wpwd, len * sizeof(__le16)); - memset(wpwd, 0, 129 * sizeof(__le16)); - - return rc; -} - -/* Does the NT MD4 hash then des encryption. */ -int -SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24, - const struct nls_table *codepage) -{ - int rc; - unsigned char p16[16], p21[21]; - - memset(p16, '\0', 16); - memset(p21, '\0', 21); - - rc = E_md4hash(passwd, p16, codepage); - if (rc) { - cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); - return rc; - } - memcpy(p21, p16, 16); - rc = E_P24(p21, c8, p24); - return rc; -} diff --git a/ANDROID_3.4.5/fs/cifs/smberr.h b/ANDROID_3.4.5/fs/cifs/smberr.h deleted file mode 100644 index 7f16cb82..00000000 --- a/ANDROID_3.4.5/fs/cifs/smberr.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * fs/cifs/smberr.h - * - * Copyright (c) International Business Machines Corp., 2002,2004 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * See Error Codes section of the SNIA CIFS Specification - * for more information - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define SUCCESS 0x00 /* The request was successful. */ -#define ERRDOS 0x01 /* Error is from the core DOS operating system set */ -#define ERRSRV 0x02 /* Error is generated by the file server daemon */ -#define ERRHRD 0x03 /* Error is a hardware error. */ -#define ERRCMD 0xFF /* Command was not in the "SMB" format. */ - -/* The following error codes may be generated with the SUCCESS error class.*/ - -/*#define SUCCESS 0 The request was successful. */ - -/* The following error codes may be generated with the ERRDOS error class.*/ - -#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. */ -#define ERRbadfile 2 /* File not found. The last component - of a file's pathname could not be - found. */ -#define ERRbadpath 3 /* Directory invalid. A directory - component in a pathname could not be - found. */ -#define ERRnofids 4 /* Too many open files. The server has - no file handles available. */ -#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 */ -#define ERRbadfid 6 /* Invalid file handle. The file handle - specified was not recognized by the - server. */ -#define ERRbadmcb 7 /* Memory control blocks destroyed. */ -#define ERRnomem 8 /* Insufficient server memory to - perform the requested function. */ -#define ERRbadmem 9 /* Invalid memory block address. */ -#define ERRbadenv 10 /* Invalid environment. */ -#define ERRbadformat 11 /* Invalid format. */ -#define ERRbadaccess 12 /* Invalid open mode. */ -#define ERRbaddata 13 /* Invalid data (generated only by - IOCTL calls within the server). */ -#define ERRbaddrive 15 /* Invalid drive specified. */ -#define ERRremcd 16 /* A Delete Directory request attempted - to remove the server's current - directory. */ -#define ERRdiffdevice 17 /* Not same device (e.g., a cross - volume rename was attempted */ -#define ERRnofiles 18 /* A File Search command can find no - more files matching the specified - criteria. */ -#define ERRwriteprot 19 /* media is write protected */ -#define ERRgeneral 31 -#define ERRbadshare 32 /* The sharing mode specified for an - Open conflicts with existing FIDs on - the file. */ -#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. */ -#define ERRunsup 50 -#define ERRnosuchshare 67 -#define ERRfilexists 80 /* The file named in the request - already exists. */ -#define ERRinvparm 87 -#define ERRdiskfull 112 -#define ERRinvname 123 -#define ERRinvlevel 124 -#define ERRdirnotempty 145 -#define ERRnotlocked 158 -#define ERRcancelviolation 173 -#define ERRalreadyexists 183 -#define ERRbadpipe 230 -#define ERRpipebusy 231 -#define ERRpipeclosing 232 -#define ERRnotconnected 233 -#define ERRmoredata 234 -#define ERReasnotsupported 282 -#define ErrQuota 0x200 /* The operation would cause a quota - limit to be exceeded. */ -#define ErrNotALink 0x201 /* A link operation was performed on a - pathname that was not a link. */ - -/* Below errors are used internally (do not come over the wire) for passthrough - from STATUS codes to POSIX only */ -#define ERRsymlink 0xFFFD -#define ErrTooManyLinks 0xFFFE - -/* Following error codes may be generated with the ERRSRV error class.*/ - -#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. */ -#define ERRbadpw 2 /* Bad password - name/password pair in - a TreeConnect or Session Setup are - invalid. */ -#define ERRbadtype 3 /* used for indicating DFS referral - needed */ -#define ERRaccess 4 /* The client does not have the - necessary access rights within the - specified context for requested - function. */ -#define ERRinvtid 5 /* The Tid specified in a command was - invalid. */ -#define ERRinvnetname 6 /* Invalid network name in tree - connect. */ -#define ERRinvdevice 7 /* Invalid device - printer request - made to non-printer connection or - non-printer request made to printer - connection. */ -#define ERRqfull 49 /* Print queue full (files) -- returned - by open print file. */ -#define ERRqtoobig 50 /* Print queue full -- no space. */ -#define ERRqeof 51 /* EOF on print queue dump */ -#define ERRinvpfid 52 /* Invalid print file FID. */ -#define ERRsmbcmd 64 /* The server did not recognize the - command received. */ -#define ERRsrverror 65 /* The server encountered an internal - error, e.g., system file - unavailable. */ -#define ERRbadBID 66 /* (obsolete) */ -#define ERRfilespecs 67 /* The Fid and pathname parameters - contained an invalid combination of - values. */ -#define ERRbadLink 68 /* (obsolete) */ -#define ERRbadpermits 69 /* The access permissions specified for - a file or directory are not a valid - combination. */ -#define ERRbadPID 70 -#define ERRsetattrmode 71 /* attribute (mode) is invalid */ -#define ERRpaused 81 /* Server is paused */ -#define ERRmsgoff 82 /* reserved - messaging off */ -#define ERRnoroom 83 /* reserved - no room for message */ -#define ERRrmuns 87 /* reserved - too many remote names */ -#define ERRtimeout 88 /* operation timed out */ -#define ERRnoresource 89 /* No resources available for request - */ -#define ERRtoomanyuids 90 /* Too many UIDs active on this session - */ -#define ERRbaduid 91 /* The UID is not known as a valid user - */ -#define ERRusempx 250 /* temporarily unable to use raw */ -#define ERRusestd 251 /* temporarily unable to use either raw - or mpx */ -#define ERR_NOTIFY_ENUM_DIR 1024 -#define ERRnoSuchUser 2238 /* user account does not exist */ -#define ERRaccountexpired 2239 -#define ERRbadclient 2240 /* can not logon from this client */ -#define ERRbadLogonTime 2241 /* logon hours do not allow this */ -#define ERRpasswordExpired 2242 -#define ERRnetlogonNotStarted 2455 -#define ERRnosupport 0xFFFF diff --git a/ANDROID_3.4.5/fs/cifs/smbfsctl.h b/ANDROID_3.4.5/fs/cifs/smbfsctl.h deleted file mode 100644 index 7056b891..00000000 --- a/ANDROID_3.4.5/fs/cifs/smbfsctl.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * fs/cifs/smbfsctl.h: SMB, CIFS, SMB2 FSCTL definitions - * - * Copyright (c) International Business Machines Corp., 2002,2009 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* IOCTL information */ -/* - * List of ioctl/fsctl function codes that are or could be useful in the - * future to remote clients like cifs or SMB2 client. There is probably - * a slightly larger set of fsctls that NTFS local filesystem could handle, - * including the seven below that we do not have struct definitions for. - * Even with protocol definitions for most of these now available, we still - * need to do some experimentation to identify which are practical to do - * remotely. Some of the following, such as the encryption/compression ones - * could be invoked from tools via a specialized hook into the VFS rather - * than via the standard vfs entry points - */ -#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000 -#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004 -#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008 -#define FSCTL_LOCK_VOLUME 0x00090018 -#define FSCTL_UNLOCK_VOLUME 0x0009001C -#define FSCTL_IS_PATHNAME_VALID 0x0009002C /* BB add struct */ -#define FSCTL_GET_COMPRESSION 0x0009003C /* BB add struct */ -#define FSCTL_SET_COMPRESSION 0x0009C040 /* BB add struct */ -#define FSCTL_QUERY_FAT_BPB 0x00090058 /* BB add struct */ -/* Verify the next FSCTL number, we had it as 0x00090090 before */ -#define FSCTL_FILESYSTEM_GET_STATS 0x00090060 /* BB add struct */ -#define FSCTL_GET_NTFS_VOLUME_DATA 0x00090064 /* BB add struct */ -#define FSCTL_GET_RETRIEVAL_POINTERS 0x00090073 /* BB add struct */ -#define FSCTL_IS_VOLUME_DIRTY 0x00090078 /* BB add struct */ -#define FSCTL_ALLOW_EXTENDED_DASD_IO 0x00090083 /* BB add struct */ -#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C -#define FSCTL_FIND_FILES_BY_SID 0x0009008F /* BB add struct */ -#define FSCTL_SET_OBJECT_ID 0x00090098 /* BB add struct */ -#define FSCTL_GET_OBJECT_ID 0x0009009C /* BB add struct */ -#define FSCTL_DELETE_OBJECT_ID 0x000900A0 /* BB add struct */ -#define FSCTL_SET_REPARSE_POINT 0x000900A4 /* BB add struct */ -#define FSCTL_GET_REPARSE_POINT 0x000900A8 /* BB add struct */ -#define FSCTL_DELETE_REPARSE_POINT 0x000900AC /* BB add struct */ -#define FSCTL_SET_OBJECT_ID_EXTENDED 0x000900BC /* BB add struct */ -#define FSCTL_CREATE_OR_GET_OBJECT_ID 0x000900C0 /* BB add struct */ -#define FSCTL_SET_SPARSE 0x000900C4 /* BB add struct */ -#define FSCTL_SET_ZERO_DATA 0x000900C8 /* BB add struct */ -#define FSCTL_SET_ENCRYPTION 0x000900D7 /* BB add struct */ -#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB /* BB add struct */ -#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF /* BB add struct */ -#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3 /* BB add struct */ -#define FSCTL_READ_FILE_USN_DATA 0x000900EB /* BB add struct */ -#define FSCTL_WRITE_USN_CLOSE_RECORD 0x000900EF /* BB add struct */ -#define FSCTL_SIS_COPYFILE 0x00090100 /* BB add struct */ -#define FSCTL_RECALL_FILE 0x00090117 /* BB add struct */ -#define FSCTL_QUERY_SPARING_INFO 0x00090138 /* BB add struct */ -#define FSCTL_SET_ZERO_ON_DEALLOC 0x00090194 /* BB add struct */ -#define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4 /* BB add struct */ -#define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF /* BB add struct */ -#define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134 /* BB add struct */ -#define FSCTL_SIS_LINK_FILES 0x0009C104 -#define FSCTL_PIPE_PEEK 0x0011400C /* BB add struct */ -#define FSCTL_PIPE_TRANSCEIVE 0x0011C017 /* BB add struct */ -/* strange that the number for this op is not sequential with previous op */ -#define FSCTL_PIPE_WAIT 0x00110018 /* BB add struct */ -#define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */ -#define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */ - -#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 -#define IO_REPARSE_TAG_HSM 0xC0000004 -#define IO_REPARSE_TAG_SIS 0x80000007 diff --git a/ANDROID_3.4.5/fs/cifs/transport.c b/ANDROID_3.4.5/fs/cifs/transport.c deleted file mode 100644 index 09613365..00000000 --- a/ANDROID_3.4.5/fs/cifs/transport.c +++ /dev/null @@ -1,956 +0,0 @@ -/* - * fs/cifs/transport.c - * - * Copyright (C) International Business Machines Corp., 2002,2008 - * Author(s): Steve French (sfrench@us.ibm.com) - * Jeremy Allison (jra@samba.org) 2006. - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/fs.h> -#include <linux/list.h> -#include <linux/gfp.h> -#include <linux/wait.h> -#include <linux/net.h> -#include <linux/delay.h> -#include <linux/freezer.h> -#include <asm/uaccess.h> -#include <asm/processor.h> -#include <linux/mempool.h> -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifs_debug.h" - -extern mempool_t *cifs_mid_poolp; - -static void -wake_up_task(struct mid_q_entry *mid) -{ - wake_up_process(mid->callback_data); -} - -struct mid_q_entry * -AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) -{ - struct mid_q_entry *temp; - - if (server == NULL) { - cERROR(1, "Null TCP session in AllocMidQEntry"); - return NULL; - } - - temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS); - if (temp == NULL) - return temp; - else { - memset(temp, 0, sizeof(struct mid_q_entry)); - temp->mid = smb_buffer->Mid; /* always LE */ - temp->pid = current->pid; - temp->command = cpu_to_le16(smb_buffer->Command); - cFYI(1, "For smb_command %d", smb_buffer->Command); - /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */ - /* when mid allocated can be before when sent */ - temp->when_alloc = jiffies; - - /* - * The default is for the mid to be synchronous, so the - * default callback just wakes up the current task. - */ - temp->callback = wake_up_task; - temp->callback_data = current; - } - - atomic_inc(&midCount); - temp->mid_state = MID_REQUEST_ALLOCATED; - return temp; -} - -void -DeleteMidQEntry(struct mid_q_entry *midEntry) -{ -#ifdef CONFIG_CIFS_STATS2 - unsigned long now; -#endif - midEntry->mid_state = MID_FREE; - atomic_dec(&midCount); - if (midEntry->large_buf) - cifs_buf_release(midEntry->resp_buf); - else - cifs_small_buf_release(midEntry->resp_buf); -#ifdef CONFIG_CIFS_STATS2 - now = jiffies; - /* commands taking longer than one second are indications that - something is wrong, unless it is quite a slow link or server */ - if ((now - midEntry->when_alloc) > HZ) { - if ((cifsFYI & CIFS_TIMER) && - (midEntry->command != cpu_to_le16(SMB_COM_LOCKING_ANDX))) { - printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %llu", - midEntry->command, midEntry->mid); - printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n", - now - midEntry->when_alloc, - now - midEntry->when_sent, - now - midEntry->when_received); - } - } -#endif - mempool_free(midEntry, cifs_mid_poolp); -} - -static void -delete_mid(struct mid_q_entry *mid) -{ - spin_lock(&GlobalMid_Lock); - list_del(&mid->qhead); - spin_unlock(&GlobalMid_Lock); - - DeleteMidQEntry(mid); -} - -static int -smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) -{ - int rc = 0; - int i = 0; - struct msghdr smb_msg; - __be32 *buf_len = (__be32 *)(iov[0].iov_base); - unsigned int len = iov[0].iov_len; - unsigned int total_len; - int first_vec = 0; - unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base); - struct socket *ssocket = server->ssocket; - - if (ssocket == NULL) - return -ENOTSOCK; /* BB eventually add reconnect code here */ - - smb_msg.msg_name = (struct sockaddr *) &server->dstaddr; - smb_msg.msg_namelen = sizeof(struct sockaddr); - smb_msg.msg_control = NULL; - smb_msg.msg_controllen = 0; - if (server->noblocksnd) - smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; - else - smb_msg.msg_flags = MSG_NOSIGNAL; - - total_len = 0; - for (i = 0; i < n_vec; i++) - total_len += iov[i].iov_len; - - cFYI(1, "Sending smb: total_len %d", total_len); - dump_smb(iov[0].iov_base, len); - - i = 0; - while (total_len) { - rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec], - n_vec - first_vec, total_len); - if ((rc == -ENOSPC) || (rc == -EAGAIN)) { - i++; - /* - * If blocking send we try 3 times, since each can block - * for 5 seconds. For nonblocking we have to try more - * but wait increasing amounts of time allowing time for - * socket to clear. The overall time we wait in either - * case to send on the socket is about 15 seconds. - * Similarly we wait for 15 seconds for a response from - * the server in SendReceive[2] for the server to send - * a response back for most types of requests (except - * SMB Write past end of file which can be slow, and - * blocking lock operations). NFS waits slightly longer - * than CIFS, but this can make it take longer for - * nonresponsive servers to be detected and 15 seconds - * is more than enough time for modern networks to - * send a packet. In most cases if we fail to send - * after the retries we will kill the socket and - * reconnect which may clear the network problem. - */ - if ((i >= 14) || (!server->noblocksnd && (i > 2))) { - cERROR(1, "sends on sock %p stuck for 15 seconds", - ssocket); - rc = -EAGAIN; - break; - } - msleep(1 << i); - continue; - } - if (rc < 0) - break; - - if (rc == total_len) { - total_len = 0; - break; - } else if (rc > total_len) { - cERROR(1, "sent %d requested %d", rc, total_len); - break; - } - if (rc == 0) { - /* should never happen, letting socket clear before - retrying is our only obvious option here */ - cERROR(1, "tcp sent no data"); - msleep(500); - continue; - } - total_len -= rc; - /* the line below resets i */ - for (i = first_vec; i < n_vec; i++) { - if (iov[i].iov_len) { - if (rc > iov[i].iov_len) { - rc -= iov[i].iov_len; - iov[i].iov_len = 0; - } else { - iov[i].iov_base += rc; - iov[i].iov_len -= rc; - first_vec = i; - break; - } - } - } - i = 0; /* in case we get ENOSPC on the next send */ - } - - if ((total_len > 0) && (total_len != smb_buf_length + 4)) { - cFYI(1, "partial send (%d remaining), terminating session", - total_len); - /* If we have only sent part of an SMB then the next SMB - could be taken as the remainder of this one. We need - to kill the socket so the server throws away the partial - SMB */ - server->tcpStatus = CifsNeedReconnect; - } - - if (rc < 0 && rc != -EINTR) - cERROR(1, "Error %d sending data on socket to server", rc); - else - rc = 0; - - /* Don't want to modify the buffer as a side effect of this call. */ - *buf_len = cpu_to_be32(smb_buf_length); - - return rc; -} - -int -smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer, - unsigned int smb_buf_length) -{ - struct kvec iov; - - iov.iov_base = smb_buffer; - iov.iov_len = smb_buf_length + 4; - - return smb_sendv(server, &iov, 1); -} - -static int -wait_for_free_credits(struct TCP_Server_Info *server, const int optype, - int *credits) -{ - int rc; - - spin_lock(&server->req_lock); - if (optype == CIFS_ASYNC_OP) { - /* oplock breaks must not be held up */ - server->in_flight++; - *credits -= 1; - spin_unlock(&server->req_lock); - return 0; - } - - while (1) { - if (*credits <= 0) { - spin_unlock(&server->req_lock); - cifs_num_waiters_inc(server); - rc = wait_event_killable(server->request_q, - has_credits(server, credits)); - cifs_num_waiters_dec(server); - if (rc) - return rc; - spin_lock(&server->req_lock); - } else { - if (server->tcpStatus == CifsExiting) { - spin_unlock(&server->req_lock); - return -ENOENT; - } - - /* - * Can not count locking commands against total - * as they are allowed to block on server. - */ - - /* update # of requests on the wire to server */ - if (optype != CIFS_BLOCKING_OP) { - *credits -= 1; - server->in_flight++; - } - spin_unlock(&server->req_lock); - break; - } - } - return 0; -} - -static int -wait_for_free_request(struct TCP_Server_Info *server, const int optype) -{ - return wait_for_free_credits(server, optype, get_credits_field(server)); -} - -static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, - struct mid_q_entry **ppmidQ) -{ - if (ses->server->tcpStatus == CifsExiting) { - return -ENOENT; - } - - if (ses->server->tcpStatus == CifsNeedReconnect) { - cFYI(1, "tcp session dead - return to caller to retry"); - return -EAGAIN; - } - - if (ses->status != CifsGood) { - /* check if SMB session is bad because we are setting it up */ - if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && - (in_buf->Command != SMB_COM_NEGOTIATE)) - return -EAGAIN; - /* else ok - we are setting up session */ - } - *ppmidQ = AllocMidQEntry(in_buf, ses->server); - if (*ppmidQ == NULL) - return -ENOMEM; - spin_lock(&GlobalMid_Lock); - list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q); - spin_unlock(&GlobalMid_Lock); - return 0; -} - -static int -wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) -{ - int error; - - error = wait_event_freezekillable(server->response_q, - midQ->mid_state != MID_REQUEST_SUBMITTED); - if (error < 0) - return -ERESTARTSYS; - - return 0; -} - -static int -cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov, - unsigned int nvec, struct mid_q_entry **ret_mid) -{ - int rc; - struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base; - struct mid_q_entry *mid; - - /* enable signing if server requires it */ - if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) - hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - - mid = AllocMidQEntry(hdr, server); - if (mid == NULL) - return -ENOMEM; - - /* put it on the pending_mid_q */ - spin_lock(&GlobalMid_Lock); - list_add_tail(&mid->qhead, &server->pending_mid_q); - spin_unlock(&GlobalMid_Lock); - - rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number); - if (rc) - delete_mid(mid); - *ret_mid = mid; - return rc; -} - -/* - * Send a SMB request and set the callback function in the mid to handle - * the result. Caller is responsible for dealing with timeouts. - */ -int -cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, - unsigned int nvec, mid_receive_t *receive, - mid_callback_t *callback, void *cbdata, bool ignore_pend) -{ - int rc; - struct mid_q_entry *mid; - - rc = wait_for_free_request(server, ignore_pend ? CIFS_ASYNC_OP : 0); - if (rc) - return rc; - - mutex_lock(&server->srv_mutex); - rc = cifs_setup_async_request(server, iov, nvec, &mid); - if (rc) { - mutex_unlock(&server->srv_mutex); - cifs_add_credits(server, 1); - wake_up(&server->request_q); - return rc; - } - - mid->receive = receive; - mid->callback = callback; - mid->callback_data = cbdata; - mid->mid_state = MID_REQUEST_SUBMITTED; - - cifs_in_send_inc(server); - rc = smb_sendv(server, iov, nvec); - cifs_in_send_dec(server); - cifs_save_when_sent(mid); - mutex_unlock(&server->srv_mutex); - - if (rc) - goto out_err; - - return rc; -out_err: - delete_mid(mid); - cifs_add_credits(server, 1); - wake_up(&server->request_q); - return rc; -} - -/* - * - * Send an SMB Request. No response info (other than return code) - * needs to be parsed. - * - * flags indicate the type of request buffer and how long to wait - * and whether to log NT STATUS code (error) before mapping it to POSIX error - * - */ -int -SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, - char *in_buf, int flags) -{ - int rc; - struct kvec iov[1]; - int resp_buf_type; - - iov[0].iov_base = in_buf; - iov[0].iov_len = get_rfc1002_length(in_buf) + 4; - flags |= CIFS_NO_RESP; - rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); - cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc); - - return rc; -} - -static int -cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) -{ - int rc = 0; - - cFYI(1, "%s: cmd=%d mid=%llu state=%d", __func__, - le16_to_cpu(mid->command), mid->mid, mid->mid_state); - - spin_lock(&GlobalMid_Lock); - switch (mid->mid_state) { - case MID_RESPONSE_RECEIVED: - spin_unlock(&GlobalMid_Lock); - return rc; - case MID_RETRY_NEEDED: - rc = -EAGAIN; - break; - case MID_RESPONSE_MALFORMED: - rc = -EIO; - break; - case MID_SHUTDOWN: - rc = -EHOSTDOWN; - break; - default: - list_del_init(&mid->qhead); - cERROR(1, "%s: invalid mid state mid=%llu state=%d", __func__, - mid->mid, mid->mid_state); - rc = -EIO; - } - spin_unlock(&GlobalMid_Lock); - - DeleteMidQEntry(mid); - return rc; -} - -/* - * An NT cancel request header looks just like the original request except: - * - * The Command is SMB_COM_NT_CANCEL - * The WordCount is zeroed out - * The ByteCount is zeroed out - * - * This function mangles an existing request buffer into a - * SMB_COM_NT_CANCEL request and then sends it. - */ -static int -send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf, - struct mid_q_entry *mid) -{ - int rc = 0; - - /* -4 for RFC1001 length and +2 for BCC field */ - in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2); - in_buf->Command = SMB_COM_NT_CANCEL; - in_buf->WordCount = 0; - put_bcc(0, in_buf); - - mutex_lock(&server->srv_mutex); - rc = cifs_sign_smb(in_buf, server, &mid->sequence_number); - if (rc) { - mutex_unlock(&server->srv_mutex); - return rc; - } - rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); - mutex_unlock(&server->srv_mutex); - - cFYI(1, "issued NT_CANCEL for mid %u, rc = %d", - in_buf->Mid, rc); - - return rc; -} - -int -cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, - bool log_error) -{ - unsigned int len = get_rfc1002_length(mid->resp_buf) + 4; - - dump_smb(mid->resp_buf, min_t(u32, 92, len)); - - /* convert the length into a more usable form */ - if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { - struct kvec iov; - - iov.iov_base = mid->resp_buf; - iov.iov_len = len; - /* FIXME: add code to kill session */ - if (cifs_verify_signature(&iov, 1, server, - mid->sequence_number + 1) != 0) - cERROR(1, "Unexpected SMB signature"); - } - - /* BB special case reconnect tid and uid here? */ - return map_smb_to_linux_error(mid->resp_buf, log_error); -} - -static int -cifs_setup_request(struct cifs_ses *ses, struct kvec *iov, - unsigned int nvec, struct mid_q_entry **ret_mid) -{ - int rc; - struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base; - struct mid_q_entry *mid; - - rc = allocate_mid(ses, hdr, &mid); - if (rc) - return rc; - rc = cifs_sign_smb2(iov, nvec, ses->server, &mid->sequence_number); - if (rc) - delete_mid(mid); - *ret_mid = mid; - return rc; -} - -int -SendReceive2(const unsigned int xid, struct cifs_ses *ses, - struct kvec *iov, int n_vec, int *pRespBufType /* ret */, - const int flags) -{ - int rc = 0; - int long_op; - struct mid_q_entry *midQ; - char *buf = iov[0].iov_base; - - long_op = flags & CIFS_TIMEOUT_MASK; - - *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ - - if ((ses == NULL) || (ses->server == NULL)) { - cifs_small_buf_release(buf); - cERROR(1, "Null session"); - return -EIO; - } - - if (ses->server->tcpStatus == CifsExiting) { - cifs_small_buf_release(buf); - return -ENOENT; - } - - /* - * Ensure that we do not send more than 50 overlapping requests - * to the same server. We may make this configurable later or - * use ses->maxReq. - */ - - rc = wait_for_free_request(ses->server, long_op); - if (rc) { - cifs_small_buf_release(buf); - return rc; - } - - /* - * Make sure that we sign in the same order that we send on this socket - * and avoid races inside tcp sendmsg code that could cause corruption - * of smb data. - */ - - mutex_lock(&ses->server->srv_mutex); - - rc = cifs_setup_request(ses, iov, n_vec, &midQ); - if (rc) { - mutex_unlock(&ses->server->srv_mutex); - cifs_small_buf_release(buf); - /* Update # of requests on wire to server */ - cifs_add_credits(ses->server, 1); - return rc; - } - - midQ->mid_state = MID_REQUEST_SUBMITTED; - cifs_in_send_inc(ses->server); - rc = smb_sendv(ses->server, iov, n_vec); - cifs_in_send_dec(ses->server); - cifs_save_when_sent(midQ); - - mutex_unlock(&ses->server->srv_mutex); - - if (rc < 0) { - cifs_small_buf_release(buf); - goto out; - } - - if (long_op == CIFS_ASYNC_OP) { - cifs_small_buf_release(buf); - goto out; - } - - rc = wait_for_response(ses->server, midQ); - if (rc != 0) { - send_nt_cancel(ses->server, (struct smb_hdr *)buf, midQ); - spin_lock(&GlobalMid_Lock); - if (midQ->mid_state == MID_REQUEST_SUBMITTED) { - midQ->callback = DeleteMidQEntry; - spin_unlock(&GlobalMid_Lock); - cifs_small_buf_release(buf); - cifs_add_credits(ses->server, 1); - return rc; - } - spin_unlock(&GlobalMid_Lock); - } - - cifs_small_buf_release(buf); - - rc = cifs_sync_mid_result(midQ, ses->server); - if (rc != 0) { - cifs_add_credits(ses->server, 1); - return rc; - } - - if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) { - rc = -EIO; - cFYI(1, "Bad MID state?"); - goto out; - } - - buf = (char *)midQ->resp_buf; - iov[0].iov_base = buf; - iov[0].iov_len = get_rfc1002_length(buf) + 4; - if (midQ->large_buf) - *pRespBufType = CIFS_LARGE_BUFFER; - else - *pRespBufType = CIFS_SMALL_BUFFER; - - rc = cifs_check_receive(midQ, ses->server, flags & CIFS_LOG_ERROR); - - /* mark it so buf will not be freed by delete_mid */ - if ((flags & CIFS_NO_RESP) == 0) - midQ->resp_buf = NULL; -out: - delete_mid(midQ); - cifs_add_credits(ses->server, 1); - - return rc; -} - -int -SendReceive(const unsigned int xid, struct cifs_ses *ses, - struct smb_hdr *in_buf, struct smb_hdr *out_buf, - int *pbytes_returned, const int long_op) -{ - int rc = 0; - struct mid_q_entry *midQ; - - if (ses == NULL) { - cERROR(1, "Null smb session"); - return -EIO; - } - if (ses->server == NULL) { - cERROR(1, "Null tcp session"); - return -EIO; - } - - if (ses->server->tcpStatus == CifsExiting) - return -ENOENT; - - /* Ensure that we do not send more than 50 overlapping requests - to the same server. We may make this configurable later or - use ses->maxReq */ - - if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize + - MAX_CIFS_HDR_SIZE - 4) { - cERROR(1, "Illegal length, greater than maximum frame, %d", - be32_to_cpu(in_buf->smb_buf_length)); - return -EIO; - } - - rc = wait_for_free_request(ses->server, long_op); - if (rc) - return rc; - - /* make sure that we sign in the same order that we send on this socket - and avoid races inside tcp sendmsg code that could cause corruption - of smb data */ - - mutex_lock(&ses->server->srv_mutex); - - rc = allocate_mid(ses, in_buf, &midQ); - if (rc) { - mutex_unlock(&ses->server->srv_mutex); - /* Update # of requests on wire to server */ - cifs_add_credits(ses->server, 1); - return rc; - } - - rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); - if (rc) { - mutex_unlock(&ses->server->srv_mutex); - goto out; - } - - midQ->mid_state = MID_REQUEST_SUBMITTED; - - cifs_in_send_inc(ses->server); - rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); - cifs_in_send_dec(ses->server); - cifs_save_when_sent(midQ); - mutex_unlock(&ses->server->srv_mutex); - - if (rc < 0) - goto out; - - if (long_op == CIFS_ASYNC_OP) - goto out; - - rc = wait_for_response(ses->server, midQ); - if (rc != 0) { - send_nt_cancel(ses->server, in_buf, midQ); - spin_lock(&GlobalMid_Lock); - if (midQ->mid_state == MID_REQUEST_SUBMITTED) { - /* no longer considered to be "in-flight" */ - midQ->callback = DeleteMidQEntry; - spin_unlock(&GlobalMid_Lock); - cifs_add_credits(ses->server, 1); - return rc; - } - spin_unlock(&GlobalMid_Lock); - } - - rc = cifs_sync_mid_result(midQ, ses->server); - if (rc != 0) { - cifs_add_credits(ses->server, 1); - return rc; - } - - if (!midQ->resp_buf || !out_buf || - midQ->mid_state != MID_RESPONSE_RECEIVED) { - rc = -EIO; - cERROR(1, "Bad MID state?"); - goto out; - } - - *pbytes_returned = get_rfc1002_length(midQ->resp_buf); - memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); - rc = cifs_check_receive(midQ, ses->server, 0); -out: - delete_mid(midQ); - cifs_add_credits(ses->server, 1); - - return rc; -} - -/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows - blocking lock to return. */ - -static int -send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon, - struct smb_hdr *in_buf, - struct smb_hdr *out_buf) -{ - int bytes_returned; - struct cifs_ses *ses = tcon->ses; - LOCK_REQ *pSMB = (LOCK_REQ *)in_buf; - - /* We just modify the current in_buf to change - the type of lock from LOCKING_ANDX_SHARED_LOCK - or LOCKING_ANDX_EXCLUSIVE_LOCK to - LOCKING_ANDX_CANCEL_LOCK. */ - - pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES; - pSMB->Timeout = 0; - pSMB->hdr.Mid = GetNextMid(ses->server); - - return SendReceive(xid, ses, in_buf, out_buf, - &bytes_returned, 0); -} - -int -SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, - struct smb_hdr *in_buf, struct smb_hdr *out_buf, - int *pbytes_returned) -{ - int rc = 0; - int rstart = 0; - struct mid_q_entry *midQ; - struct cifs_ses *ses; - - if (tcon == NULL || tcon->ses == NULL) { - cERROR(1, "Null smb session"); - return -EIO; - } - ses = tcon->ses; - - if (ses->server == NULL) { - cERROR(1, "Null tcp session"); - return -EIO; - } - - if (ses->server->tcpStatus == CifsExiting) - return -ENOENT; - - /* Ensure that we do not send more than 50 overlapping requests - to the same server. We may make this configurable later or - use ses->maxReq */ - - if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize + - MAX_CIFS_HDR_SIZE - 4) { - cERROR(1, "Illegal length, greater than maximum frame, %d", - be32_to_cpu(in_buf->smb_buf_length)); - return -EIO; - } - - rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP); - if (rc) - return rc; - - /* make sure that we sign in the same order that we send on this socket - and avoid races inside tcp sendmsg code that could cause corruption - of smb data */ - - mutex_lock(&ses->server->srv_mutex); - - rc = allocate_mid(ses, in_buf, &midQ); - if (rc) { - mutex_unlock(&ses->server->srv_mutex); - return rc; - } - - rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); - if (rc) { - delete_mid(midQ); - mutex_unlock(&ses->server->srv_mutex); - return rc; - } - - midQ->mid_state = MID_REQUEST_SUBMITTED; - cifs_in_send_inc(ses->server); - rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); - cifs_in_send_dec(ses->server); - cifs_save_when_sent(midQ); - mutex_unlock(&ses->server->srv_mutex); - - if (rc < 0) { - delete_mid(midQ); - return rc; - } - - /* Wait for a reply - allow signals to interrupt. */ - rc = wait_event_interruptible(ses->server->response_q, - (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) || - ((ses->server->tcpStatus != CifsGood) && - (ses->server->tcpStatus != CifsNew))); - - /* Were we interrupted by a signal ? */ - if ((rc == -ERESTARTSYS) && - (midQ->mid_state == MID_REQUEST_SUBMITTED) && - ((ses->server->tcpStatus == CifsGood) || - (ses->server->tcpStatus == CifsNew))) { - - if (in_buf->Command == SMB_COM_TRANSACTION2) { - /* POSIX lock. We send a NT_CANCEL SMB to cause the - blocking lock to return. */ - rc = send_nt_cancel(ses->server, in_buf, midQ); - if (rc) { - delete_mid(midQ); - return rc; - } - } else { - /* Windows lock. We send a LOCKINGX_CANCEL_LOCK - to cause the blocking lock to return. */ - - rc = send_lock_cancel(xid, tcon, in_buf, out_buf); - - /* If we get -ENOLCK back the lock may have - already been removed. Don't exit in this case. */ - if (rc && rc != -ENOLCK) { - delete_mid(midQ); - return rc; - } - } - - rc = wait_for_response(ses->server, midQ); - if (rc) { - send_nt_cancel(ses->server, in_buf, midQ); - spin_lock(&GlobalMid_Lock); - if (midQ->mid_state == MID_REQUEST_SUBMITTED) { - /* no longer considered to be "in-flight" */ - midQ->callback = DeleteMidQEntry; - spin_unlock(&GlobalMid_Lock); - return rc; - } - spin_unlock(&GlobalMid_Lock); - } - - /* We got the response - restart system call. */ - rstart = 1; - } - - rc = cifs_sync_mid_result(midQ, ses->server); - if (rc != 0) - return rc; - - /* rcvd frame is ok */ - if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) { - rc = -EIO; - cERROR(1, "Bad MID state?"); - goto out; - } - - *pbytes_returned = get_rfc1002_length(midQ->resp_buf); - memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); - rc = cifs_check_receive(midQ, ses->server, 0); -out: - delete_mid(midQ); - if (rstart && rc == -EACCES) - return -ERESTARTSYS; - return rc; -} diff --git a/ANDROID_3.4.5/fs/cifs/xattr.c b/ANDROID_3.4.5/fs/cifs/xattr.c deleted file mode 100644 index 10d92cf5..00000000 --- a/ANDROID_3.4.5/fs/cifs/xattr.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * fs/cifs/xattr.c - * - * Copyright (c) International Business Machines Corp., 2003, 2007 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/fs.h> -#include <linux/posix_acl_xattr.h> -#include <linux/slab.h> -#include <linux/xattr.h> -#include "cifsfs.h" -#include "cifspdu.h" -#include "cifsglob.h" -#include "cifsproto.h" -#include "cifs_debug.h" - -#define MAX_EA_VALUE_SIZE 65535 -#define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" -#define CIFS_XATTR_CIFS_ACL "system.cifs_acl" - -/* BB need to add server (Samba e.g) support for security and trusted prefix */ - -int cifs_removexattr(struct dentry *direntry, const char *ea_name) -{ - int rc = -EOPNOTSUPP; -#ifdef CONFIG_CIFS_XATTR - int xid; - struct cifs_sb_info *cifs_sb; - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - struct super_block *sb; - char *full_path = NULL; - - if (direntry == NULL) - return -EIO; - if (direntry->d_inode == NULL) - return -EIO; - sb = direntry->d_inode->i_sb; - if (sb == NULL) - return -EIO; - - cifs_sb = CIFS_SB(sb); - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - pTcon = tlink_tcon(tlink); - - xid = GetXid(); - - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - goto remove_ea_exit; - } - if (ea_name == NULL) { - cFYI(1, "Null xattr names not supported"); - } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) - && (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN))) { - cFYI(1, - "illegal xattr request %s (only user namespace supported)", - ea_name); - /* BB what if no namespace prefix? */ - /* Should we just pass them to server, except for - system and perhaps security prefixes? */ - } else { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - goto remove_ea_exit; - - ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ - rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL, - (__u16)0, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - } -remove_ea_exit: - kfree(full_path); - FreeXid(xid); - cifs_put_tlink(tlink); -#endif - return rc; -} - -int cifs_setxattr(struct dentry *direntry, const char *ea_name, - const void *ea_value, size_t value_size, int flags) -{ - int rc = -EOPNOTSUPP; -#ifdef CONFIG_CIFS_XATTR - int xid; - struct cifs_sb_info *cifs_sb; - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - struct super_block *sb; - char *full_path; - - if (direntry == NULL) - return -EIO; - if (direntry->d_inode == NULL) - return -EIO; - sb = direntry->d_inode->i_sb; - if (sb == NULL) - return -EIO; - - cifs_sb = CIFS_SB(sb); - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - pTcon = tlink_tcon(tlink); - - xid = GetXid(); - - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - goto set_ea_exit; - } - /* return dos attributes as pseudo xattr */ - /* return alt name if available as pseudo attr */ - - /* if proc/fs/cifs/streamstoxattr is set then - search server for EAs or streams to - returns as xattrs */ - if (value_size > MAX_EA_VALUE_SIZE) { - cFYI(1, "size of EA value too large"); - rc = -EOPNOTSUPP; - goto set_ea_exit; - } - - if (ea_name == NULL) { - cFYI(1, "Null xattr names not supported"); - } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) - == 0) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - goto set_ea_exit; - if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) - cFYI(1, "attempt to set cifs inode metadata"); - - ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ - rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, - (__u16)value_size, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) - == 0) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - goto set_ea_exit; - - ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ - rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, - (__u16)value_size, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, - strlen(CIFS_XATTR_CIFS_ACL)) == 0) { -#ifdef CONFIG_CIFS_ACL - struct cifs_ntsd *pacl; - pacl = kmalloc(value_size, GFP_KERNEL); - if (!pacl) { - cFYI(1, "%s: Can't allocate memory for ACL", - __func__); - rc = -ENOMEM; - } else { - memcpy(pacl, ea_value, value_size); - rc = set_cifs_acl(pacl, value_size, - direntry->d_inode, full_path, CIFS_ACL_DACL); - if (rc == 0) /* force revalidate of the inode */ - CIFS_I(direntry->d_inode)->time = 0; - kfree(pacl); - } -#else - cFYI(1, "Set CIFS ACL not supported yet"); -#endif /* CONFIG_CIFS_ACL */ - } else { - int temp; - temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, - strlen(POSIX_ACL_XATTR_ACCESS)); - if (temp == 0) { -#ifdef CONFIG_CIFS_POSIX - if (sb->s_flags & MS_POSIXACL) - rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, - ea_value, (const int)value_size, - ACL_TYPE_ACCESS, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - cFYI(1, "set POSIX ACL rc %d", rc); -#else - cFYI(1, "set POSIX ACL not supported"); -#endif - } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, - strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { -#ifdef CONFIG_CIFS_POSIX - if (sb->s_flags & MS_POSIXACL) - rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, - ea_value, (const int)value_size, - ACL_TYPE_DEFAULT, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - cFYI(1, "set POSIX default ACL rc %d", rc); -#else - cFYI(1, "set default POSIX ACL not supported"); -#endif - } else { - cFYI(1, "illegal xattr request %s (only user namespace" - " supported)", ea_name); - /* BB what if no namespace prefix? */ - /* Should we just pass them to server, except for - system and perhaps security prefixes? */ - } - } - -set_ea_exit: - kfree(full_path); - FreeXid(xid); - cifs_put_tlink(tlink); -#endif - return rc; -} - -ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, - void *ea_value, size_t buf_size) -{ - ssize_t rc = -EOPNOTSUPP; -#ifdef CONFIG_CIFS_XATTR - int xid; - struct cifs_sb_info *cifs_sb; - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - struct super_block *sb; - char *full_path; - - if (direntry == NULL) - return -EIO; - if (direntry->d_inode == NULL) - return -EIO; - sb = direntry->d_inode->i_sb; - if (sb == NULL) - return -EIO; - - cifs_sb = CIFS_SB(sb); - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - pTcon = tlink_tcon(tlink); - - xid = GetXid(); - - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - goto get_ea_exit; - } - /* return dos attributes as pseudo xattr */ - /* return alt name if available as pseudo attr */ - if (ea_name == NULL) { - cFYI(1, "Null xattr names not supported"); - } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) - == 0) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - goto get_ea_exit; - - if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) { - cFYI(1, "attempt to query cifs inode metadata"); - /* revalidate/getattr then populate from inode */ - } /* BB add else when above is implemented */ - ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ - rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, - buf_size, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - goto get_ea_exit; - - ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ - rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, - buf_size, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, - strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { -#ifdef CONFIG_CIFS_POSIX - if (sb->s_flags & MS_POSIXACL) - rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, - ea_value, buf_size, ACL_TYPE_ACCESS, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); -#else - cFYI(1, "Query POSIX ACL not supported yet"); -#endif /* CONFIG_CIFS_POSIX */ - } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, - strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { -#ifdef CONFIG_CIFS_POSIX - if (sb->s_flags & MS_POSIXACL) - rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, - ea_value, buf_size, ACL_TYPE_DEFAULT, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); -#else - cFYI(1, "Query POSIX default ACL not supported yet"); -#endif /* CONFIG_CIFS_POSIX */ - } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, - strlen(CIFS_XATTR_CIFS_ACL)) == 0) { -#ifdef CONFIG_CIFS_ACL - u32 acllen; - struct cifs_ntsd *pacl; - - pacl = get_cifs_acl(cifs_sb, direntry->d_inode, - full_path, &acllen); - if (IS_ERR(pacl)) { - rc = PTR_ERR(pacl); - cERROR(1, "%s: error %zd getting sec desc", - __func__, rc); - } else { - if (ea_value) { - if (acllen > buf_size) - acllen = -ERANGE; - else - memcpy(ea_value, pacl, acllen); - } - rc = acllen; - kfree(pacl); - } -#else - cFYI(1, "Query CIFS ACL not supported yet"); -#endif /* CONFIG_CIFS_ACL */ - } else if (strncmp(ea_name, - XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { - cFYI(1, "Trusted xattr namespace not supported yet"); - } else if (strncmp(ea_name, - XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) { - cFYI(1, "Security xattr namespace not supported yet"); - } else - cFYI(1, - "illegal xattr request %s (only user namespace supported)", - ea_name); - - /* We could add an additional check for streams ie - if proc/fs/cifs/streamstoxattr is set then - search server for EAs or streams to - returns as xattrs */ - - if (rc == -EINVAL) - rc = -EOPNOTSUPP; - -get_ea_exit: - kfree(full_path); - FreeXid(xid); - cifs_put_tlink(tlink); -#endif - return rc; -} - -ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) -{ - ssize_t rc = -EOPNOTSUPP; -#ifdef CONFIG_CIFS_XATTR - int xid; - struct cifs_sb_info *cifs_sb; - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - struct super_block *sb; - char *full_path; - - if (direntry == NULL) - return -EIO; - if (direntry->d_inode == NULL) - return -EIO; - sb = direntry->d_inode->i_sb; - if (sb == NULL) - return -EIO; - - cifs_sb = CIFS_SB(sb); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - return -EOPNOTSUPP; - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - pTcon = tlink_tcon(tlink); - - xid = GetXid(); - - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - goto list_ea_exit; - } - /* return dos attributes as pseudo xattr */ - /* return alt name if available as pseudo attr */ - - /* if proc/fs/cifs/streamstoxattr is set then - search server for EAs or streams to - returns as xattrs */ - rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data, - buf_size, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - -list_ea_exit: - kfree(full_path); - FreeXid(xid); - cifs_put_tlink(tlink); -#endif - return rc; -} |