Implemented the level 1010 NT rename level. Many fixes for Samba4 test
[vlendec/samba-autobuild/.git] / source3 / smbd / files.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Files[] structure handling
4    Copyright (C) Andrew Tridgell 1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 static int real_max_open_files;
24
25 #define VALID_FNUM(fnum)   (((fnum) >= 0) && ((fnum) < real_max_open_files))
26
27 #define FILE_HANDLE_OFFSET 0x1000
28
29 static struct bitmap *file_bmap;
30
31 static files_struct *Files;
32  
33 /* a fsp to use when chaining */
34 static files_struct *chain_fsp = NULL;
35 /* a fsp to use to save when breaking an oplock. */
36 static files_struct *oplock_save_chain_fsp = NULL;
37
38 static int files_used;
39
40 /****************************************************************************
41  Return a unique number identifying this fsp over the life of this pid.
42 ****************************************************************************/
43
44 static unsigned long get_gen_count(void)
45 {
46         static unsigned long file_gen_counter;
47
48         if ((++file_gen_counter) == 0)
49                 return ++file_gen_counter;
50         return file_gen_counter;
51 }
52
53 /****************************************************************************
54  Find first available file slot.
55 ****************************************************************************/
56
57 files_struct *file_new(connection_struct *conn)
58 {
59         int i;
60         static int first_file;
61         files_struct *fsp, *next;
62
63         /* we want to give out file handles differently on each new
64            connection because of a common bug in MS clients where they try to
65            reuse a file descriptor from an earlier smb connection. This code
66            increases the chance that the errant client will get an error rather
67            than causing corruption */
68         if (first_file == 0) {
69                 first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files;
70         }
71
72         i = bitmap_find(file_bmap, first_file);
73         if (i == -1) {
74                 /* 
75                  * Before we give up, go through the open files 
76                  * and see if there are any files opened with a
77                  * batch oplock. If so break the oplock and then
78                  * re-use that entry (if it becomes closed).
79                  * This may help as NT/95 clients tend to keep
80                  * files batch oplocked for quite a long time
81                  * after they have finished with them.
82                  */
83                 for (fsp=Files;fsp;fsp=next) {
84                         next=fsp->next;
85                         if (attempt_close_oplocked_file(fsp)) {
86                                 return file_new(conn);
87                         }
88                 }
89
90                 DEBUG(0,("ERROR! Out of file structures\n"));
91                 unix_ERR_class = ERRSRV;
92                 unix_ERR_code = ERRnofids;
93                 return NULL;
94         }
95
96         fsp = (files_struct *)malloc(sizeof(*fsp));
97         if (!fsp) {
98                 unix_ERR_class = ERRSRV;
99                 unix_ERR_code = ERRnofids;
100                 return NULL;
101         }
102
103         ZERO_STRUCTP(fsp);
104         fsp->fd = -1;
105         fsp->conn = conn;
106         fsp->file_id = get_gen_count();
107         GetTimeOfDay(&fsp->open_time);
108
109         first_file = (i+1) % real_max_open_files;
110
111         bitmap_set(file_bmap, i);
112         files_used++;
113
114         fsp->fnum = i + FILE_HANDLE_OFFSET;
115         SMB_ASSERT(fsp->fnum < 65536);
116
117         string_set(&fsp->fsp_name,"");
118         
119         DLIST_ADD(Files, fsp);
120
121         DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
122                  i, fsp->fnum, files_used));
123
124         chain_fsp = fsp;
125         
126         return fsp;
127 }
128
129 /****************************************************************************
130  Close all open files for a connection.
131 ****************************************************************************/
132
133 void file_close_conn(connection_struct *conn)
134 {
135         files_struct *fsp, *next;
136         
137         for (fsp=Files;fsp;fsp=next) {
138                 next = fsp->next;
139                 if (fsp->conn == conn) {
140                         close_file(fsp,False); 
141                 }
142         }
143 }
144
145 /****************************************************************************
146  Initialise file structures.
147 ****************************************************************************/
148
149 #define MAX_OPEN_FUDGEFACTOR 20
150
151 void file_init(void)
152 {
153         int request_max_open_files = lp_max_open_files();
154         int real_lim;
155
156         /*
157          * Set the max_open files to be the requested
158          * max plus a fudgefactor to allow for the extra
159          * fd's we need such as log files etc...
160          */
161         real_lim = set_maxfiles(request_max_open_files + MAX_OPEN_FUDGEFACTOR);
162
163         real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR;
164
165         if (real_max_open_files + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536)
166                 real_max_open_files = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES;
167
168         if(real_max_open_files != request_max_open_files) {
169                 DEBUG(1,("file_init: Information only: requested %d \
170 open files, %d are available.\n", request_max_open_files, real_max_open_files));
171         }
172
173         SMB_ASSERT(real_max_open_files > 100);
174
175         file_bmap = bitmap_allocate(real_max_open_files);
176         
177         if (!file_bmap) {
178                 exit_server("out of memory in file_init");
179         }
180         
181         /*
182          * Ensure that pipe_handle_oppset is set correctly.
183          */
184         set_pipe_handle_offset(real_max_open_files);
185 }
186
187 /****************************************************************************
188  Close files open by a specified vuid.
189 ****************************************************************************/
190
191 void file_close_user(int vuid)
192 {
193         files_struct *fsp, *next;
194
195         for (fsp=Files;fsp;fsp=next) {
196                 next=fsp->next;
197                 if (fsp->vuid == vuid) {
198                         close_file(fsp,False);
199                 }
200         }
201 }
202
203 void file_dump_open_table(void)
204 {
205         int count=0;
206         files_struct *fsp;
207
208         for (fsp=Files;fsp;fsp=fsp->next,count++) {
209                 DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, fileid = %lu, dev = %x, inode = %.0f\n",
210                         count, fsp->fnum, fsp->fsp_name, fsp->fd, (unsigned long)fsp->file_id,
211                         (unsigned int)fsp->dev, (double)fsp->inode ));
212         }
213 }
214
215 /****************************************************************************
216  Find a fsp given a file descriptor.
217 ****************************************************************************/
218
219 files_struct *file_find_fd(int fd)
220 {
221         int count=0;
222         files_struct *fsp;
223
224         for (fsp=Files;fsp;fsp=fsp->next,count++) {
225                 if (fsp->fd == fd) {
226                         if (count > 10) {
227                                 DLIST_PROMOTE(Files, fsp);
228                         }
229                         return fsp;
230                 }
231         }
232
233         return NULL;
234 }
235
236 /****************************************************************************
237  Find a fsp given a device, inode and file_id.
238 ****************************************************************************/
239
240 files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id)
241 {
242         int count=0;
243         files_struct *fsp;
244
245         for (fsp=Files;fsp;fsp=fsp->next,count++) {
246                 /* We can have a fsp->fd == -1 here as it could be a stat open. */
247                 if (fsp->dev == dev && 
248                     fsp->inode == inode &&
249                     fsp->file_id == file_id ) {
250                         if (count > 10) {
251                                 DLIST_PROMOTE(Files, fsp);
252                         }
253                         /* Paranoia check. */
254                         if (fsp->fd == -1 && fsp->oplock_type != NO_OPLOCK) {
255                                 DEBUG(0,("file_find_dif: file %s dev = %x, inode = %.0f, file_id = %u \
256 oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, (unsigned int)fsp->dev,
257                                                 (double)fsp->inode, (unsigned int)fsp->file_id,
258                                                 (unsigned int)fsp->oplock_type ));
259                                 smb_panic("file_find_dif\n");
260                         }
261                         return fsp;
262                 }
263         }
264
265         return NULL;
266 }
267
268 /****************************************************************************
269  Check if an fsp still exists.
270 ****************************************************************************/
271
272 files_struct *file_find_fsp(files_struct *orig_fsp)
273 {
274         files_struct *fsp;
275
276     for (fsp=Files;fsp;fsp=fsp->next) {
277         if (fsp == orig_fsp)
278             return fsp;
279     }
280
281     return NULL;
282 }
283
284 /****************************************************************************
285  Find the first fsp given a device and inode.
286 ****************************************************************************/
287
288 files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode)
289 {
290     files_struct *fsp;
291
292     for (fsp=Files;fsp;fsp=fsp->next) {
293         if ( fsp->fd != -1 &&
294             fsp->dev == dev &&
295             fsp->inode == inode )
296             return fsp;
297     }
298
299     return NULL;
300 }
301
302 /****************************************************************************
303  Find the next fsp having the same device and inode.
304 ****************************************************************************/
305
306 files_struct *file_find_di_next(files_struct *start_fsp)
307 {
308     files_struct *fsp;
309
310     for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
311         if ( fsp->fd != -1 &&
312             fsp->dev == start_fsp->dev &&
313             fsp->inode == start_fsp->inode )
314             return fsp;
315     }
316
317     return NULL;
318 }
319
320 /****************************************************************************
321  Find a fsp that is open for printing.
322 ****************************************************************************/
323
324 files_struct *file_find_print(void)
325 {
326         files_struct *fsp;
327
328         for (fsp=Files;fsp;fsp=fsp->next) {
329                 if (fsp->print_file) return fsp;
330         } 
331
332         return NULL;
333 }
334
335 /****************************************************************************
336  Sync open files on a connection.
337 ****************************************************************************/
338
339 void file_sync_all(connection_struct *conn)
340 {
341         files_struct *fsp, *next;
342
343         for (fsp=Files;fsp;fsp=next) {
344                 next=fsp->next;
345                 if ((conn == fsp->conn) && (fsp->fd != -1)) {
346                         sync_file(conn,fsp);
347                 }
348         }
349 }
350
351 /****************************************************************************
352  Free up a fsp.
353 ****************************************************************************/
354
355 void file_free(files_struct *fsp)
356 {
357         DLIST_REMOVE(Files, fsp);
358
359         string_free(&fsp->fsp_name);
360
361         if (fsp->fake_file_handle) {
362                 destroy_fake_file_handle(&fsp->fake_file_handle);
363         }
364
365         bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
366         files_used--;
367
368         DEBUG(5,("freed files structure %d (%d used)\n",
369                  fsp->fnum, files_used));
370
371         /* this is paranoia, just in case someone tries to reuse the 
372            information */
373         ZERO_STRUCTP(fsp);
374
375         if (fsp == chain_fsp) chain_fsp = NULL;
376
377         SAFE_FREE(fsp);
378 }
379
380 /****************************************************************************
381  Get a fsp from a packet given the offset of a 16 bit fnum.
382 ****************************************************************************/
383
384 files_struct *file_fsp(char *buf, int where)
385 {
386         int fnum, count=0;
387         files_struct *fsp;
388
389         if (chain_fsp)
390                 return chain_fsp;
391
392         fnum = SVAL(buf, where);
393
394         for (fsp=Files;fsp;fsp=fsp->next, count++) {
395                 if (fsp->fnum == fnum) {
396                         chain_fsp = fsp;
397                         if (count > 10) {
398                                 DLIST_PROMOTE(Files, fsp);
399                         }
400                         return fsp;
401                 }
402         }
403         return NULL;
404 }
405
406 /****************************************************************************
407  Reset the chained fsp - done at the start of a packet reply.
408 ****************************************************************************/
409
410 void file_chain_reset(void)
411 {
412         chain_fsp = NULL;
413 }
414
415 /****************************************************************************
416 Save the chained fsp - done when about to do an oplock break.
417 ****************************************************************************/
418
419 void file_chain_save(void)
420 {
421         oplock_save_chain_fsp = chain_fsp;
422 }
423
424 /****************************************************************************
425 Restore the chained fsp - done after an oplock break.
426 ****************************************************************************/
427
428 void file_chain_restore(void)
429 {
430         chain_fsp = oplock_save_chain_fsp;
431 }