[GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch.
[samba.git] / source / smbd / close.c
index c4aa2e2e28c0b1c36bf43cdae2d11c0e8be7871b..ae45aaa6dac81e7bd6adf601f83c6fa8c35d4736 100644 (file)
@@ -1,23 +1,22 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
    file closing
    Copyright (C) Andrew Tridgell 1992-1998
    Copyright (C) Jeremy Allison 1992-2007.
    Copyright (C) Volker Lendecke 2005
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
@@ -30,60 +29,73 @@ extern struct current_user current_user;
 
 static void check_magic(files_struct *fsp,connection_struct *conn)
 {
-       if (!*lp_magicscript(SNUM(conn)))
+       int ret;
+       const char *magic_output = NULL;
+       SMB_STRUCT_STAT st;
+       int tmp_fd, outfd;
+       TALLOC_CTX *ctx = NULL;
+       const char *p;
+
+       if (!*lp_magicscript(SNUM(conn))) {
                return;
+       }
 
        DEBUG(5,("checking magic for %s\n",fsp->fsp_name));
 
-       {
-               char *p;
-               if (!(p = strrchr_m(fsp->fsp_name,'/')))
-                       p = fsp->fsp_name;
-               else
-                       p++;
-
-               if (!strequal(lp_magicscript(SNUM(conn)),p))
-                       return;
-       }
-
-       {
-               int ret;
-               pstring magic_output;
-               pstring fname;
-               SMB_STRUCT_STAT st;
-               int tmp_fd, outfd;
-
-               pstrcpy(fname,fsp->fsp_name);
-               if (*lp_magicoutput(SNUM(conn)))
-                       pstrcpy(magic_output,lp_magicoutput(SNUM(conn)));
-               else
-                       slprintf(magic_output,sizeof(fname)-1, "%s.out",fname);
-
-               chmod(fname,0755);
-               ret = smbrun(fname,&tmp_fd);
-               DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
-               unlink(fname);
-               if (ret != 0 || tmp_fd == -1) {
-                       if (tmp_fd != -1)
-                               close(tmp_fd);
-                       return;
-               }
-               outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
-               if (outfd == -1) {
-                       close(tmp_fd);
-                       return;
-               }
+       if (!(p = strrchr_m(fsp->fsp_name,'/'))) {
+               p = fsp->fsp_name;
+       } else {
+               p++;
+       }
+
+       if (!strequal(lp_magicscript(SNUM(conn)),p)) {
+               return;
+       }
+
+       ctx = talloc_stackframe();
+
+       if (*lp_magicoutput(SNUM(conn))) {
+               magic_output = lp_magicoutput(SNUM(conn));
+       } else {
+               magic_output = talloc_asprintf(ctx,
+                               "%s.out",
+                               fsp->fsp_name);
+       }
+       if (!magic_output) {
+               TALLOC_FREE(ctx);
+               return;
+       }
+
+       chmod(fsp->fsp_name,0755);
+       ret = smbrun(fsp->fsp_name,&tmp_fd);
+       DEBUG(3,("Invoking magic command %s gave %d\n",
+               fsp->fsp_name,ret));
 
-               if (sys_fstat(tmp_fd,&st) == -1) {
+       unlink(fsp->fsp_name);
+       if (ret != 0 || tmp_fd == -1) {
+               if (tmp_fd != -1) {
                        close(tmp_fd);
-                       close(outfd);
-                       return;
                }
+               TALLOC_FREE(ctx);
+               return;
+       }
+       outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
+       if (outfd == -1) {
+               close(tmp_fd);
+               TALLOC_FREE(ctx);
+               return;
+       }
 
-               transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size);
+       if (sys_fstat(tmp_fd,&st) == -1) {
                close(tmp_fd);
                close(outfd);
+               return;
        }
+
+       transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size);
+       close(tmp_fd);
+       close(outfd);
+       TALLOC_FREE(ctx);
 }
 
 /****************************************************************************
@@ -91,7 +103,7 @@ static void check_magic(files_struct *fsp,connection_struct *conn)
 ****************************************************************************/
 
 static NTSTATUS close_filestruct(files_struct *fsp)
-{   
+{
        NTSTATUS status = NT_STATUS_OK;
        connection_struct *conn = fsp->conn;
     
@@ -103,7 +115,6 @@ static NTSTATUS close_filestruct(files_struct *fsp)
        }
 
        conn->num_files_open--;
-       SAFE_FREE(fsp->wbmpx_ptr);
        return status;
 }    
 
@@ -155,6 +166,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
        struct share_mode_lock *lck;
        SMB_STRUCT_STAT sbuf;
        NTSTATUS status = NT_STATUS_OK;
+       int ret;
        struct file_id id;
 
        /*
@@ -248,8 +260,14 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
 
        /* We can only delete the file if the name we have is still valid and
           hasn't been renamed. */
-       
-       if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) {
+
+       if (fsp->posix_open) {
+               ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
+       } else {
+               ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
+       }
+
+       if (ret != 0) {
                DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
                         "was set and stat failed with error %s\n",
                         fsp->fsp_name, strerror(errno) ));
