moved trans2.h and nterr.h into includes.h with all our other includes
[abartlet/samba.git/.git] / source3 / smbd / trans2.c
index bbbfda74687ed1177ad73d4d49a7553fa6a8ca44..4e502f767bdc13086479965e8ecdcb57895cfbae 100644 (file)
 */
 
 #include "includes.h"
-#include "trans2.h"
 
 extern int DEBUGLEVEL;
 extern int Protocol;
 extern BOOL case_sensitive;
-extern int Client;
 extern int smb_read_error;
 extern fstring local_machine;
 extern int global_oplock_break;
@@ -66,7 +64,7 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params,
      the empty packet */
   if(params_to_send == 0 && data_to_send == 0)
   {
-    send_smb(Client,outbuf);
+    send_smb(smbd_server_fd(),outbuf);
     return 0;
   }
 
@@ -95,7 +93,14 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params,
     total_sent_thistime = params_to_send + data_to_send + 
                             alignment_offset + data_alignment_offset;
     /* We can never send more than useable_space */
-    total_sent_thistime = MIN(total_sent_thistime, useable_space);
+    /*
+     * Note that 'useable_space' does not include the alignment offsets,
+     * but we must include the alignment offsets in the calculation of
+     * the length of the data we send over the wire, as the alignment offsets
+     * are sent here. Fix from Marc_Jacobsen@hp.com.
+     */
+    total_sent_thistime = MIN(total_sent_thistime, useable_space+
+                               alignment_offset + data_alignment_offset);
 
     set_message(outbuf, 10, total_sent_thistime, True);
 
@@ -111,21 +116,19 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params,
     data_sent_thistime = MIN(data_sent_thistime,data_to_send);
 
     SSVAL(outbuf,smb_prcnt, params_sent_thistime);
+
+    /* smb_proff is the offset from the start of the SMB header to the
+       parameter bytes, however the first 4 bytes of outbuf are
+       the Netbios over TCP header. Thus use smb_base() to subtract
+       them from the calculation */
+
+    SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
+
     if(params_sent_thistime == 0)
-    {
-      SSVAL(outbuf,smb_proff,0);
       SSVAL(outbuf,smb_prdisp,0);
-    }
     else
-    {
-      /* smb_proff is the offset from the start of the SMB header to the
-         parameter bytes, however the first 4 bytes of outbuf are
-         the Netbios over TCP header. Thus use smb_base() to subtract
-         them from the calculation */
-      SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
       /* Absolute displacement of param bytes sent in this packet */
       SSVAL(outbuf,smb_prdisp,pp - params);
-    }
 
     SSVAL(outbuf,smb_drcnt, data_sent_thistime);
     if(data_sent_thistime == 0)
@@ -156,7 +159,7 @@ static int send_trans2_replies(char *outbuf, int bufsize, char *params,
           params_to_send, data_to_send, paramsize, datasize));
 
     /* Send the packet */
-    send_smb(Client,outbuf);
+    send_smb(smbd_server_fd(),outbuf);
 
     pp += params_sent_thistime;
     pd += data_sent_thistime;
@@ -217,10 +220,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf,
 
   unix_convert(fname,conn,0,&bad_path,NULL);
     
