2 Unix SMB/CIFS implementation.
3 Files[] structure handling
4 Copyright (C) Andrew Tridgell 1998
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.
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.
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/>.
21 #include "smbd/smbd.h"
22 #include "smbd/globals.h"
23 #include "libcli/security/security.h"
25 #include <ccan/hash/hash.h>
26 #include "lib/util/bitmap.h"
28 #define FILE_HANDLE_OFFSET 0x1000
30 /****************************************************************************
31 Return a unique number identifying this fsp over the life of this pid,
32 and try to make it as globally unique as possible.
33 See bug #8995 for the details.
34 ****************************************************************************/
36 static unsigned long get_gen_count(struct smbd_server_connection
*sconn
)
39 * While fsp->fh->gen_id is 'unsigned long' currently
40 * (which might by 8 bytes),
41 * there's some oplock code which truncates it to
42 * uint32_t(using IVAL()).
44 if (sconn
->file_gen_counter
== 0) {
45 sconn
->file_gen_counter
= generate_random();
47 sconn
->file_gen_counter
+= 1;
48 if (sconn
->file_gen_counter
>= UINT32_MAX
) {
49 sconn
->file_gen_counter
= 0;
51 if (sconn
->file_gen_counter
== 0) {
52 sconn
->file_gen_counter
+= 1;
54 return sconn
->file_gen_counter
;
57 /****************************************************************************
58 Find first available file slot.
59 ****************************************************************************/
61 NTSTATUS
file_new(struct smb_request
*req
, connection_struct
*conn
,
62 files_struct
**result
)
64 struct smbd_server_connection
*sconn
= conn
->sconn
;
69 if (sconn
->file_bmap
!= NULL
) {
72 * we want to give out file handles differently on each new
73 * connection because of a common bug in MS clients where they
74 * try to reuse a file descriptor from an earlier smb
75 * connection. This code increases the chance that the errant
76 * client will get an error rather than causing corruption
78 if (sconn
->first_file
== 0) {
79 sconn
->first_file
= (getpid() ^ (int)time(NULL
));
80 sconn
->first_file
%= sconn
->real_max_open_files
;
83 /* TODO: Port the id-tree implementation from Samba4 */
85 i
= bitmap_find(sconn
->file_bmap
, sconn
->first_file
);
87 DEBUG(0,("ERROR! Out of file structures\n"));
89 * TODO: We have to unconditionally return a DOS error
90 * here, W2k3 even returns ERRDOS/ERRnofids for
91 * ntcreate&x with NTSTATUS negotiated
93 return NT_STATUS_TOO_MANY_OPENED_FILES
;
98 * Make a child of the connection_struct as an fsp can't exist
99 * independent of a connection.
101 fsp
= talloc_zero(conn
, struct files_struct
);
103 return NT_STATUS_NO_MEMORY
;
107 * This can't be a child of fsp because the file_handle can be ref'd
108 * when doing a dos/fcb open, which will then share the file_handle
109 * across multiple fsps.
111 fsp
->fh
= talloc_zero(conn
, struct fd_handle
);
114 return NT_STATUS_NO_MEMORY
;
117 fsp
->fh
->ref_count
= 1;
122 GetTimeOfDay(&fsp
->open_time
);
124 if (sconn
->file_bmap
!= NULL
) {
125 sconn
->first_file
= (i
+1) % (sconn
->real_max_open_files
);
127 bitmap_set(sconn
->file_bmap
, i
);
129 fsp
->fnum
= i
+ FILE_HANDLE_OFFSET
;
130 SMB_ASSERT(fsp
->fnum
< 65536);
132 fsp
->fh
->gen_id
= get_gen_count(sconn
);
135 DLIST_ADD(sconn
->files
, fsp
);
136 sconn
->num_files
+= 1;
138 conn
->num_files_open
++;
141 * Create an smb_filename with "" for the base_name. There are very
142 * few NULL checks, so make sure it's initialized with something. to
143 * be safe until an audit can be done.
145 status
= create_synthetic_smb_fname(fsp
, "", NULL
, NULL
,
147 if (!NT_STATUS_IS_OK(status
)) {
148 file_free(NULL
, fsp
);
152 DEBUG(5,("allocated file structure %d, fnum = %d (%u used)\n",
153 i
, fsp
->fnum
, (unsigned int)sconn
->num_files
));
156 req
->chain_fsp
= fsp
;
159 /* A new fsp invalidates the positive and
160 negative fsp_fi_cache as the new fsp is pushed
161 at the start of the list and we search from
162 a cache hit to the *end* of the list. */
164 ZERO_STRUCT(sconn
->fsp_fi_cache
);
170 /****************************************************************************
171 Close all open files for a connection.
172 ****************************************************************************/
174 void file_close_conn(connection_struct
*conn
)
176 files_struct
*fsp
, *next
;
178 for (fsp
=conn
->sconn
->files
; fsp
; fsp
=next
) {
180 if (fsp
->conn
== conn
) {
181 close_file(NULL
, fsp
, SHUTDOWN_CLOSE
);
186 /****************************************************************************
187 Close all open files for a pid and a vuid.
188 ****************************************************************************/
190 void file_close_pid(struct smbd_server_connection
*sconn
, uint16 smbpid
,
193 files_struct
*fsp
, *next
;
195 for (fsp
=sconn
->files
;fsp
;fsp
=next
) {
197 if ((fsp
->file_pid
== smbpid
) && (fsp
->vuid
== vuid
)) {
198 close_file(NULL
, fsp
, SHUTDOWN_CLOSE
);
203 /****************************************************************************
204 Initialise file structures.
205 ****************************************************************************/
207 static int files_max_open_fds
;
209 bool file_init_global(void)
211 int request_max
= lp_max_open_files();
215 if (files_max_open_fds
!= 0) {
220 * Set the max_open files to be the requested
221 * max plus a fudgefactor to allow for the extra
222 * fd's we need such as log files etc...
224 real_lim
= set_maxfiles(request_max
+ MAX_OPEN_FUDGEFACTOR
);
226 real_max
= real_lim
- MAX_OPEN_FUDGEFACTOR
;
228 if (real_max
+ FILE_HANDLE_OFFSET
+ MAX_OPEN_PIPES
> 65536) {
229 real_max
= 65536 - FILE_HANDLE_OFFSET
- MAX_OPEN_PIPES
;
232 if (real_max
!= request_max
) {
233 DEBUG(1, ("file_init_global: Information only: requested %d "
234 "open files, %d are available.\n",
235 request_max
, real_max
));
238 SMB_ASSERT(real_max
> 100);
240 files_max_open_fds
= real_max
;
244 bool file_init(struct smbd_server_connection
*sconn
)
248 ok
= file_init_global();
253 sconn
->real_max_open_files
= files_max_open_fds
;
255 sconn
->file_bmap
= bitmap_talloc(sconn
, sconn
->real_max_open_files
);
256 if (!sconn
->file_bmap
) {
263 /****************************************************************************
264 Close files open by a specified vuid.
265 ****************************************************************************/
267 void file_close_user(struct smbd_server_connection
*sconn
, uint64_t vuid
)
269 files_struct
*fsp
, *next
;
271 for (fsp
=sconn
->files
; fsp
; fsp
=next
) {
273 if (fsp
->vuid
== vuid
) {
274 close_file(NULL
, fsp
, SHUTDOWN_CLOSE
);
280 * Walk the files table until "fn" returns non-NULL
283 struct files_struct
*files_forall(
284 struct smbd_server_connection
*sconn
,
285 struct files_struct
*(*fn
)(struct files_struct
*fsp
,
289 struct files_struct
*fsp
, *next
;
291 for (fsp
= sconn
->files
; fsp
; fsp
= next
) {
292 struct files_struct
*ret
;
294 ret
= fn(fsp
, private_data
);
302 /****************************************************************************
303 Find a fsp given a file descriptor.
304 ****************************************************************************/
306 files_struct
*file_find_fd(struct smbd_server_connection
*sconn
, int fd
)
311 for (fsp
=sconn
->files
; fsp
; fsp
=fsp
->next
,count
++) {
312 if (fsp
->fh
->fd
== fd
) {
314 DLIST_PROMOTE(sconn
->files
, fsp
);
323 /****************************************************************************
324 Find a fsp given a device, inode and file_id.
325 ****************************************************************************/
327 files_struct
*file_find_dif(struct smbd_server_connection
*sconn
,
328 struct file_id id
, unsigned long gen_id
)
337 for (fsp
=sconn
->files
; fsp
; fsp
=fsp
->next
,count
++) {
338 /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */
339 if (file_id_equal(&fsp
->file_id
, &id
) &&
340 fsp
->fh
->gen_id
== gen_id
) {
342 DLIST_PROMOTE(sconn
->files
, fsp
);
344 /* Paranoia check. */
345 if ((fsp
->fh
->fd
== -1) &&
346 (fsp
->oplock_type
!= NO_OPLOCK
) &&
347 (fsp
->oplock_type
!= FAKE_LEVEL_II_OPLOCK
)) {
348 DEBUG(0,("file_find_dif: file %s file_id = "
349 "%s, gen = %u oplock_type = %u is a "
350 "stat open with oplock type !\n",
352 file_id_string_tos(&fsp
->file_id
),
353 (unsigned int)fsp
->fh
->gen_id
,
354 (unsigned int)fsp
->oplock_type
));
355 smb_panic("file_find_dif");
364 /****************************************************************************
365 Find the first fsp given a device and inode.
366 We use a singleton cache here to speed up searching from getfilepathinfo
368 ****************************************************************************/
370 files_struct
*file_find_di_first(struct smbd_server_connection
*sconn
,
375 if (file_id_equal(&sconn
->fsp_fi_cache
.id
, &id
)) {
376 /* Positive or negative cache hit. */
377 return sconn
->fsp_fi_cache
.fsp
;
380 sconn
->fsp_fi_cache
.id
= id
;
382 for (fsp
=sconn
->files
;fsp
;fsp
=fsp
->next
) {
383 if (file_id_equal(&fsp
->file_id
, &id
)) {
384 /* Setup positive cache. */
385 sconn
->fsp_fi_cache
.fsp
= fsp
;
390 /* Setup negative cache. */
391 sconn
->fsp_fi_cache
.fsp
= NULL
;
395 /****************************************************************************
396 Find the next fsp having the same device and inode.
397 ****************************************************************************/
399 files_struct
*file_find_di_next(files_struct
*start_fsp
)
403 for (fsp
= start_fsp
->next
;fsp
;fsp
=fsp
->next
) {
404 if (file_id_equal(&fsp
->file_id
, &start_fsp
->file_id
)) {
412 /****************************************************************************
413 Find any fsp open with a pathname below that of an already open path.
414 ****************************************************************************/
416 bool file_find_subpath(files_struct
*dir_fsp
)
420 char *d_fullname
= NULL
;
422 d_fullname
= talloc_asprintf(talloc_tos(), "%s/%s",
423 dir_fsp
->conn
->connectpath
,
424 dir_fsp
->fsp_name
->base_name
);
430 dlen
= strlen(d_fullname
);
432 for (fsp
=dir_fsp
->conn
->sconn
->files
; fsp
; fsp
=fsp
->next
) {
435 if (fsp
== dir_fsp
) {
439 d1_fullname
= talloc_asprintf(talloc_tos(),
441 fsp
->conn
->connectpath
,
442 fsp
->fsp_name
->base_name
);
445 * If the open file has a path that is a longer
446 * component, then it's a subpath.
448 if (strnequal(d_fullname
, d1_fullname
, dlen
) &&
449 (d1_fullname
[dlen
] == '/')) {
450 TALLOC_FREE(d1_fullname
);
451 TALLOC_FREE(d_fullname
);
454 TALLOC_FREE(d1_fullname
);
457 TALLOC_FREE(d_fullname
);
461 /****************************************************************************
462 Sync open files on a connection.
463 ****************************************************************************/
465 void file_sync_all(connection_struct
*conn
)
467 files_struct
*fsp
, *next
;
469 for (fsp
=conn
->sconn
->files
; fsp
; fsp
=next
) {
471 if ((conn
== fsp
->conn
) && (fsp
->fh
->fd
!= -1)) {
472 sync_file(conn
, fsp
, True
/* write through */);
477 /****************************************************************************
479 ****************************************************************************/
481 void file_free(struct smb_request
*req
, files_struct
*fsp
)
483 struct smbd_server_connection
*sconn
= fsp
->conn
->sconn
;
485 DLIST_REMOVE(sconn
->files
, fsp
);
486 SMB_ASSERT(sconn
->num_files
> 0);
489 TALLOC_FREE(fsp
->fake_file_handle
);
491 if (fsp
->fh
->ref_count
== 1) {
492 TALLOC_FREE(fsp
->fh
);
494 fsp
->fh
->ref_count
--;
498 struct notify_context
*notify_ctx
=
499 fsp
->conn
->sconn
->notify_ctx
;
500 notify_remove(notify_ctx
, fsp
);
501 TALLOC_FREE(fsp
->notify
);
504 /* Ensure this event will never fire. */
505 TALLOC_FREE(fsp
->update_write_time_event
);
507 if (sconn
->file_bmap
!= NULL
) {
508 bitmap_clear(sconn
->file_bmap
, fsp
->fnum
- FILE_HANDLE_OFFSET
);
510 DEBUG(5,("freed files structure %d (%u used)\n",
511 fsp
->fnum
, (unsigned int)sconn
->num_files
));
513 fsp
->conn
->num_files_open
--;
515 if ((req
!= NULL
) && (fsp
== req
->chain_fsp
)) {
516 req
->chain_fsp
= NULL
;
520 * Clear all possible chained fsp
521 * pointers in the SMB2 request queue.
523 if (req
!= NULL
&& req
->smb2req
) {
524 remove_smb2_chained_fsp(fsp
);
527 /* Closing a file can invalidate the positive cache. */
528 if (fsp
== sconn
->fsp_fi_cache
.fsp
) {
529 ZERO_STRUCT(sconn
->fsp_fi_cache
);
532 /* Drop all remaining extensions. */
533 vfs_remove_all_fsp_extensions(fsp
);
535 /* this is paranoia, just in case someone tries to reuse the
539 /* fsp->fsp_name is a talloc child and is free'd automatically. */
543 /****************************************************************************
544 Get an fsp from a 16 bit fnum.
545 ****************************************************************************/
547 static struct files_struct
*file_fnum(struct smbd_server_connection
*sconn
,
553 for (fsp
=sconn
->files
; fsp
; fsp
=fsp
->next
, count
++) {
554 if (fsp
->fnum
== -1) {
558 if (fsp
->fnum
== fnum
) {
560 DLIST_PROMOTE(sconn
->files
, fsp
);
568 /****************************************************************************
569 Get an fsp from a packet given a 16 bit fnum.
570 ****************************************************************************/
572 files_struct
*file_fsp(struct smb_request
*req
, uint16 fid
)
578 * We should never get here. req==NULL could in theory
579 * only happen from internal opens with a non-zero
580 * root_dir_fid. Internal opens just don't do that, at
581 * least they are not supposed to do so. And if they
582 * start to do so, they better fake up a smb_request
583 * from which we get the right smbd_server_conn. While
584 * this should never happen, let's return NULL here.
589 if (req
->chain_fsp
!= NULL
) {
590 return req
->chain_fsp
;
593 fsp
= file_fnum(req
->sconn
, fid
);
595 req
->chain_fsp
= fsp
;
600 uint64_t fsp_persistent_id(const struct files_struct
*fsp
)
602 uint64_t persistent_id
;
605 * This calculates a number that is most likely
606 * globally unique. In future we will have a database
607 * to make it completely unique.
609 * 32-bit random gen_id
610 * 16-bit truncated open_time
611 * 16-bit fnum (valatile_id)
613 persistent_id
= fsp
->fh
->gen_id
& UINT32_MAX
;
614 persistent_id
<<= 16;
615 persistent_id
&= 0x0000FFFFFFFF0000LLU
;
616 persistent_id
|= fsp
->open_time
.tv_usec
& UINT16_MAX
;
617 persistent_id
<<= 16;
618 persistent_id
&= 0xFFFFFFFFFFFF0000LLU
;
619 persistent_id
|= fsp
->fnum
& UINT16_MAX
;
621 return persistent_id
;
624 struct files_struct
*file_fsp_smb2(struct smbd_smb2_request
*smb2req
,
625 uint64_t persistent_id
,
626 uint64_t volatile_id
)
628 struct files_struct
*fsp
;
629 uint64_t fsp_persistent
;
631 if (smb2req
->compat_chain_fsp
!= NULL
) {
632 return smb2req
->compat_chain_fsp
;
635 if (volatile_id
> UINT16_MAX
) {
639 fsp
= file_fnum(smb2req
->sconn
, (uint16_t)volatile_id
);
643 fsp_persistent
= fsp_persistent_id(fsp
);
645 if (persistent_id
!= fsp_persistent
) {
649 if (smb2req
->tcon
== NULL
) {
653 if (smb2req
->tcon
->compat_conn
!= fsp
->conn
) {
657 if (smb2req
->session
== NULL
) {
661 if (smb2req
->session
->vuid
!= fsp
->vuid
) {
665 smb2req
->compat_chain_fsp
= fsp
;
669 /****************************************************************************
670 Duplicate the file handle part for a DOS or FCB open.
671 ****************************************************************************/
673 NTSTATUS
dup_file_fsp(struct smb_request
*req
, files_struct
*from
,
674 uint32 access_mask
, uint32 share_access
,
675 uint32 create_options
, files_struct
*to
)
677 /* this can never happen for print files */
678 SMB_ASSERT(from
->print_file
== NULL
);
685 to
->file_id
= from
->file_id
;
686 to
->initial_allocation_size
= from
->initial_allocation_size
;
687 to
->file_pid
= from
->file_pid
;
688 to
->vuid
= from
->vuid
;
689 to
->open_time
= from
->open_time
;
690 to
->access_mask
= access_mask
;
691 to
->share_access
= share_access
;
692 to
->oplock_type
= from
->oplock_type
;
693 to
->can_lock
= from
->can_lock
;
694 to
->can_read
= ((access_mask
& FILE_READ_DATA
) != 0);
696 CAN_WRITE(from
->conn
) &&
697 ((access_mask
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0);
698 to
->modified
= from
->modified
;
699 to
->is_directory
= from
->is_directory
;
700 to
->aio_write_behind
= from
->aio_write_behind
;
702 return fsp_set_smb_fname(to
, from
->fsp_name
);
706 * Return a jenkins hash of a pathname on a connection.
709 NTSTATUS
file_name_hash(connection_struct
*conn
,
710 const char *name
, uint32_t *p_name_hash
)
712 char *fullpath
= NULL
;
714 /* Set the hash of the full pathname. */
715 fullpath
= talloc_asprintf(talloc_tos(),
720 return NT_STATUS_NO_MEMORY
;
722 *p_name_hash
= hash(fullpath
, talloc_get_size(fullpath
), 0);
724 DEBUG(10,("file_name_hash: %s hash 0x%x\n",
726 (unsigned int)*p_name_hash
));
728 TALLOC_FREE(fullpath
);
733 * The only way that the fsp->fsp_name field should ever be set.
735 NTSTATUS
fsp_set_smb_fname(struct files_struct
*fsp
,
736 const struct smb_filename
*smb_fname_in
)
739 struct smb_filename
*smb_fname_new
;
741 status
= copy_smb_filename(fsp
, smb_fname_in
, &smb_fname_new
);
742 if (!NT_STATUS_IS_OK(status
)) {
746 TALLOC_FREE(fsp
->fsp_name
);
747 fsp
->fsp_name
= smb_fname_new
;
749 return file_name_hash(fsp
->conn
,
750 smb_fname_str_dbg(fsp
->fsp_name
),