Merge of new 2.2 code into HEAD (Gerald I hate you :-) :-). Allows new SAMR
[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
69 static int close_filestruct(files_struct *fsp)
70 {   
71         connection_struct *conn = fsp->conn;
72         int ret = 0;
73     
74         if(flush_write_cache(fsp, CLOSE_FLUSH) == -1)
75                 ret = -1;
76
77         delete_write_cache(fsp);
78
79         fsp->is_directory = False; 
80         fsp->stat_open = False; 
81     
82         conn->num_files_open--;
83         if(fsp->wbmpx_ptr) {  
84                 free((char *)fsp->wbmpx_ptr);
85                 fsp->wbmpx_ptr = NULL; 
86         }  
87
88         return ret;
89 }    
90
91 /****************************************************************************
92  Close a file - possibly invalidating the read prediction.
93
94  If normal_close is 1 then this came from a normal SMBclose (or equivalent)
95  operation otherwise it came as the result of some other operation such as
96  the closing of the connection. In the latter case printing and
97  magic scripts are not run.
98 ****************************************************************************/
99
100 static int close_normal_file(files_struct *fsp, BOOL normal_close)
101 {
102         BOOL delete_on_close = fsp->delete_on_close;
103         connection_struct *conn = fsp->conn;
104         int err = 0;
105         int err1 = 0;
106
107         remove_pending_lock_requests_by_fid(fsp);
108
109         /*
110          * If we're flushing on a close we can get a write
111          * error here, we must remember this.
112          */
113
114         if (close_filestruct(fsp) == -1)
115                 err1 = -1;
116
117         if (fsp->print_file) {
118                 print_fsp_end(fsp, normal_close);
119                 file_free(fsp);
120                 return 0;
121         }
122
123         lock_share_entry_fsp(fsp);
124         del_share_mode(fsp);
125         unlock_share_entry_fsp(fsp);
126
127         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
128                 release_file_oplock(fsp);
129
130         locking_close_file(fsp);
131
132         err = fd_close(conn, fsp);
133
134         /* check for magic scripts */
135         if (normal_close) {
136                 check_magic(fsp,conn);
137         }
138
139         /*
140          * NT can set delete_on_close of the last open
141          * reference to a file.
142          */
143
144     if (normal_close && delete_on_close) {
145         DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n",
146             fsp->fsp_name));
147                 if(fsp->conn->vfs_ops.unlink(conn,dos_to_unix(fsp->fsp_name, False)) != 0) {
148           /*
149            * This call can potentially fail as another smbd may have
150            * had the file open with delete on close set and deleted
151            * it when its last reference to this file went away. Hence
152            * we log this but not at debug level zero.
153            */
154
155           DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \
156 with error %s\n", fsp->fsp_name, strerror(errno) ));
157         }
158     }
159
160         DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
161                  conn->user,fsp->fsp_name,
162                  conn->num_files_open, err ? strerror(err) : ""));
163
164         if (fsp->fsp_name) {
165                 string_free(&fsp->fsp_name);
166         }
167
168         file_free(fsp);
169
170         if (err == -1 || err1 == -1)
171                 return -1;
172         else
173                 return 0;
174 }
175
176 /****************************************************************************
177  Close a directory opened by an NT SMB call. 
178 ****************************************************************************/
179   
180 static int close_directory(files_struct *fsp, BOOL normal_close)
181 {
182         remove_pending_change_notify_requests_by_fid(fsp);
183
184         /*
185          * NT can set delete_on_close of the last open
186          * reference to a directory also.
187          */
188
189         if (normal_close && fsp->directory_delete_on_close) {
190                 BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name);
191                 DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
192                         fsp->fsp_name, ok ? "succeeded" : "failed" ));
193
194                 /*
195                  * Ensure we remove any change notify requests that would
196                  * now fail as the directory has been deleted.
197                  */
198
199                 if(ok)
200                         remove_pending_change_notify_requests_by_filename(fsp);
201     }
202
203         /*
204          * Do the code common to files and directories.
205          */
206         close_filestruct(fsp);
207         
208         if (fsp->fsp_name)
209                 string_free(&fsp->fsp_name);
210         
211         file_free(fsp);
212
213         return 0;
214 }
215
216 /****************************************************************************
217  Close a file opened with null permissions in order to read permissions.
218 ****************************************************************************/
219
220 static int close_statfile(files_struct *fsp, BOOL normal_close)
221 {
222         close_filestruct(fsp);
223         
224         if (fsp->fsp_name)
225                 string_free(&fsp->fsp_name);
226         
227         file_free(fsp);
228
229         return 0;
230 }
231
232 /****************************************************************************
233  Close a directory opened by an NT SMB call. 
234 ****************************************************************************/
235   
236 int close_file(files_struct *fsp, BOOL normal_close)
237 {
238         if(fsp->is_directory)
239                 return close_directory(fsp, normal_close);
240         else if(fsp->stat_open)
241                 return close_statfile(fsp, normal_close);
242         return close_normal_file(fsp, normal_close);
243 }