s3: include smbd/smbd.h where needed.
[nivanova/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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "smbd/smbd.h"
22 #include "smbd/globals.h"
23 #include "libcli/security/security.h"
24
25 #define VALID_FNUM(fnum)   (((fnum) >= 0) && ((fnum) < real_max_open_files))
26
27 #define FILE_HANDLE_OFFSET 0x1000
28
29 /****************************************************************************
30  Return a unique number identifying this fsp over the life of this pid.
31 ****************************************************************************/
32
33 static unsigned long get_gen_count(struct smbd_server_connection *sconn)
34 {
35         sconn->file_gen_counter += 1;
36         if (sconn->file_gen_counter == 0) {
37                 sconn->file_gen_counter += 1;
38         }
39         return sconn->file_gen_counter;
40 }
41
42 /****************************************************************************
43  Find first available file slot.
44 ****************************************************************************/
45
46 NTSTATUS file_new(struct smb_request *req, connection_struct *conn,
47                   files_struct **result)
48 {
49         struct smbd_server_connection *sconn = conn->sconn;
50         int i;
51         files_struct *fsp;
52         NTSTATUS status;
53
54         /* we want to give out file handles differently on each new
55            connection because of a common bug in MS clients where they try to
56            reuse a file descriptor from an earlier smb connection. This code
57            increases the chance that the errant client will get an error rather
58            than causing corruption */
59         if (sconn->first_file == 0) {
60                 sconn->first_file = (sys_getpid() ^ (int)time(NULL));
61                 sconn->first_file %= sconn->real_max_open_files;
62         }
63
64         /* TODO: Port the id-tree implementation from Samba4 */
65
66         i = bitmap_find(sconn->file_bmap, sconn->first_file);
67         if (i == -1) {
68                 DEBUG(0,("ERROR! Out of file structures\n"));
69                 /* TODO: We have to unconditionally return a DOS error here,
70                  * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with
71                  * NTSTATUS negotiated */
72                 return NT_STATUS_TOO_MANY_OPENED_FILES;
73         }
74
75         /*
76          * Make a child of the connection_struct as an fsp can't exist
77          * independent of a connection.
78          */
79         fsp = talloc_zero(conn, struct files_struct);
80         if (!fsp) {
81                 return NT_STATUS_NO_MEMORY;
82         }
83
84         /*
85          * This can't be a child of fsp because the file_handle can be ref'd
86          * when doing a dos/fcb open, which will then share the file_handle
87          * across multiple fsps.
88          */
89         fsp->fh = talloc_zero(conn, struct fd_handle);
90         if (!fsp->fh) {
91                 TALLOC_FREE(fsp);
92                 return NT_STATUS_NO_MEMORY;
93         }
94
95         fsp->fh->ref_count = 1;
96         fsp->fh->fd = -1;
97
98         fsp->conn = conn;
99         fsp->fh->gen_id = get_gen_count(sconn);
100         GetTimeOfDay(&fsp->open_time);
101
102         sconn->first_file = (i+1) % (sconn->real_max_open_files);
103
104         bitmap_set(sconn->file_bmap, i);
105         sconn->files_used += 1;
106
107         fsp->fnum = i + FILE_HANDLE_OFFSET;
108         SMB_ASSERT(fsp->fnum < 65536);
109
110         /*
111          * Create an smb_filename with "" for the base_name.  There are very
112          * few NULL checks, so make sure it's initialized with something. to
113          * be safe until an audit can be done.
114          */
115         status = create_synthetic_smb_fname(fsp, "", NULL, NULL,
116                                             &fsp->fsp_name);
117         if (!NT_STATUS_IS_OK(status)) {
118                 TALLOC_FREE(fsp);
119                 TALLOC_FREE(fsp->fh);
120         }
121
122         DLIST_ADD(sconn->files, fsp);
123
124         DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
125                  i, fsp->fnum, sconn->files_used));
126
127         if (req != NULL) {
128                 req->chain_fsp = fsp;
129         }
130
131         /* A new fsp invalidates the positive and
132           negative fsp_fi_cache as the new fsp is pushed
133           at the start of the list and we search from
134           a cache hit to the *end* of the list. */
135
136         ZERO_STRUCT(sconn->fsp_fi_cache);
137
138         conn->num_files_open++;
139
140         *result = fsp;
141         return NT_STATUS_OK;
142 }
143
144 /****************************************************************************
145  Close all open files for a connection.
146 ****************************************************************************/
147
148 void file_close_conn(connection_struct *conn)
149 {
150         files_struct *fsp, *next;
151
152         for (fsp=conn->sconn->files; fsp; fsp=next) {
153                 next = fsp->next;
154                 if (fsp->conn == conn) {
155                         close_file(NULL, fsp, SHUTDOWN_CLOSE);
156                 }
157         }
158 }
159
160 /****************************************************************************
161  Close all open files for a pid and a vuid.
162 ****************************************************************************/
163
164 void file_close_pid(struct smbd_server_connection *sconn, uint16 smbpid,
165                     int vuid)
166 {
167         files_struct *fsp, *next;
168
169         for (fsp=sconn->files;fsp;fsp=next) {
170                 next = fsp->next;
171                 if ((fsp->file_pid == smbpid) && (fsp->vuid == vuid)) {
172                         close_file(NULL, fsp, SHUTDOWN_CLOSE);
173                 }
174         }
175 }
176
177 /****************************************************************************
178  Initialise file structures.
179 ****************************************************************************/
180
181 bool file_init(struct smbd_server_connection *sconn)
182 {
183         int request_max_open_files = lp_max_open_files();
184         int real_lim;
185
186         /*
187          * Set the max_open files to be the requested
188          * max plus a fudgefactor to allow for the extra
189          * fd's we need such as log files etc...
190          */
191         real_lim = set_maxfiles(request_max_open_files + MAX_OPEN_FUDGEFACTOR);
192
193         sconn->real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR;
194
195         if (sconn->real_max_open_files + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES
196             > 65536)
197                 sconn->real_max_open_files =
198                         65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES;
199
200         if(sconn->real_max_open_files != request_max_open_files) {
201                 DEBUG(1, ("file_init: Information only: requested %d "
202                           "open files, %d are available.\n",
203                           request_max_open_files, sconn->real_max_open_files));
204         }
205
206         SMB_ASSERT(sconn->real_max_open_files > 100);
207
208         sconn->file_bmap = bitmap_talloc(sconn, sconn->real_max_open_files);
209
210         if (!sconn->file_bmap) {
211                 return false;
212         }
213         return true;
214 }
215
216 /****************************************************************************
217  Close files open by a specified vuid.
218 ****************************************************************************/
219
220 void file_close_user(struct smbd_server_connection *sconn, int vuid)
221 {
222         files_struct *fsp, *next;
223
224         for (fsp=sconn->files; fsp; fsp=next) {
225                 next=fsp->next;
226                 if (fsp->vuid == vuid) {
227                         close_file(NULL, fsp, SHUTDOWN_CLOSE);
228                 }
229         }
230 }
231
232 /*
233  * Walk the files table until "fn" returns non-NULL
234  */
235
236 struct files_struct *files_forall(
237         struct smbd_server_connection *sconn,
238         struct files_struct *(*fn)(struct files_struct *fsp,
239                                    void *private_data),
240         void *private_data)
241 {
242         struct files_struct *fsp, *next;
243
244         for (fsp = sconn->files; fsp; fsp = next) {
245                 struct files_struct *ret;
246                 next = fsp->next;
247                 ret = fn(fsp, private_data);
248                 if (ret != NULL) {
249                         return ret;
250                 }
251         }
252         return NULL;
253 }
254
255 /****************************************************************************
256  Find a fsp given a file descriptor.
257 ****************************************************************************/
258
259 files_struct *file_find_fd(struct smbd_server_connection *sconn, int fd)
260 {
261         int count=0;
262         files_struct *fsp;
263
264         for (fsp=sconn->files; fsp; fsp=fsp->next,count++) {
265                 if (fsp->fh->fd == fd) {
266                         if (count > 10) {
267                                 DLIST_PROMOTE(sconn->files, fsp);
268                         }
269                         return fsp;
270                 }
271         }
272
273         return NULL;
274 }
275
276 /****************************************************************************
277  Find a fsp given a device, inode and file_id.
278 ****************************************************************************/
279
280 files_struct *file_find_dif(struct smbd_server_connection *sconn,
281                             struct file_id id, unsigned long gen_id)
282 {
283         int count=0;
284         files_struct *fsp;
285
286         for (fsp=sconn->files; fsp; fsp=fsp->next,count++) {
287                 /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */
288                 if (file_id_equal(&fsp->file_id, &id) &&
289                     fsp->fh->gen_id == gen_id ) {
290                         if (count > 10) {
291                                 DLIST_PROMOTE(sconn->files, fsp);
292                         }
293                         /* Paranoia check. */
294                         if ((fsp->fh->fd == -1) &&
295                             (fsp->oplock_type != NO_OPLOCK) &&
296                             (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {
297                                 DEBUG(0,("file_find_dif: file %s file_id = "
298                                          "%s, gen = %u oplock_type = %u is a "
299                                          "stat open with oplock type !\n",
300                                          fsp_str_dbg(fsp),
301                                          file_id_string_tos(&fsp->file_id),
302                                          (unsigned int)fsp->fh->gen_id,
303                                          (unsigned int)fsp->oplock_type ));
304                                 smb_panic("file_find_dif");
305                         }
306                         return fsp;
307                 }
308         }
309
310         return NULL;
311 }
312
313 /****************************************************************************
314  Find the first fsp given a device and inode.
315  We use a singleton cache here to speed up searching from getfilepathinfo
316  calls.
317 ****************************************************************************/
318
319 files_struct *file_find_di_first(struct smbd_server_connection *sconn,
320                                  struct file_id id)
321 {
322         files_struct *fsp;
323
324         if (file_id_equal(&sconn->fsp_fi_cache.id, &id)) {
325                 /* Positive or negative cache hit. */
326                 return sconn->fsp_fi_cache.fsp;
327         }
328
329         sconn->fsp_fi_cache.id = id;
330
331         for (fsp=sconn->files;fsp;fsp=fsp->next) {
332                 if (file_id_equal(&fsp->file_id, &id)) {
333                         /* Setup positive cache. */
334                         sconn->fsp_fi_cache.fsp = fsp;
335                         return fsp;
336                 }
337         }
338
339         /* Setup negative cache. */
340         sconn->fsp_fi_cache.fsp = NULL;
341         return NULL;
342 }
343
344 /****************************************************************************
345  Find the next fsp having the same device and inode.
346 ****************************************************************************/
347
348 files_struct *file_find_di_next(files_struct *start_fsp)
349 {
350         files_struct *fsp;
351
352         for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
353                 if (file_id_equal(&fsp->file_id, &start_fsp->file_id)) {
354                         return fsp;
355                 }
356         }
357
358         return NULL;
359 }
360
361 /****************************************************************************
362  Find any fsp open with a pathname below that of an already open path.
363 ****************************************************************************/
364
365 bool file_find_subpath(files_struct *dir_fsp)
366 {
367         files_struct *fsp;
368         size_t dlen;
369         char *d_fullname = NULL;
370
371         d_fullname = talloc_asprintf(talloc_tos(), "%s/%s",
372                                      dir_fsp->conn->connectpath,
373                                      dir_fsp->fsp_name->base_name);
374
375         if (!d_fullname) {
376                 return false;
377         }
378
379         dlen = strlen(d_fullname);
380
381         for (fsp=dir_fsp->conn->sconn->files; fsp; fsp=fsp->next) {
382                 char *d1_fullname;
383
384                 if (fsp == dir_fsp) {
385                         continue;
386                 }
387
388                 d1_fullname = talloc_asprintf(talloc_tos(),
389                                         "%s/%s",
390                                         fsp->conn->connectpath,
391                                         fsp->fsp_name->base_name);
392
393                 /*
394                  * If the open file has a path that is a longer
395                  * component, then it's a subpath.
396                  */
397                 if (strnequal(d_fullname, d1_fullname, dlen) &&
398                                 (d1_fullname[dlen] == '/')) {
399                         TALLOC_FREE(d1_fullname);
400                         TALLOC_FREE(d_fullname);
401                         return true;
402                 }
403                 TALLOC_FREE(d1_fullname);
404         }
405
406         TALLOC_FREE(d_fullname);
407         return false;
408 }
409
410 /****************************************************************************
411  Sync open files on a connection.
412 ****************************************************************************/
413
414 void file_sync_all(connection_struct *conn)
415 {
416         files_struct *fsp, *next;
417
418         for (fsp=conn->sconn->files; fsp; fsp=next) {
419                 next=fsp->next;
420                 if ((conn == fsp->conn) && (fsp->fh->fd != -1)) {
421                         sync_file(conn, fsp, True /* write through */);
422                 }
423         }
424 }
425
426 /****************************************************************************
427  Free up a fsp.
428 ****************************************************************************/
429
430 void file_free(struct smb_request *req, files_struct *fsp)
431 {
432         struct smbd_server_connection *sconn = fsp->conn->sconn;
433
434         DLIST_REMOVE(sconn->files, fsp);
435
436         TALLOC_FREE(fsp->fake_file_handle);
437
438         if (fsp->fh->ref_count == 1) {
439                 TALLOC_FREE(fsp->fh);
440         } else {
441                 fsp->fh->ref_count--;
442         }
443
444         if (fsp->notify) {
445                 if (fsp->is_directory) {
446                         notify_remove_onelevel(fsp->conn->notify_ctx,
447                                                &fsp->file_id, fsp);
448                 }
449                 notify_remove(fsp->conn->notify_ctx, fsp);
450                 TALLOC_FREE(fsp->notify);
451         }
452
453         /* Ensure this event will never fire. */
454         TALLOC_FREE(fsp->oplock_timeout);
455
456         /* Ensure this event will never fire. */
457         TALLOC_FREE(fsp->update_write_time_event);
458
459         bitmap_clear(sconn->file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
460         sconn->files_used--;
461
462         DEBUG(5,("freed files structure %d (%d used)\n",
463                  fsp->fnum, sconn->files_used));
464
465         fsp->conn->num_files_open--;
466
467         if ((req != NULL) && (fsp == req->chain_fsp)) {
468                 req->chain_fsp = NULL;
469         }
470
471         /*
472          * Clear all possible chained fsp
473          * pointers in the SMB2 request queue.
474          */
475         if (req != NULL && req->smb2req) {
476                 remove_smb2_chained_fsp(fsp);
477         }
478
479         /* Closing a file can invalidate the positive cache. */
480         if (fsp == sconn->fsp_fi_cache.fsp) {
481                 ZERO_STRUCT(sconn->fsp_fi_cache);
482         }
483
484         /* Drop all remaining extensions. */
485         while (fsp->vfs_extension) {
486                 vfs_remove_fsp_extension(fsp->vfs_extension->owner, fsp);
487         }
488
489         /* this is paranoia, just in case someone tries to reuse the
490            information */
491         ZERO_STRUCTP(fsp);
492
493         /* fsp->fsp_name is a talloc child and is free'd automatically. */
494         TALLOC_FREE(fsp);
495 }
496
497 /****************************************************************************
498  Get an fsp from a 16 bit fnum.
499 ****************************************************************************/
500
501 static struct files_struct *file_fnum(struct smbd_server_connection *sconn,
502                                       uint16 fnum)
503 {
504         files_struct *fsp;
505         int count=0;
506
507         for (fsp=sconn->files; fsp; fsp=fsp->next, count++) {
508                 if (fsp->fnum == fnum) {
509                         if (count > 10) {
510                                 DLIST_PROMOTE(sconn->files, fsp);
511                         }
512                         return fsp;
513                 }
514         }
515         return NULL;
516 }
517
518 /****************************************************************************
519  Get an fsp from a packet given a 16 bit fnum.
520 ****************************************************************************/
521
522 files_struct *file_fsp(struct smb_request *req, uint16 fid)
523 {
524         files_struct *fsp;
525
526         if (req == NULL) {
527                 /*
528                  * We should never get here. req==NULL could in theory
529                  * only happen from internal opens with a non-zero
530                  * root_dir_fid. Internal opens just don't do that, at
531                  * least they are not supposed to do so. And if they
532                  * start to do so, they better fake up a smb_request
533                  * from which we get the right smbd_server_conn. While
534                  * this should never happen, let's return NULL here.
535                  */
536                 return NULL;
537         }
538
539         if (req->chain_fsp != NULL) {
540                 return req->chain_fsp;
541         }
542
543         fsp = file_fnum(req->sconn, fid);
544         if (fsp != NULL) {
545                 req->chain_fsp = fsp;
546         }
547         return fsp;
548 }
549
550 /****************************************************************************
551  Duplicate the file handle part for a DOS or FCB open.
552 ****************************************************************************/
553
554 NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from,
555                       uint32 access_mask, uint32 share_access,
556                       uint32 create_options, files_struct *to)
557 {
558         TALLOC_FREE(to->fh);
559
560         to->fh = from->fh;
561         to->fh->ref_count++;
562
563         to->file_id = from->file_id;
564         to->initial_allocation_size = from->initial_allocation_size;
565         to->mode = from->mode;
566         to->file_pid = from->file_pid;
567         to->vuid = from->vuid;
568         to->open_time = from->open_time;
569         to->access_mask = access_mask;
570         to->share_access = share_access;
571         to->oplock_type = from->oplock_type;
572         to->can_lock = from->can_lock;
573         to->can_read = (access_mask & (FILE_READ_DATA)) ? True : False;
574         if (!CAN_WRITE(from->conn)) {
575                 to->can_write = False;
576         } else {
577                 to->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False;
578         }
579         to->modified = from->modified;
580         to->is_directory = from->is_directory;
581         to->aio_write_behind = from->aio_write_behind;
582
583         if (from->print_file) {
584                 to->print_file = talloc(to, struct print_file_data);
585                 if (!to->print_file) return NT_STATUS_NO_MEMORY;
586                 to->print_file->rap_jobid = from->print_file->rap_jobid;
587         } else {
588                 to->print_file = NULL;
589         }
590
591         return fsp_set_smb_fname(to, from->fsp_name);
592 }
593
594 /**
595  * Return a jenkins hash of a pathname on a connection.
596  */
597
598 NTSTATUS file_name_hash(connection_struct *conn,
599                         const char *name, uint32_t *p_name_hash)
600 {
601         TDB_DATA key;
602         char *fullpath = NULL;
603
604         /* Set the hash of the full pathname. */
605         fullpath = talloc_asprintf(talloc_tos(),
606                         "%s/%s",
607                         conn->connectpath,
608                         name);
609         if (!fullpath) {
610                 return NT_STATUS_NO_MEMORY;
611         }
612         key = string_term_tdb_data(fullpath);
613         *p_name_hash = tdb_jenkins_hash(&key);
614
615         DEBUG(10,("file_name_hash: %s hash 0x%x\n",
616                 fullpath,
617                 (unsigned int)*p_name_hash ));
618
619         TALLOC_FREE(fullpath);
620         return NT_STATUS_OK;
621 }
622
623 /**
624  * The only way that the fsp->fsp_name field should ever be set.
625  */
626 NTSTATUS fsp_set_smb_fname(struct files_struct *fsp,
627                            const struct smb_filename *smb_fname_in)
628 {
629         NTSTATUS status;
630         struct smb_filename *smb_fname_new;
631
632         status = copy_smb_filename(fsp, smb_fname_in, &smb_fname_new);
633         if (!NT_STATUS_IS_OK(status)) {
634                 return status;
635         }
636
637         TALLOC_FREE(fsp->fsp_name);
638         fsp->fsp_name = smb_fname_new;
639
640         return file_name_hash(fsp->conn,
641                         smb_fname_str_dbg(fsp->fsp_name),
642                         &fsp->name_hash);
643 }