fsp->fsp_name->st = full_fname->st;
}
TALLOC_FREE(full_fname);
- errno = ENOENT;
+ errno = ELOOP;
}
return ret;
}
# ls commands.
#
smbclient_expect_error "ls" "$name" "" "NT_STATUS_OK" || return 1
- smbclient_expect_error "ls" "$name/noexist" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
- smbclient_expect_error "ls" "$name/*" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
+ smbclient_expect_error "ls" "$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "$name/*" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
smbclient_expect_error "ls" "$name/*/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
# Now in subdirectory emptydir
smbclient_expect_error "ls" "emptydir/$name" "" "NT_STATUS_OK" || return 1
- smbclient_expect_error "ls" "emptydir/$name/noexist" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
- smbclient_expect_error "ls" "emptydir/$name/*" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
+ smbclient_expect_error "ls" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "emptydir/$name/*" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
smbclient_expect_error "ls" "emptydir/$name/*/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
#
# SMB1+POSIX stat commands. All symlinks can be stat'ed.
# del commands. Under SMB1+POSIX we can legitimately delete symlinks, so don't
# try and delete symlink targets, we need them for the later tests.
#
- smbclient_expect_error "del" "$name/noexist" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
+ smbclient_expect_error "del" "$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
# Now in subdirectory emptydir
- smbclient_expect_error "del" "emptydir/$name/noexist" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
+ smbclient_expect_error "del" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
if [ "$do_rename" = "do rename" ]; then
#
#include "fake_file.h"
#include "smbd/smbd.h"
#include "smbd/globals.h"
-#include "lib/util/memcache.h"
#include "libcli/smb/reparse.h"
uint32_t ucf_flags_from_smb_request(struct smb_request *req)
return NT_STATUS_OK;
}
-/*
- * Open smb_fname_rel->fsp as a pathref fsp with a case insensitive
- * fallback using GETREALFILENAME_CACHE and get_real_filename_at() if
- * the first attempt based on the filename sent by the client gives
- * ENOENT.
- */
-static NTSTATUS openat_pathref_fsp_case_insensitive(
- struct files_struct *dirfsp,
- struct smb_filename *smb_fname_rel,
- uint32_t ucf_flags)
-{
- const bool posix = (ucf_flags & UCF_POSIX_PATHNAMES);
- DATA_BLOB cache_key = { .data = NULL, };
- char *found_name = NULL;
- NTSTATUS status;
- bool ok;
-
- SET_STAT_INVALID(smb_fname_rel->st);
-
- /* Check veto files - only looks at last component. */
- if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
- DBG_DEBUG("veto files rejecting last component %s\n",
- smb_fname_str_dbg(smb_fname_rel));
- return NT_STATUS_NETWORK_OPEN_RESTRICTION;
- }
-
- status = openat_pathref_fsp(dirfsp, smb_fname_rel);
-
- if (NT_STATUS_IS_OK(status)) {
- return NT_STATUS_OK;
- }
-
- if (VALID_STAT(smb_fname_rel->st)) {
- /*
- * We got an error although the object existed. Might
- * be a symlink we don't want.
- */
- return status;
- }
-
- if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
- /*
- * Only retry on ENOENT
- */
- return status;
- }
-
- if (posix || dirfsp->conn->case_sensitive) {
- /*
- * Only return case insensitive if required
- */
- return status;
- }
-
- if (lp_stat_cache()) {
- char *base_name = smb_fname_rel->base_name;
- char *original_relname = NULL;
- DATA_BLOB value = { .data = NULL };
-
- ok = get_real_filename_cache_key(
- talloc_tos(), dirfsp, base_name, &cache_key);
- if (!ok) {
- /*
- * probably ENOMEM, just bail
- */
- return status;
- }
-
- DO_PROFILE_INC(statcache_lookups);
-
- ok = memcache_lookup(
- NULL, GETREALFILENAME_CACHE, cache_key, &value);
- if (!ok) {
- DO_PROFILE_INC(statcache_misses);
- goto lookup;
- }
- DO_PROFILE_INC(statcache_hits);
-
- /*
- * For the "new filename" case we need to preserve the
- * capitalization the client sent us, see
- * https://bugzilla.samba.org/show_bug.cgi?id=15481
- */
- original_relname = smb_fname_rel->base_name;
-
- smb_fname_rel->base_name = talloc_memdup(
- smb_fname_rel, value.data, value.length);
- if (smb_fname_rel->base_name == NULL) {
- TALLOC_FREE(cache_key.data);
- return NT_STATUS_NO_MEMORY;
- }
-
- if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
- DBG_DEBUG("veto files rejecting last component %s\n",
- smb_fname_str_dbg(smb_fname_rel));
- TALLOC_FREE(cache_key.data);
- return NT_STATUS_NETWORK_OPEN_RESTRICTION;
- }
-
- status = openat_pathref_fsp(dirfsp, smb_fname_rel);
- if (NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(cache_key.data);
- TALLOC_FREE(original_relname);
- return NT_STATUS_OK;
- }
-
- memcache_delete(NULL, GETREALFILENAME_CACHE, cache_key);
- TALLOC_FREE(smb_fname_rel->base_name);
- smb_fname_rel->base_name = original_relname;
- }
-
-lookup:
- status = get_real_filename_at(
- dirfsp, smb_fname_rel->base_name, smb_fname_rel, &found_name);
- if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
- (ucf_flags & UCF_PREP_CREATEFILE)) {
- /*
- * dropbox
- */
- status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
-
- if (NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(smb_fname_rel->base_name);
- smb_fname_rel->base_name = found_name;
-
- if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
- DBG_DEBUG("veto files rejecting last component %s\n",
- smb_fname_str_dbg(smb_fname_rel));
- return NT_STATUS_NETWORK_OPEN_RESTRICTION;
- }
-
- status = openat_pathref_fsp(dirfsp, smb_fname_rel);
- }
-
- if (NT_STATUS_IS_OK(status) && (cache_key.data != NULL)) {
- DATA_BLOB value = {
- .data = (uint8_t *)smb_fname_rel->base_name,
- .length = strlen(smb_fname_rel->base_name) + 1,
- };
-
- memcache_add(NULL, GETREALFILENAME_CACHE, cache_key, value);
- }
-
- TALLOC_FREE(cache_key.data);
-
- return status;
-}
-
static const char *previous_slash(const char *name_in, const char *slash)
{
const char *prev = NULL;
struct smb_filename *smb_dirname = NULL;
struct smb_filename *smb_fname_rel = NULL;
struct smb_filename *smb_fname = NULL;
+ struct open_symlink_err *symlink_err = NULL;
const bool posix = (ucf_flags & UCF_POSIX_PATHNAMES);
char *dirname = NULL;
const char *fname_rel = NULL;
posix ? SMB_FILENAME_POSIX_PATH : 0,
&smb_dirname);
} else {
- struct open_symlink_err *symlink_err = NULL;
-
status = normalize_filename_case(conn, dirname, ucf_flags);
if (!NT_STATUS_IS_OK(status)) {
DBG_ERR("normalize_filename_case %s failed: %s\n",
if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
size_t name_in_len, dirname_len;
- if (lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) &&
- strnequal(symlink_err->reparse->substitute_name,
- "msdfs:",
- 6)) {
- status = NT_STATUS_PATH_NOT_COVERED;
- goto fail;
- }
-
name_in_len = strlen(name_in);
dirname_len = strlen(dirname);
goto fail;
}
- status = openat_pathref_fsp_case_insensitive(
- smb_dirname->fsp, smb_fname_rel, ucf_flags);
+ status = openat_pathref_fsp_lcomp(smb_dirname->fsp,
+ smb_fname_rel,
+ ucf_flags);
- if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
- VALID_STAT(smb_fname_rel->st) &&
- S_ISLNK(smb_fname_rel->st.st_ex_mode)) {
+ if (NT_STATUS_IS_OK(status) && S_ISLNK(smb_fname_rel->st.st_ex_mode)) {
/*
- * If we're on an MSDFS share, see if this is
- * an MSDFS link.
+ * Upper layers might need the link target. Here we
+ * still have the relname around, get the symlink err.
*/
- if (lp_host_msdfs() &&
- lp_msdfs_root(SNUM(conn)) &&
- is_msdfs_link(smb_dirname->fsp, smb_fname_rel))
- {
- status = NT_STATUS_PATH_NOT_COVERED;
+ status = create_open_symlink_err(mem_ctx,
+ smb_dirname->fsp,
+ smb_fname_rel,
+ &symlink_err);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("Could not read symlink for %s: %s\n",
+ smb_fname_str_dbg(
+ smb_fname_rel->fsp->fsp_name),
+ nt_errstr(status));
goto fail;
}
-
-#if defined(WITH_SMB1SERVER)
- /*
- * In SMB1 posix mode, if this is a symlink,
- * allow access to the name with a NULL smb_fname->fsp.
- */
- if (ucf_flags & UCF_LCOMP_LNK_OK) {
- SMB_ASSERT(smb_fname_rel->fsp == NULL);
- SMB_ASSERT(streamname == NULL);
-
- smb_fname = full_path_from_dirfsp_atname(
- mem_ctx,
- smb_dirname->fsp,
- smb_fname_rel);
- if (smb_fname == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto fail;
- }
- goto done;
- }
-#endif
}
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
done:
*_dirfsp = smb_dirname->fsp;
*_smb_fname = smb_fname;
+ *_symlink_err = symlink_err;
smb_fname_fsp_unlink(smb_fname_rel);
TALLOC_FREE(smb_fname_rel);
_smb_fname,
&symlink_err);
+ if (NT_STATUS_IS_OK(status) && S_ISLNK((*_smb_fname)->st.st_ex_mode)) {
+ /*
+ * lcomp is a symlink
+ */
+ if (ucf_flags & UCF_LCOMP_LNK_OK) {
+ TALLOC_FREE(symlink_err);
+ return NT_STATUS_OK;
+ }
+ close_file_free(NULL, _dirfsp, ERROR_CLOSE);
+ status = NT_STATUS_STOPPED_ON_SYMLINK;
+ }
+
if (!NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
return status;
}
+ /*
+ * If we're on an MSDFS share, see if this is
+ * an MSDFS link.
+ */
+ if (lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) &&
+ strnequal(symlink_err->reparse->substitute_name, "msdfs:", 6))
+ {
+ TALLOC_FREE(*_smb_fname);
+ TALLOC_FREE(symlink_err);
+ return NT_STATUS_PATH_NOT_COVERED;
+ }
+
if (!lp_follow_symlinks(SNUM(conn))) {
status = (symlink_err->unparsed == 0)
? NT_STATUS_OBJECT_NAME_NOT_FOUND
#include "util_tdb.h"
#include "lib/util/bitmap.h"
#include "lib/util/strv.h"
+#include "lib/util/memcache.h"
#include "libcli/smb/reparse.h"
#define FILE_HANDLE_OFFSET 0x1000
return NT_STATUS_OK;
}
+static int smb_vfs_openat_ci(TALLOC_CTX *mem_ctx,
+ bool case_sensitive,
+ struct connection_struct *conn,
+ struct files_struct *dirfsp,
+ struct smb_filename *smb_fname_rel,
+ files_struct *fsp,
+ const struct vfs_open_how *how)
+{
+ char *orig_base_name = smb_fname_rel->base_name;
+ DATA_BLOB cache_key = {
+ .data = NULL,
+ };
+ DATA_BLOB cache_value = {
+ .data = NULL,
+ };
+ NTSTATUS status;
+ int fd;
+ bool ok;
+
+ fd = SMB_VFS_OPENAT(conn, dirfsp, smb_fname_rel, fsp, how);
+ if ((fd >= 0) || case_sensitive) {
+ return fd;
+ }
+ if (errno != ENOENT) {
+ return -1;
+ }
+
+ if (!lp_stat_cache()) {
+ goto lookup;
+ }
+
+ ok = get_real_filename_cache_key(mem_ctx,
+ dirfsp,
+ orig_base_name,
+ &cache_key);
+ if (!ok) {
+ /*
+ * probably ENOMEM, just bail
+ */
+ errno = ENOMEM;
+ return -1;
+ }
+
+ DO_PROFILE_INC(statcache_lookups);
+
+ ok = memcache_lookup(NULL,
+ GETREALFILENAME_CACHE,
+ cache_key,
+ &cache_value);
+ if (!ok) {
+ DO_PROFILE_INC(statcache_misses);
+ goto lookup;
+ }
+ DO_PROFILE_INC(statcache_hits);
+
+ smb_fname_rel->base_name = talloc_strndup(mem_ctx,
+ (char *)cache_value.data,
+ cache_value.length);
+ if (smb_fname_rel->base_name == NULL) {
+ TALLOC_FREE(cache_key.data);
+ smb_fname_rel->base_name = orig_base_name;
+ errno = ENOMEM;
+ return -1;
+ }
+
+ if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
+ DBG_DEBUG("veto files rejecting last component %s\n",
+ smb_fname_str_dbg(smb_fname_rel));
+ TALLOC_FREE(cache_key.data);
+ smb_fname_rel->base_name = orig_base_name;
+ errno = EPERM;
+ return -1;
+ }
+
+ fd = SMB_VFS_OPENAT(conn, dirfsp, smb_fname_rel, fsp, how);
+ if (fd >= 0) {
+ TALLOC_FREE(cache_key.data);
+ return fd;
+ }
+
+ memcache_delete(NULL, GETREALFILENAME_CACHE, cache_key);
+
+ /*
+ * For the "new filename" case we need to preserve the
+ * capitalization the client sent us, see
+ * https://bugzilla.samba.org/show_bug.cgi?id=15481
+ */
+ TALLOC_FREE(smb_fname_rel->base_name);
+ smb_fname_rel->base_name = orig_base_name;
+
+lookup:
+
+ status = get_real_filename_at(dirfsp,
+ orig_base_name,
+ mem_ctx,
+ &smb_fname_rel->base_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("get_real_filename_at() failed: %s\n",
+ nt_errstr(status));
+ errno = ENOENT;
+ return -1;
+ }
+
+ if (IS_VETO_PATH(conn, smb_fname_rel->base_name)) {
+ DBG_DEBUG("found veto files path component "
+ "%s => %s\n",
+ orig_base_name,
+ smb_fname_rel->base_name);
+ TALLOC_FREE(smb_fname_rel->base_name);
+ smb_fname_rel->base_name = orig_base_name;
+ errno = ENOENT;
+ return -1;
+ }
+
+ fd = SMB_VFS_OPENAT(conn, dirfsp, smb_fname_rel, fsp, how);
+
+ if ((fd >= 0) && (cache_key.data != NULL)) {
+ DATA_BLOB value = {
+ .data = (uint8_t *)smb_fname_rel->base_name,
+ .length = strlen(smb_fname_rel->base_name) + 1,
+ };
+
+ memcache_add(NULL, GETREALFILENAME_CACHE, cache_key, value);
+ TALLOC_FREE(cache_key.data);
+ }
+
+ return fd;
+}
+
NTSTATUS openat_pathref_fsp_nosymlink(TALLOC_CTX *mem_ctx,
struct connection_struct *conn,
struct files_struct *in_dirfsp,
struct open_symlink_err *symlink_err = NULL;
struct files_struct *fsp = NULL;
char *path = NULL, *next = NULL;
- bool case_sensitive, ok, is_toplevel;
+ bool ok, is_toplevel;
int fd;
NTSTATUS status;
struct vfs_open_how how = {
next:
next = strv_next(path, rel_fname.base_name);
- fd = SMB_VFS_OPENAT(
- conn,
- dirfsp,
- &rel_fname,
- fsp,
- &how);
-
- case_sensitive = (posix || conn->case_sensitive);
-
- if ((fd == -1) && (errno == ENOENT) && !case_sensitive) {
- const char *orig_base_name = rel_fname.base_name;
-
- status = get_real_filename_at(
- dirfsp,
- rel_fname.base_name,
- talloc_tos(),
- &rel_fname.base_name);
-
- if (!NT_STATUS_IS_OK(status)) {
- DBG_DEBUG("get_real_filename_at failed: %s\n",
- nt_errstr(status));
- goto fail;
- }
-
- /* Name might have been demangled - check veto files. */
- if (IS_VETO_PATH(conn, rel_fname.base_name)) {
- DBG_DEBUG("%s contains veto files path component "
- "%s => %s\n",
- path_in,
- orig_base_name,
- rel_fname.base_name);
- status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
- goto fail;
- }
-
- fd = SMB_VFS_OPENAT(
- conn,
- dirfsp,
- &rel_fname,
- fsp,
- &how);
- }
+ fd = smb_vfs_openat_ci(talloc_tos(),
+ posix || conn->case_sensitive,
+ conn,
+ dirfsp,
+ &rel_fname,
+ fsp,
+ &how);
#ifndef O_PATH
if ((fd == -1) && (errno == ELOOP)) {
return status;
}
+/*
+ * Open smb_fname_rel->fsp as a pathref fsp with a case insensitive
+ * fallback using GETREALFILENAME_CACHE and get_real_filename_at() if
+ * the first attempt based on the filename sent by the client gives
+ * ENOENT.
+ */
+NTSTATUS openat_pathref_fsp_lcomp(struct files_struct *dirfsp,
+ struct smb_filename *smb_fname_rel,
+ uint32_t ucf_flags)
+{
+ struct connection_struct *conn = dirfsp->conn;
+ const char *orig_rel_base_name = smb_fname_rel->base_name;
+ struct files_struct *fsp = NULL;
+ struct smb_filename *full_fname = NULL;
+ struct vfs_open_how how = {
+ .flags = O_RDONLY | O_NONBLOCK | O_NOFOLLOW,
+ };
+ NTSTATUS status;
+ int ret, fd;
+
+ /*
+ * Make sure we don't need of the all the magic in
+ * openat_pathref_fsp() with regards non_widelink_open etc.
+ */
+
+ SMB_ASSERT((smb_fname_rel->fsp == NULL) &&
+ (dirfsp != dirfsp->conn->cwd_fsp) &&
+ (strchr_m(smb_fname_rel->base_name, '/') == NULL) &&
+ !is_named_stream(smb_fname_rel));
+
+ SET_STAT_INVALID(smb_fname_rel->st);
+
+ /* Check veto files - only looks at last component. */
+ if (IS_VETO_PATH(dirfsp->conn, smb_fname_rel->base_name)) {
+ DBG_DEBUG("veto files rejecting last component %s\n",
+ smb_fname_str_dbg(smb_fname_rel));
+ return NT_STATUS_NETWORK_OPEN_RESTRICTION;
+ }
+
+ status = fsp_new(conn, conn, &fsp);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("fsp_new() failed: %s\n", nt_errstr(status));
+ return status;
+ }
+
+ GetTimeOfDay(&fsp->open_time);
+ fsp_set_gen_id(fsp);
+ ZERO_STRUCT(conn->sconn->fsp_fi_cache);
+
+ fsp->fsp_flags.is_pathref = true;
+
+ full_fname = full_path_from_dirfsp_atname(conn, dirfsp, smb_fname_rel);
+ if (full_fname == NULL) {
+ DBG_DEBUG("full_path_from_dirfsp_atname(%s/%s) failed\n",
+ dirfsp->fsp_name->base_name,
+ smb_fname_rel->base_name);
+ file_free(NULL, fsp);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = fsp_attach_smb_fname(fsp, &full_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("fsp_attach_smb_fname(fsp, %s) failed: %s\n",
+ smb_fname_str_dbg(full_fname),
+ nt_errstr(status));
+ file_free(NULL, fsp);
+ return status;
+ }
+
+ fd = smb_vfs_openat_ci(smb_fname_rel,
+ (ucf_flags & UCF_POSIX_PATHNAMES) ||
+ conn->case_sensitive,
+ conn,
+ dirfsp,
+ smb_fname_rel,
+ fsp,
+ &how);
+
+ if ((fd == -1) && (errno == ENOENT)) {
+ status = map_nt_error_from_unix(errno);
+ DBG_DEBUG("smb_vfs_openat(%s/%s) failed: %s\n",
+ dirfsp->fsp_name->base_name,
+ smb_fname_rel->base_name,
+ strerror(errno));
+ file_free(NULL, fsp);
+ return status;
+ }
+
+ if (smb_fname_rel->base_name != orig_rel_base_name) {
+ struct smb_filename new_fullname = *smb_fname_rel;
+
+ DBG_DEBUG("rel->base_name changed from %s to %s\n",
+ orig_rel_base_name,
+ smb_fname_rel->base_name);
+
+ new_fullname.base_name = full_path_from_dirfsp_at_basename(
+ talloc_tos(), dirfsp, new_fullname.base_name);
+ if (new_fullname.base_name == NULL) {
+ fd_close(fsp);
+ file_free(NULL, fsp);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = fsp_set_smb_fname(fsp, &new_fullname);
+ if (!NT_STATUS_IS_OK(status)) {
+ fd_close(fsp);
+ file_free(NULL, fsp);
+ return status;
+ }
+ }
+
+ fsp_set_fd(fsp, fd);
+
+ if (fd >= 0) {
+ ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
+ } else {
+ ret = SMB_VFS_FSTATAT(fsp->conn,
+ dirfsp,
+ smb_fname_rel,
+ &fsp->fsp_name->st,
+ AT_SYMLINK_NOFOLLOW);
+ }
+ if (ret == -1) {
+ status = map_nt_error_from_unix(errno);
+ DBG_DEBUG("SMB_VFS_%sSTAT(%s/%s) failed: %s\n",
+ (fd >= 0) ? "F" : "",
+ dirfsp->fsp_name->base_name,
+ smb_fname_rel->base_name,
+ nt_errstr(status));
+ fd_close(fsp);
+ file_free(NULL, fsp);
+ return status;
+ }
+
+ fsp->fsp_flags.is_directory = S_ISDIR(fsp->fsp_name->st.st_ex_mode);
+ fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
+
+ smb_fname_rel->st = fsp->fsp_name->st;
+
+ status = fsp_smb_fname_link(fsp,
+ &smb_fname_rel->fsp_link,
+ &smb_fname_rel->fsp);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("fsp_smb_fname_link() failed: %s\n",
+ nt_errstr(status));
+ fd_close(fsp);
+ file_free(NULL, fsp);
+ return status;
+ }
+
+ DBG_DEBUG("fsp [%s]: OK, fd=%d\n", fsp_str_dbg(fsp), fd);
+
+ talloc_set_destructor(smb_fname_rel, smb_fname_fsp_destructor);
+ return NT_STATUS_OK;
+}
+
void smb_fname_fsp_unlink(struct smb_filename *smb_fname)
{
talloc_set_destructor(smb_fname, NULL);
goto fail;
}
+ if (!(create_options & FILE_OPEN_REPARSE_POINT) &&
+ (smb_fname->fsp != NULL) && /* new files don't have an fsp */
+ VALID_STAT(smb_fname->fsp->fsp_name->st))
+ {
+ mode_t type = (smb_fname->fsp->fsp_name->st.st_ex_mode &
+ S_IFMT);
+
+ switch (type) {
+ case S_IFREG:
+ FALL_THROUGH;
+ case S_IFDIR:
+ break;
+ case S_IFLNK:
+ /*
+ * We should never get this far with a symlink
+ * "as such". Report as not existing.
+ */
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ goto fail;
+ default:
+ status = NT_STATUS_IO_REPARSE_TAG_NOT_HANDLED;
+ goto fail;
+ }
+ }
+
if (req == NULL) {
oplock_request |= INTERNAL_OPEN_ONLY;
}
bool posix,
struct smb_filename **_smb_fname,
struct open_symlink_err **_symlink_err);
+NTSTATUS openat_pathref_fsp_lcomp(struct files_struct *dirfsp,
+ struct smb_filename *smb_fname_rel,
+ uint32_t ucf_flags);
NTSTATUS readlink_talloc(
TALLOC_CTX *mem_ctx,
struct files_struct *dirfsp,
&state->info,
&in_context_blobs,
state->out_context_blobs);
+ if (NT_STATUS_IS_OK(status) &&
+ !(state->in_create_options & FILE_OPEN_REPARSE_POINT))
+ {
+
+ mode_t mode = state->result->fsp_name->st.st_ex_mode;
+
+ if (!(S_ISREG(mode) || S_ISDIR(mode))) {
+ /*
+ * Only open files and dirs without
+ * FILE_OPEN_REPARSE_POINT
+ */
+ close_file_free(smb1req, &state->result, ERROR_CLOSE);
+ status = NT_STATUS_IO_REPARSE_TAG_NOT_HANDLED;
+ }
+ }
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(smb1req->xconn, smb1req->mid)) {
SMBPROFILE_IOBYTES_ASYNC_SET_IDLE(smb2req->profile);