This is a *big* checkin that may break some things, but implements the
authorJeremy Allison <jra@samba.org>
Sat, 22 Apr 2000 00:33:16 +0000 (00:33 +0000)
committerJeremy Allison <jra@samba.org>
Sat, 22 Apr 2000 00:33:16 +0000 (00:33 +0000)
new open mechanism Andrew & I discussed.

config.sub:
configure: Included the QNX patch.

include/vfs.h:
smbd/vfs-wrap.c:
smbd/vfs.c: Added ftruncate vfs call (needed).

Note that we will also need locking calls in the vfs (to be added).

lib/util_unistr.c:
nmbd/nmbd_processlogon.c: Fix for NT domain logons causing nmbd to core dump.
                          Also fix for sidsize DOS bug.

locking/locking.c: Check value of ret before using it for memdup.

printing/printing.c: Convert print_fsp_open to return an allocated fsp.

rpc_server/srv_lsa.c: Fix for NT domain logons.

I have removed all use of lp_share_modes() from the code (although I
left the parameter in the table for backwards compatibility). It no longer makes
sense for this to exist.

smbd/close.c: Removed lp_share_modes().
smbd/fileio.c: Fixed parameters to unlock_share_entry call in panic code.
smbd/files.c: Correctly set the unix_ERR_code to ERRnofids on fsp allocation fail.

smbd/nttrans.c:
smbd/reply.c:
smbd/trans2.c: Changed all occurrences of open_file_shared/open_directory/
               open_file_stat to return an fsp from the call.

smbd/open.c: Changed all occurrences of open_file_shared/open_directory/
             open_file_stat to return an fsp from the call.

In addition I have fixed a long standing race condition in the deny mode
processing w.r.t. two smbd's creating a file. Andrew, please note that
your original idea of using open with O_EXCL in this case would not work
(I went over the races very carefully) and so we must re-check deny modes
*after* the open() call returns. This is because there is a race between
the open with O_EXCL and the lock of the share mode entry. Imagine the
case where the first smbd does the open with O_EXCL and a deny mode of DENY_ALL,
but is pre-empted before it locks the share modes and creates the deny
mode entry for DENY_ALL. A second smbd could then come in with O_RDONLY
and a deny mode of DENY_NONE and the two opens would be allowed.

The *only* way to fix this race is to lock the share modes after the
open and then do the deny mode checks *after* this lock in the case
where the file did not originally exist.

This code will need extensive testing but seems to initially work.

Jeremy.

17 files changed:
source/config.sub
source/include/proto.h
source/include/vfs.h
source/lib/util_unistr.c
source/locking/locking.c
source/nmbd/nmbd_processlogon.c
source/printing/printing.c
source/rpc_server/srv_lsa.c
source/smbd/close.c
source/smbd/fileio.c
source/smbd/files.c
source/smbd/nttrans.c
source/smbd/open.c
source/smbd/reply.c
source/smbd/trans2.c
source/smbd/vfs-wrap.c
source/smbd/vfs.c

index ccbdb0257d2b70f9e8c70332f166e6a916b17f3a..90516535a1eb213650a6eb8c3a86f81aa507efc2 100755 (executable)
@@ -827,7 +827,7 @@ case $os in
              | -riscix*  | -lites* \
              | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
              | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta | -udi \
-             | -eabi* | -ieee*)
+             | -eabi* | -ieee* | -qnx*)
                ;;
        # CYGNUS LOCAL
        -go32 | -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
index 4e5b614f56cf1f7402d97e44e9e8a26b6fb8334c..dfa76b39952cb418c7e61d3495778930976b2130 100644 (file)
@@ -493,8 +493,7 @@ char *string_truncate(char *s, int length);
 int dos_PutUniCode(char *dst,const char *src, ssize_t len, BOOL null_terminate);
 void ascii_to_unistr(uint16 *dest, const char *src, int maxlen);
 void unistr_to_ascii(char *dest, const uint16 *src, int len);
-char *skip_unibuf(char *src, int len);
-char *skip_unicode_string(char *buf,int n);
+char *skip_unibuf(char *src, size_t len);
 char *dos_unistrn2(uint16 *src, int len);
 char *dos_unistr2(uint16 *src);
 char *dos_unistr2_to_str(UNISTR2 *str);
@@ -1602,7 +1601,7 @@ int print_queue_snum(char *qname);
 BOOL print_queue_pause(int snum);
 BOOL print_queue_resume(int snum);
 BOOL print_queue_purge(int snum);
-void print_fsp_open(files_struct *fsp,connection_struct *conn,char *jobname);
+files_struct *print_fsp_open(connection_struct *conn,char *jobname);
 void print_fsp_end(files_struct *fsp);
 
 /*The following definitions come from  profile/profile.c  */
