Merged initial allocation code for IFSTEST fix.
authorJeremy Allison <jra@samba.org>
Fri, 23 Aug 2002 15:51:28 +0000 (15:51 +0000)
committerJeremy Allison <jra@samba.org>
Fri, 23 Aug 2002 15:51:28 +0000 (15:51 +0000)
Jeremy.

source/include/config.h.in
source/include/smb.h
source/include/smb_macros.h
source/smbd/nttrans.c
source/smbd/trans2.c

index 4a138b6db6ad5d97c52e1f930b9d503f539b6cab..8c06e2539684fc4be0232cd4b682ae46f06a6b2a 100644 (file)
 #undef HAVE_LDAP
 #undef HAVE_STAT_ST_BLOCKS
 #undef STAT_ST_BLOCKSIZE
+#undef HAVE_STAT_ST_BLKSIZE
 #undef HAVE_DEVICE_MAJOR_FN
 #undef HAVE_DEVICE_MINOR_FN
 #undef HAVE_PASSWD_PW_COMMENT
index 9101e947a7f798350ac03b34da18a245593a51bb..958a5636428b80988a88e5ae705063654986798f 100644 (file)
@@ -391,6 +391,7 @@ typedef struct files_struct
        BOOL delete_on_close;
        SMB_OFF_T pos;
        SMB_OFF_T size;
+       SMB_OFF_T initial_allocation_size; /* Faked up initial allocation on disk. */
        mode_t mode;
        uint16 vuid;
        write_bmpx_struct *wbmpx_ptr;
index a2351c705eaede2d1e14f8f71e894540ea38fe8d..ccf151fab2b901ce30031631123f82fee0f32127 100644 (file)
 /* this is how errors are generated */
 #define UNIXERROR(defclass,deferror) unix_error_packet(outbuf,defclass,deferror,__LINE__,__FILE__)
 
-#define SMB_ROUNDUP(x,g) (((x)+((g)-1))&~((g)-1))
-#define SMB_ROUNDUP_ALLOCATION(s) ((s) ? (SMB_ROUNDUP((SMB_OFF_T)((s)+1), ((SMB_OFF_T)SMB_ROUNDUP_ALLOCATION_SIZE))) : 0 )
+#define SMB_ROUNDUP(x,r) ( ((x)%(r)) ? ( (((x)+(r))/(r))*(r) ) : (x))
 
 /* Extra macros added by Ying Chen at IBM - speed increase by inlining. */
 #define smb_buf(buf) (((char *)(buf)) + smb_size + CVAL(buf,smb_wct)*2)
index 722a7ff8bf39302c5d1f2418fb3fcf43a9775e31..ff35771644f53cb2531730ca3fbe7d8dfab5ac7f 100644 (file)
@@ -548,6 +548,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
        uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
        uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions);
        uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid);
+       SMB_OFF_T allocation_size = 0;
        int smb_ofun;
        int smb_open_mode;
        int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
@@ -571,7 +572,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
 file_attributes = 0x%x, share_access = 0x%x, create_disposition = 0x%x \
 create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attributes,
                        share_access, create_disposition,
-                       root_dir_fid, create_options ));
+                       create_options, root_dir_fid ));
 
        /* If it's an IPC, use the pipe handler. */
 
@@ -805,6 +806,22 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                return ERROR_DOS(ERRDOS,ERRnoaccess);
        } 
        
+       /* Save the requested allocation size. */
+       allocation_size = IVAL(inbuf,smb_ntcreate_AllocationSize);
+#ifdef LARGE_SMB_OFF_T
+       allocation_size |= (((SMB_OFF_T)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32);
+#endif
+       if (allocation_size && (allocation_size > file_len)) {
+               fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
+               if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
+                       close_file(fsp,False);
+                       END_PROFILE(SMBntcreateX);
+                       return ERROR_NT(NT_STATUS_DISK_FULL);
+               }
+       } else {
+               fsp->initial_allocation_size = SMB_ROUNDUP(file_len,SMB_ROUNDUP_ALLOCATION_SIZE);
+       }
+
        /* 
         * If the caller set the extended oplock request bit
         * and we granted one (by whatever means) - set the
@@ -869,7 +886,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
        p += 8;
        SIVAL(p,0,fmode); /* File Attributes. */
        p += 4;
-       SOFF_T(p, 0, get_allocation_size(&sbuf));
+       SOFF_T(p, 0, get_allocation_size(fsp,&sbuf));
        p += 8;
        SOFF_T(p,0,file_len);
        p += 12;