-  fsp = file_new();
-  if (!fsp)
-    return(ERROR(ERRSRV,ERRnofids));
-
   if (!check_name(fname,conn))
   {
     if((errno == ENOENT) && bad_path)
@@ -228,27 +227,25 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf,
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
-    file_free(fsp);
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
-  unixmode = unix_mode(conn,open_attr | aARCH);
+  unixmode = unix_mode(conn,open_attr | aARCH, fname);
       
-  open_file_shared(fsp,conn,fname,open_mode,open_ofun,unixmode,
+  fsp = open_file_shared(conn,fname,open_mode,open_ofun,unixmode,
                   oplock_request, &rmode,&smb_action);
       
-  if (!fsp->open)
+  if (!fsp)
   {
     if((errno == ENOENT) && bad_path)
     {
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
-    file_free(fsp);
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
-  if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
+  if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) {
     close_file(fsp,False);
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
@@ -315,9 +312,6 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
   uint32 len;
   time_t mdate=0, adate=0, cdate=0;
   char *nameptr;
-  BOOL isrootdir = (strequal(conn->dirpath,"./") ||
-                   strequal(conn->dirpath,".") ||
-                   strequal(conn->dirpath,"/"));
   BOOL was_8_3;
   int nt_extmode; /* Used for NT connections instead of mode */
   BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
@@ -390,14 +384,11 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
       if (dont_descend && !isdots)
         continue;
          
-      if (isrootdir && isdots)
-        continue;
-
       pstrcpy(pathreal,conn->dirpath);
       if(needslash)
         pstrcat(pathreal,"/");
       pstrcat(pathreal,dname);
-      if (dos_stat(pathreal,&sbuf) != 0) 
+      if (conn->vfs_ops.stat(dos_to_unix(pathreal,False),&sbuf) != 0) 
       {
         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
         continue;
@@ -686,6 +677,8 @@ static int call_trans2findfirst(connection_struct *conn,
   pstrcpy(directory, params + 12); /* Complete directory path with 
                                     wildcard mask appended */
 
+  RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
+
   DEBUG(5,("path=%s\n",directory));
 
   unix_convert(directory,conn,0,&bad_path,NULL);
@@ -764,7 +757,7 @@ static int call_trans2findfirst(connection_struct *conn,
 
   for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
   {
-    BOOL got_exact_match;
+    BOOL got_exact_match = False;
 
     /* this is a heuristic to avoid seeking the dirptr except when 
        absolutely necessary. It allows for a filename of about 40 chars */
@@ -1034,7 +1027,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
 
   for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
   {
-    BOOL got_exact_match;
+    BOOL got_exact_match = False;
 
     /* this is a heuristic to avoid seeking the dirptr except when 
        absolutely necessary. It allows for a filename of about 40 chars */
@@ -1117,7 +1110,7 @@ static int call_trans2qfsinfo(connection_struct *conn,
 
   DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
 
-  if(dos_stat(".",&st)!=0) {
+  if(conn->vfs_ops.stat(".",&st)!=0) {
     DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
     return (ERROR(ERRSRV,ERRinvdevice));
   }
@@ -1131,7 +1124,7 @@ static int call_trans2qfsinfo(connection_struct *conn,
     {
       SMB_BIG_UINT dfree,dsize,bsize;
       data_len = 18;
-      sys_disk_free(".",False,&bsize,&dfree,&dsize);   
+      conn->vfs_ops.disk_free(".",False,&bsize,&dfree,&dsize); 
       SIVAL(pdata,l1_idFileSystem,st.st_dev);
       SIVAL(pdata,l1_cSectorUnit,bsize/512);
       SIVAL(pdata,l1_cUnit,dsize);
@@ -1163,13 +1156,14 @@ static int call_trans2qfsinfo(connection_struct *conn,
     {
       int fstype_len;
       SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
-            lp_nt_acl_support() ? FILE_PERSISTENT_ACLS : 0); /* FS ATTRIBUTES */
+                       FILE_DEVICE_IS_MOUNTED|
+            (lp_nt_acl_support() ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
 #if 0 /* Old code. JRA. */
       SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
 #endif /* Old code. */
 
       SIVAL(pdata,4,128); /* Max filename component length */
-      fstype_len = dos_PutUniCode(pdata+12,unix_to_dos(fstype,False),sizeof(pstring)/2);
+      fstype_len = dos_PutUniCode(pdata+12,unix_to_dos(fstype,False),sizeof(pstring), False);
       SIVAL(pdata,8,fstype_len);
       data_len = 12 + fstype_len;
       SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
@@ -1192,14 +1186,15 @@ static int call_trans2qfsinfo(connection_struct *conn,
       /* NT4 always serves this up as unicode but expects it to be
        * delivered as ascii! (tridge && JRA)
        */
-      if (global_client_caps & CAP_NT_SMBS) {
+      if ((get_remote_arch() != RA_WIN2K) && (global_client_caps & CAP_NT_SMBS)) {
              data_len = 18 + strlen(vname);
              SIVAL(pdata,12,strlen(vname));
              pstrcpy(pdata+18,vname);      
       } else {
              data_len = 18 + 2*strlen(vname);
              SIVAL(pdata,12,strlen(vname)*2);
-             dos_PutUniCode(pdata+18,unix_to_dos(vname,False),sizeof(pstring)/2);      
+             dos_PutUniCode(pdata+18,unix_to_dos(vname,False),sizeof(pstring), False);
+                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
       }
 
       DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", 
@@ -1209,7 +1204,7 @@ static int call_trans2qfsinfo(connection_struct *conn,
     {
       SMB_BIG_UINT dfree,dsize,bsize;
       data_len = 24;
-      sys_disk_free(".",False,&bsize,&dfree,&dsize);   
+      conn->vfs_ops.disk_free(".",False,&bsize,&dfree,&dsize); 
       SBIG_UINT(pdata,0,dsize);
       SBIG_UINT(pdata,8,dfree);
       SIVAL(pdata,16,bsize/512);
@@ -1300,7 +1295,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
 
     DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
 
-    if(fsp && fsp->open && (fsp->is_directory || fsp->stat_open)) {
+    if(fsp && (fsp->is_directory || fsp->stat_open)) {
       /*
        * This is actually a QFILEINFO on a directory
        * handle (returned from an NT SMB). NT5.0 seems
@@ -1308,7 +1303,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
        */
       fname = fsp->fsp_name;
       unix_convert(fname,conn,0,&bad_path,&sbuf);
-      if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) {
+      if (!check_name(fname,conn) || 
+          (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) {
         DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
         if((errno == ENOENT) && bad_path)
         {
@@ -1328,14 +1324,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
       CHECK_ERROR(fsp);
 
       fname = fsp->fsp_name;
-      if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
+      if (fsp->conn->vfs_ops.fstat(fsp->fd,&sbuf) != 0) {
         DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
         return(UNIXERROR(ERRDOS,ERRbadfid));
       }
-      if((pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1)
+      if((pos = fsp->conn->vfs_ops.lseek(fsp->fd,0,SEEK_CUR)) == -1)
         return(UNIXERROR(ERRDOS,ERRnoaccess));
 
-      delete_pending = fsp->fd_ptr->delete_on_close;
+      delete_pending = fsp->delete_on_close;
     }
   } else {
     /* qpathinfo */
@@ -1345,8 +1341,12 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
 
     fname = &fname1[0];
     pstrcpy(fname,&params[6]);
+
+    RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+
     unix_convert(fname,conn,0,&bad_path,&sbuf);
-    if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) {
+    if (!check_name(fname,conn) || 
+        (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) {
       DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
       if((errno == ENOENT) && bad_path)
       {
@@ -1465,7 +1465,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
         }
         strupper(short_name);
         l = strlen(short_name);
-        dos_PutUniCode(pdata + 4, unix_to_dos(short_name,False),sizeof(pstring)*2);
+        dos_PutUniCode(pdata + 4, unix_to_dos(short_name,False),sizeof(pstring), False);
         data_size = 4 + (2*l);
         SIVAL(pdata,0,2*l);
       }
@@ -1481,7 +1481,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
       if(strequal(".", fname) && (global_client_caps & CAP_UNICODE)) {
         l = l*2;
         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
-        dos_PutUniCode(pdata + 4, unix_to_dos("\\",False),sizeof(pstring)*2);
+        dos_PutUniCode(pdata + 4, unix_to_dos("\\",False),sizeof(pstring), False);
       } else {
         pstrcpy(pdata+4,fname);
       }
@@ -1578,7 +1578,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
     fsp = file_fsp(params,0);
     info_level = SVAL(params,2);    
 
-    if(fsp && fsp->open && (fsp->is_directory || fsp->stat_open)) {
+    if(fsp && (fsp->is_directory || fsp->stat_open)) {
       /*
        * This is actually a SETFILEINFO on a directory
        * handle (returned from an NT SMB). NT5.0 seems
@@ -1586,7 +1586,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
        */
       fname = fsp->fsp_name;
       unix_convert(fname,conn,0,&bad_path,&st);
-      if (!check_name(fname,conn) || (!VALID_STAT(st) && dos_stat(fname,&st))) {
+      if (!check_name(fname,conn) || 
+          (!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st))) {
         DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
         if((errno == ENOENT) && bad_path)
         {
@@ -1603,9 +1604,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
       CHECK_ERROR(fsp);
 
       fname = fsp->fsp_name;
-      fd = fsp->fd_ptr->fd;
+      fd = fsp->fd;
 
-      if (sys_fstat(fd,&st) != 0) {
+      if (fsp->conn->vfs_ops.fstat(fd,&st) != 0) {
         DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
         return(UNIXERROR(ERRDOS,ERRbadfid));
       }
@@ -1626,7 +1627,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
       return(UNIXERROR(ERRDOS,ERRbadpath));
     }
  
-    if(!VALID_STAT(st) && dos_stat(fname,&st)!=0) {
+    if(!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st)!=0) {
       DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
       if((errno == ENOENT) && bad_path)
       {
@@ -1706,7 +1707,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
       write_time = interpret_long_date(pdata+16);
       changed_time = interpret_long_date(pdata+24);
 
-      tvs.modtime = MAX(write_time, changed_time);
+      tvs.modtime = MIN(write_time, changed_time);
 
       /* Prefer a defined time to an undefined one. */
       if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
@@ -1786,113 +1787,110 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
            * the share mode contained ALLOW_SHARE_DELETE
            */
 
-          if(lp_share_modes(SNUM(conn)))
+          if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode))
+            return(ERROR(ERRDOS,ERRnoaccess));
+
+          /*
+           * If the flag has been set then
+           * modify the share mode entry for all files we have open
+           * on this device and inode to tell other smbds we have 
+           * changed the delete on close flag.
+           */
+
+          if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode))
           {
-            if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode))
+            int i;
+            files_struct *iterate_fsp;
+            SMB_DEV_T dev = fsp->dev;
+            SMB_INO_T inode = fsp->inode;
+            int num_share_modes;
+            share_mode_entry *current_shares = NULL;
+
+            if (lock_share_entry_fsp(fsp) == False)
               return(ERROR(ERRDOS,ERRnoaccess));
 
             /*
-             * If the flag has been set then
-             * modify the share mode entry for all files we have open
-             * on this device and inode to tell other smbds we have 
-             * changed the delete on close flag.
+             * Before we allow this we need to ensure that all current opens
+             * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they
+             * do not then we deny this (as we are essentially deleting the
+             * file at this point.
              */
 
-            if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode))
+            num_share_modes = get_share_modes(conn, dev, inode, &current_shares);
+            for(i = 0; i < num_share_modes; i++)
             {
-              int i;
-              files_struct *iterate_fsp;
-              SMB_DEV_T dev = fsp->fd_ptr->dev;
-              SMB_INO_T inode = fsp->fd_ptr->inode;
-              int num_share_modes;
-              share_mode_entry *current_shares = NULL;
-
-              if(lock_share_entry(fsp->conn, dev, inode) == False)
-                return(ERROR(ERRDOS,ERRnoaccess));
-
-              /*
-               * Before we allow this we need to ensure that all current opens
-               * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they
-               * do not then we deny this (as we are essentially deleting the
-               * file at this point.
-               */
-
-              num_share_modes = get_share_modes(conn, dev, inode, &current_shares);
-              for(i = 0; i < num_share_modes; i++)
+              if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode))
               {
-                if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode))
-                {
-                  DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \
+                DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \
 file %s as a share exists that was not opened with FILE_DELETE access.\n",
-                        fsp->fnum, fsp->fsp_name ));
-                  /*
-                   * Release the lock.
-                   */
+                      fsp->fnum, fsp->fsp_name ));
+                /*
+                 * Release the lock.
+                 */
 
-                  unlock_share_entry(fsp->conn, dev, inode);
+                unlock_share_entry_fsp(fsp);
 
-                  /*
-                   * current_shares was malloced by get_share_modes - free it here.
-                   */
+                /*
+                 * current_shares was malloced by get_share_modes - free it here.
+                 */
 
-                  free((char *)current_shares);
+                free((char *)current_shares);
 
-                  /*
-                   * Even though share violation would be more appropriate here,
-                   * return ERRnoaccess as that's what NT does.
-                   */
+                /*
+                 * Even though share violation would be more appropriate here,
+                 * return ERRnoaccess as that's what NT does.
+                 */
 
-                  return(ERROR(ERRDOS,ERRnoaccess));
-                }
+                return(ERROR(ERRDOS,ERRnoaccess));
               }
+            }
 
-              /*
-               * current_shares was malloced by get_share_modes - free it here.
-               */
+            /*
+             * current_shares was malloced by get_share_modes - free it here.
+             */
 
-              free((char *)current_shares);
+            free((char *)current_shares);
 
-              DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
-                   delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
+            DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
+                 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
 
-              /*
-               * 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 have to fend for themselves. We
-               * take care of this (rare) case in close_file(). See the comment there.
-               */
+            /*
+             * 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 have to fend for themselves. We
+             * take care of this (rare) case in close_file(). See the comment there.
+             */
 
-              for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp;
-                                    iterate_fsp = file_find_di_next(iterate_fsp))
-              {
-                int new_share_mode = (delete_on_close ? 
-                                      (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) :
-                                      (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) );
+            for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp;
+                                  iterate_fsp = file_find_di_next(iterate_fsp))
+            {
+              int new_share_mode = (delete_on_close ? 
+                                    (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) :
+                                    (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) );
 
-                DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \
+              DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \
 dev = %x, inode = %.0f from %x to %x\n", 
-                      iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, 
-                      (double)inode, iterate_fsp->share_mode, new_share_mode ));
+                    iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, 
+                    (double)inode, iterate_fsp->share_mode, new_share_mode ));
 
-                if(modify_share_mode(iterate_fsp, new_share_mode, iterate_fsp->oplock_type)==False)
-                  DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \
+              if(modify_share_mode(iterate_fsp, new_share_mode, iterate_fsp->oplock_type)==False)
+                DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \
 dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode));
-              }
+            }
 
-              /*
-               * Set the delete on close flag in the reference
-               * counted struct. Delete when the last reference
-               * goes away.
-               */
-             fsp->fd_ptr->delete_on_close = delete_on_close;
+            /*
+             * Set the delete on close flag in the reference
+             * counted struct. Delete when the last reference
+             * goes away.
+             */
+           fsp->delete_on_close = delete_on_close;
 
-             unlock_share_entry(fsp->conn, dev, inode);
+           unlock_share_entry_fsp(fsp);
 
-             DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
-                   delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
+           DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
+                 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
 
-            } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */
-          } /* end if lp_share_modes() */
+          } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */
         } /* end if is_directory. */
       } else
         return(ERROR(ERRDOS,ERRunknownlevel));
@@ -1973,13 +1971,13 @@ dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode))
           fname, (double)size ));
 
     if (fd == -1) {
-      fd = dos_open(fname,O_RDWR,0);
+      fd = conn->vfs_ops.open(dos_to_unix(fname,False),O_RDWR,0);
       if (fd == -1)
         return(UNIXERROR(ERRDOS,ERRbadpath));
-      set_filelen(fd, size);
-      close(fd);
+      set_filelen(fd, size); /* tpot vfs */
+      conn->vfs_ops.close(fd);
     } else {
-      set_filelen(fd, size);
+        set_filelen(fd, size); /* tpot vfs */
     }
 
     if(fsp)
