Fix VFS layer:
[kai/samba.git] / source / smbd / trans2.c
index a66c029286338e83ced354241ca853fd2ecf51a8..c9eef637d9598330bdee2c698f52e87d2d2b0459 100644 (file)
@@ -28,21 +28,25 @@ extern int smb_read_error;
 extern fstring local_machine;
 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_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
 {
-       SMB_OFF_T ret;
-       ret = sbuf->st_blksize * (SMB_OFF_T)sbuf->st_blocks;
-       ret = SMB_ROUNDUP_ALLOCATION(ret);
+       SMB_BIG_UINT ret;
+#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
+       ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
+#else
+       ret = (SMB_BIG_UINT)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
@@ -456,7 +460,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                                 BOOL *out_of_space, BOOL *got_exact_match,
                                 int *last_name_off)
 {
-       char *dname;
+       const char *dname;
        BOOL found = False;
        SMB_STRUCT_STAT sbuf;
        pstring mask;
@@ -467,7 +471,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
        int prev_dirpos=0;
        int mode=0;
        SMB_OFF_T file_size = 0;
-       SMB_OFF_T allocation_size = 0;
+       SMB_BIG_UINT allocation_size = 0;
        uint32 len;
        time_t mdate=0, adate=0, cdate=0;
        char *nameptr;
@@ -545,12 +549,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        pstrcat(pathreal,dname);
 
                        if (INFO_LEVEL_IS_UNIX(info_level)) {
-                               if (vfs_lstat(conn,pathreal,&sbuf) != 0) {
+                               if (VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
                                        DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
                                                pathreal,strerror(errno)));
                                        continue;
                                }
-                       } else if (vfs_stat(conn,pathreal,&sbuf) != 0) {
+                       } else if (VFS_STAT(conn,pathreal,&sbuf) != 0) {
 
                                /* Needed to show the msdfs symlinks as 
                                 * directories */
@@ -579,7 +583,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)));
@@ -622,7 +626,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        nameptr = p;
                        p += align_string(outbuf, p, 0);
                        len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
-                       SCVAL(nameptr, -1, len);
+                       if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
+                               SCVAL(nameptr, -1, len-2);
+                       else
+                               SCVAL(nameptr, -1, len-1);
                        p += len;
                        break;
 
@@ -640,10 +647,13 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        SIVAL(p,l2_cbList,0); /* No extended attributes */
                        p += l2_achName;
                        nameptr = p;
-                       len = srvstr_push(outbuf, p, fname, -1, STR_NOALIGN);
-                       SCVAL(p, -1, len);
+                       p += align_string(outbuf, p, 0);
+                       len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
+                       if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
+                               SCVAL(nameptr, -1, len-2);
+                       else
+                               SCVAL(nameptr, -1, len-1);
                        p += len;
-                       *p++ = 0; /* craig from unisys pointed out we need this */
                        break;
 
                case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
@@ -660,6 +670,11 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        SIVAL(p,0,nt_extmode); p += 4;
                        q = p; p += 4;
                        SIVAL(p,0,0); p += 4;