@@ -2928,6 +2927,7 @@ BOOL check_plaintext_password(char *user, char *old_passwd,
 
 /*The following definitions come from  smbd/close.c  */
 
+void close_filestruct(files_struct *fsp);
 int close_file(files_struct *fsp, BOOL normal_close);
 
 /*The following definitions come from  smbd/conn.c  */
@@ -3092,11 +3092,11 @@ int reply_nttrans(connection_struct *conn,
 /*The following definitions come from  smbd/open.c  */
 
 int fd_close(struct connection_struct *conn, files_struct *fsp);
-void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun,
+files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mode,int ofun,
                      mode_t mode,int oplock_request, int *Access,int *action);
-int open_file_stat(files_struct *fsp,connection_struct *conn,
+files_struct *open_file_stat(connection_struct *conn,
                   char *fname, int smb_ofun, SMB_STRUCT_STAT *pst, int *action);
-int open_directory(files_struct *fsp,connection_struct *conn,
+files_struct *open_directory(connection_struct *conn,
                   char *fname, int smb_ofun, mode_t unixmode, int *action);
 BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op);
 
@@ -3311,6 +3311,7 @@ int vfswrap_lstat(char *path,
 int vfswrap_unlink(char *path);
 int vfswrap_chmod(char *path, mode_t mode);
 int vfswrap_utime(char *path, struct utimbuf *times);
+int vfswrap_ftruncate(int fd, SMB_OFF_T offset);
 
 /*The following definitions come from  smbd/vfs.c  */
 
index fca9f7da84ac0861d853c4af97164d03aabefa99..a09991a0e7368c2ca8bc0dbead561c583cc9249c 100644 (file)
@@ -136,6 +136,7 @@ struct vfs_ops {
     int (*unlink)(char *path);
     int (*chmod)(char *path, mode_t mode);
     int (*utime)(char *path, struct utimbuf *times);
+       int (*ftruncate)(int fd, SMB_OFF_T offset);
 };
 
 struct vfs_options {
index 0c88a0c7c721500b376b4c73d42377064df885b1..71ef32a1fd98d48e74eaa0ddef05a7ca93345725 100644 (file)
@@ -137,29 +137,22 @@ void unistr_to_ascii(char *dest, const uint16 *src, int len)
        *dest = 0;
 }
 
-/* from TNG - should be fixed */
-char *skip_unibuf(char *src, int len)
-{
-       char *srcend = src + len;
-
-       while (src < srcend && SVAL(src,0)) src += 2;
-
-       return src;
-}
-
-
 /*******************************************************************
- Skip past some unicode strings in a buffer.
+ Skip past a unicode string, but not more than len. Always move
+ past a terminating zero if found.
 ********************************************************************/
 
-char *skip_unicode_string(char *buf,int n)
+char *skip_unibuf(char *src, size_t len)
 {
-       while (n--) {
-               while (*buf)
-                       buf += 2;
-               buf += 2;
-       }
-       return(buf);
+    char *srcend = src + len;
+
+    while (src < srcend && SVAL(src,0))
+        src += 2;
+
+    if(!SVAL(src,0))
+        src += 2;
+
+    return src;
 }
 
 /*******************************************************************
index bde1ffb567ee3f027650b7b7c743ad14f1591b6f..affda89f08cdc75f64a3e98a513391cf2762fa9d 100644 (file)
@@ -662,7 +662,8 @@ int get_share_modes(connection_struct *conn,
 
        data = (struct locking_data *)dbuf.dptr;
        ret = data->num_share_mode_entries;
-       *shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), ret * sizeof(**shares));
+       if(ret)
+               *shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), ret * sizeof(**shares));
        free(dbuf.dptr);
 
        if (! *shares) return 0;
index 9784afe9e2ec600b216ac501916f196f66301159..bb4b7547a6e017d3900d08513ccb506905d4b082 100644 (file)
@@ -67,7 +67,7 @@ logons are not enabled.\n", inet_ntoa(p->ip) ));
   strupper(my_name);
 
   code = SVAL(buf,0);
-  DEBUG(1,("process_logon_packet: Logon from %s: code = %x\n", inet_ntoa(p->ip), code));
+  DEBUG(1,("process_logon_packet: Logon from %s: code = 0x%x\n", inet_ntoa(p->ip), code));
 
   switch (code)
   {
@@ -202,10 +202,15 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
       domainsidsize = IVAL(q, 0);
       q += 4;
 
-      if (domainsidsize != 0) {
+      DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d, len = %d\n", domainsidsize, len));
+
+      if (domainsidsize < (len - PTR_DIFF(q, buf)) && (domainsidsize != 0)) {
              q += domainsidsize;
              q = ALIGN4(q, buf);
       }
+
+      DEBUG(3,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %d\n", len, PTR_DIFF(q, buf) ));
+
       if (len - PTR_DIFF(q, buf) > 8) {
              /* with NT5 clients we can sometimes
                 get additional data - a length specificed string
@@ -213,7 +218,7 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
                 data (no idea what it is) */
              int dom_len = CVAL(q, 0);
              q++;
-             if (dom_len != 0) {
+             if (dom_len < (len - PTR_DIFF(q, buf)) && (dom_len != 0)) {
                      q += dom_len + 1;
              }
              q += 16;
index 3202c6937de20b918cdbba95b5a26bddd1f1aa03..58f284b4fc704d4604e6a904f0dd9e815ea0299d 100644 (file)
@@ -856,20 +856,27 @@ BOOL print_queue_purge(int snum)
 open a print file and setup a fsp for it. This is a wrapper around
 print_job_start().
 ***************************************************************************/
-void print_fsp_open(files_struct *fsp,connection_struct *conn,char *jobname)
+
+files_struct *print_fsp_open(connection_struct *conn,char *jobname)
 {
        int jobid;
        SMB_STRUCT_STAT sbuf;
        extern struct current_user current_user;
+       files_struct *fsp = file_new();
+
+       if(!fsp)
+               return NULL;
 
        jobid = print_job_start(SNUM(conn), jobname);
-       if (jobid == -1) return;
+       if (jobid == -1) {
+               file_free(fsp);
+               return NULL;
+       }
 
        /* setup a full fsp */
        fsp->print_jobid = jobid;
        fsp->fd = print_job_fd(jobid);
        conn->vfs_ops.fstat(fsp->fd, &sbuf);
-       conn->num_files_open++;
        fsp->mode = sbuf.st_mode;
        fsp->inode = sbuf.st_ino;
        fsp->dev = sbuf.st_dev;
@@ -893,6 +900,10 @@ void print_fsp_open(files_struct *fsp,connection_struct *conn,char *jobname)
        string_set(&fsp->fsp_name,print_job_fname(jobid));
        fsp->wbmpx_ptr = NULL;      
        fsp->wcp = NULL; 
+
+       conn->num_files_open++;
+
+       return fsp;
 }
 
 /****************************************************************************
index 81e9b737eeeca30c32b77f2e92374efc347423a9..f5dd09d05e108c5662391f5f71c80f6f4c026118 100644 (file)
@@ -512,8 +512,12 @@ static BOOL api_lsa_query_info(prs_struct *data, prs_struct *rdata)
 
        switch (q_i.info_class) {
        case 0x03:
-               fstrcpy(name, global_myworkgroup);
-               sid = &global_sam_sid;
+               if(lp_domain_logons()) {
+                       fstrcpy(name, global_myworkgroup);
+                       sid = &global_sam_sid;
+               } else {
+                       *name = '\0';
+               }
                break;
        case 0x05:
                fstrcpy(name, global_myname);
index c4d323b1ba6150b6845d6f880290919b246b3b62..ec28ff354038f3019be93e4a7fc20b5c2ec97f2f 100644 (file)
@@ -65,7 +65,8 @@ static void check_magic(files_struct *fsp,connection_struct *conn)
 /****************************************************************************
   Common code to close a file or a directory.
 ****************************************************************************/
-static void close_filestruct(files_struct *fsp)
+
+void close_filestruct(files_struct *fsp)
 {   
        connection_struct *conn = fsp->conn;
     
@@ -106,19 +107,15 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
                return 0;
        }
 
-       if (lp_share_modes(SNUM(conn))) {
-               lock_share_entry_fsp(fsp);
-               del_share_mode(fsp);
-       }
+       lock_share_entry_fsp(fsp);
+       del_share_mode(fsp);
+       unlock_share_entry_fsp(fsp);
 
        if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
                release_file_oplock(fsp);
 
        locking_close_file(fsp);
 
-       if (lp_share_modes(SNUM(conn)))
-               unlock_share_entry_fsp(fsp);
-
        err = fd_close(conn, fsp);
 
        /* check for magic scripts */
index 5d8c3a9710f5a503025c7bf1eabc739dcde4e0da..8f8f17563e448d36a1466e82bf5f6e849e44ace2 100644 (file)
@@ -234,6 +234,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n)
       /* Paranoia .... */
       if (EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) {
         DEBUG(0,("write_file: PANIC. share mode entry %d is an exlusive oplock !\n", i ));
+        unlock_share_entry(fsp->conn, fsp->dev, fsp->inode);
         abort();
       }
 
@@ -249,6 +250,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n)
         /* Paranoia check... */
         if(new_fsp == NULL) {
           DEBUG(0,("write_file: PANIC. share mode entry %d is not a local file !\n", i ));
+          unlock_share_entry(fsp->conn, fsp->dev, fsp->inode);
           abort();
         }
         oplock_break_level2(new_fsp, True, token);
index e971de095b7237ee5891b14901c7f98788a93b20..6c0465097b9ca1999a3314ae3d8cdb6caff31e79 100644 (file)
@@ -77,11 +77,17 @@ files_struct *file_new(void )
                }
 
                DEBUG(0,("ERROR! Out of file structures\n"));
+               unix_ERR_class = ERRSRV;
+               unix_ERR_code = ERRnofids;
                return NULL;
        }
 
        fsp = (files_struct *)malloc(sizeof(*fsp));