@@ -259,7 +277,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
                goto done;
        }
 
-       id = file_id_sbuf(&sbuf);
+       id = vfs_file_id_from_sbuf(conn, &sbuf);
 
        if (!file_id_equal(&fsp->file_id, &id)) {
                DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
@@ -268,8 +286,8 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
                DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, "
                         "stat file_id %s\n",
                         fsp->fsp_name,
-                        file_id_static_string(&fsp->file_id),
-                        file_id_static_string2(&id)));
+                        file_id_string_tos(&fsp->file_id),
+                        file_id_string_tos(&id)));
                /*
                 * Don't save the errno here, we ignore this error
                 */
@@ -327,16 +345,28 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_
        NTSTATUS status = NT_STATUS_OK;
        NTSTATUS saved_status1 = NT_STATUS_OK;
        NTSTATUS saved_status2 = NT_STATUS_OK;
+       NTSTATUS saved_status3 = NT_STATUS_OK;
        connection_struct *conn = fsp->conn;
 
-       cancel_aio_by_fsp(fsp);
+       if (fsp->aio_write_behind) {
+               /*
+                * If we're finishing write behind on a close we can get a write
+                * error here, we must remember this.
+                */
+               int ret = wait_for_aio_completion(fsp);
+               if (ret) {
+                       saved_status1 = map_nt_error_from_unix(ret);
+               }
+       } else {
+               cancel_aio_by_fsp(fsp);
+       }
  
        /*
         * If we're flushing on a close we can get a write
         * error here, we must remember this.
         */
 
-       saved_status1 = close_filestruct(fsp);
+       saved_status2 = close_filestruct(fsp);
 
        if (fsp->print_file) {
                print_fsp_end(fsp, close_type);
@@ -350,7 +380,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_
 
        if (fsp->fh->ref_count == 1) {
                /* Should we return on error here... ? */
-               saved_status2 = close_remove_share_mode(fsp, close_type);
+               saved_status3 = close_remove_share_mode(fsp, close_type);
        }
 
        if(fsp->oplock_type) {
@@ -381,6 +411,8 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_
                        status = saved_status1;
                } else if (!NT_STATUS_IS_OK(saved_status2)) {
                        status = saved_status2;
+               } else if (!NT_STATUS_IS_OK(saved_status3)) {
+                       status = saved_status3;
                }
        }
 
@@ -473,7 +505,8 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty
 
                TALLOC_FREE(lck);
 
-               status = rmdir_internals(fsp->conn, fsp->fsp_name);
+               status = rmdir_internals(talloc_tos(),
+                               fsp->conn, fsp->fsp_name);
 
                DEBUG(5,("close_directory: %s. Delete on close was set - "
                         "deleting directory returned %s.\n",