@@ -1045,6 +1062,7 @@ static int call_nt_transact_create(connection_struct *conn,
        uint32 create_options;
        uint32 sd_len;
        uint16 root_dir_fid;
+       SMB_OFF_T allocation_size = 0;
        int smb_ofun;
        int smb_open_mode;
        int smb_attr;
@@ -1282,6 +1300,22 @@ static int call_nt_transact_create(connection_struct *conn,
        
        restore_case_semantics(file_attributes);
 
+       /* Save the requested allocation size. */
+       allocation_size = IVAL(params,12);
+#ifdef LARGE_SMB_OFF_T
+       allocation_size |= (((SMB_OFF_T)IVAL(params,16)) << 32);
+#endif
+       if (allocation_size && (allocation_size > file_len)) {
+               fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
+               if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
+                       close_file(fsp,False);
+                       END_PROFILE(SMBntcreateX);
+                       return ERROR_NT(NT_STATUS_DISK_FULL);
+               }
+       } else {
+               fsp->initial_allocation_size = SMB_ROUNDUP(file_len,SMB_ROUNDUP_ALLOCATION_SIZE);
+       }
+
        /* Realloc the size of parameters and data we will return */
        params = Realloc(*ppparams, 69);
        if(params == NULL)
@@ -1325,7 +1359,7 @@ static int call_nt_transact_create(connection_struct *conn,
        p += 8;
        SIVAL(p,0,fmode); /* File Attributes. */
        p += 4;
-       SOFF_T(p, 0, get_allocation_size(&sbuf));
+       SOFF_T(p, 0, get_allocation_size(fsp,&sbuf));
        p += 8;
        SOFF_T(p,0,file_len);
 
index 91e76012e6db0ab02f2719b8a0487b966b2b601a..8def7c0250c59674197dad1a1bb3f145b5aaa7ce 100644 (file)
@@ -30,19 +30,26 @@ extern int global_oplock_break;
 extern uint32 global_client_caps;
 extern pstring global_myname;
 
+#define get_file_size(sbuf) (sbuf.st_size)
+
 /* 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 get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
 {
        SMB_OFF_T ret;
+#if defined(HAVE_STAT_ST_BLKSIZE) && defined(HAVE_STAT_ST_BLOCKS)
        ret = sbuf->st_blksize * (SMB_OFF_T)sbuf->st_blocks;
-       ret = SMB_ROUNDUP_ALLOCATION(ret);
+#elif defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
+       ret = (SMB_OFF_T)STAT_ST_BLOCKSIZE * (SMB_OFF_T)sbuf->st_blocks;
+#else
+       ret = get_file_size(*sbuf);
+#endif
+       if (!ret && fsp && fsp->initial_allocation_size)
+               ret = fsp->initial_allocation_size;
+       ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
        return ret;
 }
 
-#define get_file_size(sbuf) (sbuf.st_size)
-
-
 /****************************************************************************
   Send the required number of replies back.
   We assume all fields other than the data fields are
@@ -579,7 +586,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        }
 
                        file_size = get_file_size(sbuf);
-                       allocation_size = get_allocation_size(&sbuf);
+                       allocation_size = get_allocation_size(NULL,&sbuf);
                        mdate = sbuf.st_mtime;
                        adate = sbuf.st_atime;
                        cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
@@ -756,12 +763,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        SOFF_T(p,0,get_file_size(sbuf));             /* File size 64 Bit */
                        p+= 8;
 
-#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
-                       SOFF_T(p,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
-#else
-                       /* Can't get the value - fake it using size. */
-                       SOFF_T(p,0,get_file_size(sbuf));             /* Number of bytes used on disk - 64 Bit */
-#endif
+                       SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
                        p+= 8;
 
                        put_long_date(p,sbuf.st_ctime);       /* Creation Time 64 Bit */
@@ -1559,12 +1561,16 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
        BOOL delete_pending = False;
        int len;
        time_t c_time;
+       files_struct *fsp = NULL;
 
        if (!params)
                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
 
        if (tran_call == TRANSACT2_QFILEINFO) {
-               files_struct *fsp = file_fsp(params,0);
+               if (total_params < 4)
+                       return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
+               fsp = file_fsp(params,0);
                info_level = SVAL(params,2);
 
                DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
@@ -1662,7 +1668,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
        mode = dos_mode(conn,fname,&sbuf);
        fullpathname = fname;
        file_size = get_file_size(sbuf);
-       allocation_size = get_allocation_size(&sbuf);
+       allocation_size = get_allocation_size(fsp,&sbuf);
        if (mode & aDIR)
                file_size = 0;
 
@@ -1982,12 +1988,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
                        SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
                        pdata += 8;
 
-#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
-                       SOFF_T(pdata,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
-#else
-                       /* Can't get the value - fake it using size. */
-                       SOFF_T(pdata,0,get_file_size(sbuf));             /* Number of bytes used on disk - 64 Bit */
-#endif
+                       SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
                        pdata += 8;
 
                        put_long_date(pdata,sbuf.st_ctime);       /* Creation Time 64 Bit */
@@ -2422,11 +2423,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
                case SMB_SET_FILE_ALLOCATION_INFO:
                {
                        int ret = -1;
-                       SMB_OFF_T allocation_size = IVAL(pdata,0);
+                       SMB_OFF_T allocation_size;
 
                        if (total_data < 8)
                                return(ERROR_DOS(ERRDOS,ERRinvalidparam));
 
+                       allocation_size = IVAL(pdata,0);
 #ifdef LARGE_SMB_OFF_T
                        allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
 #else /* LARGE_SMB_OFF_T */
@@ -2436,6 +2438,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
                        DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
                                        fname, (double)allocation_size ));
 
+                       if (allocation_size)
+                               allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
+
                        if(allocation_size != get_file_size(sbuf)) {
                                SMB_STRUCT_STAT new_sbuf;