c4d323b1ba6150b6845d6f880290919b246b3b62
[tprouty/samba.git] / source / smbd / close.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    file closing
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25
26 /****************************************************************************
27 run a file if it is a magic script
28 ****************************************************************************/
29 static void check_magic(files_struct *fsp,connection_struct *conn)
30 {
31   if (!*lp_magicscript(SNUM(conn)))
32     return;
33
34   DEBUG(5,("checking magic for %s\n",fsp->fsp_name));
35
36   {
37     char *p;
38     if (!(p = strrchr(fsp->fsp_name,'/')))
39       p = fsp->fsp_name;
40     else
41       p++;
42
43     if (!strequal(lp_magicscript(SNUM(conn)),p))
44       return;
45   }
46
47   {
48     int ret;
49     pstring magic_output;
50     pstring fname;
51     pstrcpy(fname,fsp->fsp_name);
52
53     if (*lp_magicoutput(SNUM(conn)))
54       pstrcpy(magic_output,lp_magicoutput(SNUM(conn)));
55     else
56       slprintf(magic_output,sizeof(fname)-1, "%s.out",fname);
57
58     chmod(fname,0755);
59     ret = smbrun(fname,magic_output,False);
60     DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
61     unlink(fname);
62   }
63 }
64
65 /****************************************************************************
66   Common code to close a file or a directory.
67 ****************************************************************************/
68 static void close_filestruct(files_struct *fsp)
69 {   
70         connection_struct *conn = fsp->conn;
71     
72     flush_write_cache(fsp, CLOSE_FLUSH);
73
74         fsp->open = False;
75         fsp->is_directory = False; 
76     
77         conn->num_files_open--;
78         if(fsp->wbmpx_ptr) {  
79                 free((char *)fsp->wbmpx_ptr);
80                 fsp->wbmpx_ptr = NULL; 
81         }  
82 }    
83
84 /****************************************************************************
85  Close a file - possibly invalidating the read prediction.
86
87  If normal_close is 1 then this came from a normal SMBclose (or equivalent)
88  operation otherwise it came as the result of some other operation such as
89  the closing of the connection. In the latter case printing and
90  magic scripts are not run.
91 ****************************************************************************/
92
93 static int close_normal_file(files_struct *fsp, BOOL normal_close)
94 {
95         BOOL delete_on_close = fsp->delete_on_close;
96         connection_struct *conn = fsp->conn;
97         int err = 0;
98
99         remove_pending_lock_requests_by_fid(fsp);
100
101         close_filestruct(fsp);
102
103         if (normal_close && fsp->print_file) {
104                 print_fsp_end(fsp);
105                 file_free(fsp);
106                 return 0;
107         }
108
109         if (lp_share_modes(SNUM(conn))) {
110                 lock_share_entry_fsp(fsp);
111                 del_share_mode(fsp);
112         }
113
114         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
115                 release_file_oplock(fsp);
116
117         locking_close_file(fsp);
118
119         if (lp_share_modes(SNUM(conn)))
120                 unlock_share_entry_fsp(fsp);
121
122         err = fd_close(conn, fsp);
123
124         /* check for magic scripts */
125         if (normal_close) {
126                 check_magic(fsp,conn);
127         }
128
129         /*
130          * NT can set delete_on_close of the last open
131          * reference to a file.
132          */
133
134     if (normal_close && delete_on_close) {
135         DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n",
136             fsp->fsp_name));
137                 if(fsp->conn->vfs_ops.unlink(dos_to_unix(fsp->fsp_name, False)) != 0) {
138           /*
139            * This call can potentially fail as another smbd may have
140            * had the file open with delete on close set and deleted
141            * it when its last reference to this file went away. Hence
142            * we log this but not at debug level zero.
143            */
144
145           DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \
146 with error %s\n", fsp->fsp_name, strerror(errno) ));
147         }
148     }
149
150         DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
151                  conn->user,fsp->fsp_name,
152                  conn->num_files_open, err ? strerror(err) : ""));
153
154         if (fsp->fsp_name) {
155                 string_free(&fsp->fsp_name);
156         }
157
158         file_free(fsp);
159
160         return err;
161 }
162
163 /****************************************************************************
164  Close a directory opened by an NT SMB call. 
165 ****************************************************************************/
166   
167 static int close_directory(files_struct *fsp, BOOL normal_close)
168 {
169         remove_pending_change_notify_requests_by_fid(fsp);
170
171         /*
172          * NT can set delete_on_close of the last open
173          * reference to a directory also.
174          */
175
176         if (normal_close && fsp->directory_delete_on_close) {
177                 BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name);
178                 DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
179                         fsp->fsp_name, ok ? "succeeded" : "failed" ));
180
181                 /*
182                  * Ensure we remove any change notify requests that would
183                  * now fail as the directory has been deleted.
184                  */
185
186                 if(ok)
187                         remove_pending_change_notify_requests_by_filename(fsp);
188     }
189
190         /*
191          * Do the code common to files and directories.
192          */
193         close_filestruct(fsp);
194         
195         if (fsp->fsp_name)
196                 string_free(&fsp->fsp_name);
197         
198         file_free(fsp);
199
200         return 0;
201 }
202
203 /****************************************************************************
204  Close a file opened with null permissions in order to read permissions.
205 ****************************************************************************/
206
207 static int close_statfile(files_struct *fsp, BOOL normal_close)
208 {
209         close_filestruct(fsp);
210         
211         if (fsp->fsp_name)
212                 string_free(&fsp->fsp_name);
213         
214         file_free(fsp);
215
216         return 0;
217 }
218
219 /****************************************************************************
220  Close a directory opened by an NT SMB call. 
221 ****************************************************************************/
222   
223 int close_file(files_struct *fsp, BOOL normal_close)
224 {
225         if(fsp->is_directory)
226                 return close_directory(fsp, normal_close);
227         else if(fsp->stat_open)
228                 return close_statfile(fsp, normal_close);
229         return close_normal_file(fsp, normal_close);
230 }