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 "smbd/smbXsrv_open.h"
24 #include "libcli/security/security.h"
26 #include "lib/util/bitmap.h"
28 #define FILE_HANDLE_OFFSET 0x1000
30 static NTSTATUS
fsp_attach_smb_fname(struct files_struct
*fsp
,
31 struct smb_filename
**_smb_fname
);
34 * create new fsp to be used for file_new or a durable handle reconnect
36 NTSTATUS
fsp_new(struct connection_struct
*conn
, TALLOC_CTX
*mem_ctx
,
37 files_struct
**result
)
39 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
40 files_struct
*fsp
= NULL
;
41 struct smbd_server_connection
*sconn
= conn
->sconn
;
43 fsp
= talloc_zero(mem_ctx
, struct files_struct
);
49 * This can't be a child of fsp because the file_handle can be ref'd
50 * when doing a dos/fcb open, which will then share the file_handle
51 * across multiple fsps.
53 fsp
->fh
= fd_handle_create(mem_ctx
);
54 if (fsp
->fh
== NULL
) {
58 fsp
->fsp_flags
.use_ofd_locks
= !lp_smbd_force_process_locks(SNUM(conn
));
59 #ifndef HAVE_OFD_LOCKS
60 fsp
->fsp_flags
.use_ofd_locks
= false;
63 fh_set_refcount(fsp
->fh
, 1);
66 fsp
->fnum
= FNUM_FIELD_INVALID
;
68 fsp
->close_write_time
= make_omit_timespec();
70 DLIST_ADD(sconn
->files
, fsp
);
71 sconn
->num_files
+= 1;
73 conn
->num_files_open
++;
75 DBG_INFO("allocated files structure (%u used)\n",
76 (unsigned int)sconn
->num_files
);
90 void fsp_set_gen_id(files_struct
*fsp
)
92 static uint64_t gen_id
= 1;
95 * A billion of 64-bit increments per second gives us
96 * more than 500 years of runtime without wrap.
99 fh_set_gen_id(fsp
->fh
, gen_id
);
102 /****************************************************************************
103 Find first available file slot.
104 ****************************************************************************/
106 NTSTATUS
fsp_bind_smb(struct files_struct
*fsp
, struct smb_request
*req
)
108 struct smbXsrv_open
*op
= NULL
;
113 DBG_DEBUG("INTERNAL_OPEN_ONLY, skipping smbXsrv_open\n");
117 now
= timeval_to_nttime(&fsp
->open_time
);
119 status
= smbXsrv_open_create(req
->xconn
,
120 fsp
->conn
->session_info
,
123 if (!NT_STATUS_IS_OK(status
)) {
128 fsp
->fnum
= op
->local_id
;
131 req
->chain_fsp
= fsp
;
133 DBG_DEBUG("fsp [%s] mid [%" PRIu64
"]\n",
134 fsp_str_dbg(fsp
), fsp
->mid
);
139 NTSTATUS
file_new(struct smb_request
*req
, connection_struct
*conn
,
140 files_struct
**result
)
142 struct smbd_server_connection
*sconn
= conn
->sconn
;
146 status
= fsp_new(conn
, conn
, &fsp
);
147 if (!NT_STATUS_IS_OK(status
)) {
151 GetTimeOfDay(&fsp
->open_time
);
153 status
= fsp_bind_smb(fsp
, req
);
154 if (!NT_STATUS_IS_OK(status
)) {
155 file_free(NULL
, fsp
);
162 * Create an smb_filename with "" for the base_name. There are very
163 * few NULL checks, so make sure it's initialized with something. to
164 * be safe until an audit can be done.
166 fsp
->fsp_name
= synthetic_smb_fname(fsp
,
172 if (fsp
->fsp_name
== NULL
) {
173 file_free(NULL
, fsp
);
174 return NT_STATUS_NO_MEMORY
;
177 DBG_INFO("new file %s\n", fsp_fnum_dbg(fsp
));
179 /* A new fsp invalidates the positive and
180 negative fsp_fi_cache as the new fsp is pushed
181 at the start of the list and we search from
182 a cache hit to the *end* of the list. */
184 ZERO_STRUCT(sconn
->fsp_fi_cache
);
190 NTSTATUS
create_internal_fsp(connection_struct
*conn
,
191 const struct smb_filename
*smb_fname
,
192 struct files_struct
**_fsp
)
194 struct files_struct
*fsp
= NULL
;
197 status
= file_new(NULL
, conn
, &fsp
);
198 if (!NT_STATUS_IS_OK(status
)) {
202 status
= fsp_set_smb_fname(fsp
, smb_fname
);
203 if (!NT_STATUS_IS_OK(status
)) {
204 file_free(NULL
, fsp
);
213 * Create an internal fsp for an *existing* directory.
215 * This should only be used by callers in the VFS that need to control the
216 * opening of the directory. Otherwise use open_internal_dirfsp_at().
218 NTSTATUS
create_internal_dirfsp(connection_struct
*conn
,
219 const struct smb_filename
*smb_dname
,
220 struct files_struct
**_fsp
)
222 struct files_struct
*fsp
= NULL
;
225 status
= create_internal_fsp(conn
, smb_dname
, &fsp
);
226 if (!NT_STATUS_IS_OK(status
)) {
230 fsp
->access_mask
= FILE_LIST_DIRECTORY
;
231 fsp
->fsp_flags
.is_directory
= true;
232 fsp
->fsp_flags
.is_dirfsp
= true;
239 * Open an internal fsp for an *existing* directory.
241 NTSTATUS
open_internal_dirfsp(connection_struct
*conn
,
242 const struct smb_filename
*smb_dname
,
244 struct files_struct
**_fsp
)
246 struct files_struct
*fsp
= NULL
;
249 status
= create_internal_dirfsp(conn
, smb_dname
, &fsp
);
250 if (!NT_STATUS_IS_OK(status
)) {
255 open_flags
|= O_DIRECTORY
;
257 status
= fd_openat(conn
->cwd_fsp
, fsp
->fsp_name
, fsp
, open_flags
, 0);
258 if (!NT_STATUS_IS_OK(status
)) {
259 DBG_INFO("Could not open fd for %s (%s)\n",
260 smb_fname_str_dbg(smb_dname
),
262 file_free(NULL
, fsp
);
266 status
= vfs_stat_fsp(fsp
);
267 if (!NT_STATUS_IS_OK(status
)) {
268 file_free(NULL
, fsp
);
272 if (!S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
273 DBG_ERR("%s is not a directory!\n",
274 smb_fname_str_dbg(smb_dname
));
275 file_free(NULL
, fsp
);
276 return NT_STATUS_NOT_A_DIRECTORY
;
279 fsp
->file_id
= vfs_file_id_from_sbuf(conn
, &fsp
->fsp_name
->st
);
286 * Convert a pathref dirfsp into a real fsp. No need to do any cwd
287 * tricks, we just open ".".
289 NTSTATUS
openat_internal_dir_from_pathref(
290 struct files_struct
*dirfsp
,
292 struct files_struct
**_fsp
)
294 struct connection_struct
*conn
= dirfsp
->conn
;
295 struct smb_filename
*smb_dname
= dirfsp
->fsp_name
;
296 struct files_struct
*fsp
= NULL
;
298 struct smb_filename smb_dot
= {
300 .flags
= smb_dname
->flags
,
301 .twrp
= smb_dname
->twrp
,
305 status
= create_internal_dirfsp(conn
, smb_dname
, &fsp
);
306 if (!NT_STATUS_IS_OK(status
)) {
311 * Pointless for opening ".", but you never know...
313 open_flags
|= O_NOFOLLOW
;
315 status
= fd_openat(dirfsp
, &smb_dot
, fsp
, open_flags
, 0);
316 if (!NT_STATUS_IS_OK(status
)) {
317 DBG_INFO("fd_openat(\"%s\", \".\") failed: %s\n",
320 file_free(NULL
, fsp
);
324 fsp
->fsp_name
->st
= smb_dname
->st
;
325 fsp
->file_id
= vfs_file_id_from_sbuf(conn
, &fsp
->fsp_name
->st
);
331 * The "link" in the name doesn't imply link in the filesystem
332 * sense. It's a object that "links" together an fsp and an smb_fname
333 * and the link allocated as talloc child of an fsp.
335 * The link is created for fsps that openat_pathref_fsp() returns in
336 * smb_fname->fsp. When this fsp is freed by file_free() by some caller
337 * somewhere, the destructor fsp_smb_fname_link_destructor() on the link object
338 * will use the link to reset the reference in smb_fname->fsp that is about to
341 * This prevents smb_fname_internal_fsp_destructor() from seeing dangling fsp
345 struct fsp_smb_fname_link
{
346 struct fsp_smb_fname_link
**smb_fname_link
;
347 struct files_struct
**smb_fname_fsp
;
350 static int fsp_smb_fname_link_destructor(struct fsp_smb_fname_link
*link
)
352 if (link
->smb_fname_link
== NULL
) {
356 *link
->smb_fname_link
= NULL
;
357 *link
->smb_fname_fsp
= NULL
;
361 static NTSTATUS
fsp_smb_fname_link(struct files_struct
*fsp
,
362 struct fsp_smb_fname_link
**smb_fname_link
,
363 struct files_struct
**smb_fname_fsp
)
365 struct fsp_smb_fname_link
*link
= NULL
;
367 SMB_ASSERT(*smb_fname_link
== NULL
);
368 SMB_ASSERT(*smb_fname_fsp
== NULL
);
370 link
= talloc_zero(fsp
, struct fsp_smb_fname_link
);
372 return NT_STATUS_NO_MEMORY
;
375 link
->smb_fname_link
= smb_fname_link
;
376 link
->smb_fname_fsp
= smb_fname_fsp
;
377 *smb_fname_link
= link
;
378 *smb_fname_fsp
= fsp
;
380 talloc_set_destructor(link
, fsp_smb_fname_link_destructor
);
385 * Free a link, carefully avoiding to trigger the link destructor
387 static void destroy_fsp_smb_fname_link(struct fsp_smb_fname_link
**_link
)
389 struct fsp_smb_fname_link
*link
= *_link
;
394 talloc_set_destructor(link
, NULL
);
400 * Talloc destructor set on an smb_fname set by openat_pathref_fsp() used to
401 * close the embedded smb_fname->fsp.
403 static int smb_fname_fsp_destructor(struct smb_filename
*smb_fname
)
405 struct files_struct
*fsp
= smb_fname
->fsp
;
407 int saved_errno
= errno
;
409 destroy_fsp_smb_fname_link(&smb_fname
->fsp_link
);
416 if (fsp_is_alternate_stream(fsp
)) {
417 struct files_struct
*tmp_base_fsp
= fsp
->base_fsp
;
419 fsp_set_base_fsp(fsp
, NULL
);
421 status
= fd_close(tmp_base_fsp
);
422 if (!NT_STATUS_IS_OK(status
)) {
423 DBG_ERR("Closing fd for fsp [%s] failed: %s. "
424 "Please check your filesystem!!!\n",
425 fsp_str_dbg(fsp
), nt_errstr(status
));
427 file_free(NULL
, tmp_base_fsp
);
430 status
= fd_close(fsp
);
431 if (!NT_STATUS_IS_OK(status
)) {
432 DBG_ERR("Closing fd for fsp [%s] failed: %s. "
433 "Please check your filesystem!!!\n",
434 fsp_str_dbg(fsp
), nt_errstr(status
));
436 file_free(NULL
, fsp
);
437 smb_fname
->fsp
= NULL
;
443 static NTSTATUS
openat_pathref_fullname(
444 const struct files_struct
*dirfsp
,
445 struct smb_filename
**full_fname
,
446 struct smb_filename
*smb_fname
)
448 struct connection_struct
*conn
= dirfsp
->conn
;
449 struct files_struct
*fsp
= NULL
;
452 DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(smb_fname
));
454 SMB_ASSERT(smb_fname
->fsp
== NULL
);
456 status
= fsp_new(conn
, conn
, &fsp
);
457 if (!NT_STATUS_IS_OK(status
)) {
461 GetTimeOfDay(&fsp
->open_time
);
463 ZERO_STRUCT(conn
->sconn
->fsp_fi_cache
);
465 fsp
->fsp_flags
.is_pathref
= true;
467 status
= fsp_attach_smb_fname(fsp
, full_fname
);
468 if (!NT_STATUS_IS_OK(status
)) {
473 dirfsp
, smb_fname
, fsp
, O_RDONLY
|O_NONBLOCK
, 0);
474 if (!NT_STATUS_IS_OK(status
)) {
476 smb_fname
->st
= fsp
->fsp_name
->st
;
478 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
) ||
479 NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
) ||
480 NT_STATUS_EQUAL(status
, NT_STATUS_STOPPED_ON_SYMLINK
))
483 * streams_xattr return NT_STATUS_NOT_FOUND for
484 * opens of not yet existing streams.
486 * ELOOP maps to NT_STATUS_OBJECT_PATH_NOT_FOUND
487 * and this will result from a open request from
488 * a POSIX client on a symlink.
490 * NT_STATUS_OBJECT_NAME_NOT_FOUND is the simple
493 * NT_STATUS_STOPPED_ON_SYMLINK is returned when trying
494 * to open a symlink, our callers are not interested in
497 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
503 * fd_openat() has done an FSTAT on the handle
504 * so update the smb_fname stat info with "truth".
507 smb_fname
->st
= fsp
->fsp_name
->st
;
509 fsp
->fsp_flags
.is_directory
= S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
);
511 fsp
->file_id
= vfs_file_id_from_sbuf(conn
, &fsp
->fsp_name
->st
);
513 status
= fsp_smb_fname_link(fsp
,
514 &smb_fname
->fsp_link
,
516 if (!NT_STATUS_IS_OK(status
)) {
520 DBG_DEBUG("fsp [%s]: OK\n", fsp_str_dbg(fsp
));
522 talloc_set_destructor(smb_fname
, smb_fname_fsp_destructor
);
526 DBG_DEBUG("Opening pathref for [%s] failed: %s\n",
527 smb_fname_str_dbg(smb_fname
),
531 file_free(NULL
, fsp
);
536 * Open an internal O_PATH based fsp for smb_fname. If O_PATH is not
537 * available, open O_RDONLY as root. Both is done in fd_open() ->
538 * non_widelink_open(), triggered by setting fsp->fsp_flags.is_pathref to
541 NTSTATUS
openat_pathref_fsp(const struct files_struct
*dirfsp
,
542 struct smb_filename
*smb_fname
)
544 connection_struct
*conn
= dirfsp
->conn
;
545 struct smb_filename
*full_fname
= NULL
;
546 struct smb_filename
*base_fname
= NULL
;
549 DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(smb_fname
));
551 if (smb_fname
->fsp
!= NULL
) {
552 /* We already have one for this name. */
553 DBG_DEBUG("smb_fname [%s] already has a pathref fsp.\n",
554 smb_fname_str_dbg(smb_fname
));
558 if (!(conn
->fs_capabilities
& FILE_NAMED_STREAMS
) ||
559 !is_named_stream(smb_fname
)) {
561 * openat_pathref_fullname() will make "full_fname" a
562 * talloc child of the smb_fname->fsp. Don't use
563 * talloc_tos() to allocate it to avoid making the
564 * talloc stackframe pool long-lived.
566 full_fname
= full_path_from_dirfsp_atname(
570 if (full_fname
== NULL
) {
571 status
= NT_STATUS_NO_MEMORY
;
574 status
= openat_pathref_fullname(
575 dirfsp
, &full_fname
, smb_fname
);
576 TALLOC_FREE(full_fname
);
583 base_fname
= cp_smb_filename_nostream(conn
, smb_fname
);
584 if (base_fname
== NULL
) {
585 return NT_STATUS_NO_MEMORY
;
588 full_fname
= full_path_from_dirfsp_atname(
589 conn
, /* no talloc_tos(), see comment above */
592 if (full_fname
== NULL
) {
593 status
= NT_STATUS_NO_MEMORY
;
597 status
= openat_pathref_fullname(
598 dirfsp
, &full_fname
, base_fname
);
599 TALLOC_FREE(full_fname
);
600 if (!NT_STATUS_IS_OK(status
)) {
601 DBG_DEBUG("openat_pathref_nostream failed: %s\n",
606 status
= open_stream_pathref_fsp(&base_fname
->fsp
, smb_fname
);
607 if (!NT_STATUS_IS_OK(status
)) {
608 DBG_DEBUG("open_stream_pathref_fsp failed: %s\n",
613 smb_fname_fsp_unlink(base_fname
);
615 TALLOC_FREE(base_fname
);
620 * Open a stream given an already opened base_fsp. Avoid
621 * non_widelink_open: This is only valid for the case where we have a
622 * valid non-cwd_fsp dirfsp that we can pass to SMB_VFS_OPENAT()
624 NTSTATUS
open_stream_pathref_fsp(
625 struct files_struct
**_base_fsp
,
626 struct smb_filename
*smb_fname
)
628 struct files_struct
*base_fsp
= *_base_fsp
;
629 connection_struct
*conn
= base_fsp
->conn
;
630 struct smb_filename
*base_fname
= base_fsp
->fsp_name
;
631 struct smb_filename
*full_fname
= NULL
;
632 struct files_struct
*fsp
= NULL
;
636 SMB_ASSERT(smb_fname
->fsp
== NULL
);
637 SMB_ASSERT(is_named_stream(smb_fname
));
639 status
= fsp_new(conn
, conn
, &fsp
);
640 if (!NT_STATUS_IS_OK(status
)) {
644 GetTimeOfDay(&fsp
->open_time
);
646 ZERO_STRUCT(conn
->sconn
->fsp_fi_cache
);
648 fsp
->fsp_flags
.is_pathref
= true;
650 full_fname
= synthetic_smb_fname(
652 base_fname
->base_name
,
653 smb_fname
->stream_name
,
657 if (full_fname
== NULL
) {
658 status
= NT_STATUS_NO_MEMORY
;
662 status
= fsp_attach_smb_fname(fsp
, &full_fname
);
663 if (!NT_STATUS_IS_OK(status
)) {
667 fsp_set_base_fsp(fsp
, *_base_fsp
);
670 * non_widelink_open() not required: See the asserts above,
671 * this will only open the stream relative to.
676 NULL
, /* stream open is relative to fsp->base_fsp */
684 status
= map_nt_error_from_unix(errno
);
685 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
686 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
691 ret
= SMB_VFS_FSTAT(fsp
, &fsp
->fsp_name
->st
);
693 status
= map_nt_error_from_unix(errno
);
697 smb_fname
->st
= fsp
->fsp_name
->st
;
699 fsp
->fsp_flags
.is_directory
= false; /* streams can't be a directory */
700 fsp
->file_id
= vfs_file_id_from_sbuf(conn
, &fsp
->fsp_name
->st
);
702 status
= fsp_smb_fname_link(fsp
,
703 &smb_fname
->fsp_link
,
705 if (!NT_STATUS_IS_OK(status
)) {
709 DBG_DEBUG("fsp [%s]: OK\n", fsp_str_dbg(fsp
));
711 talloc_set_destructor(smb_fname
, smb_fname_fsp_destructor
);
716 fsp_set_base_fsp(fsp
, NULL
);
718 file_free(NULL
, fsp
);
723 void smb_fname_fsp_unlink(struct smb_filename
*smb_fname
)
725 talloc_set_destructor(smb_fname
, NULL
);
726 smb_fname
->fsp
= NULL
;
727 destroy_fsp_smb_fname_link(&smb_fname
->fsp_link
);
731 * Move any existing embedded fsp refs from the src name to the
732 * destination. It's safe to call this on src smb_fname's that have no embedded
735 NTSTATUS
move_smb_fname_fsp_link(struct smb_filename
*smb_fname_dst
,
736 struct smb_filename
*smb_fname_src
)
741 * The target should always not be linked yet!
743 SMB_ASSERT(smb_fname_dst
->fsp
== NULL
);
744 SMB_ASSERT(smb_fname_dst
->fsp_link
== NULL
);
746 if (smb_fname_src
->fsp
== NULL
) {
750 status
= fsp_smb_fname_link(smb_fname_src
->fsp
,
751 &smb_fname_dst
->fsp_link
,
752 &smb_fname_dst
->fsp
);
753 if (!NT_STATUS_IS_OK(status
)) {
757 talloc_set_destructor(smb_fname_dst
, smb_fname_fsp_destructor
);
759 smb_fname_fsp_unlink(smb_fname_src
);
765 * Create an smb_fname and open smb_fname->fsp pathref
767 NTSTATUS
synthetic_pathref(TALLOC_CTX
*mem_ctx
,
768 struct files_struct
*dirfsp
,
769 const char *base_name
,
770 const char *stream_name
,
771 const SMB_STRUCT_STAT
*psbuf
,
774 struct smb_filename
**_smb_fname
)
776 struct smb_filename
*smb_fname
= NULL
;
779 smb_fname
= synthetic_smb_fname(mem_ctx
,
785 if (smb_fname
== NULL
) {
786 return NT_STATUS_NO_MEMORY
;
789 status
= openat_pathref_fsp(dirfsp
, smb_fname
);
790 if (!NT_STATUS_IS_OK(status
)) {
791 DBG_ERR("opening [%s] failed\n",
792 smb_fname_str_dbg(smb_fname
));
793 TALLOC_FREE(smb_fname
);
797 *_smb_fname
= smb_fname
;
801 static int atname_destructor(struct smb_filename
*smb_fname
)
803 destroy_fsp_smb_fname_link(&smb_fname
->fsp_link
);
808 * Turn a path into a parent pathref and atname
810 * This returns the parent pathref in _parent and the name relative to it. If
811 * smb_fname was a pathref (ie smb_fname->fsp != NULL), then _atname will be a
812 * pathref as well, ie _atname->fsp will point at the same fsp as
815 NTSTATUS
parent_pathref(TALLOC_CTX
*mem_ctx
,
816 struct files_struct
*dirfsp
,
817 const struct smb_filename
*smb_fname
,
818 struct smb_filename
**_parent
,
819 struct smb_filename
**_atname
)
821 struct smb_filename
*parent
= NULL
;
822 struct smb_filename
*atname
= NULL
;
825 status
= SMB_VFS_PARENT_PATHNAME(dirfsp
->conn
,
830 if (!NT_STATUS_IS_OK(status
)) {
835 * We know that the parent name must
836 * exist, and the name has been canonicalized
837 * even if this was a POSIX pathname.
838 * Ensure that we follow symlinks for
839 * the parent. See the torture test
840 * POSIX-SYMLINK-PARENT for details.
842 parent
->flags
&= ~SMB_FILENAME_POSIX_PATH
;
844 status
= openat_pathref_fsp(dirfsp
, parent
);
845 if (!NT_STATUS_IS_OK(status
)) {
850 if (smb_fname
->fsp
!= NULL
) {
851 status
= fsp_smb_fname_link(smb_fname
->fsp
,
854 if (!NT_STATUS_IS_OK(status
)) {
858 talloc_set_destructor(atname
, atname_destructor
);
865 static bool close_file_in_loop(struct files_struct
*fsp
)
867 if (fsp_is_alternate_stream(fsp
)) {
869 * This is a stream, it can't be a base
871 SMB_ASSERT(fsp
->stream_fsp
== NULL
);
872 SMB_ASSERT(fsp
->base_fsp
->stream_fsp
== fsp
);
875 * Remove the base<->stream link so that
876 * close_file_free() does not close fsp->base_fsp as
877 * well. This would destroy walking the linked list of
880 fsp
->base_fsp
->stream_fsp
= NULL
;
881 fsp
->base_fsp
= NULL
;
883 close_file_free(NULL
, &fsp
, SHUTDOWN_CLOSE
);
887 if (fsp
->stream_fsp
!= NULL
) {
889 * This is the base of a stream.
891 SMB_ASSERT(fsp
->stream_fsp
->base_fsp
== fsp
);
894 * Remove the base<->stream link. This will make fsp
895 * look like a normal fsp for the next round.
897 fsp
->stream_fsp
->base_fsp
= NULL
;
898 fsp
->stream_fsp
= NULL
;
901 * Have us called back a second time. In the second
902 * round, "fsp" now looks like a normal fsp.
907 close_file_free(NULL
, &fsp
, SHUTDOWN_CLOSE
);
911 /****************************************************************************
912 Close all open files for a connection.
913 ****************************************************************************/
915 struct file_close_conn_state
{
916 struct connection_struct
*conn
;
917 bool fsp_left_behind
;
920 static struct files_struct
*file_close_conn_fn(
921 struct files_struct
*fsp
,
924 struct file_close_conn_state
*state
= private_data
;
927 if (fsp
->conn
!= state
->conn
) {
931 if (fsp
->op
!= NULL
&& fsp
->op
->global
->durable
) {
933 * A tree disconnect closes a durable handle
935 fsp
->op
->global
->durable
= false;
938 did_close
= close_file_in_loop(fsp
);
940 state
->fsp_left_behind
= true;
946 void file_close_conn(connection_struct
*conn
)
948 struct file_close_conn_state state
= { .conn
= conn
};
950 files_forall(conn
->sconn
, file_close_conn_fn
, &state
);
952 if (state
.fsp_left_behind
) {
953 state
.fsp_left_behind
= false;
954 files_forall(conn
->sconn
, file_close_conn_fn
, &state
);
955 SMB_ASSERT(!state
.fsp_left_behind
);
959 /****************************************************************************
960 Initialise file structures.
961 ****************************************************************************/
963 static int files_max_open_fds
;
965 bool file_init_global(void)
967 int request_max
= lp_max_open_files();
971 if (files_max_open_fds
!= 0) {
976 * Set the max_open files to be the requested
977 * max plus a fudgefactor to allow for the extra
978 * fd's we need such as log files etc...
980 real_lim
= set_maxfiles(request_max
+ MAX_OPEN_FUDGEFACTOR
);
982 real_max
= real_lim
- MAX_OPEN_FUDGEFACTOR
;
984 if (real_max
+ FILE_HANDLE_OFFSET
+ MAX_OPEN_PIPES
> 65536) {
985 real_max
= 65536 - FILE_HANDLE_OFFSET
- MAX_OPEN_PIPES
;
988 if (real_max
!= request_max
) {
989 DEBUG(1, ("file_init_global: Information only: requested %d "
990 "open files, %d are available.\n",
991 request_max
, real_max
));
994 SMB_ASSERT(real_max
> 100);
996 files_max_open_fds
= real_max
;
1000 bool file_init(struct smbd_server_connection
*sconn
)
1004 ok
= file_init_global();
1009 sconn
->real_max_open_files
= files_max_open_fds
;
1014 /****************************************************************************
1015 Close files open by a specified vuid.
1016 ****************************************************************************/
1018 struct file_close_user_state
{
1020 bool fsp_left_behind
;
1023 static struct files_struct
*file_close_user_fn(
1024 struct files_struct
*fsp
,
1027 struct file_close_user_state
*state
= private_data
;
1030 if (fsp
->vuid
!= state
->vuid
) {
1034 did_close
= close_file_in_loop(fsp
);
1036 state
->fsp_left_behind
= true;
1042 void file_close_user(struct smbd_server_connection
*sconn
, uint64_t vuid
)
1044 struct file_close_user_state state
= { .vuid
= vuid
};
1046 files_forall(sconn
, file_close_user_fn
, &state
);
1048 if (state
.fsp_left_behind
) {
1049 state
.fsp_left_behind
= false;
1050 files_forall(sconn
, file_close_user_fn
, &state
);
1051 SMB_ASSERT(!state
.fsp_left_behind
);
1056 * Walk the files table until "fn" returns non-NULL
1059 struct files_struct
*files_forall(
1060 struct smbd_server_connection
*sconn
,
1061 struct files_struct
*(*fn
)(struct files_struct
*fsp
,
1062 void *private_data
),
1065 struct files_struct
*fsp
, *next
;
1067 for (fsp
= sconn
->files
; fsp
; fsp
= next
) {
1068 struct files_struct
*ret
;
1070 ret
= fn(fsp
, private_data
);
1078 /****************************************************************************
1079 Find a fsp given a file descriptor.
1080 ****************************************************************************/
1082 files_struct
*file_find_fd(struct smbd_server_connection
*sconn
, int fd
)
1087 for (fsp
=sconn
->files
; fsp
; fsp
=fsp
->next
,count
++) {
1088 if (fsp_get_pathref_fd(fsp
) == fd
) {
1090 DLIST_PROMOTE(sconn
->files
, fsp
);
1099 /****************************************************************************
1100 Find a fsp given a device, inode and file_id.
1101 ****************************************************************************/
1103 files_struct
*file_find_dif(struct smbd_server_connection
*sconn
,
1104 struct file_id id
, unsigned long gen_id
)
1113 for (fsp
= sconn
->files
; fsp
; fsp
= fsp
->next
,count
++) {
1115 * We can have a fsp->fh->fd == -1 here as it could be a stat
1118 if (!file_id_equal(&fsp
->file_id
, &id
)) {
1121 if (!fsp
->fsp_flags
.is_fsa
) {
1124 if (fh_get_gen_id(fsp
->fh
) != gen_id
) {
1128 DLIST_PROMOTE(sconn
->files
, fsp
);
1130 /* Paranoia check. */
1131 if ((fsp_get_pathref_fd(fsp
) == -1) &&
1132 (fsp
->oplock_type
!= NO_OPLOCK
&&
1133 fsp
->oplock_type
!= LEASE_OPLOCK
))
1135 struct file_id_buf idbuf
;
1137 DBG_ERR("file %s file_id = "
1138 "%s, gen = %u oplock_type = %u is a "
1139 "stat open with oplock type !\n",
1141 file_id_str_buf(fsp
->file_id
, &idbuf
),
1142 (unsigned int)fh_get_gen_id(fsp
->fh
),
1143 (unsigned int)fsp
->oplock_type
);
1144 smb_panic("file_find_dif");
1152 /****************************************************************************
1153 Find the first fsp given a device and inode.
1154 We use a singleton cache here to speed up searching from getfilepathinfo
1156 ****************************************************************************/
1158 files_struct
*file_find_di_first(struct smbd_server_connection
*sconn
,
1164 if (file_id_equal(&sconn
->fsp_fi_cache
.id
, &id
)) {
1165 /* Positive or negative cache hit. */
1166 return sconn
->fsp_fi_cache
.fsp
;
1169 sconn
->fsp_fi_cache
.id
= id
;
1171 for (fsp
=sconn
->files
;fsp
;fsp
=fsp
->next
) {
1172 if (need_fsa
&& !fsp
->fsp_flags
.is_fsa
) {
1175 if (file_id_equal(&fsp
->file_id
, &id
)) {
1176 /* Setup positive cache. */
1177 sconn
->fsp_fi_cache
.fsp
= fsp
;
1182 /* Setup negative cache. */
1183 sconn
->fsp_fi_cache
.fsp
= NULL
;
1187 /****************************************************************************
1188 Find the next fsp having the same device and inode.
1189 ****************************************************************************/
1191 files_struct
*file_find_di_next(files_struct
*start_fsp
,
1196 for (fsp
= start_fsp
->next
;fsp
;fsp
=fsp
->next
) {
1197 if (need_fsa
&& !fsp
->fsp_flags
.is_fsa
) {
1200 if (file_id_equal(&fsp
->file_id
, &start_fsp
->file_id
)) {
1208 struct files_struct
*file_find_one_fsp_from_lease_key(
1209 struct smbd_server_connection
*sconn
,
1210 const struct smb2_lease_key
*lease_key
)
1212 struct files_struct
*fsp
;
1214 for (fsp
= sconn
->files
; fsp
; fsp
=fsp
->next
) {
1215 if ((fsp
->lease
!= NULL
) &&
1216 (fsp
->lease
->lease
.lease_key
.data
[0] ==
1217 lease_key
->data
[0]) &&
1218 (fsp
->lease
->lease
.lease_key
.data
[1] ==
1219 lease_key
->data
[1])) {
1226 /****************************************************************************
1227 Find any fsp open with a pathname below that of an already open path.
1228 ****************************************************************************/
1230 bool file_find_subpath(files_struct
*dir_fsp
)
1234 char *d_fullname
= NULL
;
1236 d_fullname
= talloc_asprintf(talloc_tos(), "%s/%s",
1237 dir_fsp
->conn
->connectpath
,
1238 dir_fsp
->fsp_name
->base_name
);
1244 dlen
= strlen(d_fullname
);
1246 for (fsp
=dir_fsp
->conn
->sconn
->files
; fsp
; fsp
=fsp
->next
) {
1249 if (fsp
== dir_fsp
) {
1253 d1_fullname
= talloc_asprintf(talloc_tos(),
1255 fsp
->conn
->connectpath
,
1256 fsp
->fsp_name
->base_name
);
1259 * If the open file has a path that is a longer
1260 * component, then it's a subpath.
1262 if (strnequal(d_fullname
, d1_fullname
, dlen
) &&
1263 (d1_fullname
[dlen
] == '/')) {
1264 TALLOC_FREE(d1_fullname
);
1265 TALLOC_FREE(d_fullname
);
1268 TALLOC_FREE(d1_fullname
);
1271 TALLOC_FREE(d_fullname
);
1275 /****************************************************************************
1277 ****************************************************************************/
1279 static void fsp_free(files_struct
*fsp
)
1281 struct smbd_server_connection
*sconn
= fsp
->conn
->sconn
;
1283 if (fsp
== sconn
->fsp_fi_cache
.fsp
) {
1284 ZERO_STRUCT(sconn
->fsp_fi_cache
);
1287 DLIST_REMOVE(sconn
->files
, fsp
);
1288 SMB_ASSERT(sconn
->num_files
> 0);
1291 TALLOC_FREE(fsp
->fake_file_handle
);
1293 if (fh_get_refcount(fsp
->fh
) == 1) {
1294 TALLOC_FREE(fsp
->fh
);
1296 size_t new_refcount
= fh_get_refcount(fsp
->fh
) - 1;
1297 fh_set_refcount(fsp
->fh
, new_refcount
);
1300 if (fsp
->lease
!= NULL
) {
1301 if (fsp
->lease
->ref_count
== 1) {
1302 TALLOC_FREE(fsp
->lease
);
1304 fsp
->lease
->ref_count
--;
1308 fsp
->conn
->num_files_open
--;
1310 if (fsp
->fsp_name
!= NULL
&&
1311 fsp
->fsp_name
->fsp_link
!= NULL
)
1314 * Free fsp_link of fsp->fsp_name. To do this in the correct
1315 * talloc destructor order we have to do it here. The
1316 * talloc_free() of the link should set the fsp pointer to NULL.
1318 TALLOC_FREE(fsp
->fsp_name
->fsp_link
);
1319 SMB_ASSERT(fsp
->fsp_name
->fsp
== NULL
);
1322 /* this is paranoia, just in case someone tries to reuse the
1326 /* fsp->fsp_name is a talloc child and is free'd automatically. */
1331 * Rundown of all smb-related sub-structures of an fsp
1333 void fsp_unbind_smb(struct smb_request
*req
, files_struct
*fsp
)
1335 if (fsp
== fsp
->conn
->cwd_fsp
) {
1340 size_t len
= fsp_fullbasepath(fsp
, NULL
, 0);
1341 char fullpath
[len
+1];
1343 fsp_fullbasepath(fsp
, fullpath
, sizeof(fullpath
));
1346 * Avoid /. at the end of the path name. notify can't
1349 if (len
> 1 && fullpath
[len
-1] == '.' &&
1350 fullpath
[len
-2] == '/') {
1351 fullpath
[len
-2] = '\0';
1354 notify_remove(fsp
->conn
->sconn
->notify_ctx
, fsp
, fullpath
);
1355 TALLOC_FREE(fsp
->notify
);
1358 /* Ensure this event will never fire. */
1359 TALLOC_FREE(fsp
->update_write_time_event
);
1361 if (fsp
->op
!= NULL
) {
1362 fsp
->op
->compat
= NULL
;
1364 TALLOC_FREE(fsp
->op
);
1366 if ((req
!= NULL
) && (fsp
== req
->chain_fsp
)) {
1367 req
->chain_fsp
= NULL
;
1371 * Clear all possible chained fsp
1372 * pointers in the SMB2 request queue.
1374 remove_smb2_chained_fsp(fsp
);
1377 void file_free(struct smb_request
*req
, files_struct
*fsp
)
1379 struct smbd_server_connection
*sconn
= fsp
->conn
->sconn
;
1380 uint64_t fnum
= fsp
->fnum
;
1382 fsp_unbind_smb(req
, fsp
);
1384 /* Drop all remaining extensions. */
1385 vfs_remove_all_fsp_extensions(fsp
);
1389 DBG_INFO("freed files structure %"PRIu64
" (%zu used)\n",
1394 /****************************************************************************
1395 Get an fsp from a packet given a 16 bit fnum.
1396 ****************************************************************************/
1398 files_struct
*file_fsp(struct smb_request
*req
, uint16_t fid
)
1400 struct smbXsrv_open
*op
;
1407 * We should never get here. req==NULL could in theory
1408 * only happen from internal opens with a non-zero
1409 * root_dir_fid. Internal opens just don't do that, at
1410 * least they are not supposed to do so. And if they
1411 * start to do so, they better fake up a smb_request
1412 * from which we get the right smbd_server_conn. While
1413 * this should never happen, let's return NULL here.
1418 if (req
->chain_fsp
!= NULL
) {
1419 if (req
->chain_fsp
->fsp_flags
.closing
) {
1422 return req
->chain_fsp
;
1425 if (req
->xconn
== NULL
) {
1429 now
= timeval_to_nttime(&req
->request_time
);
1431 status
= smb1srv_open_lookup(req
->xconn
,
1433 if (!NT_STATUS_IS_OK(status
)) {
1442 if (fsp
->fsp_flags
.closing
) {
1446 req
->chain_fsp
= fsp
;
1450 struct files_struct
*file_fsp_get(struct smbd_smb2_request
*smb2req
,
1451 uint64_t persistent_id
,
1452 uint64_t volatile_id
)
1454 struct smbXsrv_open
*op
;
1457 struct files_struct
*fsp
;
1459 now
= timeval_to_nttime(&smb2req
->request_time
);
1461 status
= smb2srv_open_lookup(smb2req
->xconn
,
1462 persistent_id
, volatile_id
,
1464 if (!NT_STATUS_IS_OK(status
)) {
1473 if (smb2req
->tcon
== NULL
) {
1477 if (smb2req
->tcon
->compat
!= fsp
->conn
) {
1481 if (smb2req
->session
== NULL
) {
1485 if (smb2req
->session
->global
->session_wire_id
!= fsp
->vuid
) {
1489 if (fsp
->fsp_flags
.closing
) {
1496 struct files_struct
*file_fsp_smb2(struct smbd_smb2_request
*smb2req
,
1497 uint64_t persistent_id
,
1498 uint64_t volatile_id
)
1500 struct files_struct
*fsp
;
1502 if (smb2req
->compat_chain_fsp
!= NULL
) {
1503 if (smb2req
->compat_chain_fsp
->fsp_flags
.closing
) {
1506 return smb2req
->compat_chain_fsp
;
1509 fsp
= file_fsp_get(smb2req
, persistent_id
, volatile_id
);
1514 smb2req
->compat_chain_fsp
= fsp
;
1518 /****************************************************************************
1519 Duplicate the file handle part for a DOS or FCB open.
1520 ****************************************************************************/
1522 NTSTATUS
dup_file_fsp(
1524 uint32_t access_mask
,
1527 size_t new_refcount
;
1529 /* this can never happen for print files */
1530 SMB_ASSERT(from
->print_file
== NULL
);
1532 TALLOC_FREE(to
->fh
);
1535 new_refcount
= fh_get_refcount(to
->fh
) + 1;
1536 fh_set_refcount(to
->fh
, new_refcount
);
1538 to
->file_id
= from
->file_id
;
1539 to
->initial_allocation_size
= from
->initial_allocation_size
;
1540 to
->file_pid
= from
->file_pid
;
1541 to
->vuid
= from
->vuid
;
1542 to
->open_time
= from
->open_time
;
1543 to
->access_mask
= access_mask
;
1544 to
->oplock_type
= from
->oplock_type
;
1545 to
->fsp_flags
.can_lock
= from
->fsp_flags
.can_lock
;
1546 to
->fsp_flags
.can_read
= ((access_mask
& FILE_READ_DATA
) != 0);
1547 to
->fsp_flags
.can_write
=
1548 CAN_WRITE(from
->conn
) &&
1549 ((access_mask
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0);
1550 to
->fsp_flags
.modified
= from
->fsp_flags
.modified
;
1551 to
->fsp_flags
.is_directory
= from
->fsp_flags
.is_directory
;
1552 to
->fsp_flags
.aio_write_behind
= from
->fsp_flags
.aio_write_behind
;
1553 to
->fsp_flags
.is_fsa
= from
->fsp_flags
.is_fsa
;
1554 to
->fsp_flags
.is_pathref
= from
->fsp_flags
.is_pathref
;
1555 to
->fsp_flags
.have_proc_fds
= from
->fsp_flags
.have_proc_fds
;
1556 to
->fsp_flags
.is_dirfsp
= from
->fsp_flags
.is_dirfsp
;
1558 return fsp_set_smb_fname(to
, from
->fsp_name
);
1562 * Return a jenkins hash of a pathname on a connection.
1565 NTSTATUS
file_name_hash(connection_struct
*conn
,
1566 const char *name
, uint32_t *p_name_hash
)
1568 char tmpbuf
[PATH_MAX
];
1569 char *fullpath
, *to_free
;
1573 /* Set the hash of the full pathname. */
1575 if (name
[0] == '/') {
1576 strlcpy(tmpbuf
, name
, sizeof(tmpbuf
));
1578 len
= strlen(fullpath
);
1581 len
= full_path_tos(conn
->connectpath
,
1589 return NT_STATUS_NO_MEMORY
;
1591 key
= (TDB_DATA
) { .dptr
= (uint8_t *)fullpath
, .dsize
= len
+1 };
1592 *p_name_hash
= tdb_jenkins_hash(&key
);
1594 DEBUG(10,("file_name_hash: %s hash 0x%x\n",
1596 (unsigned int)*p_name_hash
));
1598 TALLOC_FREE(to_free
);
1599 return NT_STATUS_OK
;
1602 static NTSTATUS
fsp_attach_smb_fname(struct files_struct
*fsp
,
1603 struct smb_filename
**_smb_fname
)
1605 struct smb_filename
*smb_fname_new
= talloc_move(fsp
, _smb_fname
);
1606 const char *name_str
= NULL
;
1607 uint32_t name_hash
= 0;
1610 name_str
= smb_fname_str_dbg(smb_fname_new
);
1611 if (name_str
== NULL
) {
1612 return NT_STATUS_NO_MEMORY
;
1615 status
= file_name_hash(fsp
->conn
,
1618 if (!NT_STATUS_IS_OK(status
)) {
1622 status
= fsp_smb_fname_link(fsp
,
1623 &smb_fname_new
->fsp_link
,
1624 &smb_fname_new
->fsp
);
1625 if (!NT_STATUS_IS_OK(status
)) {
1629 fsp
->name_hash
= name_hash
;
1630 fsp
->fsp_name
= smb_fname_new
;
1632 return NT_STATUS_OK
;
1636 * The only way that the fsp->fsp_name field should ever be set.
1638 NTSTATUS
fsp_set_smb_fname(struct files_struct
*fsp
,
1639 const struct smb_filename
*smb_fname_in
)
1641 struct smb_filename
*smb_fname_old
= fsp
->fsp_name
;
1642 struct smb_filename
*smb_fname_new
= NULL
;
1645 smb_fname_new
= cp_smb_filename(fsp
, smb_fname_in
);
1646 if (smb_fname_new
== NULL
) {
1647 return NT_STATUS_NO_MEMORY
;
1650 status
= fsp_attach_smb_fname(fsp
, &smb_fname_new
);
1651 if (!NT_STATUS_IS_OK(status
)) {
1652 TALLOC_FREE(smb_fname_new
);
1656 if (smb_fname_old
!= NULL
) {
1657 smb_fname_fsp_unlink(smb_fname_old
);
1658 TALLOC_FREE(smb_fname_old
);
1661 return NT_STATUS_OK
;
1664 size_t fsp_fullbasepath(struct files_struct
*fsp
, char *buf
, size_t buflen
)
1667 char tmp_buf
[1] = {'\0'};
1670 * Don't pass NULL buffer to snprintf (to satisfy static checker)
1671 * Some callers will call this function with NULL for buf and
1672 * 0 for buflen in order to get length of fullbasepath (without
1673 * needing to allocate or write to buf)
1677 SMB_ASSERT(buflen
==0);
1680 len
= snprintf(buf
, buflen
, "%s/%s", fsp
->conn
->connectpath
,
1681 fsp
->fsp_name
->base_name
);
1687 void fsp_set_base_fsp(struct files_struct
*fsp
, struct files_struct
*base_fsp
)
1689 SMB_ASSERT(fsp
->stream_fsp
== NULL
);
1690 if (base_fsp
!= NULL
) {
1691 SMB_ASSERT(base_fsp
->base_fsp
== NULL
);
1692 SMB_ASSERT(base_fsp
->stream_fsp
== NULL
);
1695 if (fsp
->base_fsp
!= NULL
) {
1696 SMB_ASSERT(fsp
->base_fsp
->stream_fsp
== fsp
);
1697 fsp
->base_fsp
->stream_fsp
= NULL
;
1700 fsp
->base_fsp
= base_fsp
;
1701 if (fsp
->base_fsp
!= NULL
) {
1702 fsp
->base_fsp
->stream_fsp
= fsp
;
1706 bool fsp_is_alternate_stream(const struct files_struct
*fsp
)
1708 return (fsp
->base_fsp
!= NULL
);
1711 struct files_struct
*metadata_fsp(struct files_struct
*fsp
)
1713 if (fsp_is_alternate_stream(fsp
)) {
1714 return fsp
->base_fsp
;