-       if (!fsp) return NULL;
+       if (!fsp) {
+               unix_ERR_class = ERRSRV;
+               unix_ERR_code = ERRnofids;
+               return NULL;
+       }
 
        ZERO_STRUCTP(fsp);
        fsp->fd = -1;
index bd77f17802d419e94fb58493c83d83dfae935a58..c82a8074d9d2c24d9a20d898e514c986fa69813b 100644 (file)
@@ -747,12 +747,6 @@ int reply_ntcreate_and_X(connection_struct *conn,
                
        unix_convert(fname,conn,0,&bad_path,NULL);
                
-       fsp = file_new();
-       if (!fsp) {
-               restore_case_semantics(file_attributes);
-               return(ERROR(ERRSRV,ERRnofids));
-       }
-               
        unixmode = unix_mode(conn,smb_attr | aARCH, fname);
     
        /* 
@@ -762,13 +756,11 @@ int reply_ntcreate_and_X(connection_struct *conn,
        if(create_options & FILE_DIRECTORY_FILE) {
                oplock_request = 0;
                
-               open_directory(fsp, conn, fname, smb_ofun, 
-                              unixmode, &smb_action);
+               fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action);
                        
                restore_case_semantics(file_attributes);
 
-               if(!fsp->open) {
-                       file_free(fsp);
+               if(!fsp) {
                        return(UNIXERROR(ERRDOS,ERRnoaccess));
                }
        } else {
@@ -789,10 +781,10 @@ int reply_ntcreate_and_X(connection_struct *conn,
                 * before issuing an oplock break request to
                 * our client. JRA.  */
 
-               open_file_shared(fsp,conn,fname,smb_open_mode,
+               fsp = open_file_shared(conn,fname,smb_open_mode,
                                 smb_ofun,unixmode, oplock_request,&rmode,&smb_action);
 
-               if (!fsp->open) { 
+               if (!fsp) { 
                        /* We cheat here. There are two cases we
                         * care about. One is a directory rename,
                         * where the NT client will attempt to
@@ -819,17 +811,15 @@ int reply_ntcreate_and_X(connection_struct *conn,
                                 */
 
                                if (create_options & FILE_NON_DIRECTORY_FILE) {
-                                       file_free(fsp);
                                        restore_case_semantics(file_attributes);
                                        SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
                                        return(ERROR(0, 0xc0000000|NT_STATUS_FILE_IS_A_DIRECTORY));
                                }
        
                                oplock_request = 0;
-                               open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action);
+                               fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action);
                                
-                               if(!fsp->open) {
-                                       file_free(fsp);
+                               if(!fsp) {
                                        restore_case_semantics(file_attributes);
                                        return(UNIXERROR(ERRDOS,ERRnoaccess));
                                }
@@ -845,10 +835,9 @@ int reply_ntcreate_and_X(connection_struct *conn,
 
                                oplock_request = 0;
 
-                               open_file_stat(fsp,conn,fname,smb_open_mode,&sbuf,&smb_action);
+                               fsp = open_file_stat(conn,fname,smb_open_mode,&sbuf,&smb_action);
 
-                               if(!fsp->open) {
-                                       file_free(fsp);
+                               if(!fsp) {
                                        restore_case_semantics(file_attributes);
                                        return(UNIXERROR(ERRDOS,ERRnoaccess));
                                }
@@ -860,8 +849,6 @@ int reply_ntcreate_and_X(connection_struct *conn,
                                        unix_ERR_code = ERRbadpath;
                                }
                                
-                               file_free(fsp);
-                               
                                restore_case_semantics(file_attributes);
                                
                                return(UNIXERROR(ERRDOS,ERRnoaccess));
@@ -1109,12 +1096,6 @@ static int call_nt_transact_create(connection_struct *conn,
 
     unix_convert(fname,conn,0,&bad_path,NULL);
     
-    fsp = file_new();
-    if (!fsp) {
-           restore_case_semantics(file_attributes);
-           return(ERROR(ERRSRV,ERRnofids));
-    }
-
     unixmode = unix_mode(conn,smb_attr | aARCH, fname);
     
     /*
@@ -1131,10 +1112,9 @@ static int call_nt_transact_create(connection_struct *conn,
        * CreateDirectory() call.
        */
 
-      open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action);
+      fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action);
 
-      if(!fsp->open) {
-        file_free(fsp);
+      if(!fsp) {
         restore_case_semantics(file_attributes);
         return(UNIXERROR(ERRDOS,ERRnoaccess));
       }
@@ -1152,10 +1132,10 @@ static int call_nt_transact_create(connection_struct *conn,
        * Ordinary file case.
        */
 
-      open_file_shared(fsp,conn,fname,smb_open_mode,smb_ofun,unixmode,
+      fsp = open_file_shared(conn,fname,smb_open_mode,smb_ofun,unixmode,
                        oplock_request,&rmode,&smb_action);
 
-      if (!fsp->open) { 
+      if (!fsp) { 
 
                if(errno == EISDIR) {
 
@@ -1164,17 +1144,15 @@ static int call_nt_transact_create(connection_struct *conn,
                         */
 
                        if (create_options & FILE_NON_DIRECTORY_FILE) {
-                               file_free(fsp);
                                restore_case_semantics(file_attributes);
                                SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
                                return(ERROR(0, 0xc0000000|NT_STATUS_FILE_IS_A_DIRECTORY));
                        }
        
                        oplock_request = 0;
-                       open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action);
+                       fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action);
                                
-                       if(!fsp->open) {
-                               file_free(fsp);
+                       if(!fsp) {
                                restore_case_semantics(file_attributes);
                                return(UNIXERROR(ERRDOS,ERRnoaccess));
                        }
@@ -1191,10 +1169,9 @@ static int call_nt_transact_create(connection_struct *conn,
 
                        oplock_request = 0;
 
-                       open_file_stat(fsp,conn,fname,smb_open_mode,&sbuf,&smb_action);
+                       fsp = open_file_stat(conn,fname,smb_open_mode,&sbuf,&smb_action);
 
-                       if(!fsp->open) {
-                               file_free(fsp);
+                       if(!fsp) {
                                restore_case_semantics(file_attributes);
                                return(UNIXERROR(ERRDOS,ERRnoaccess));
                        }
@@ -1204,7 +1181,6 @@ static int call_nt_transact_create(connection_struct *conn,
                                unix_ERR_class = ERRDOS;
                                unix_ERR_code = ERRbadpath;
                        }
-                       file_free(fsp);
 
                        restore_case_semantics(file_attributes);
 
index bd8e860a17e5e6a141d1935c1e95e360c2f0c565..d2368aa44d3be5153307ec8265814b898319eee0 100644 (file)
@@ -82,7 +82,7 @@ static void check_for_pipe(char *fname)
  Open a file.
 ****************************************************************************/
 
-static void open_file(files_struct *fsp,connection_struct *conn,
+static BOOL open_file(files_struct *fsp,connection_struct *conn,
                      char *fname1,int flags,mode_t mode)
 {
        extern struct current_user current_user;
@@ -114,7 +114,7 @@ static void open_file(files_struct *fsp,connection_struct *conn,
                if(accmode != O_RDONLY) {
                        DEBUG(3,("Permission denied opening %s\n",fname));
                        check_for_pipe(fname);
-                       return;
+                       return False;
                } else if(flags & O_CREAT) {
                        /* We don't want to write - but we must make sure that O_CREAT
                           doesn't create the file if we have write access into the
@@ -131,7 +131,7 @@ static void open_file(files_struct *fsp,connection_struct *conn,
                DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
                         fname,strerror(errno),flags));
                check_for_pipe(fname);
-               return;
+               return False;
        }
 
        conn->vfs_ops.fstat(fsp->fd, &sbuf);
@@ -145,10 +145,9 @@ static void open_file(files_struct *fsp,connection_struct *conn,
        if(S_ISDIR(sbuf.st_mode)) {
                fd_close(conn, fsp);
                errno = EISDIR;
-               return;
+               return False;
        }
 
-       conn->num_files_open++;
        fsp->mode = sbuf.st_mode;
        fsp->inode = sbuf.st_ino;
        fsp->dev = sbuf.st_dev;
@@ -184,7 +183,9 @@ static void open_file(files_struct *fsp,connection_struct *conn,
        DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
                 *sesssetup_user ? sesssetup_user : conn->user,fsp->fsp_name,
                 BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
-                conn->num_files_open));
+                conn->num_files_open + 1));
+
+       return True;
 }
 
 /****************************************************************************
@@ -193,35 +194,27 @@ static void open_file(files_struct *fsp,connection_struct *conn,
   Truncate a file after checking locking; close file if locked.
   **************************************************************************/
 
-static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, int token, 
-                                  BOOL *share_locked)
+static int truncate_unless_locked(struct connection_struct *conn, files_struct *fsp)
 {
-       if (fsp->can_write){
-               SMB_OFF_T mask2 = ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
-               SMB_OFF_T mask = (mask2<<2);
-               
-               if (is_locked(fsp,conn,~mask,0,WRITE_LOCK)){
-                       /* If share modes are in force for this connection we
-                          have the share entry locked. Unlock it before closing. */
-                       if (*share_locked && lp_share_modes(SNUM(conn)))
-                               unlock_share_entry_fsp(fsp);
-                       close_file(fsp,False);   
-                       /* Share mode no longer locked. */
-                       *share_locked = False;
-                       errno = EACCES;
-                       unix_ERR_class = ERRDOS;
-                 unix_ERR_code = ERRlock;
-               } else {
-                       sys_ftruncate(fsp->fd,0); 
-               }
+       SMB_BIG_UINT mask = (SMB_BIG_UINT)-1;
+
+       if (!fsp->can_write)
+               return -1;
+
+       if (is_locked(fsp,fsp->conn,mask,0,WRITE_LOCK)){
+               errno = EACCES;
+               unix_ERR_class = ERRDOS;
+               unix_ERR_code = ERRlock;
+               return -1;
+       } else {
+               return conn->vfs_ops.ftruncate(fsp->fd,0); 
        }
 }
 
-
 /*******************************************************************
 return True if the filename is one of the special executable types
 ********************************************************************/
-static BOOL is_executable(char *fname)
+static BOOL is_executable(const char *fname)
 {
        if ((fname = strrchr(fname,'.'))) {
                if (strequal(fname,".com") ||
@@ -334,364 +327,426 @@ check if we can open a file with a share mode
 ****************************************************************************/
 
 static int check_share_mode( share_mode_entry *share, int deny_mode, 
-                            char *fname,
-                            BOOL fcbopen, int *flags)
+                            const char *fname, BOOL fcbopen, int *flags)
 {
-  int old_open_mode = GET_OPEN_MODE(share->share_mode);
-  int old_deny_mode = GET_DENY_MODE(share->share_mode);
+       int old_open_mode = GET_OPEN_MODE(share->share_mode);
+       int old_deny_mode = GET_DENY_MODE(share->share_mode);
+
+       /*
+        * Don't allow any open once the delete on close flag has been
+        * set.
+        */
+
+       if(GET_DELETE_ON_CLOSE_FLAG(share->share_mode)) {
+               DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n",
+                       fname ));
+               unix_ERR_class = ERRDOS;
+               unix_ERR_code = ERRnoaccess;
+               return False;
+       }
+
+       {
+               int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
+                                                                               (share->pid == getpid()),is_executable(fname));
+
+               if ((access_allowed == AFAIL) ||
+                       (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) ||
+                       (access_allowed == AREAD && *flags != O_RDONLY) ||
+                       (access_allowed == AWRITE && *flags != O_WRONLY)) {
+
+                       DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n",
+                               deny_mode,old_deny_mode,old_open_mode,
+                               (int)share->pid,fname, fcbopen, *flags, access_allowed));
+
+                       unix_ERR_class = ERRDOS;
+                       unix_ERR_code = ERRbadshare;
+
+                       return False;
+               }
+
+               if (access_allowed == AREAD)
+                       *flags = O_RDONLY;
+
+               if (access_allowed == AWRITE)
+                       *flags = O_WRONLY;
+
+       }
+
+       return True;
+}
+
+/****************************************************************************
+ Deal with open deny mode and oplock break processing.
+ Invarient: Share mode must be locked on entry and exit.
+ Returns -1 on error, or number of share modes on success (may be zero).
+****************************************************************************/
+
+static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T dev,
+                                                       SMB_INO_T inode, int share_mode, int *p_flags, int *p_oplock_request,
+                                                       BOOL *p_all_current_opens_are_level_II)
+{
+  int i;
+  int num_share_modes;
+  int oplock_contention_count = 0;
+  share_mode_entry *old_shares = 0;
+  BOOL fcbopen = False;
+  int deny_mode = GET_DENY_MODE(share_mode);
+  BOOL broke_oplock;   
+
+  if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB)
+    fcbopen = True;
+
+  num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
+
+  if(num_share_modes == 0)
+    return 0;
 
   /*
-   * Don't allow any open once the delete on close flag has been
-   * set.
+   * Check if the share modes will give us access.
    */
 
-  if(GET_DELETE_ON_CLOSE_FLAG(share->share_mode))
-  {
-    DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n",
-          fname ));
-    unix_ERR_class = ERRDOS;
-    unix_ERR_code = ERRnoaccess;
-    return False;
-  }
+  do {
 
-  {
-    int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
-                                     (share->pid == getpid()),is_executable(fname));
+    broke_oplock = False;
+    *p_all_current_opens_are_level_II = True;
 
-    if ((access_allowed == AFAIL) ||
-        (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) ||
-        (access_allowed == AREAD && *flags != O_RDONLY) ||
-        (access_allowed == AWRITE && *flags != O_WRONLY))
-    {
-      DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n",
-                deny_mode,old_deny_mode,old_open_mode,
-                (int)share->pid,fname, fcbopen, *flags, access_allowed));
+    for(i = 0; i < num_share_modes; i++) {
+      share_mode_entry *share_entry = &old_shares[i];
+
+      /* 
+       * By observation of NetBench, oplocks are broken *before* share
+       * modes are checked. This allows a file to be closed by the client
+       * if the share mode would deny access and the client has an oplock. 
+       * Check if someone has an oplock on this file. If so we must break 
+       * it before continuing. 
+       */
 
-      unix_ERR_class = ERRDOS;
-      unix_ERR_code = ERRbadshare;
+      if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) ||
+         (!*p_oplock_request && (share_entry->op_type != NO_OPLOCK))) {
 
-      return False;
+        BOOL opb_ret;
+
+        DEBUG(5,("open_mode_check: breaking oplock (%x) on file %s, \
+dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode));
+
+        /* Oplock break - unlock to request it. */
+        unlock_share_entry(conn, dev, inode);
+
+        opb_ret = request_oplock_break(share_entry, dev, inode);
+
+        /* Now relock. */
+        lock_share_entry(conn, dev, inode);
+
+        if(opb_ret == False) {
+          free((char *)old_shares);
+          DEBUG(0,("open_mode_check: FAILED when breaking oplock (%x) on file %s, \
+dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode));
+          errno = EACCES;
+          unix_ERR_class = ERRDOS;
+          unix_ERR_code = ERRbadshare;
+          return -1;
+        }
+
+        broke_oplock = True;
+        *p_all_current_opens_are_level_II = False;
+        break;
+
+      } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) {
+        *p_all_current_opens_are_level_II = False;
+      }
+
+      /* someone else has a share lock on it, check to see 
+         if we can too */
+
+      if(check_share_mode(share_entry, deny_mode, fname, fcbopen, p_flags) == False) {
+        free((char *)old_shares);
+        errno = EACCES;
+        return -1;
+      }
+
+    } /* end for */
+
+    if(broke_oplock) {
+      free((char *)old_shares);
+      num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
+      oplock_contention_count++;
     }
+  } while(broke_oplock);
 
-    if (access_allowed == AREAD)
-      *flags = O_RDONLY;
+  if(old_shares != 0)
+    free((char *)old_shares);
 
-    if (access_allowed == AWRITE)
-      *flags = O_WRONLY;
+  /*
+   * Refuse to grant an oplock in case the contention limit is
+   * reached when going through the lock list multiple times.
+   */
 
+  if(oplock_contention_count >= lp_oplock_contention_limit(SNUM(conn))) {
+    *p_oplock_request = 0;
+    DEBUG(4,("open_mode_check: oplock contention = %d. Not granting oplock.\n",
+          oplock_contention_count ));
   }
 
-  return True;
+  return num_share_modes;
 }
 
 /****************************************************************************
-open a file with a share mode
+ Open a file with a share mode.
 ****************************************************************************/
 
-void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun,
+files_struct *open_file_shared(connection_struct *conn,char *fname,int share_mode,int ofun,
                      mode_t mode,int oplock_request, int *Access,int *action)
 {
-  int flags=0;
-  int flags2=0;
-  int deny_mode = GET_DENY_MODE(share_mode);
-  BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode);
-  SMB_STRUCT_STAT sbuf;
-  BOOL file_existed = vfs_file_exist(conn, fname, &sbuf);
-  BOOL share_locked = False;
-  BOOL fcbopen = False;
-  int token = 0;
-  SMB_DEV_T dev = 0;
-  SMB_INO_T inode = 0;
-  int num_share_modes = 0;
-  int oplock_contention_count = 0;
-  BOOL all_current_opens_are_level_II = False;
-  fsp->open = False;
-  fsp->fd = -1;
-
-  if (conn->printer) {
-         /* printers are handled completely differently. Most of the passed parameters are
-            ignored */
-         *Access = DOS_OPEN_WRONLY;
-         *action = FILE_WAS_CREATED;
-         print_fsp_open(fsp, conn, fname);
-         return;
-  }
+       int flags=0;
+       int flags2=0;
+       int deny_mode = GET_DENY_MODE(share_mode);
+       BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode);
+       SMB_STRUCT_STAT sbuf;
+       BOOL file_existed = vfs_file_exist(conn, fname, &sbuf);
+       BOOL fcbopen = False;
+       SMB_DEV_T dev = 0;
+       SMB_INO_T inode = 0;
+       int num_share_modes = 0;
+       BOOL all_current_opens_are_level_II = False;
+       files_struct *fsp = NULL;
+       int open_mode=0;
+       uint16 port = 0;
+
+       if (conn->printer) {
+               /* printers are handled completely differently. Most of the passed parameters are
+                       ignored */
+               *Access = DOS_OPEN_WRONLY;
+               *action = FILE_WAS_CREATED;
+               return print_fsp_open(conn, fname);
+       }
 
-  DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n",
-        fname, share_mode, ofun, (int)mode,  oplock_request ));
+       fsp = file_new();
+       if(!fsp)
+               return NULL;
 
-  if (!check_name(fname,conn)) {
-         return;
-  } 
+       fsp->open = False;
+       fsp->fd = -1;
 
-  /* ignore any oplock requests if oplocks are disabled */
-  if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) {
-         oplock_request = 0;
-  }
+       DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n",
+               fname, share_mode, ofun, (int)mode,  oplock_request ));
 
-  /* this is for OS/2 EAs - try and say we don't support them */
-  if (strstr(fname,".+,;=[].")) 
-  {
-    unix_ERR_class = ERRDOS;
-    /* OS/2 Workplace shell fix may be main code stream in a later release. */ 
+       if (!check_name(fname,conn)) {
+               file_free(fsp);
+               return NULL;
+       } 
+
+       /* ignore any oplock requests if oplocks are disabled */
+       if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) {
+               oplock_request = 0;
+       }
+
+       /* this is for OS/2 EAs - try and say we don't support them */
+       if (strstr(fname,".+,;=[].")) {
+               unix_ERR_class = ERRDOS;
+               /* OS/2 Workplace shell fix may be main code stream in a later release. */ 
 #if 1 /* OS2_WPS_FIX - Recent versions of OS/2 need this. */
-    unix_ERR_code = ERRcannotopen;
+               unix_ERR_code = ERRcannotopen;
 #else /* OS2_WPS_FIX */
-    unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
+               unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
 #endif /* OS2_WPS_FIX */
 
-    DEBUG(5,("open_file_shared: OS/2 EA's are not supported.\n"));
-    return;
-  }
+               DEBUG(5,("open_file_shared: OS/2 EA's are not supported.\n"));
+               file_free(fsp);
+               return NULL;
+       }
 
-  if ((GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) && file_existed)  
-  {
-    DEBUG(5,("open_file_shared: create new requested for file %s and file already exists.\n",
-          fname ));
-    errno = EEXIST;
-    return;
-  }
+       if ((GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) && file_existed)  {
+               DEBUG(5,("open_file_shared: create new requested for file %s and file already exists.\n",
+                       fname ));
+               file_free(fsp);
+               errno = EEXIST;
+               return NULL;
+       }
       
-  if (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST)
-    flags2 |= O_CREAT;
-
-  if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)
-    flags2 |= O_TRUNC;
-
-  if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL)
-    flags2 |= O_EXCL;
-
-  /* note that we ignore the append flag as 
-     append does not mean the same thing under dos and unix */
-
-  switch (GET_OPEN_MODE(share_mode))
-  {
-    case DOS_OPEN_WRONLY: 
-      flags = O_WRONLY; 
-      break;
-    case DOS_OPEN_FCB: 
-      fcbopen = True;
-      flags = O_RDWR; 
-      break;
-    case DOS_OPEN_RDWR: 
-      flags = O_RDWR; 
-      break;
-    default:
-      flags = O_RDONLY;
-      break;
-  }
+       if (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST)
+               flags2 |= O_CREAT;
+
+       if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)
+               flags2 |= O_TRUNC;
+
+       if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL)
+               flags2 |= O_EXCL;
+
+       /* note that we ignore the append flag as 
+               append does not mean the same thing under dos and unix */
+
+       switch (GET_OPEN_MODE(share_mode)) {
+               case DOS_OPEN_WRONLY: 
+                       flags = O_WRONLY; 
+                       break;
+               case DOS_OPEN_FCB: 
+                       fcbopen = True;
+                       flags = O_RDWR; 
+                       break;
+               case DOS_OPEN_RDWR: 
+                       flags = O_RDWR; 
+                       break;
+               default:
+                       flags = O_RDONLY;
+                       break;
+       }
 
 #if defined(O_SYNC)
