first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[kai/samba.git] / source3 / 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         SMB_DEV_T dev = fsp->fd_ptr->dev;
96         SMB_INO_T inode = fsp->fd_ptr->inode;
97         int token;
98         BOOL last_reference = False;
99         BOOL delete_on_close = fsp->fd_ptr->delete_on_close;
100         connection_struct *conn = fsp->conn;
101         int err = 0;
102
103         remove_pending_lock_requests_by_fid(fsp);
104
105         close_filestruct(fsp);
106
107 #if USE_READ_PREDICTION
108         invalidate_read_prediction(fsp->fd_ptr->fd);
109 #endif
110
111         if (lp_share_modes(SNUM(conn))) {
112                 lock_share_entry(conn, dev, inode, &token);
113                 del_share_mode(token, fsp);
114         }
115
116         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
117                 release_file_oplock(fsp);
118
119         if(fd_attempt_close(fsp->fd_ptr,&err) == 0)
120                 last_reference = True;
121
122     fsp->fd_ptr = NULL;
123
124         if (lp_share_modes(SNUM(conn)))
125                 unlock_share_entry(conn, dev, inode, token);
126
127         /* NT uses smbclose to start a print - weird */
128         if (normal_close && fsp->print_file)
129                 print_file(conn, fsp);
130
131         /* check for magic scripts */
132         if (normal_close) {
133                 check_magic(fsp,conn);
134         }
135
136         /*
137          * NT can set delete_on_close of the last open
138          * reference to a file.
139          */
140
141     if (normal_close && last_reference && delete_on_close) {
142         DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n",
143             fsp->fsp_name));
144                 if(dos_unlink(fsp->fsp_name) != 0) {
145
146           /*
147            * This call can potentially fail as another smbd may have
148            * had the file open with delete on close set and deleted
149            * it when its last reference to this file went away. Hence
150            * we log this but not at debug level zero.
151            */
152
153           DEBUG(5,("close_file: file %s. Delete on close was set and unlink failed \
154 with error %s\n", fsp->fsp_name, strerror(errno) ));
155         }
156     }
157
158         DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
159                  conn->user,fsp->fsp_name,
160                  conn->num_files_open, err ? strerror(err) : ""));
161
162         if (fsp->fsp_name) {
163                 string_free(&fsp->fsp_name);
164         }
165
166         file_free(fsp);
167
168         return err;
169 }
170
171 /****************************************************************************
172  Close a directory opened by an NT SMB call. 
173 ****************************************************************************/
174   
175 static int close_directory(files_struct *fsp, BOOL normal_close)
176 {
177         remove_pending_change_notify_requests_by_fid(fsp);
178
179         /*
180          * NT can set delete_on_close of the last open
181          * reference to a directory also.
182          */
183
184         if (normal_close && fsp->directory_delete_on_close) {
185                 BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name);
186                 DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
187                         fsp->fsp_name, ok ? "succeeded" : "failed" ));
188
189                 /*
190                  * Ensure we remove any change notify requests that would
191                  * now fail as the directory has been deleted.
192                  */
193
194                 if(ok)
195                         remove_pending_change_notify_requests_by_filename(fsp);
196     }
197
198         /*
199          * Do the code common to files and directories.
200          */
201         close_filestruct(fsp);
202         
203         if (fsp->fsp_name)
204                 string_free(&fsp->fsp_name);
205         
206         file_free(fsp);
207
208         return 0;
209 }
210
211 /****************************************************************************
212  Close a file opened with null permissions in order to read permissions.
213 ****************************************************************************/
214
215 static int close_statfile(files_struct *fsp, BOOL normal_close)
216 {
217         close_filestruct(fsp);
218         
219         if (fsp->fsp_name)
220                 string_free(&fsp->fsp_name);
221         
222         file_free(fsp);
223
224         return 0;
225 }
226
227 /****************************************************************************
228  Close a directory opened by an NT SMB call. 
229 ****************************************************************************/
230   
231 int close_file(files_struct *fsp, BOOL normal_close)
232 {
233         if(fsp->is_directory)
234                 return close_directory(fsp, normal_close);
235         else if(fsp->stat_open)
236                 return close_statfile(fsp, normal_close);
237         return close_normal_file(fsp, normal_close);
238 }