converted smbd to use NTSTATUS by default
[sfrench/samba-autobuild/.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_m(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         SMB_STRUCT_STAT st;
52         int tmp_fd, outfd;
53
54     pstrcpy(fname,fsp->fsp_name);
55     if (*lp_magicoutput(SNUM(conn)))
56       pstrcpy(magic_output,lp_magicoutput(SNUM(conn)));
57     else
58       slprintf(magic_output,sizeof(fname)-1, "%s.out",fname);
59
60     chmod(fname,0755);
61     ret = smbrun(fname,&tmp_fd);
62     DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
63     unlink(fname);
64         if (ret != 0 || tmp_fd == -1) {
65                 if (tmp_fd != -1)
66                         close(tmp_fd);
67                 return;
68         }
69         outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
70         if (outfd == -1) {
71                 close(tmp_fd);
72                 return;
73         }
74
75         if (sys_fstat(tmp_fd,&st) == -1) {
76                 close(tmp_fd);
77                 close(outfd);
78                 return;
79         }
80
81         transfer_file(tmp_fd,outfd,st.st_size, NULL,0,0);
82         close(tmp_fd);
83         close(outfd);
84   }
85 }
86
87 /****************************************************************************
88   Common code to close a file or a directory.
89 ****************************************************************************/
90
91 static int close_filestruct(files_struct *fsp)
92 {   
93         connection_struct *conn = fsp->conn;
94         int ret = 0;
95     
96         if(flush_write_cache(fsp, CLOSE_FLUSH) == -1)
97                 ret = -1;
98
99         delete_write_cache(fsp);
100
101         fsp->is_directory = False; 
102         fsp->stat_open = False; 
103     
104         conn->num_files_open--;
105
106         return ret;
107 }    
108
109 /****************************************************************************
110  Close a file.
111
112  If normal_close is 1 then this came from a normal SMBclose (or equivalent)
113  operation otherwise it came as the result of some other operation such as
114  the closing of the connection. In the latter case printing and
115  magic scripts are not run.
116 ****************************************************************************/
117
118 static int close_normal_file(files_struct *fsp, BOOL normal_close)
119 {
120         share_mode_entry *share_entry = NULL;
121         size_t share_entry_count = 0;
122         BOOL delete_on_close = False;
123         connection_struct *conn = fsp->conn;
124         int err = 0;
125         int err1 = 0;
126
127         remove_pending_lock_requests_by_fid(fsp);
128
129         /*
130          * If we're flushing on a close we can get a write
131          * error here, we must remember this.
132          */
133
134         if (close_filestruct(fsp) == -1)
135                 err1 = -1;
136
137         if (fsp->print_file) {
138                 print_fsp_end(fsp, normal_close);
139                 file_free(fsp);
140                 return 0;
141         }
142
143         /*
144          * Lock the share entries, and determine if we should delete
145          * on close. If so delete whilst the lock is still in effect.
146          * This prevents race conditions with the file being created. JRA.
147          */
148
149         lock_share_entry_fsp(fsp);
150         share_entry_count = del_share_mode(fsp, &share_entry);
151
152         DEBUG(10,("close_normal_file: share_entry_count = %d for file %s\n",
153                 share_entry_count, fsp->fsp_name ));
154
155         /*
156          * We delete on close if it's the last open, and the
157          * delete on close flag was set in the entry we just deleted.
158          */
159
160         if ((share_entry_count == 0) && share_entry && 
161                         GET_DELETE_ON_CLOSE_FLAG(share_entry->share_mode) )
162                 delete_on_close = True;
163
164         safe_free(share_entry);
165
166         /*
167          * NT can set delete_on_close of the last open
168          * reference to a file.
169          */
170
171     if (normal_close && delete_on_close) {
172         DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n",
173             fsp->fsp_name));
174                 if(fsp->conn->vfs_ops.unlink(conn,fsp->fsp_name) != 0) {
175           /*
176            * This call can potentially fail as another smbd may have
177            * had the file open with delete on close set and deleted
178            * it when its last reference to this file went away. Hence
179            * we log this but not at debug level zero.
180            */
181
182           DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \
183 with error %s\n", fsp->fsp_name, strerror(errno) ));
184         }
185     }
186
187         unlock_share_entry_fsp(fsp);
188
189         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
190                 release_file_oplock(fsp);
191
192         locking_close_file(fsp);
193
194         err = fd_close(conn, fsp);
195
196         /* check for magic scripts */
197         if (normal_close) {
198                 check_magic(fsp,conn);
199         }
200
201
202         DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
203                  conn->user,fsp->fsp_name,
204                  conn->num_files_open, err ? strerror(err) : ""));
205
206         if (fsp->fsp_name) {
207                 string_free(&fsp->fsp_name);
208         }
209
210         file_free(fsp);
211
212         if (err == -1 || err1 == -1)
213                 return -1;
214         else
215                 return 0;
216 }
217
218 /****************************************************************************
219  Close a directory opened by an NT SMB call. 
220 ****************************************************************************/
221   
222 static int close_directory(files_struct *fsp, BOOL normal_close)
223 {
224         remove_pending_change_notify_requests_by_fid(fsp);
225
226         /*
227          * NT can set delete_on_close of the last open
228          * reference to a directory also.
229          */
230
231         if (normal_close && fsp->directory_delete_on_close) {
232                 BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name);
233                 DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
234                         fsp->fsp_name, ok ? "succeeded" : "failed" ));
235
236                 /*
237                  * Ensure we remove any change notify requests that would
238                  * now fail as the directory has been deleted.
239                  */
240
241                 if(ok)
242                         remove_pending_change_notify_requests_by_filename(fsp);
243     }
244
245         /*
246          * Do the code common to files and directories.
247          */
248         close_filestruct(fsp);
249         
250         if (fsp->fsp_name)
251                 string_free(&fsp->fsp_name);
252         
253         file_free(fsp);
254
255         return 0;
256 }
257
258 /****************************************************************************
259  Close a file opened with null permissions in order to read permissions.
260 ****************************************************************************/
261
262 static int close_statfile(files_struct *fsp, BOOL normal_close)
263 {
264         close_filestruct(fsp);
265         
266         if (fsp->fsp_name)
267                 string_free(&fsp->fsp_name);
268         
269         file_free(fsp);
270
271         return 0;
272 }
273
274 /****************************************************************************
275  Close a directory opened by an NT SMB call. 
276 ****************************************************************************/
277   
278 int close_file(files_struct *fsp, BOOL normal_close)
279 {
280         if(fsp->is_directory)
281                 return close_directory(fsp, normal_close);
282         else if(fsp->stat_open)
283                 return close_statfile(fsp, normal_close);
284         return close_normal_file(fsp, normal_close);
285 }