-  if (GET_FILE_SYNC_OPENMODE(share_mode)) {
-         flags2 |= O_SYNC;
-  }
+       if (GET_FILE_SYNC_OPENMODE(share_mode)) {
+               flags2 |= O_SYNC;
+       }
 #endif /* O_SYNC */
   
-  if (flags != O_RDONLY && file_existed && 
-      (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf)))) 
-  {
-    if (!fcbopen) 
-    {
-      DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n",
-            fname, !CAN_WRITE(conn) ? "share" : "file" ));
-      errno = EACCES;
-      return;
-    }
-    flags = O_RDONLY;
-  }
-
-  if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) 
-  {
-    DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
-    errno = EINVAL;
-    return;
-  }
-
-  if (lp_share_modes(SNUM(conn))) 
-  {
-    int i;
-    share_mode_entry *old_shares = 0;
-
-    if (file_existed)
-    {
-      dev = sbuf.st_dev;
-      inode = sbuf.st_ino;
-      lock_share_entry(conn, dev, inode);
-      share_locked = True;
-      num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
-    }
+       if (flags != O_RDONLY && file_existed && 
+                       (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf)))) {
+               if (!fcbopen) {
+                       DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n",
+                               fname, !CAN_WRITE(conn) ? "share" : "file" ));
+                       file_free(fsp);
+                       errno = EACCES;
+                       return NULL;
+               }
+               flags = O_RDONLY;
+       }
 