+                       /* Clear the short name buffer. This is
+                        * IMPORTANT as not doing so will trigger
+                        * a Win2k client bug. JRA.
+                        */
+                       memset(p,'\0',26);
                        if (!was_8_3) {
                                pstring mangled_name;
                                pstrcpy(mangled_name, fname);
@@ -751,12 +766,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 */
@@ -899,7 +909,11 @@ close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
 
        p = strrchr_m(directory,'/');
        if(p == NULL) {
-               pstrcpy(mask,directory);
+               /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
+               if((directory[0] == '.') && (directory[1] == '\0'))
+                       pstrcpy(mask,"*");
+               else
+                       pstrcpy(mask,directory);
                pstrcpy(directory,"./");
        } else {
                pstrcpy(mask,p+1);
@@ -1165,7 +1179,8 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
                 */
 
                int current_pos, start_pos;
-               char *dname = NULL;
+               const char *dname = NULL;
+               pstring dname_pstring;
                void *dirptr = conn->dirptr;
                start_pos = TellDir(dirptr);
                for(current_pos = start_pos; current_pos >= 0; current_pos--) {
@@ -1173,21 +1188,24 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
 
                        SeekDir(dirptr, current_pos);
                        dname = ReadDirName(dirptr);
+                       if (dname) {
+                               /*
+                                * Remember, mangle_map is called by
+                                * get_lanman2_dir_entry(), so the resume name
+                                * could be mangled. Ensure we do the same
+                                * here.
+                                */
+                               
+                               /* make sure we get a copy that mangle_map can modify */
 
-                       /*
-                        * Remember, mangle_map is called by
-                        * get_lanman2_dir_entry(), so the resume name
-                        * could be mangled. Ensure we do the same
-                        * here.
-                        */
-
-                       if(dname != NULL)
-                               mangle_map( dname, False, True, SNUM(conn));
-
-                       if(dname && strcsequal( resume_name, dname)) {
-                               SeekDir(dirptr, current_pos+1);
-                               DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
-                               break;
+                               pstrcpy(dname_pstring, dname);
+                               mangle_map( dname_pstring, False, True, SNUM(conn));
+                               
+                               if(strcsequal( resume_name, dname_pstring)) {
+                                       SeekDir(dirptr, current_pos+1);
+                                       DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
+                                       break;
+                               }
                        }
                }
 
@@ -1207,13 +1225,17 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
                                 * here.
                                 */
 
-                               if(dname != NULL)
-                                       mangle_map( dname, False, True, SNUM(conn));
+                               if(dname) {
+                                       /* make sure we get a copy that mangle_map can modify */
+                                       
+                                       pstrcpy(dname_pstring, dname);
+                                       mangle_map(dname_pstring, False, True, SNUM(conn));
 
-                               if(dname && strcsequal( resume_name, dname)) {
-                                       SeekDir(dirptr, current_pos+1);
-                                       DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
-                                       break;
+                                       if(strcsequal( resume_name, dname_pstring)) {
+                                               SeekDir(dirptr, current_pos+1);
+                                               DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
+                                               break;
+                                       }
                                }
                        } /* end for */
                } /* end if current_pos */
@@ -1261,7 +1283,6 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
                dptr_close(&dptr_num); /* This frees up the saved mask */
        }
 
-
        /* Set up the return parameter block */
        SSVAL(params,0,numentries);
        SSVAL(params,2,finished);
@@ -1300,7 +1321,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
 
        DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
 
-       if(vfs_stat(conn,".",&st)!=0) {
+       if(VFS_STAT(conn,".",&st)!=0) {
                DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
                return ERROR_DOS(ERRSRV,ERRinvdevice);
        }
@@ -1317,7 +1338,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
                {
                        SMB_BIG_UINT dfree,dsize,bsize;
                        data_len = 18;
-                       conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);   
+                       VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);     
                        SIVAL(pdata,l1_idFileSystem,st.st_dev);
                        SIVAL(pdata,l1_cSectorUnit,bsize/512);
                        SIVAL(pdata,l1_cUnit,dsize);
@@ -1385,7 +1406,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
                {
                        SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
                        data_len = 24;
-                       conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
+                       VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
                        block_size = lp_block_size(snum);
                        if (bsize < block_size) {
                                SMB_BIG_UINT factor = block_size/bsize;
@@ -1415,7 +1436,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                {
                        SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
                        data_len = 32;
-                       conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
+                       VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
                        block_size = lp_block_size(snum);
                        if (bsize < block_size) {
                                SMB_BIG_UINT factor = block_size/bsize;
@@ -1542,7 +1563,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
        uint16 info_level;
        int mode=0;
        SMB_OFF_T file_size=0;
-       SMB_OFF_T allocation_size=0;
+       SMB_BIG_UINT allocation_size=0;
        unsigned int data_size;
        SMB_STRUCT_STAT sbuf;
        pstring fname, dos_fname;
@@ -1554,12 +1575,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));
@@ -1580,13 +1605,13 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
                  
                        if (INFO_LEVEL_IS_UNIX(info_level)) {
                                /* Always do lstat for UNIX calls. */
-                               if (vfs_lstat(conn,fname,&sbuf)) {
-                                       DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
+                               if (VFS_LSTAT(conn,fname,&sbuf)) {
+                                       DEBUG(3,("call_trans2qfilepathinfo: VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
                                        set_bad_path_error(errno, bad_path);
                                        return(UNIXERROR(ERRDOS,ERRbadpath));
                                }
-                       } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
-                               DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
+                       } else if (!VALID_STAT(sbuf) && VFS_STAT(conn,fname,&sbuf)) {
+                               DEBUG(3,("call_trans2qfilepathinfo: VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
                                set_bad_path_error(errno, bad_path);
                                return(UNIXERROR(ERRDOS,ERRbadpath));
                        }
@@ -1599,11 +1624,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
                        CHECK_FSP(fsp,conn);
 
                        pstrcpy(fname, fsp->fsp_name);
-                       if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
+                       if (VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
                                DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
                                return(UNIXERROR(ERRDOS,ERRbadfid));
                        }
-                       if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
+                       if((pos = VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1)
                                return(UNIXERROR(ERRDOS,ERRnoaccess));
 
                        delete_pending = fsp->delete_on_close;
@@ -1630,13 +1655,13 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
 
                if (INFO_LEVEL_IS_UNIX(info_level)) {
                        /* Always do lstat for UNIX calls. */
-                       if (vfs_lstat(conn,fname,&sbuf)) {
-                               DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
+                       if (VFS_LSTAT(conn,fname,&sbuf)) {
+                               DEBUG(3,("call_trans2qfilepathinfo: VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
                                set_bad_path_error(errno, bad_path);
                                return(UNIXERROR(ERRDOS,ERRbadpath));
                        }
-               } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
-                       DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
+               } else if (!VALID_STAT(sbuf) && VFS_STAT(conn,fname,&sbuf)) {
+                       DEBUG(3,("call_trans2qfilepathinfo: VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
                        set_bad_path_error(errno, bad_path);
                        return(UNIXERROR(ERRDOS,ERRbadpath));
                }
@@ -1657,7 +1682,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;
 
@@ -1774,6 +1799,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
 
                /* Get the 8.3 name - used if NT SMB was negotiated. */
                case SMB_QUERY_FILE_ALT_NAME_INFO:
+               case SMB_FILE_ALTERNATE_NAME_INFORMATION:
                {
                        pstring short_name;
 
@@ -1782,7 +1808,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
                        if(!mangle_is_8_3(short_name, True)) {
                                mangle_map(short_name,True,True,SNUM(conn));
                        }
-                       len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_TERMINATE|STR_UPPER);
+                       len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
                        data_size = 4 + len;
                        SIVAL(pdata,0,len);
                        break;
@@ -1842,7 +1868,12 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
                        break;
 
                case SMB_FILE_INTERNAL_INFORMATION:
-                       /* This should be an index number - looks like dev/ino to me :-) */
+                       /* This should be an index number - looks like
+                          dev/ino to me :-) 
+
+                          I think this causes us to fail the IFSKIT
+                          BasicFileInformationTest. -tpot */
+
                        SIVAL(pdata,0,sbuf.st_dev);
                        SIVAL(pdata,4,sbuf.st_ino);
                        data_size = 8;
@@ -1905,15 +1936,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
                }
 #endif
 
-               case SMB_FILE_ALTERNATE_NAME_INFORMATION:
-                       /* Last component of pathname. */
-                       {
-                               size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False);
-                               SIVAL(pdata,0,byte_len);
-                               data_size = 4 + byte_len;
-                               break;
-                       }
-               
 #if 0
                /*
                 * NT4 server just returns "invalid query" to this - if we try to answer
@@ -1972,12 +1994,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 */
@@ -2037,7 +2054,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
 #else
                                return(UNIXERROR(ERRDOS,ERRbadlink));
 #endif
-                               len = conn->vfs_ops.readlink(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
+                               len = VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
                                if (len == -1)
                                        return(UNIXERROR(ERRDOS,ERRnoaccess));
                                buffer[len] = 0;
@@ -2089,59 +2106,42 @@ NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
                DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
                        delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
        } else {
+               fsp->delete_on_close = delete_on_close;
+               DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
+                       delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
+       }
 
-               files_struct *iterate_fsp;
-
-               /*
-                * Modify the share mode entry for all files open
-                * on this device and inode to tell other smbds we have 
-                * changed the delete on close flag. This will be noticed
-                * in the close code, the last closer will delete the file
-                * if flag is set.
-                */
+       return NT_STATUS_OK;
+}
 
-               DEBUG(10,("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
-                                       delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
+/****************************************************************************
+ Sets the delete on close flag over all share modes on this file.
+ Modify the share mode entry for all files open
+ on this device and inode to tell other smbds we have
+ changed the delete on close flag. This will be noticed
+ in the close code, the last closer will delete the file
+ if flag is set.
+****************************************************************************/
 
-               if (lock_share_entry_fsp(fsp) == False)
-                               return NT_STATUS_ACCESS_DENIED;
+NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
+{
+       DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
+               delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
 
-               if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
-                       DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
-                                       fsp->fsp_name ));
-                       unlock_share_entry_fsp(fsp);
-                       return NT_STATUS_ACCESS_DENIED;
-               }
+       if (fsp->is_directory || fsp->is_stat)
+               return NT_STATUS_OK;
 
-               /*
-                * Release the lock.
-                */
+       if (lock_share_entry_fsp(fsp) == False)
+               return NT_STATUS_ACCESS_DENIED;
 
+       if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
+               DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
+                       fsp->fsp_name ));
                unlock_share_entry_fsp(fsp);
-
-               /*
-                * Go through all files we have open on the same device and
-                * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
-                * Other smbd's that have this file open will look in the share_mode on close.
-                * take care of this (rare) case in close_file(). See the comment there.
-                * NB. JRA. We don't really need to do this anymore - all should be taken
-                * care of in the share_mode changes in the tdb.
-                */
-
-               for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode);
-                               iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp))
-                                               fsp->delete_on_close = delete_on_close;
-
-               /*
-                * Set the delete on close flag in the fsp.
-                */
-               fsp->delete_on_close = delete_on_close;
-
-               DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
-                       delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
-
+               return NT_STATUS_ACCESS_DENIED;
        }
 
+       unlock_share_entry_fsp(fsp);
        return NT_STATUS_OK;
 }
 
@@ -2178,7 +2178,7 @@ static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in
                pstrcpy(link_dest, "./");
        }
                
-       if (conn->vfs_ops.realpath(conn,link_dest,resolved_name) == NULL)
+       if (VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
                return -1;
 
        pstrcpy(link_dest, resolved_name);
@@ -2269,7 +2269,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
                        pstrcpy(fname, fsp->fsp_name);
                        fd = fsp->fd;
 
-                       if (vfs_fstat(fsp,fd,&sbuf) != 0) {
+                       if (VFS_FSTAT(fsp,fd,&sbuf) != 0) {
                                DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
                                return(UNIXERROR(ERRDOS,ERRbadfid));
                        }
@@ -2334,7 +2334,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
 
        switch (info_level) {
                case SMB_INFO_STANDARD:
-               case SMB_INFO_QUERY_EA_SIZE:
                {
                        if (total_data < l1_cbFile+4)
                                return(ERROR_DOS(ERRDOS,ERRinvalidparam));
@@ -2351,6 +2350,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
                        break;
                }
 
+               case SMB_INFO_SET_EA:
+                       return(ERROR_DOS(ERRDOS,ERReasnotsupported));
+
                /* XXXX um, i don't think this is right.
                        it's also not in the cifs6.txt spec.
                */
@@ -2412,13 +2414,14 @@ 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_BIG_UINT allocation_size;
 
                        if (total_data < 8)
                                return(ERROR_DOS(ERRDOS,ERRinvalidparam));
 
+                       allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
 #ifdef LARGE_SMB_OFF_T
-                       allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
+                       allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
 #else /* LARGE_SMB_OFF_T */
                        if (IVAL(pdata,4) != 0) /* more than 32 bits? */
                                return ERROR_DOS(ERRDOS,ERRunknownlevel);
@@ -2426,6 +2429,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;
  
@@ -2455,7 +2461,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
                                        if (new_fsp == NULL)
                                                return(UNIXERROR(ERRDOS,ERRbadpath));
                                        ret = vfs_allocate_file_space(new_fsp, allocation_size);
-                                       if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
+                                       if (VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
                                                DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
                                                                        new_fsp->fnum, strerror(errno)));
                                                ret = -1;
@@ -2463,7 +2469,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
                                        close_file(new_fsp,True);
                                } else {
                                        ret = vfs_allocate_file_space(fsp, allocation_size);
-                                       if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
+                                       if (VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
                                                DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
                                                                        fsp->fnum, strerror(errno)));
                                                ret = -1;
@@ -2513,6 +2519,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
 
                        status = set_delete_on_close_internal(fsp, delete_on_close);
  
+                       if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
+                               return ERROR_NT(status);
+
+                       /* The set is across all open files on this dev/inode pair. */
+                       status =set_delete_on_close_over_all(fsp, delete_on_close);
                        if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
                                return ERROR_NT(status);
 
@@ -2598,9 +2609,11 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
 0%o for file %s\n", (double)dev, unixmode, fname ));
 
                                /* Ok - do the mknod. */
-                               if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
+                               if (VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
                                        return(UNIXERROR(ERRDOS,ERRnoaccess));
 
+                               inherit_access_acl(conn, fname, unixmode);
+
                                SSVAL(params,0,0);
                                send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
                                return(-1);
@@ -2615,7 +2628,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                        if (raw_unixmode != SMB_MODE_NO_CHANGE) {
                                DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
                                        (unsigned int)unixmode, fname ));
-                               if (vfs_chmod(conn,fname,unixmode) != 0)
+                               if (VFS_CHMOD(conn,fname,unixmode) != 0)
                                        return(UNIXERROR(ERRDOS,ERRnoaccess));
                        }
 
@@ -2626,7 +2639,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                        if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
                                DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
                                        (unsigned int)set_owner, fname ));