@@ -2014,7 +2012,8 @@ static int call_trans2mkdir(connection_struct *conn,
 
   unix_convert(directory,conn,0,&bad_path,NULL);
   if (check_name(directory,conn))
-    ret = dos_mkdir(directory,unix_mode(conn,aDIR));
+    ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
+                             unix_mode(conn,aDIR,directory));
   
   if(ret < 0)
     {
@@ -2108,6 +2107,47 @@ static int call_trans2findnotifynext(connection_struct *conn,
   return(-1);
 }
 
+/****************************************************************************
+  reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>
+****************************************************************************/
+static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
+                                    char* outbuf, int length, int bufsize,
+                                    char** pparams, char** ppdata)
+{
+  char *params = *pparams;
+  enum remote_arch_types ra_type = get_remote_arch();
+  BOOL NT_arch = ((ra_type == RA_WINNT) || (ra_type == RA_WIN2K));
+  pstring pathname;
+  int reply_size = 0;
+  int max_referral_level = SVAL(params,0);
+
+
+  DEBUG(10,("call_trans2getdfsreferral\n"));
+
+  if(!lp_host_msdfs())
+    return(ERROR(ERRDOS,ERRbadfunc));
+
+  /* if pathname is in UNICODE, convert to DOS */
+  /* NT always sends in UNICODE, may not set UNICODE flag */
+  if(NT_arch || (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS))
+    {
+      unistr_to_dos(pathname, &params[2]);
+      DEBUG(10,("UNICODE referral for %s\n",pathname));
+    }
+  else
+    pstrcpy(pathname,&params[2]);
+
+  if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
+    return(ERROR(ERRDOS,ERRbadfile));
+    
+  SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_UNICODE_STRINGS | 
+       FLAGS2_DFS_PATHNAMES);
+  send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
+
+  return(-1);
+}
+
+
 /****************************************************************************
   reply to a SMBfindclose (stop trans2 directory search)
 ****************************************************************************/
@@ -2237,7 +2277,7 @@ int reply_trans2(connection_struct *conn,
                /* We need to send an interim response then receive the rest
                   of the parameter/data bytes */
                outsize = set_message(outbuf,0,0,True);
-               send_smb(Client,outbuf);
+               send_smb(smbd_server_fd(),outbuf);
 
                while (num_data_sofar < total_data || 
                       num_params_sofar < total_params) {
@@ -2341,6 +2381,11 @@ int reply_trans2(connection_struct *conn,
                outsize = call_trans2mkdir(conn, inbuf, outbuf, length, 
                                           bufsize, &params, &data);
                break;
+
+       case TRANSACT2_GET_DFS_REFERRAL:
+               outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length,
+                                                   bufsize, &params, &data);
+               break;
        default:
                /* Error in request */
                DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));