-    /*
-     * Check if the share modes will give us access.
-     */
+       if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
+               DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
+               file_free(fsp);
+               errno = EINVAL;
+               return NULL;
+       }
 
-    if(share_locked && (num_share_modes != 0))
-    {
-      BOOL broke_oplock;
+       if (file_existed) {
+               dev = sbuf.st_dev;
+               inode = sbuf.st_ino;
 
-      do
-      {
+               lock_share_entry(conn, dev, inode);
 
-        broke_oplock = False;
-        all_current_opens_are_level_II = True;
+               num_share_modes = open_mode_check(conn, fname, dev, inode, share_mode,
+                                                               &flags, &oplock_request, &all_current_opens_are_level_II);
+               if(num_share_modes == -1) {
+                       unlock_share_entry(conn, dev, inode);
+                       file_free(fsp);
+                       return NULL;
+               }
 
-        for(i = 0; i < num_share_modes; i++)
-        {
-          share_mode_entry *share_entry = &old_shares[i];
-
-          /* 
-           * By observation of NetBench, oplocks are broken *before* share
-           * modes are checked. This allows a file to be closed by the client
-           * if the share mode would deny access and the client has an oplock. 
-           * Check if someone has an oplock on this file. If so we must break 
-           * it before continuing. 
-           */
-          if((oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) ||
-             (!oplock_request && (share_entry->op_type != NO_OPLOCK)))
-          {
+               /*
+                * We exit this block with the share entry *locked*.....
+                */
+       }
 
-            DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \
-dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode));
+       DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
+                       flags,flags2,(int)mode));
 
