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"
26 #define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < real_max_open_files))
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 /* we want to give out file handles differently on each new
70 connection because of a common bug in MS clients where they try to
71 reuse a file descriptor from an earlier smb connection. This code
72 increases the chance that the errant client will get an error rather
73 than causing corruption */
74 if (sconn
->first_file
== 0) {
75 sconn
->first_file
= (sys_getpid() ^ (int)time(NULL
));
76 sconn
->first_file
%= sconn
->real_max_open_files
;
79 /* TODO: Port the id-tree implementation from Samba4 */
81 i
= bitmap_find(sconn
->file_bmap
, sconn
->first_file
);
83 DEBUG(0,("ERROR! Out of file structures\n"));
84 /* TODO: We have to unconditionally return a DOS error here,
85 * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with
86 * NTSTATUS negotiated */
87 return NT_STATUS_TOO_MANY_OPENED_FILES
;
91 * Make a child of the connection_struct as an fsp can't exist
92 * independent of a connection.
94 fsp
= talloc_zero(conn
, struct files_struct
);
96 return NT_STATUS_NO_MEMORY
;
100 * This can't be a child of fsp because the file_handle can be ref'd
101 * when doing a dos/fcb open, which will then share the file_handle
102 * across multiple fsps.
104 fsp
->fh
= talloc_zero(conn
, struct fd_handle
);
107 return NT_STATUS_NO_MEMORY
;
110 fsp
->fh
->ref_count
= 1;
114 fsp
->fh
->gen_id
= get_gen_count(sconn
);
115 GetTimeOfDay(&fsp
->open_time
);
117 sconn
->first_file
= (i
+1) % (sconn
->real_max_open_files
);
119 bitmap_set(sconn
->file_bmap
, i
);
120 sconn
->files_used
+= 1;
122 fsp
->fnum
= i
+ FILE_HANDLE_OFFSET
;
123 SMB_ASSERT(fsp
->fnum
< 65536);
126 * Create an smb_filename with "" for the base_name. There are very
127 * few NULL checks, so make sure it's initialized with something. to
128 * be safe until an audit can be done.
130 status
= create_synthetic_smb_fname(fsp
, "", NULL
, NULL
,
132 if (!NT_STATUS_IS_OK(status
)) {
134 TALLOC_FREE(fsp
->fh
);
137 DLIST_ADD(sconn
->files
, fsp
);
139 DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
140 i
, fsp
->fnum
, sconn
->files_used
));
143 req
->chain_fsp
= fsp
;
146 /* A new fsp invalidates the positive and
147 negative fsp_fi_cache as the new fsp is pushed
148 at the start of the list and we search from
149 a cache hit to the *end* of the list. */
151 ZERO_STRUCT(sconn
->fsp_fi_cache
);
153 conn
->num_files_open
++;
159 /****************************************************************************
160 Close all open files for a connection.
161 ****************************************************************************/
163 void file_close_conn(connection_struct
*conn
)
165 files_struct
*fsp
, *next
;
167 for (fsp
=conn
->sconn
->files
; fsp
; fsp
=next
) {
169 if (fsp
->conn
== conn
) {
170 close_file(NULL
, fsp
, SHUTDOWN_CLOSE
);
175 /****************************************************************************
176 Close all open files for a pid and a vuid.
177 ****************************************************************************/
179 void file_close_pid(struct smbd_server_connection
*sconn
, uint16 smbpid
,
182 files_struct
*fsp
, *next
;
184 for (fsp
=sconn
->files
;fsp
;fsp
=next
) {
186 if ((fsp
->file_pid
== smbpid
) && (fsp
->vuid
== vuid
)) {
187 close_file(NULL
, fsp
, SHUTDOWN_CLOSE
);
192 /****************************************************************************
193 Initialise file structures.
194 ****************************************************************************/
196 bool file_init(struct smbd_server_connection
*sconn
)
198 int request_max_open_files
= lp_max_open_files();
202 * Set the max_open files to be the requested
203 * max plus a fudgefactor to allow for the extra
204 * fd's we need such as log files etc...
206 real_lim
= set_maxfiles(request_max_open_files
+ MAX_OPEN_FUDGEFACTOR
);
208 sconn
->real_max_open_files
= real_lim
- MAX_OPEN_FUDGEFACTOR
;
210 if (sconn
->real_max_open_files
+ FILE_HANDLE_OFFSET
+ MAX_OPEN_PIPES
212 sconn
->real_max_open_files
=
213 65536 - FILE_HANDLE_OFFSET
- MAX_OPEN_PIPES
;
215 if(sconn
->real_max_open_files
!= request_max_open_files
) {
216 DEBUG(1, ("file_init: Information only: requested %d "
217 "open files, %d are available.\n",
218 request_max_open_files
, sconn
->real_max_open_files
));
221 SMB_ASSERT(sconn
->real_max_open_files
> 100);
223 sconn
->file_bmap
= bitmap_talloc(sconn
, sconn
->real_max_open_files
);
225 if (!sconn
->file_bmap
) {
231 /****************************************************************************
232 Close files open by a specified vuid.
233 ****************************************************************************/
235 void file_close_user(struct smbd_server_connection
*sconn
, int vuid
)
237 files_struct
*fsp
, *next
;
239 for (fsp
=sconn
->files
; fsp
; fsp
=next
) {
241 if (fsp
->vuid
== vuid
) {
242 close_file(NULL
, fsp
, SHUTDOWN_CLOSE
);
248 * Walk the files table until "fn" returns non-NULL
251 struct files_struct
*files_forall(
252 struct smbd_server_connection
*sconn
,
253 struct files_struct
*(*fn
)(struct files_struct
*fsp
,
257 struct files_struct
*fsp
, *next
;
259 for (fsp
= sconn
->files
; fsp
; fsp
= next
) {
260 struct files_struct
*ret
;
262 ret
= fn(fsp
, private_data
);
270 /****************************************************************************
271 Find a fsp given a file descriptor.
272 ****************************************************************************/
274 files_struct
*file_find_fd(struct smbd_server_connection
*sconn
, int fd
)
279 for (fsp
=sconn
->files
; fsp
; fsp
=fsp
->next
,count
++) {
280 if (fsp
->fh
->fd
== fd
) {
282 DLIST_PROMOTE(sconn
->files
, fsp
);
291 /****************************************************************************
292 Find a fsp given a device, inode and file_id.
293 ****************************************************************************/
295 files_struct
*file_find_dif(struct smbd_server_connection
*sconn
,
296 struct file_id id
, unsigned long gen_id
)
305 for (fsp
=sconn
->files
; fsp
; fsp
=fsp
->next
,count
++) {
306 /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */
307 if (file_id_equal(&fsp
->file_id
, &id
) &&
308 fsp
->fh
->gen_id
== gen_id
) {
310 DLIST_PROMOTE(sconn
->files
, fsp
);
312 /* Paranoia check. */
313 if ((fsp
->fh
->fd
== -1) &&
314 (fsp
->oplock_type
!= NO_OPLOCK
) &&
315 (fsp
->oplock_type
!= FAKE_LEVEL_II_OPLOCK
)) {
316 DEBUG(0,("file_find_dif: file %s file_id = "
317 "%s, gen = %u oplock_type = %u is a "
318 "stat open with oplock type !\n",
320 file_id_string_tos(&fsp
->file_id
),
321 (unsigned int)fsp
->fh
->gen_id
,
322 (unsigned int)fsp
->oplock_type
));
323 smb_panic("file_find_dif");
332 /****************************************************************************
333 Find the first fsp given a device and inode.
334 We use a singleton cache here to speed up searching from getfilepathinfo
336 ****************************************************************************/
338 files_struct
*file_find_di_first(struct smbd_server_connection
*sconn
,
343 if (file_id_equal(&sconn
->fsp_fi_cache
.id
, &id
)) {
344 /* Positive or negative cache hit. */
345 return sconn
->fsp_fi_cache
.fsp
;
348 sconn
->fsp_fi_cache
.id
= id
;
350 for (fsp
=sconn
->files
;fsp
;fsp
=fsp
->next
) {
351 if (file_id_equal(&fsp
->file_id
, &id
)) {
352 /* Setup positive cache. */
353 sconn
->fsp_fi_cache
.fsp
= fsp
;
358 /* Setup negative cache. */
359 sconn
->fsp_fi_cache
.fsp
= NULL
;
363 /****************************************************************************
364 Find the next fsp having the same device and inode.
365 ****************************************************************************/
367 files_struct
*file_find_di_next(files_struct
*start_fsp
)
371 for (fsp
= start_fsp
->next
;fsp
;fsp
=fsp
->next
) {
372 if (file_id_equal(&fsp
->file_id
, &start_fsp
->file_id
)) {
380 /****************************************************************************
381 Find any fsp open with a pathname below that of an already open path.
382 ****************************************************************************/
384 bool file_find_subpath(files_struct
*dir_fsp
)
388 char *d_fullname
= NULL
;
390 d_fullname
= talloc_asprintf(talloc_tos(), "%s/%s",
391 dir_fsp
->conn
->connectpath
,
392 dir_fsp
->fsp_name
->base_name
);
398 dlen
= strlen(d_fullname
);
400 for (fsp
=dir_fsp
->conn
->sconn
->files
; fsp
; fsp
=fsp
->next
) {
403 if (fsp
== dir_fsp
) {
407 d1_fullname
= talloc_asprintf(talloc_tos(),
409 fsp
->conn
->connectpath
,
410 fsp
->fsp_name
->base_name
);
413 * If the open file has a path that is a longer
414 * component, then it's a subpath.
416 if (strnequal(d_fullname
, d1_fullname
, dlen
) &&
417 (d1_fullname
[dlen
] == '/')) {
418 TALLOC_FREE(d1_fullname
);
419 TALLOC_FREE(d_fullname
);
422 TALLOC_FREE(d1_fullname
);
425 TALLOC_FREE(d_fullname
);
429 /****************************************************************************
430 Sync open files on a connection.
431 ****************************************************************************/
433 void file_sync_all(connection_struct
*conn
)
435 files_struct
*fsp
, *next
;
437 for (fsp
=conn
->sconn
->files
; fsp
; fsp
=next
) {
439 if ((conn
== fsp
->conn
) && (fsp
->fh
->fd
!= -1)) {
440 sync_file(conn
, fsp
, True
/* write through */);
445 /****************************************************************************
447 ****************************************************************************/
449 void file_free(struct smb_request
*req
, files_struct
*fsp
)
451 struct smbd_server_connection
*sconn
= fsp
->conn
->sconn
;
453 DLIST_REMOVE(sconn
->files
, fsp
);
455 TALLOC_FREE(fsp
->fake_file_handle
);
457 if (fsp
->fh
->ref_count
== 1) {
458 TALLOC_FREE(fsp
->fh
);
460 fsp
->fh
->ref_count
--;
464 if (fsp
->is_directory
) {
465 notify_remove_onelevel(fsp
->conn
->notify_ctx
,
468 notify_remove(fsp
->conn
->notify_ctx
, fsp
);
469 TALLOC_FREE(fsp
->notify
);
472 /* Ensure this event will never fire. */
473 TALLOC_FREE(fsp
->oplock_timeout
);
475 /* Ensure this event will never fire. */
476 TALLOC_FREE(fsp
->update_write_time_event
);
478 bitmap_clear(sconn
->file_bmap
, fsp
->fnum
- FILE_HANDLE_OFFSET
);
481 DEBUG(5,("freed files structure %d (%d used)\n",
482 fsp
->fnum
, sconn
->files_used
));
484 fsp
->conn
->num_files_open
--;
486 if ((req
!= NULL
) && (fsp
== req
->chain_fsp
)) {
487 req
->chain_fsp
= NULL
;
491 * Clear all possible chained fsp
492 * pointers in the SMB2 request queue.
494 if (req
!= NULL
&& req
->smb2req
) {
495 remove_smb2_chained_fsp(fsp
);
498 /* Closing a file can invalidate the positive cache. */
499 if (fsp
== sconn
->fsp_fi_cache
.fsp
) {
500 ZERO_STRUCT(sconn
->fsp_fi_cache
);
503 /* Drop all remaining extensions. */
504 while (fsp
->vfs_extension
) {
505 vfs_remove_fsp_extension(fsp
->vfs_extension
->owner
, fsp
);
508 /* this is paranoia, just in case someone tries to reuse the
512 /* fsp->fsp_name is a talloc child and is free'd automatically. */
516 /****************************************************************************
517 Get an fsp from a 16 bit fnum.
518 ****************************************************************************/
520 static struct files_struct
*file_fnum(struct smbd_server_connection
*sconn
,
526 for (fsp
=sconn
->files
; fsp
; fsp
=fsp
->next
, count
++) {
527 if (fsp
->fnum
== fnum
) {
529 DLIST_PROMOTE(sconn
->files
, fsp
);
537 /****************************************************************************
538 Get an fsp from a packet given a 16 bit fnum.
539 ****************************************************************************/
541 files_struct
*file_fsp(struct smb_request
*req
, uint16 fid
)
547 * We should never get here. req==NULL could in theory
548 * only happen from internal opens with a non-zero
549 * root_dir_fid. Internal opens just don't do that, at
550 * least they are not supposed to do so. And if they
551 * start to do so, they better fake up a smb_request
552 * from which we get the right smbd_server_conn. While
553 * this should never happen, let's return NULL here.
558 if (req
->chain_fsp
!= NULL
) {
559 return req
->chain_fsp
;
562 fsp
= file_fnum(req
->sconn
, fid
);
564 req
->chain_fsp
= fsp
;
569 uint64_t fsp_persistent_id(const struct files_struct
*fsp
)
571 uint64_t persistent_id
;
574 * This calculates a number that is most likely
575 * globally unique. In future we will have a database
576 * to make it completely unique.
578 * 32-bit random gen_id
579 * 16-bit truncated open_time
580 * 16-bit fnum (valatile_id)
582 persistent_id
= fsp
->fh
->gen_id
& UINT32_MAX
;
583 persistent_id
<<= 16;
584 persistent_id
&= 0x0000FFFFFFFF0000LLU
;
585 persistent_id
|= fsp
->open_time
.tv_usec
& UINT16_MAX
;
586 persistent_id
<<= 16;
587 persistent_id
&= 0xFFFFFFFFFFFF0000LLU
;
588 persistent_id
|= fsp
->fnum
& UINT16_MAX
;
590 return persistent_id
;
593 struct files_struct
*file_fsp_smb2(struct smbd_smb2_request
*smb2req
,
594 uint64_t persistent_id
,
595 uint64_t volatile_id
)
597 struct files_struct
*fsp
;
598 uint64_t fsp_persistent
;
600 if (smb2req
->compat_chain_fsp
!= NULL
) {
601 return smb2req
->compat_chain_fsp
;
604 if (volatile_id
> UINT16_MAX
) {
608 fsp
= file_fnum(smb2req
->sconn
, (uint16_t)volatile_id
);
612 fsp_persistent
= fsp_persistent_id(fsp
);
614 if (persistent_id
!= fsp_persistent
) {
618 if (smb2req
->tcon
== NULL
) {
622 if (smb2req
->tcon
->compat_conn
!= fsp
->conn
) {
626 if (smb2req
->session
== NULL
) {
630 if (smb2req
->session
->vuid
!= fsp
->vuid
) {
634 smb2req
->compat_chain_fsp
= fsp
;
638 /****************************************************************************
639 Duplicate the file handle part for a DOS or FCB open.
640 ****************************************************************************/
642 NTSTATUS
dup_file_fsp(struct smb_request
*req
, files_struct
*from
,
643 uint32 access_mask
, uint32 share_access
,
644 uint32 create_options
, files_struct
*to
)
651 to
->file_id
= from
->file_id
;
652 to
->initial_allocation_size
= from
->initial_allocation_size
;
653 to
->mode
= from
->mode
;
654 to
->file_pid
= from
->file_pid
;
655 to
->vuid
= from
->vuid
;
656 to
->open_time
= from
->open_time
;
657 to
->access_mask
= access_mask
;
658 to
->share_access
= share_access
;
659 to
->oplock_type
= from
->oplock_type
;
660 to
->can_lock
= from
->can_lock
;
661 to
->can_read
= (access_mask
& (FILE_READ_DATA
)) ? True
: False
;
662 if (!CAN_WRITE(from
->conn
)) {
663 to
->can_write
= False
;
665 to
->can_write
= (access_mask
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) ? True
: False
;
667 to
->modified
= from
->modified
;
668 to
->is_directory
= from
->is_directory
;
669 to
->aio_write_behind
= from
->aio_write_behind
;
671 if (from
->print_file
) {
672 to
->print_file
= talloc(to
, struct print_file_data
);
673 if (!to
->print_file
) return NT_STATUS_NO_MEMORY
;
674 to
->print_file
->rap_jobid
= from
->print_file
->rap_jobid
;
676 to
->print_file
= NULL
;
679 return fsp_set_smb_fname(to
, from
->fsp_name
);
683 * Return a jenkins hash of a pathname on a connection.
686 NTSTATUS
file_name_hash(connection_struct
*conn
,
687 const char *name
, uint32_t *p_name_hash
)
690 char *fullpath
= NULL
;
692 /* Set the hash of the full pathname. */
693 fullpath
= talloc_asprintf(talloc_tos(),
698 return NT_STATUS_NO_MEMORY
;
700 key
= string_term_tdb_data(fullpath
);
701 *p_name_hash
= tdb_jenkins_hash(&key
);
703 DEBUG(10,("file_name_hash: %s hash 0x%x\n",
705 (unsigned int)*p_name_hash
));
707 TALLOC_FREE(fullpath
);
712 * The only way that the fsp->fsp_name field should ever be set.
714 NTSTATUS
fsp_set_smb_fname(struct files_struct
*fsp
,
715 const struct smb_filename
*smb_fname_in
)
718 struct smb_filename
*smb_fname_new
;
720 status
= copy_smb_filename(fsp
, smb_fname_in
, &smb_fname_new
);
721 if (!NT_STATUS_IS_OK(status
)) {
725 TALLOC_FREE(fsp
->fsp_name
);
726 fsp
->fsp_name
= smb_fname_new
;
728 return file_name_hash(fsp
->conn
,
729 smb_fname_str_dbg(fsp
->fsp_name
),