diff options
-rw-r--r-- | source3/include/includes.h | 1 | ||||
-rw-r--r-- | source3/include/ntioctl.h | 26 | ||||
-rw-r--r-- | source3/smbd/dosmode.c | 92 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 51 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 40 |
5 files changed, 138 insertions, 72 deletions
diff --git a/source3/include/includes.h b/source3/include/includes.h index 04d11afafb..6084d583ed 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -707,6 +707,7 @@ extern int errno; #include "hash.h" #include "trans2.h" #include "nterr.h" +#include "ntioctl.h" #include "messages.h" #include "charset.h" #include "dynconfig.h" diff --git a/source3/include/ntioctl.h b/source3/include/ntioctl.h new file mode 100644 index 0000000000..4749842ddc --- /dev/null +++ b/source3/include/ntioctl.h @@ -0,0 +1,26 @@ +/* + Unix SMB/CIFS implementation. + NT ioctl code constants + Copyright (C) Andrew Tridgell 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + I'm guessing we will need to support a bunch of these eventually. For now + we only need the sparse flag +*/ + +#define NTIOCTL_SET_SPARSE 0x900c4 diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index dcffe3aa90..77d8c9cc92 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -115,65 +115,67 @@ mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname) /**************************************************************************** change a unix mode to a dos mode ****************************************************************************/ -int dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) +uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) { - int result = 0; + int result = 0; - DEBUG(8,("dos_mode: %s\n", path)); + DEBUG(8,("dos_mode: %s\n", path)); - if ((sbuf->st_mode & S_IWUSR) == 0) - result |= aRONLY; + if ((sbuf->st_mode & S_IWUSR) == 0) + result |= aRONLY; + + if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0)) + result |= aARCH; - if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0)) - result |= aARCH; - - if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0)) - result |= aSYSTEM; - - if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0)) - result |= aHIDDEN; + if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0)) + result |= aSYSTEM; + + if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0)) + result |= aHIDDEN; - if (S_ISDIR(sbuf->st_mode)) - result = aDIR | (result & aRONLY); + if (S_ISDIR(sbuf->st_mode)) + result = aDIR | (result & aRONLY); + + if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)sbuf->st_blksize) { + result |= FILE_ATTRIBUTE_SPARSE; + } #ifdef S_ISLNK #if LINKS_READ_ONLY - if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode)) - result |= aRONLY; + if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode)) + result |= aRONLY; #endif #endif - /* hide files with a name starting with a . */ - if (lp_hide_dot_files(SNUM(conn))) - { - char *p = strrchr_m(path,'/'); - if (p) - p++; - else - p = path; - - if (p[0] == '.' && p[1] != '.' && p[1] != 0) - result |= aHIDDEN; - } - - /* Optimization : Only call is_hidden_path if it's not already - hidden. */ - if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) - { - result |= aHIDDEN; - } - - DEBUG(8,("dos_mode returning ")); + /* hide files with a name starting with a . */ + if (lp_hide_dot_files(SNUM(conn))) { + char *p = strrchr_m(path,'/'); + if (p) + p++; + else + p = path; + + if (p[0] == '.' && p[1] != '.' && p[1] != 0) + result |= aHIDDEN; + } + + /* Optimization : Only call is_hidden_path if it's not already + hidden. */ + if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) { + result |= aHIDDEN; + } - if (result & aHIDDEN) DEBUG(8, ("h")); - if (result & aRONLY ) DEBUG(8, ("r")); - if (result & aSYSTEM) DEBUG(8, ("s")); - if (result & aDIR ) DEBUG(8, ("d")); - if (result & aARCH ) DEBUG(8, ("a")); + DEBUG(8,("dos_mode returning ")); - DEBUG(8,("\n")); + if (result & aHIDDEN) DEBUG(8, ("h")); + if (result & aRONLY ) DEBUG(8, ("r")); + if (result & aSYSTEM) DEBUG(8, ("s")); + if (result & aDIR ) DEBUG(8, ("d")); + if (result & aARCH ) DEBUG(8, ("a")); + + DEBUG(8,("\n")); - return(result); + return(result); } /******************************************************************* diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8f6b4ab374..cf69dfddb0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -851,7 +851,7 @@ int reply_ntcreate_and_X(connection_struct *conn, p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 4; - SOFF_T(p, 0, SMB_ROUNDUP_ALLOCATION(file_len)); + SOFF_T(p, 0, get_allocation_size(&sbuf)); p += 8; SOFF_T(p,0,file_len); p += 12; @@ -1295,7 +1295,7 @@ static int call_nt_transact_create(connection_struct *conn, p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 4; - SOFF_T(p, 0, SMB_ROUNDUP_ALLOCATION(file_len)); + SOFF_T(p, 0, get_allocation_size(&sbuf)); p += 8; SOFF_T(p,0,file_len); @@ -1594,21 +1594,46 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, } /**************************************************************************** - Reply to IOCTL - not implemented - no plans. + Reply to NT IOCTL ****************************************************************************/ - static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, - char **ppsetup, char **ppparams, char **ppdata) + char **ppsetup, int setup_count, + char **ppparams, int parameter_count, + char **ppdata, int data_count) { - static BOOL logged_message = False; + unsigned fnum, control; + static BOOL logged_message; - if(!logged_message) { - DEBUG(3,("call_nt_transact_ioctl: Currently not implemented.\n")); - logged_message = True; /* Only print this once... */ + if (setup_count != 8) { + DEBUG(3,("call_nt_transact_ioctl: invalid setup count %d\n", setup_count)); + return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } - return ERROR_DOS(ERRSRV,ERRnosupport); + + fnum = SVAL(*ppsetup, 4); + control = IVAL(*ppsetup, 0); + + DEBUG(6,("call_nt_transact_ioctl: fnum=%d control=0x%x\n", + fnum, control)); + + switch (control) { + case NTIOCTL_SET_SPARSE: + /* pretend this succeeded - tho strictly we should + mark the file sparse (if the local fs supports it) + so we can know if we need to pre-allocate or not */ + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + return -1; + + default: + if (!logged_message) { + logged_message = True; /* Only print this once... */ + DEBUG(3,("call_nt_transact_ioctl(0x%x): Currently not implemented.\n", + control)); + } + } + + return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } /**************************************************************************** @@ -1769,8 +1794,10 @@ due to being in oplock break state.\n", (unsigned int)function_code )); case NT_TRANSACT_IOCTL: START_PROFILE_NESTED(NT_transact_ioctl); outsize = call_nt_transact_ioctl(conn, inbuf, outbuf, - length, bufsize, - &setup, ¶ms, &data); + length, bufsize, + &setup, setup_count, + ¶ms, parameter_count, + &data, data_count); END_PROFILE_NESTED(NT_transact_ioctl); break; case NT_TRANSACT_SET_SECURITY_DESC: diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 7da1758dec..3a8e41c654 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -30,6 +30,17 @@ extern int global_oplock_break; extern uint32 global_client_caps; extern pstring global_myname; +/* given a stat buffer return the allocated size on disk, taking into + account sparse files */ +SMB_OFF_T get_allocation_size(SMB_STRUCT_STAT *sbuf) +{ + SMB_OFF_T ret; + ret = sbuf->st_blksize * (SMB_OFF_T)sbuf->st_blocks; + ret = SMB_ROUNDUP_ALLOCATION(ret); + return ret; +} + + /**************************************************************************** Send the required number of replies back. We assume all fields other than the data fields are @@ -566,7 +577,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } size = sbuf.st_size; - allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size); + allocation_size = get_allocation_size(&sbuf); mdate = sbuf.st_mtime; adate = sbuf.st_atime; cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); @@ -1528,7 +1539,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, uint16 tran_call = SVAL(inbuf, smb_setup0); uint16 info_level; int mode=0; - SMB_OFF_T size=0; + SMB_OFF_T file_size=0; SMB_OFF_T allocation_size=0; unsigned int data_size; SMB_STRUCT_STAT sbuf; @@ -1643,10 +1654,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, mode = dos_mode(conn,fname,&sbuf); fullpathname = fname; - size = sbuf.st_size; - allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size); + file_size = sbuf.st_size; + allocation_size = get_allocation_size(&sbuf); if (mode & aDIR) - size = 0; + file_size = 0; params = Realloc(*pparams,2); if (params == NULL) @@ -1692,7 +1703,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, put_dos_date2(pdata,l1_fdateCreation,c_time); put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ - SIVAL(pdata,l1_cbFile,(uint32)size); + SIVAL(pdata,l1_cbFile,(uint32)file_size); SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size); SSVAL(pdata,l1_attrFile,mode); SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */ @@ -1703,7 +1714,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, put_dos_date2(pdata,0,c_time); put_dos_date2(pdata,4,sbuf.st_atime); put_dos_date2(pdata,8,sbuf.st_mtime); - SIVAL(pdata,12,(uint32)size); + SIVAL(pdata,12,(uint32)file_size); SIVAL(pdata,16,(uint32)allocation_size); SIVAL(pdata,20,mode); break; @@ -1747,9 +1758,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_STANDARD_INFO: data_size = 24; - /* Fake up allocation size. */ SOFF_T(pdata,0,allocation_size); - SOFF_T(pdata,8,size); + SOFF_T(pdata,8,file_size); SIVAL(pdata,16,sbuf.st_nlink); SCVAL(pdata,20,0); SCVAL(pdata,21,(mode&aDIR)?1:0); @@ -1794,7 +1804,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_FILE_END_OF_FILE_INFORMATION: case SMB_QUERY_FILE_END_OF_FILEINFO: data_size = 8; - SOFF_T(pdata,0,size); + SOFF_T(pdata,0,file_size); break; case SMB_QUERY_FILE_ALL_INFO: @@ -1805,7 +1815,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,32,mode); pdata += 40; SOFF_T(pdata,0,allocation_size); - SOFF_T(pdata,8,size); + SOFF_T(pdata,8,file_size); SIVAL(pdata,16,sbuf.st_nlink); SCVAL(pdata,20,delete_pending); SCVAL(pdata,21,(mode&aDIR)?1:0); @@ -1917,7 +1927,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False); SIVAL(pdata,0,0); /* ??? */ SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */ - SOFF_T(pdata,8,size); + SOFF_T(pdata,8,file_size); SIVAL(pdata,16,allocation_size); SIVAL(pdata,20,0); /* ??? */ data_size = 24 + byte_len; @@ -1925,7 +1935,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case SMB_FILE_COMPRESSION_INFORMATION: - SOFF_T(pdata,0,size); + SOFF_T(pdata,0,allocation_size); SIVAL(pdata,8,0); /* ??? */ SIVAL(pdata,12,0); /* ??? */ data_size = 16; @@ -1937,7 +1947,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, put_long_date(pdata+16,sbuf.st_mtime); /* write time */ put_long_date(pdata+24,sbuf.st_mtime); /* change time */ SIVAL(pdata,32,allocation_size); - SOFF_T(pdata,40,size); + SOFF_T(pdata,40,file_size); SIVAL(pdata,48,mode); SIVAL(pdata,52,0); /* ??? */ data_size = 56; @@ -2460,7 +2470,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (ret == -1) return ERROR_NT(NT_STATUS_DISK_FULL); - /* Allocate can trucate size... */ + /* Allocate can truncate size... */ size = new_sbuf.st_size; } |