-            /* Oplock break.... */
-            unlock_share_entry(conn, dev, inode);
-            if(request_oplock_break(share_entry, dev, inode) == False)
-            {
-              free((char *)old_shares);
+       fsp->open = open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode);
 
-              DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \
-dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode));
+       if (!fsp->open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) {
+               if((fsp->open = open_file(fsp,conn,fname,O_RDONLY,mode)) == True)
+                       flags = O_RDONLY;
+       }
 
-              errno = EACCES;
-              unix_ERR_class = ERRDOS;
-              unix_ERR_code = ERRbadshare;
-              return;
-            }
-            lock_share_entry(conn, dev, inode);
-            broke_oplock = True;
-            all_current_opens_are_level_II = False;
-            break;
-          } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) {
-            all_current_opens_are_level_II = False;
-          }
+       if (!fsp->open) {
+               if(file_existed)
+                       unlock_share_entry(conn, dev, inode);
+               file_free(fsp);
+               return NULL;
+       }
 
-          /* someone else has a share lock on it, check to see 
-             if we can too */
-          if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False)
-          {
-            free((char *)old_shares);
-            unlock_share_entry(conn, dev, inode);
-            errno = EACCES;
-            return;
-          }
+       /*
+        * Deal with the race condition where two smbd's detect the file doesn't
+        * exist and do the create at the same time. One of them will win and
+        * set a share mode, the other (ie. this one) should check if the
+        * requested share mode for this create is allowed.
+        */
 
-        } /* end for */
+       if (!file_existed) { 
 
-        if(broke_oplock)
-        {
-          free((char *)old_shares);
-          num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
-          oplock_contention_count++;
-        }
-      } while(broke_oplock);
-    }
+               lock_share_entry_fsp(fsp);
 
-    if(old_shares != 0)
-      free((char *)old_shares);
-  }
+               num_share_modes = open_mode_check(conn, fname, dev, inode, share_mode,
+                                                               &flags, &oplock_request, &all_current_opens_are_level_II);
 
-  /*
-   * Refuse to grant an oplock in case the contention limit is
-   * reached when going through the lock list multiple times.
-   */
+               if(num_share_modes == -1) {
+                       unlock_share_entry_fsp(fsp);
+                       fd_close(conn,fsp);
+                       file_free(fsp);
+                       return NULL;
+               }
 
-  if(oplock_contention_count >= lp_oplock_contention_limit(SNUM(conn)))
-  {
-    oplock_request = 0;
-    DEBUG(4,("open_file_shared: oplock contention = %d. Not granting oplock.\n",
-          oplock_contention_count ));
-  }
+               /*
+                * We exit this block with the share entry *locked*.....
+                */
+       }
 
-  DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
-          flags,flags2,(int)mode));
+       /*
+        * At this point onwards, we can guarentee that the share entry
+        * is locked, whether we created the file or not, and that the
+        * deny mode is compatible with all current opens.
+        */
 
-  open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode);
-  if (!fsp->open && flags==O_RDWR && errno != ENOENT && fcbopen) {
-         flags = O_RDONLY;
-         open_file(fsp,conn,fname,flags,mode);
-  }
+       /*
+        * If requested, truncate the file.
+        */
 