-                               if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0)
+                               if (VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
                                        return(UNIXERROR(ERRDOS,ERRnoaccess));
                        }
 
@@ -2637,7 +2650,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                        if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
                                DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
                                        (unsigned int)set_owner, fname ));
-                               if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0)
+                               if (VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
                                        return(UNIXERROR(ERRDOS,ERRnoaccess));
                        }
                        break;
@@ -2664,7 +2677,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                        DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
                                fname, link_dest ));
 
-                       if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0)
+                       if (VFS_SYMLINK(conn,link_dest,fname) != 0)
                                return(UNIXERROR(ERRDOS,ERRnoaccess));
                        SSVAL(params,0,0);
                        send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
@@ -2689,7 +2702,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                        DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
                                fname, link_dest ));
 
-                       if (conn->vfs_ops.link(conn,link_dest,fname) != 0)
+                       if (VFS_LINK(conn,link_dest,fname) != 0)
                                return(UNIXERROR(ERRDOS,ERRnoaccess));
                        SSVAL(params,0,0);
                        send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
@@ -2841,7 +2854,7 @@ static int call_trans2mkdir(connection_struct *conn,
 
        unix_convert(directory,conn,0,&bad_path,&sbuf);
        if (check_name(directory,conn))
-               ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
+               ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
   
        if(ret < 0) {
                DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
@@ -2986,8 +2999,6 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf,
        
        if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
                        (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
-               uint16 rap_jobid;
-
                pdata = Realloc(*ppdata, 32);
                if(pdata == NULL)
                        return ERROR_DOS(ERRDOS,ERRnomem);
@@ -2996,9 +3007,8 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf,
                /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
                        CAN ACCEPT THIS IN UNICODE. JRA. */
 
-               rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid);                     /* Job number */
-               SSVAL(pdata,0,rap_jobid);                     /* Job number */
-               srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
+               SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
+               srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
                srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
                send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
                return(-1);
@@ -3092,7 +3102,7 @@ int reply_trans2(connection_struct *conn,
        unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
        unsigned int tran_call = SVAL(inbuf, smb_setup0);
        char *params = NULL, *data = NULL;
-       int num_params, num_params_sofar, num_data, num_data_sofar;
+       unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
        START_PROFILE(SMBtrans2);
 
        if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
@@ -3131,10 +3141,10 @@ int reply_trans2(connection_struct *conn,
                                (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
                        DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
                } else {
-                       DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
+                       DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
                        DEBUG(2,("Transaction is %d\n",tran_call));
                        END_PROFILE(SMBtrans2);
-                       return ERROR_DOS(ERRSRV,ERRerror);
+                       ERROR_DOS(ERRDOS,ERRinvalidparam);
                }
        }
     
@@ -3160,10 +3170,22 @@ int reply_trans2(connection_struct *conn,
        if (num_params > total_params || num_data > total_data)
                exit_server("invalid params in reply_trans2");
 
-       if(params)
-               memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
-       if(data)
-               memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
+       if(params) {
+               unsigned int psoff = SVAL(inbuf, smb_psoff);
+               if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
+                       goto bad_param;
+               if (smb_base(inbuf) + psoff + num_params > inbuf + length)
+                       goto bad_param;
+               memcpy( params, smb_base(inbuf) + psoff, num_params);
+       }
+       if(data) {
+               unsigned int dsoff = SVAL(inbuf, smb_dsoff);
+               if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
+                       goto bad_param;
+               if (smb_base(inbuf) + dsoff + num_data > inbuf + length)
+                       goto bad_param;
+               memcpy( data, smb_base(inbuf) + dsoff, num_data);
+       }
 
        if(num_data_sofar < total_data || num_params_sofar < total_params)  {
                /* We need to send an interim response then receive the rest
@@ -3175,6 +3197,10 @@ int reply_trans2(connection_struct *conn,
                while (num_data_sofar < total_data || 
                       num_params_sofar < total_params) {
                        BOOL ret;
+                       unsigned int param_disp;
+                       unsigned int param_off;
+                       unsigned int data_disp;
+                       unsigned int data_off;
 
                        ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
                        
@@ -3186,25 +3212,55 @@ int reply_trans2(connection_struct *conn,
                                else
                                        DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
                                                 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
-                               SAFE_FREE(params);
-                               SAFE_FREE(data);
-                               END_PROFILE(SMBtrans2);
-                               return ERROR_DOS(ERRSRV,ERRerror);
+                               goto bad_param;
                        }
       
                        /* Revise total_params and total_data in case
                            they have changed downwards */
-                       total_params = SVAL(inbuf, smb_tpscnt);
-                       total_data = SVAL(inbuf, smb_tdscnt);
-                       num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
-                       num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
+                       if (SVAL(inbuf, smb_tpscnt) < total_params)
+                               total_params = SVAL(inbuf, smb_tpscnt);
+                       if (SVAL(inbuf, smb_tdscnt) < total_data)
+                               total_data = SVAL(inbuf, smb_tdscnt);
+
+                       num_params = SVAL(inbuf,smb_spscnt);
+                       param_off = SVAL(inbuf, smb_spsoff);
+                       param_disp = SVAL(inbuf, smb_spsdisp);
+                       num_params_sofar += num_params;
+
+                       num_data = SVAL(inbuf, smb_sdscnt);
+                       data_off = SVAL(inbuf, smb_sdsoff);
+                       data_disp = SVAL(inbuf, smb_sdsdisp);
+                       num_data_sofar += num_data;
+
                        if (num_params_sofar > total_params || num_data_sofar > total_data)
-                               exit_server("data overflow in trans2");
+                               goto bad_param;
                        
-                       memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
-                               smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
-                       memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
-                               smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
+                       if (num_params) {
+                               if (param_disp + num_params >= total_params)
+                                       goto bad_param;
+                               if ((param_disp + num_params < param_disp) ||
+                                               (param_disp + num_params < num_params))
+                                       goto bad_param;
+                               if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize)
+                                       goto bad_param;
+                               if (params + param_disp < params)
+                                       goto bad_param;
+
+                               memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
+                       }
+                       if (num_data) {
+                               if (data_disp + num_data >= total_data)
+                                       goto bad_param;
+                               if ((data_disp + num_data < data_disp) ||
+                                               (data_disp + num_data < num_data))
+                                       goto bad_param;
+                               if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize)
+                                       goto bad_param;
+                               if (data + data_disp < data)
+                                       goto bad_param;
+
+                               memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
+                       }
                }
        }
        
@@ -3318,4 +3374,11 @@ int reply_trans2(connection_struct *conn,
        return outsize; /* If a correct response was needed the
                           call_trans2xxx calls have already sent
                           it. If outsize != -1 then it is returning */
+
+  bad_param:
+
+       SAFE_FREE(params);
+       SAFE_FREE(data);
+       END_PROFILE(SMBtrans2);
+       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
 }