-  if (fsp->open) 
-  {
-    int open_mode=0;
+       if ((flags2&O_TRUNC) && (truncate_unless_locked(conn,fsp) == -1)) {
+               unlock_share_entry_fsp(fsp);
+               fd_close(conn,fsp);
+               file_free(fsp);
+               return NULL;
+       }
 
-    if((share_locked == False) && lp_share_modes(SNUM(conn)))
-    {
-      /* We created the file - thus we must now lock the share entry before creating it. */
-      lock_share_entry_fsp(fsp);
-      share_locked = True;
-    }
+       switch (flags) {
+               case O_RDONLY:
+                       open_mode = DOS_OPEN_RDONLY;
+                       break;
+               case O_RDWR:
+                       open_mode = DOS_OPEN_RDWR;
+                       break;
+               case O_WRONLY:
+                       open_mode = DOS_OPEN_WRONLY;
+                       break;
+       }
 
-    switch (flags) 
-    {
-      case O_RDONLY:
-        open_mode = DOS_OPEN_RDONLY;
-        break;
-      case O_RDWR:
-        open_mode = DOS_OPEN_RDWR;
-        break;
-      case O_WRONLY:
-        open_mode = DOS_OPEN_WRONLY;
-        break;
-    }
+       fsp->share_mode = SET_DENY_MODE(deny_mode) | 
+                                               SET_OPEN_MODE(open_mode) | 
+                                               SET_ALLOW_SHARE_DELETE(allow_share_delete);
 
-    fsp->share_mode = SET_DENY_MODE(deny_mode) | 
-                      SET_OPEN_MODE(open_mode) | 
-                      SET_ALLOW_SHARE_DELETE(allow_share_delete);
+       if (Access)
+               (*Access) = open_mode;
 
-    if (Access)
-      (*Access) = open_mode;
+       if (action) {
+               if (file_existed && !(flags2 & O_TRUNC))
+                       *action = FILE_WAS_OPENED;
+               if (!file_existed)
+                       *action = FILE_WAS_CREATED;
+               if (file_existed && (flags2 & O_TRUNC))
+                       *action = FILE_WAS_OVERWRITTEN;
+       }
 
-    if (action) 
-    {
-      if (file_existed && !(flags2 & O_TRUNC)) *action = FILE_WAS_OPENED;
-      if (!file_existed) *action = FILE_WAS_CREATED;
-      if (file_existed && (flags2 & O_TRUNC)) *action = FILE_WAS_OVERWRITTEN;
-    }
-    /* We must create the share mode entry before truncate as
-       truncate can fail due to locking and have to close the
-       file (which expects the share_mode_entry to be there).
-     */
-    if (lp_share_modes(SNUM(conn)))
-    {
-      uint16 port = 0;
+       /* 
+        * Setup the oplock info in both the shared memory and
+        * file structs.
+        */
 
-      /* 
-       * Setup the oplock info in both the shared memory and
-       * file structs.
-       */
+       if(oplock_request && (num_share_modes == 0) && 
+                       !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp, oplock_request) ) {
+               port = global_oplock_port;
+       } else if (oplock_request && all_current_opens_are_level_II) {
+               port = global_oplock_port;
+               oplock_request = LEVEL_II_OPLOCK;
+               set_file_oplock(fsp, oplock_request);
+       } else {
+               port = 0;
+               oplock_request = 0;
+       }
 
-      if(oplock_request && (num_share_modes == 0) && 
-             !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp, oplock_request) ) {
-        port = global_oplock_port;
-      } else if (oplock_request && all_current_opens_are_level_II) {
-        port = global_oplock_port;
-        oplock_request = LEVEL_II_OPLOCK;
-        set_file_oplock(fsp, oplock_request);
-      } else {
-        port = 0;
-        oplock_request = 0;
-      }
+       set_share_mode(fsp, port, oplock_request);
 
-      set_share_mode(fsp, port, oplock_request);
-    }
+       unlock_share_entry_fsp(fsp);
 
-    if ((flags2&O_TRUNC) && file_existed)
-      truncate_unless_locked(fsp,conn,token,&share_locked);
-  }
+       conn->num_files_open++;
 
-  if (share_locked && lp_share_modes(SNUM(conn)))
-    unlock_share_entry_fsp(fsp);
+       return fsp;
 }
 
 /****************************************************************************
@@ -699,20 +754,26 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
  with the 'stat_open' flag set 
 ****************************************************************************/
 
-int open_file_stat(files_struct *fsp,connection_struct *conn,
+files_struct *open_file_stat(connection_struct *conn,
                   char *fname, int smb_ofun, SMB_STRUCT_STAT *pst, int *action)
 {
        extern struct current_user current_user;
+       files_struct *fsp = file_new();
+
+       if(!fsp)
+               return NULL;
 
        if(conn->vfs_ops.stat(dos_to_unix(fname, False), pst) < 0) {
                DEBUG(0,("open_file_stat: unable to stat name = %s. Error was %s\n",
                         fname, strerror(errno) ));
-               return -1;
+               file_free(fsp);
+               return NULL;
        }
 
        if(S_ISDIR(pst->st_mode)) {
                DEBUG(0,("open_file_stat: %s is a directory !\n", fname ));
-               return -1;
+               file_free(fsp);
+               return NULL;
        }
 
        *action = FILE_WAS_OPENED;
@@ -724,7 +785,6 @@ int open_file_stat(files_struct *fsp,connection_struct *conn,
         */
        
        fsp->fd = -1;
-       conn->num_files_open++;
        fsp->mode = 0;
        GetTimeOfDay(&fsp->open_time);
        fsp->vuid = current_user.vuid;
@@ -755,27 +815,34 @@ int open_file_stat(files_struct *fsp,connection_struct *conn,
        fsp->wbmpx_ptr = NULL;
     fsp->wcp = NULL; /* Write cache pointer. */
 
-       return 0;
+       conn->num_files_open++;
+
+       return fsp;
 }
 
 /****************************************************************************
  Open a directory from an NT SMB call.
 ****************************************************************************/
 
-int open_directory(files_struct *fsp,connection_struct *conn,
+files_struct *open_directory(connection_struct *conn,
                   char *fname, int smb_ofun, mode_t unixmode, int *action)
 {
        extern struct current_user current_user;
        SMB_STRUCT_STAT st;
        BOOL got_stat = False;
+       files_struct *fsp = file_new();
+
+       if(!fsp)
+               return NULL;
 
        if(conn->vfs_ops.stat(dos_to_unix(fname, False), &st) == 0) {
                got_stat = True;
        }
 
        if (got_stat && (GET_FILE_OPEN_DISPOSITION(smb_ofun) == FILE_EXISTS_FAIL)) {
+               file_free(fsp);
                errno = EEXIST; /* Setup so correct error is returned to client. */
-               return -1;
+               return NULL;
        }
 
        if (GET_FILE_CREATE_DISPOSITION(smb_ofun) == FILE_CREATE_IF_NOT_EXIST) {
@@ -784,8 +851,9 @@ int open_directory(files_struct *fsp,connection_struct *conn,
 
                        if(!S_ISDIR(st.st_mode)) {
                                DEBUG(0,("open_directory: %s is not a directory !\n", fname ));
+                               file_free(fsp);
                                errno = EACCES;
-                               return -1;
+                               return NULL;
                        }
                        *action = FILE_WAS_OPENED;
 
@@ -797,15 +865,17 @@ int open_directory(files_struct *fsp,connection_struct *conn,
 
                        if(!CAN_WRITE(conn)) {
                                DEBUG(2,("open_directory: failing create on read-only share\n"));
+                               file_free(fsp);
                                errno = EACCES;
-                               return -1;
+                               return NULL;
                        }
 
                        if(conn->vfs_ops.mkdir(dos_to_unix(fname, False), 
                                                unix_mode(conn,aDIR, fname)) < 0) {
                                DEBUG(0,("open_directory: unable to create %s. Error was %s\n",
                                         fname, strerror(errno) ));
-                               return -1;
+                               file_free(fsp);
+                               return NULL;
                        }
                        *action = FILE_WAS_CREATED;
 
@@ -819,12 +889,14 @@ int open_directory(files_struct *fsp,connection_struct *conn,
                if(!got_stat) {
                        DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n",
                                 fname, strerror(errno) ));
-                       return -1;
+                       file_free(fsp);
+                       return NULL;
                }
 
                if(!S_ISDIR(st.st_mode)) {
                        DEBUG(0,("open_directory: %s is not a directory !\n", fname ));
-                       return -1;
+                       file_free(fsp);
+                       return NULL;
                }
 
                *action = FILE_WAS_OPENED;
@@ -838,7 +910,6 @@ int open_directory(files_struct *fsp,connection_struct *conn,
         */
        
        fsp->fd = -1;
-       conn->num_files_open++;
        fsp->mode = 0;
        GetTimeOfDay(&fsp->open_time);
        fsp->vuid = current_user.vuid;
@@ -867,7 +938,9 @@ int open_directory(files_struct *fsp,connection_struct *conn,
        string_set(&fsp->fsp_name,fname);
        fsp->wbmpx_ptr = NULL;
 
-       return 0;
+       conn->num_files_open++;
+
+       return fsp;
 }
 
 /*******************************************************************
@@ -886,10 +959,8 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op)
   SMB_DEV_T dev;
   SMB_INO_T inode;
 
-  if(!lp_share_modes(SNUM(conn)))
-    return True;
-
-  if (conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == -1) return(True);
+  if (conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf) == -1)
+    return(True);
 
   dev = sbuf.st_dev;
   inode = sbuf.st_ino;
index e998e1741c043ce6a836453dac3a0d6938a13c3b..3acfd988d63ded1b6875908f2768b2d0e3491e36 100644 (file)
@@ -1545,23 +1545,18 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
 
   unix_convert(fname,conn,0,&bad_path,NULL);
     
-  fsp = file_new();
-  if (!fsp)
-    return(ERROR(ERRSRV,ERRnofids));
-
   unixmode = unix_mode(conn,aARCH,fname);
       
-  open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
+  fsp = open_file_shared(conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
                    unixmode, oplock_request,&rmode,NULL);
 
-  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));
   }
 
@@ -1639,23 +1634,18 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
 
   unix_convert(fname,conn,0,&bad_path,NULL);
     
-  fsp = file_new();
-  if (!fsp)
-    return(ERROR(ERRSRV,ERRnofids));
-
   unixmode = unix_mode(conn,smb_attr | aARCH, fname);
       
-  open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
+  fsp = open_file_shared(conn,fname,smb_mode,smb_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));
   }
 
@@ -1772,10 +1762,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
   
   unixmode = unix_mode(conn,createmode,fname);
   
-  fsp = file_new();
-  if (!fsp)
-    return(ERROR(ERRSRV,ERRnofids));
-
   if(com == SMBmknew)
   {
     /* We should fail if file exists. */
@@ -1788,17 +1774,16 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
   }
 
   /* Open file in dos compatibility share mode. */
-  open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), 
+  fsp = open_file_shared(conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), 
                    ofun, unixmode, oplock_request, NULL, NULL);
   
-  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));
   }
  
@@ -1844,25 +1829,20 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
   
   unixmode = unix_mode(conn,createmode,fname);
   
-  fsp = file_new();
-  if (fsp)
-    return(ERROR(ERRSRV,ERRnofids));
-
   pstrcpy(fname2,(char *)smbd_mktemp(fname));
 
   /* Open file in dos compatibility share mode. */
   /* We should fail if file exists. */
-  open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), 
+  fsp = open_file_shared(conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), 
                    (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
 
-  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));
   }
 
@@ -3025,15 +3005,10 @@ int reply_printopen(connection_struct *conn,
        if (!CAN_PRINT(conn))
                return(ERROR(ERRDOS,ERRnoaccess));
 
-       fsp = file_new();
-       if (!fsp)
-               return(ERROR(ERRSRV,ERRnofids));
-       
        /* Open for exclusive use, write only. */
-       print_fsp_open(fsp,conn,"dos.prn");
+       fsp = print_fsp_open(conn,"dos.prn");
 
-       if (!fsp->open) {
-               file_free(fsp);
+       if (!fsp) {
                return(UNIXERROR(ERRDOS,ERRnoaccess));
        }
 
@@ -3745,32 +3720,21 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
   if (!vfs_file_exist(conn,src,&st))
     return(False);
 
-  fsp1 = file_new();
-  if (!fsp1)
-    return(False);
-
-  open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
+  fsp1 = open_file_shared(conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
                   (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
 
-  if (!fsp1->open) {
-         file_free(fsp1);
+  if (!fsp1) {
          return(False);
   }
 
   if (!target_is_directory && count)
     ofun = 1;
 
-  fsp2 = file_new();
-  if (!fsp2) {
-         close_file(fsp1,False);
-         return(False);
-  }
-  open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
+  fsp2 = open_file_shared(conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
                   ofun,st.st_mode,0,&Access,&action);
 
-  if (!fsp2->open) {
+  if (!fsp2) {
     close_file(fsp1,False);
-    file_free(fsp2);
     return(False);
   }
 
index 2ca06ab746425452b7080524ae8bc883f5217f76..f0a645d6c73d3c37a69f29a53ffd72c6987e70ad 100644 (file)
@@ -221,10 +221,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)
@@ -232,23 +228,21 @@ 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, 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));
   }
 
@@ -1794,113 +1788,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->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));
-
-              /*
-               * 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(fsp);
+                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->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(fsp);
+           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));
index b9c22ef1f9843db364eccfc1bb1f505bd3bc5682..a3dd7520236aadc2c7d09ace17a41ce73e3e8678 100644 (file)
@@ -297,3 +297,11 @@ int vfswrap_utime(char *path, struct utimbuf *times)
     result = utime(path, times);
     return result;
 }
+
+int vfswrap_ftruncate(int fd, SMB_OFF_T offset)
+{
+    int result;
+
+    result = sys_ftruncate(fd, offset);
+    return result;
+}
index e92235e23002cc2b8470c8f0dee5383b87745439..d76d64684babc25d4acc3088f35da917b2223423 100644 (file)
@@ -64,7 +64,8 @@ struct vfs_ops default_vfs_ops = {
     vfswrap_lstat,
     vfswrap_unlink,
     vfswrap_chmod,
-    vfswrap_utime
+    vfswrap_utime,
+    vfswrap_ftruncate
 };
 
 /****************************************************************************
@@ -208,6 +209,10 @@ BOOL vfs_init_custom(connection_struct *conn)
        conn->vfs_ops.utime = default_vfs_ops.utime;
     }
     
+    if (conn->vfs_ops.ftruncate == NULL) {
+       conn->vfs_ops.ftruncate= default_vfs_ops.ftruncate;
+    }
+    
     return True;
 }
 #endif