summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorTim Prouty <tprouty@samba.org>2009-06-22 15:26:56 -0700
committerTim Prouty <tprouty@samba.org>2009-06-24 21:15:25 -0700
commite129384d7c1df664e447186673dd107e190e2894 (patch)
tree166c08e9d2ee0bbb8a88fb2ad76ed226a62f83dc /source3/smbd
parent36c10191750c845a2a7cd6cc62149b1095c0b651 (diff)
downloadsamba-e129384d7c1df664e447186673dd107e190e2894.tar.gz
samba-e129384d7c1df664e447186673dd107e190e2894.tar.bz2
samba-e129384d7c1df664e447186673dd107e190e2894.zip
s3: Plumb smb_filename through SMB_VFS_STAT and SMB_VFS_LSTAT
This patch introduces two new temporary helper functions vfs_stat_smb_fname and vfs_lstat_smb_fname. They basically allowed me to call the new smb_filename version of stat, while avoiding plumbing it through callers that are still too inconvenient. As the conversion moves along, I will be able to remove callers of this, with the goal being to remove all callers. There was also a bug in create_synthetic_smb_fname_split (also a temporary utility function) that caused it to incorrectly handle filenames with ':'s in them when in posix mode. This is now fixed.
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/close.c10
-rw-r--r--source3/smbd/dir.c106
-rw-r--r--source3/smbd/dosmode.c4
-rw-r--r--source3/smbd/file_access.c123
-rw-r--r--source3/smbd/fileio.c2
-rw-r--r--source3/smbd/filename.c111
-rw-r--r--source3/smbd/msdfs.c2
-rw-r--r--source3/smbd/notify.c32
-rw-r--r--source3/smbd/open.c126
-rw-r--r--source3/smbd/posix_acls.c13
-rw-r--r--source3/smbd/reply.c133
-rw-r--r--source3/smbd/service.c18
-rw-r--r--source3/smbd/statcache.c2
-rw-r--r--source3/smbd/trans2.c164
-rw-r--r--source3/smbd/vfs.c110
15 files changed, 573 insertions, 383 deletions
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 760a2d520c..ad21cf1d40 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -377,9 +377,9 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
hasn't been renamed. */
if (fsp->posix_open) {
- ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
+ ret = vfs_lstat_smb_fname(conn,fsp->fsp_name,&sbuf);
} else {
- ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
+ ret = vfs_stat_smb_fname(conn,fsp->fsp_name,&sbuf);
}
if (ret != 0) {
@@ -502,9 +502,11 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
ret = SMB_VFS_FSTAT(fsp, &sbuf);
} else {
if (fsp->posix_open) {
- ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name,&sbuf);
+ ret = vfs_lstat_smb_fname(fsp->conn, fsp->fsp_name,
+ &sbuf);
} else {
- ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf);
+ ret = vfs_stat_smb_fname(fsp->conn, fsp->fsp_name,
+ &sbuf);
}
}
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index fb246cdf8c..aff30a6967 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -574,11 +574,13 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx,
long *poffset,
SMB_STRUCT_STAT *pst)
{
+ struct smb_filename *smb_fname_base = NULL;
char *name = NULL;
char *pathreal = NULL;
char *found_name = NULL;
int ret;
const char *name_temp = NULL;
+ NTSTATUS status;
SET_STAT_INVALID(*pst);
@@ -624,10 +626,20 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx,
if (!pathreal)
return NULL;
- if (SMB_VFS_STAT(dptr->conn, pathreal, pst) == 0) {
+ /* Create an smb_filename with stream_name == NULL. */
+ status = create_synthetic_smb_fname(ctx, pathreal, NULL, NULL,
+ &smb_fname_base);
+ if (!NT_STATUS_IS_OK(status)) {
+ return NULL;
+ }
+
+ if (SMB_VFS_STAT(dptr->conn, smb_fname_base) == 0) {
+ *pst = smb_fname_base->st;
+ TALLOC_FREE(smb_fname_base);
name = talloc_strdup(ctx, dptr->wcard);
goto clean;
} else {
+ TALLOC_FREE(smb_fname_base);
/* If we get any other error than ENOENT or ENOTDIR
then the file exists we just can't stat it. */
if (errno != ENOENT && errno != ENOTDIR) {
@@ -893,12 +905,32 @@ bool get_dir_entry(TALLOC_CTX *ctx,
return False;
}
- if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
- DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",
- pathreal, strerror(errno) ));
- TALLOC_FREE(pathreal);
- TALLOC_FREE(filename);
- continue;
+ if (!VALID_STAT(sbuf)) {
+ struct smb_filename *smb_fname = NULL;
+ NTSTATUS status;
+
+ /* Create smb_fname with NULL stream_name. */
+ status =
+ create_synthetic_smb_fname(ctx, pathreal,
+ NULL, NULL,
+ &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(pathreal);
+ TALLOC_FREE(filename);
+ return NULL;
+ }
+
+ if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
+ DEBUG(5,("Couldn't stat 1 [%s]. Error "
+ "= %s\n", pathreal,
+ strerror(errno)));
+ TALLOC_FREE(smb_fname);
+ TALLOC_FREE(pathreal);
+ TALLOC_FREE(filename);
+ continue;
+ }
+ sbuf = smb_fname->st;
+ TALLOC_FREE(smb_fname);
}
*mode = dos_mode(conn,pathreal,&sbuf);
@@ -953,7 +985,8 @@ bool get_dir_entry(TALLOC_CTX *ctx,
use it for anything security sensitive.
********************************************************************/
-static bool user_can_read_file(connection_struct *conn, char *name)
+static bool user_can_read_file(connection_struct *conn,
+ struct smb_filename *smb_fname)
{
/*
* If user is a member of the Admin group
@@ -964,7 +997,7 @@ static bool user_can_read_file(connection_struct *conn, char *name)
return True;
}
- return can_access_file_acl(conn, name, FILE_READ_DATA);
+ return can_access_file_acl(conn, smb_fname, FILE_READ_DATA);
}
/*******************************************************************
@@ -1029,6 +1062,10 @@ bool is_visible_file(connection_struct *conn, const char *dir_path,
bool hide_unreadable = lp_hideunreadable(SNUM(conn));
bool hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
bool hide_special = lp_hide_special_files(SNUM(conn));
+ char *entry = NULL;
+ struct smb_filename *smb_fname_base = NULL;
+ NTSTATUS status;
+ bool ret = false;
if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
return True; /* . and .. are always visible. */
@@ -1041,55 +1078,70 @@ bool is_visible_file(connection_struct *conn, const char *dir_path,
}
if (hide_unreadable || hide_unwriteable || hide_special) {
- char *entry = NULL;
-
entry = talloc_asprintf(talloc_tos(), "%s/%s", dir_path, name);
- if (!entry)
- return false;
+ if (!entry) {
+ ret = false;
+ goto out;
}
/* If it's a dfs symlink, ignore _hide xxxx_ options */
if (lp_host_msdfs() &&
lp_msdfs_root(SNUM(conn)) &&
is_msdfs_link(conn, entry, NULL)) {
- TALLOC_FREE(entry);
- return true;
+ ret = true;
+ goto out;
+ }
+
+ /* Create an smb_filename with stream_name == NULL. */
+ status = create_synthetic_smb_fname(talloc_tos(), entry, NULL,
+ NULL, &smb_fname_base);
+ if (!NT_STATUS_IS_OK(status)) {
+ ret = false;
+ goto out;
}
/* If the file name does not exist, there's no point checking
* the configuration options. We succeed, on the basis that the
* checks *might* have passed if the file was present.
*/
- if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, entry, pst) != 0))
+ if (!VALID_STAT(*pst) &&
+ (SMB_VFS_STAT(conn, smb_fname_base) != 0))
{
- TALLOC_FREE(entry);
- return true;
+ ret = true;
+ goto out;
}
+ *pst = smb_fname_base->st;
+
/* Honour _hide unreadable_ option */
- if (hide_unreadable && !user_can_read_file(conn, entry)) {
+ if (hide_unreadable &&
+ !user_can_read_file(conn, smb_fname_base)) {
DEBUG(10,("is_visible_file: file %s is unreadable.\n",
entry ));
- TALLOC_FREE(entry);
- return false;
+ ret = false;
+ goto out;
}
/* Honour _hide unwriteable_ option */
if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
DEBUG(10,("is_visible_file: file %s is unwritable.\n",
entry ));
- TALLOC_FREE(entry);
- return false;
+ ret = false;
+ goto out;
}
/* Honour _hide_special_ option */
if (hide_special && file_is_special(conn, entry, pst)) {
DEBUG(10,("is_visible_file: file %s is special.\n",
entry ));
- TALLOC_FREE(entry);
- return false;
+ ret = false;
+ goto out;
}
- TALLOC_FREE(entry);
}
- return true;
+
+ ret = true;
+ out:
+ TALLOC_FREE(smb_fname_base);
+ TALLOC_FREE(entry);
+ return ret;
}
static int smb_Dir_destructor(struct smb_Dir *dirp)
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 8149eea7f5..afebb9efd0 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -81,7 +81,7 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname,
DEBUG(2, ("unix_mode(%s) inheriting from %s\n", fname,
inherit_from_dir));
- if (SMB_VFS_STAT(conn, inherit_from_dir, &sbuf) != 0) {
+ if (vfs_stat_smb_fname(conn, inherit_from_dir, &sbuf) != 0) {
DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n", fname,
inherit_from_dir, strerror(errno)));
return(0); /* *** shouldn't happen! *** */
@@ -560,7 +560,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
}
if (!VALID_STAT(*st)) {
- if (SMB_VFS_STAT(conn,fname,st))
+ if (vfs_stat_smb_fname(conn,fname,st))
return(-1);
}
diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c
index 195f722471..87d45c5e7f 100644
--- a/source3/smbd/file_access.c
+++ b/source3/smbd/file_access.c
@@ -27,18 +27,26 @@
* Security descriptor / NT Token level access check function.
*/
bool can_access_file_acl(struct connection_struct *conn,
- const char * fname,
- uint32_t access_mask)
+ const struct smb_filename *smb_fname,
+ uint32_t access_mask)
{
NTSTATUS status;
uint32_t access_granted;
struct security_descriptor *secdesc = NULL;
+ char *fname = NULL;
+ bool ret;
if (conn->server_info->utok.uid == 0 || conn->admin_user) {
/* I'm sorry sir, I didn't know you were root... */
return true;
}
+ status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ ret = false;
+ goto out;
+ }
+
status = SMB_VFS_GET_NT_ACL(conn, fname,
(OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
@@ -46,13 +54,17 @@ bool can_access_file_acl(struct connection_struct *conn,
&secdesc);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5, ("Could not get acl: %s\n", nt_errstr(status)));
- return false;
+ ret = false;
+ goto out;
}
status = se_access_check(secdesc, conn->server_info->ptok,
access_mask, &access_granted);
+ ret = NT_STATUS_IS_OK(status);
+ out:
+ TALLOC_FREE(fname);
TALLOC_FREE(secdesc);
- return NT_STATUS_IS_OK(status);
+ return ret;
}
/****************************************************************************
@@ -61,11 +73,13 @@ bool can_access_file_acl(struct connection_struct *conn,
****************************************************************************/
bool can_delete_file_in_directory(connection_struct *conn,
- const struct smb_filename *smb_fname)
+ struct smb_filename *smb_fname)
{
- SMB_STRUCT_STAT sbuf;
TALLOC_CTX *ctx = talloc_tos();
char *dname = NULL;
+ struct smb_filename *smb_fname_parent = NULL;
+ NTSTATUS status;
+ bool ret;
if (!CAN_WRITE(conn)) {
return False;
@@ -75,47 +89,49 @@ bool can_delete_file_in_directory(connection_struct *conn,
if (!parent_dirname(ctx, smb_fname->base_name, &dname, NULL)) {
return False;
}
- if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) {
- return False;
+
+ status = create_synthetic_smb_fname(ctx, dname, NULL, NULL,
+ &smb_fname_parent);
+ if (!NT_STATUS_IS_OK(status)) {
+ ret = false;
+ goto out;
+ }
+
+ if(SMB_VFS_STAT(conn, smb_fname_parent) != 0) {
+ ret = false;
+ goto out;
}
/* fast paths first */
- if (!S_ISDIR(sbuf.st_ex_mode)) {
- return False;
+ if (!S_ISDIR(smb_fname_parent->st.st_ex_mode)) {
+ ret = false;
+ goto out;
}
if (conn->server_info->utok.uid == 0 || conn->admin_user) {
/* I'm sorry sir, I didn't know you were root... */
- return True;
+ ret = true;
+ goto out;
}
#ifdef S_ISVTX
/* sticky bit means delete only by owner of file or by root or
* by owner of directory. */
- if (sbuf.st_ex_mode & S_ISVTX) {
- SMB_STRUCT_STAT sbuf_file;
- char *fname = NULL;
- NTSTATUS status;
-
- status = get_full_smb_filename(talloc_tos(), smb_fname,
- &fname);
- if (!NT_STATUS_IS_OK(status)) {
- return false;
- }
- if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) {
- TALLOC_FREE(fname);
+ if (smb_fname_parent->st.st_ex_mode & S_ISVTX) {
+ if(SMB_VFS_STAT(conn, smb_fname) != 0) {
if (errno == ENOENT) {
/* If the file doesn't already exist then
* yes we'll be able to delete it. */
- return True;
+ ret = true;
+ goto out;
}
DEBUG(10,("can_delete_file_in_directory: can't "
"stat file %s (%s)",
smb_fname_str_dbg(smb_fname),
strerror(errno) ));
- return False;
+ ret = false;
+ goto out;
}
- TALLOC_FREE(fname);
/*
* Patch from SATOH Fumiyasu <fumiyas@miraclelinux.com>
@@ -125,12 +141,15 @@ bool can_delete_file_in_directory(connection_struct *conn,
* or the owner of the directory as we have no possible
* chance of deleting. Otherwise, go on and check the ACL.
*/
- if ((conn->server_info->utok.uid != sbuf.st_ex_uid) &&
- (conn->server_info->utok.uid != sbuf_file.st_ex_uid)) {
+ if ((conn->server_info->utok.uid !=
+ smb_fname_parent->st.st_ex_uid) &&
+ (conn->server_info->utok.uid != smb_fname->st.st_ex_uid)) {
DEBUG(10,("can_delete_file_in_directory: not "
"owner of file %s or directory %s",
- smb_fname_str_dbg(smb_fname), dname));
- return False;
+ smb_fname_str_dbg(smb_fname),
+ smb_fname_str_dbg(smb_fname_parent)));
+ ret = false;
+ goto out;
}
}
#endif
@@ -146,7 +165,11 @@ bool can_delete_file_in_directory(connection_struct *conn,
* check the file DELETE permission separately.
*/
- return can_access_file_acl(conn, dname, FILE_DELETE_CHILD);
+ ret = can_access_file_acl(conn, smb_fname_parent, FILE_DELETE_CHILD);
+ out:
+ TALLOC_FREE(dname);
+ TALLOC_FREE(smb_fname_parent);
+ return ret;
}
/****************************************************************************
@@ -155,7 +178,9 @@ bool can_delete_file_in_directory(connection_struct *conn,
Note this doesn't take into account share write permissions.
****************************************************************************/
-bool can_access_file_data(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf, uint32 access_mask)
+bool can_access_file_data(connection_struct *conn,
+ const struct smb_filename *smb_fname,
+ uint32 access_mask)
{
if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) {
return False;
@@ -165,27 +190,31 @@ bool can_access_file_data(connection_struct *conn, const char *fname, const SMB_
/* some fast paths first */
DEBUG(10,("can_access_file_data: requesting 0x%x on file %s\n",
- (unsigned int)access_mask, fname ));
+ (unsigned int)access_mask, smb_fname_str_dbg(smb_fname)));
if (conn->server_info->utok.uid == 0 || conn->admin_user) {
/* I'm sorry sir, I didn't know you were root... */
return True;
}
- SMB_ASSERT(psbuf && VALID_STAT(*psbuf));
+ SMB_ASSERT(VALID_STAT(smb_fname->st));
/* Check primary owner access. */
- if (conn->server_info->utok.uid == psbuf->st_ex_uid) {
+ if (conn->server_info->utok.uid == smb_fname->st.st_ex_uid) {
switch (access_mask) {
case FILE_READ_DATA:
- return (psbuf->st_ex_mode & S_IRUSR) ? True : False;
+ return (smb_fname->st.st_ex_mode & S_IRUSR) ?
+ True : False;
case FILE_WRITE_DATA:
- return (psbuf->st_ex_mode & S_IWUSR) ? True : False;
+ return (smb_fname->st.st_ex_mode & S_IWUSR) ?
+ True : False;
default: /* FILE_READ_DATA|FILE_WRITE_DATA */
- if ((psbuf->st_ex_mode & (S_IWUSR|S_IRUSR)) == (S_IWUSR|S_IRUSR)) {
+ if ((smb_fname->st.st_ex_mode &
+ (S_IWUSR|S_IRUSR)) ==
+ (S_IWUSR|S_IRUSR)) {
return True;
} else {
return False;
@@ -195,7 +224,7 @@ bool can_access_file_data(connection_struct *conn, const char *fname, const SMB_
/* now for ACL checks */
- return can_access_file_acl(conn, fname, access_mask);
+ return can_access_file_acl(conn, smb_fname, access_mask);
}
/****************************************************************************
@@ -205,7 +234,21 @@ bool can_access_file_data(connection_struct *conn, const char *fname, const SMB_
bool can_write_to_file(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf)
{
- return can_access_file_data(conn, fname, psbuf, FILE_WRITE_DATA);
+ struct smb_filename *smb_fname;
+ NTSTATUS status;
+ bool ret;
+
+ status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
+ &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+
+ ret = can_access_file_data(conn, smb_fname, FILE_WRITE_DATA);
+
+ TALLOC_FREE(smb_fname);
+
+ return ret;
}
/****************************************************************************
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index de5f83c868..843b3f9586 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -949,7 +949,7 @@ NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_throug
int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst)
{
if (fsp->fh->fd == -1) {
- return SMB_VFS_STAT(fsp->conn, fsp->fsp_name, pst);
+ return vfs_stat_smb_fname(fsp->conn, fsp->fsp_name, pst);
} else {
return SMB_VFS_FSTAT(fsp, pst);
}
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 9854407a70..bf12e86d53 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -110,7 +110,7 @@ NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx, const struct smb_filename *smb_f
*/
NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name,
const char *stream_name,
- SMB_STRUCT_STAT *psbuf,
+ const SMB_STRUCT_STAT *psbuf,
struct smb_filename **smb_fname_out)
{
struct smb_filename smb_fname_loc;
@@ -135,15 +135,18 @@ NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name,
*/
NTSTATUS create_synthetic_smb_fname_split(TALLOC_CTX *ctx,
const char *fname,
- SMB_STRUCT_STAT *psbuf,
+ const SMB_STRUCT_STAT *psbuf,
struct smb_filename **smb_fname_out)
{
NTSTATUS status;
const char *stream_name = NULL;
char *base_name = NULL;
+ if (!lp_posix_pathnames()) {
+ stream_name = strchr_m(fname, ':');
+ }
+
/* Setup the base_name/stream_name. */
- stream_name = strchr_m(fname, ':');
if (stream_name) {
base_name = talloc_strndup(ctx, fname,
PTR_DIFF(stream_name, fname));
@@ -162,6 +165,60 @@ NTSTATUS create_synthetic_smb_fname_split(TALLOC_CTX *ctx,
}
/**
+ * XXX: This is temporary and there should be no callers of this once
+ * smb_filename is plumbed through all path based operations.
+ */
+int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname,
+ SMB_STRUCT_STAT *psbuf)
+{
+ struct smb_filename *smb_fname = NULL;
+ NTSTATUS status;
+ int ret;
+
+ status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL,
+ &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = map_errno_from_nt_status(status);
+ return -1;
+ }
+
+ ret = SMB_VFS_STAT(conn, smb_fname);
+ if (ret != -1) {
+ *psbuf = smb_fname->st;
+ }
+
+ TALLOC_FREE(smb_fname);
+ return ret;
+}
+
+/**
+ * XXX: This is temporary and there should be no callers of this once
+ * smb_filename is plumbed through all path based operations.
+ */
+int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname,
+ SMB_STRUCT_STAT *psbuf)
+{
+ struct smb_filename *smb_fname = NULL;
+ NTSTATUS status;
+ int ret;
+
+ status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL,
+ &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = map_errno_from_nt_status(status);
+ return -1;
+ }
+
+ ret = SMB_VFS_LSTAT(conn, smb_fname);
+ if (ret != -1) {
+ *psbuf = smb_fname->st;
+ }
+
+ TALLOC_FREE(smb_fname);
+ return ret;
+}
+
+/**
* Return a string using the debug_ctx()
*/
const char *smb_fname_str_dbg(const struct smb_filename *smb_fname)
@@ -315,7 +372,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
if (!(name = talloc_strdup(ctx,"."))) {
return NT_STATUS_NO_MEMORY;
}
- if (SMB_VFS_STAT(conn,name,&st) == 0) {
+ if (vfs_stat_smb_fname(conn,name,&st) == 0) {
smb_fname->st = st;
} else {
return map_nt_error_from_unix(errno);
@@ -417,9 +474,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
*/
if (posix_pathnames) {
- ret = SMB_VFS_LSTAT(conn,name,&st);
+ ret = vfs_lstat_smb_fname(conn,name,&st);
} else {
- ret = SMB_VFS_STAT(conn,name,&st);
+ ret = vfs_stat_smb_fname(conn,name,&st);
}
if (ret == 0) {
@@ -535,9 +592,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
*/
if (posix_pathnames) {
- ret = SMB_VFS_LSTAT(conn,name, &st);
+ ret = vfs_lstat_smb_fname(conn,name, &st);
} else {
- ret = SMB_VFS_STAT(conn,name, &st);
+ ret = vfs_stat_smb_fname(conn,name, &st);
}
if (ret == 0) {
@@ -764,9 +821,11 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
*/
if (posix_pathnames) {
- ret = SMB_VFS_LSTAT(conn,name, &st);
+ ret = vfs_lstat_smb_fname(conn,name,
+ &st);
} else {
- ret = SMB_VFS_STAT(conn,name, &st);
+ ret = vfs_stat_smb_fname(conn,name,
+ &st);
}
if (ret == 0) {
@@ -1073,17 +1132,11 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
const char *orig_path,
struct smb_filename *smb_fname)
{
- char *result = NULL;
NTSTATUS status;
unsigned int i, num_streams;
struct stream_struct *streams = NULL;
- status = get_full_smb_filename(mem_ctx, smb_fname, &result);
- if (!NT_STATUS_IS_OK(status)) {
- return NT_STATUS_NO_MEMORY;
- }
-
- if (SMB_VFS_STAT(conn, result, &smb_fname->st) == 0) {
+ if (SMB_VFS_STAT(conn, smb_fname) == 0) {
return NT_STATUS_OK;
}
@@ -1132,24 +1185,22 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
TALLOC_FREE(smb_fname->stream_name);
smb_fname->stream_name = talloc_strdup(mem_ctx, streams[i].name);
- TALLOC_FREE(result);
- status = get_full_smb_filename(mem_ctx, smb_fname, &result);
- if (!NT_STATUS_IS_OK(status)) {
- status = NT_STATUS_NO_MEMORY;
- goto fail;
- }
-
SET_STAT_INVALID(smb_fname->st);
- if (SMB_VFS_STAT(conn, result, &smb_fname->st) == 0) {
- stat_cache_add(orig_path, result, conn->case_sensitive);
- }
+ if (SMB_VFS_STAT(conn, smb_fname) == 0) {
+ char *result = NULL;
- TALLOC_FREE(streams);
- return NT_STATUS_OK;
+ status = get_full_smb_filename(mem_ctx, smb_fname, &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+ stat_cache_add(orig_path, result, conn->case_sensitive);
+ TALLOC_FREE(result);
+ }
+ status = NT_STATUS_OK;
fail:
- TALLOC_FREE(result);
TALLOC_FREE(streams);
return status;
}
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index e2f31f077c..e6f877cfbb 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -437,7 +437,7 @@ static bool is_msdfs_link_internal(TALLOC_CTX *ctx,
sbufp = &st;
}
- if (SMB_VFS_LSTAT(conn, path, sbufp) != 0) {
+ if (vfs_lstat_smb_fname(conn, path, sbufp) != 0) {
DEBUG(5,("is_msdfs_link_read_target: %s does not exist.\n",
path));
goto err;
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index 12a75cc9f6..a242fc3ac0 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -341,25 +341,35 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter,
char *fullpath;
char *parent;
const char *name;
- SMB_STRUCT_STAT sbuf;
if (path[0] == '.' && path[1] == '/') {
path += 2;
}
- if (asprintf(&fullpath, "%s/%s", conn->connectpath, path) == -1) {
- DEBUG(0, ("asprintf failed\n"));
- return;
+ if (parent_dirname(talloc_tos(), path, &parent, &name)) {
+ struct smb_filename *smb_fname_parent = NULL;
+ NTSTATUS status;
+
+ status = create_synthetic_smb_fname(talloc_tos(), parent, NULL,
+ NULL, &smb_fname_parent);
+ if (!NT_STATUS_IS_OK(status)) {
+ return;
+ }
+ if (SMB_VFS_STAT(conn, smb_fname_parent) != -1) {
+ notify_onelevel(conn->notify_ctx, action, filter,
+ SMB_VFS_FILE_ID_CREATE(conn, &smb_fname_parent->st),
+ name);
+ }
+ TALLOC_FREE(smb_fname_parent);
}
- if (parent_dirname(talloc_tos(), path, &parent, &name)
- && (SMB_VFS_STAT(conn, parent, &sbuf) != -1)) {
- notify_onelevel(conn->notify_ctx, action, filter,
- SMB_VFS_FILE_ID_CREATE(conn, &sbuf),
- name);
+ fullpath = talloc_asprintf(talloc_tos(), "%s/%s", conn->connectpath,
+ path);
+ if (fullpath == NULL) {
+ DEBUG(0, ("asprintf failed\n"));
+ return;
}
-
notify_trigger(conn->notify_ctx, action, filter, fullpath);
- SAFE_FREE(fullpath);
+ TALLOC_FREE(fullpath);
}
static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 72370c8c7c..5b62ff022d 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -193,31 +193,41 @@ void change_file_owner_to_parent(connection_struct *conn,
const char *inherit_from_dir,
files_struct *fsp)
{
- SMB_STRUCT_STAT parent_st;
+ struct smb_filename *smb_fname_parent = NULL;
+ NTSTATUS status;
int ret;
- ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
+ status = create_synthetic_smb_fname(talloc_tos(), inherit_from_dir,
+ NULL, NULL, &smb_fname_parent);
+ if (!NT_STATUS_IS_OK(status)) {
+ return;
+ }
+
+ ret = SMB_VFS_STAT(conn, smb_fname_parent);
if (ret == -1) {
DEBUG(0,("change_file_owner_to_parent: failed to stat parent "
"directory %s. Error was %s\n",
- inherit_from_dir, strerror(errno) ));
+ smb_fname_str_dbg(smb_fname_parent),
+ strerror(errno)));
return;
}
become_root();
- ret = SMB_VFS_FCHOWN(fsp, parent_st.st_ex_uid, (gid_t)-1);
+ ret = SMB_VFS_FCHOWN(fsp, smb_fname_parent->st.st_ex_uid, (gid_t)-1);
unbecome_root();
if (ret == -1) {
DEBUG(0,("change_file_owner_to_parent: failed to fchown "
"file %s to parent directory uid %u. Error "
"was %s\n", fsp->fsp_name,
- (unsigned int)parent_st.st_ex_uid,
+ (unsigned int)smb_fname_parent->st.st_ex_uid,
strerror(errno) ));
}
DEBUG(10,("change_file_owner_to_parent: changed new file %s to "
"parent directory uid %u.\n", fsp->fsp_name,
- (unsigned int)parent_st.st_ex_uid ));
+ (unsigned int)smb_fname_parent->st.st_ex_uid));
+
+ TALLOC_FREE(smb_fname_parent);
}
NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
@@ -225,20 +235,27 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
const char *fname,
SMB_STRUCT_STAT *psbuf)
{
+ struct smb_filename *smb_fname_parent = NULL;
+ struct smb_filename *smb_fname_cwd = NULL;
char *saved_dir = NULL;
- SMB_STRUCT_STAT sbuf;
- SMB_STRUCT_STAT parent_st;
TALLOC_CTX *ctx = talloc_tos();
NTSTATUS status = NT_STATUS_OK;
int ret;
- ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
+ status = create_synthetic_smb_fname(ctx, inherit_from_dir, NULL, NULL,
+ &smb_fname_parent);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ ret = SMB_VFS_STAT(conn, smb_fname_parent);
if (ret == -1) {
status = map_nt_error_from_unix(errno);
DEBUG(0,("change_dir_owner_to_parent: failed to stat parent "
"directory %s. Error was %s\n",
- inherit_from_dir, strerror(errno) ));
- return status;
+ smb_fname_str_dbg(smb_fname_parent),
+ strerror(errno)));
+ goto out;
}
/* We've already done an lstat into psbuf, and we know it's a
@@ -254,7 +271,7 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
DEBUG(0,("change_dir_owner_to_parent: failed to get "
"current working directory. Error was %s\n",
strerror(errno)));
- return status;
+ goto out;
}
/* Chdir into the new path. */
@@ -263,47 +280,58 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
DEBUG(0,("change_dir_owner_to_parent: failed to change "
"current working directory to %s. Error "
"was %s\n", fname, strerror(errno) ));
- goto out;
+ goto chdir;
+ }
+
+ status = create_synthetic_smb_fname(ctx, ".", NULL, NULL,
+ &smb_fname_cwd);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- if (SMB_VFS_STAT(conn,".",&sbuf) == -1) {
+ ret = SMB_VFS_STAT(conn, smb_fname_cwd);
+ if (ret == -1) {
status = map_nt_error_from_unix(errno);
DEBUG(0,("change_dir_owner_to_parent: failed to stat "
"directory '.' (%s) Error was %s\n",
fname, strerror(errno)));
- goto out;
+ goto chdir;
}
/* Ensure we're pointing at the same place. */
- if (sbuf.st_ex_dev != psbuf->st_ex_dev ||
- sbuf.st_ex_ino != psbuf->st_ex_ino ||
- sbuf.st_ex_mode != psbuf->st_ex_mode ) {
+ if (smb_fname_cwd->st.st_ex_dev != psbuf->st_ex_dev ||
+ smb_fname_cwd->st.st_ex_ino != psbuf->st_ex_ino ||
+ smb_fname_cwd->st.st_ex_mode != psbuf->st_ex_mode ) {
DEBUG(0,("change_dir_owner_to_parent: "
"device/inode/mode on directory %s changed. "
"Refusing to chown !\n", fname ));
status = NT_STATUS_ACCESS_DENIED;
- goto out;
+ goto chdir;
}
become_root();
- ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_ex_uid, (gid_t)-1);
+ ret = SMB_VFS_CHOWN(conn, ".", smb_fname_parent->st.st_ex_uid,
+ (gid_t)-1);
unbecome_root();
if (ret == -1) {
status = map_nt_error_from_unix(errno);
DEBUG(10,("change_dir_owner_to_parent: failed to chown "
"directory %s to parent directory uid %u. "
"Error was %s\n", fname,
- (unsigned int)parent_st.st_ex_uid, strerror(errno) ));
- goto out;
+ (unsigned int)smb_fname_parent->st.st_ex_uid,
+ strerror(errno) ));
+ goto chdir;
}
DEBUG(10,("change_dir_owner_to_parent: changed ownership of new "
"directory %s to parent directory uid %u.\n",
- fname, (unsigned int)parent_st.st_ex_uid ));
-
- out:
+ fname, (unsigned int)smb_fname_parent->st.st_ex_uid ));
+ chdir:
vfs_ChDir(conn,saved_dir);
+ out:
+ TALLOC_FREE(smb_fname_parent);
+ TALLOC_FREE(smb_fname_cwd);
return status;
}
@@ -537,7 +565,7 @@ static NTSTATUS open_file(files_struct *fsp,
int ret;
if (fsp->fh->fd == -1) {
- ret = SMB_VFS_STAT(conn, path, &smb_fname->st);
+ ret = SMB_VFS_STAT(conn, smb_fname);
} else {
ret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
/* If we have an fd, this stat should succeed. */
@@ -1857,8 +1885,10 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
can_access_mask = FILE_READ_DATA;
}
- if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) ||
- !can_access_file_data(conn, fname, &smb_fname->st, can_access_mask)) {
+ if (((can_access_mask & FILE_WRITE_DATA) &&
+ !CAN_WRITE(conn)) ||
+ !can_access_file_data(conn, smb_fname,
+ can_access_mask)) {
can_access = False;
}
@@ -2347,7 +2377,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
/* Ensure we're checking for a symlink here.... */
/* We don't want to get caught by a symlink racer. */
- if (SMB_VFS_LSTAT(conn, name, psbuf) == -1) {
+ if (vfs_lstat_smb_fname(conn, name, psbuf) == -1) {
DEBUG(2, ("Could not stat directory '%s' just created: %s\n",
name, strerror(errno)));
return map_nt_error_from_unix(errno);
@@ -2471,7 +2501,7 @@ static NTSTATUS open_directory(connection_struct *conn,
* We want to follow symlinks here.
*/
- if (SMB_VFS_STAT(conn, fname, &smb_dname->st) != 0) {
+ if (SMB_VFS_STAT(conn, smb_dname) != 0) {
return map_nt_error_from_unix(errno);
}
@@ -2836,34 +2866,24 @@ NTSTATUS open_streams_for_delete(connection_struct *conn,
for (i=0; i<num_streams; i++) {
struct smb_filename *smb_fname = NULL;
- char *streamname = NULL;
- SMB_STRUCT_STAT sbuf;
if (strequal(stream_info[i].name, "::$DATA")) {
streams[i] = NULL;
continue;
}
- streamname = talloc_asprintf(talloc_tos(), "%s%s", fname,
- stream_info[i].name);
- if (streamname == NULL) {
- DEBUG(0, ("talloc_aprintf failed\n"));
- status = NT_STATUS_NO_MEMORY;
- }
-
- if (SMB_VFS_STAT(conn, streamname, &sbuf) == -1) {
- SET_STAT_INVALID(sbuf);
- }
-
- TALLOC_FREE(streamname);
-
status = create_synthetic_smb_fname(talloc_tos(), fname,
stream_info[i].name,
- &sbuf, &smb_fname);
+ NULL, &smb_fname);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
+ if (SMB_VFS_STAT(conn, smb_fname) == -1) {
+ DEBUG(10, ("Unable to stat stream: %s\n",
+ smb_fname_str_dbg(smb_fname)));
+ }
+
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
NULL, /* req */
@@ -2999,7 +3019,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
&& (share_access & FILE_SHARE_DELETE)
&& (access_mask & DELETE_ACCESS)
&& (!(can_delete_file_in_directory(conn, smb_fname) ||
- can_access_file_acl(conn, fname, DELETE_ACCESS)))) {
+ can_access_file_acl(conn, smb_fname, DELETE_ACCESS)))) {
status = NT_STATUS_ACCESS_DENIED;
DEBUG(10,("create_file_unixpath: open file %s "
"for delete ACCESS_DENIED\n",
@@ -3036,7 +3056,6 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
&& (!(create_options & NTCREATEX_OPTIONS_PRIVATE_STREAM_DELETE))) {
uint32 base_create_disposition;
struct smb_filename *smb_fname_base = NULL;
- SMB_STRUCT_STAT sbuf;
if (create_options & FILE_DIRECTORY_FILE) {
status = NT_STATUS_NOT_A_DIRECTORY;
@@ -3052,19 +3071,20 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
break;
}
- if (SMB_VFS_STAT(conn, smb_fname->base_name, &sbuf) == -1) {
- SET_STAT_INVALID(sbuf);
- }
-
/* Create an smb_filename with stream_name == NULL. */
status = create_synthetic_smb_fname(talloc_tos(),
smb_fname->base_name,
- NULL, &sbuf,
+ NULL, NULL,
&smb_fname_base);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
+ if (SMB_VFS_STAT(conn, smb_fname_base) == -1) {
+ DEBUG(10, ("Unable to stat stream: %s\n",
+ smb_fname_str_dbg(smb_fname_base)));
+ }
+
/* Open the base file. */
status = create_file_unixpath(conn, NULL, smb_fname_base, 0,
FILE_SHARE_READ
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index bdd27fb794..437112c751 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -3351,7 +3351,7 @@ NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
DEBUG(10,("posix_get_nt_acl: called for file %s\n", name ));
/* Get the stat struct for the owner info. */
- if(SMB_VFS_STAT(conn, name, &sbuf) != 0) {
+ if(vfs_stat_smb_fname(conn, name, &sbuf) != 0) {
return map_nt_error_from_unix(errno);
}
@@ -3432,7 +3432,7 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
return -1;
}
- if (SMB_VFS_STAT(conn,fname,&st)) {
+ if (vfs_stat_smb_fname(conn,fname,&st)) {
return -1;
}
@@ -3685,7 +3685,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
*/
if(fsp->is_directory || fsp->fh->fd == -1) {
- if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0)
+ if(vfs_stat_smb_fname(fsp->conn,fsp->fsp_name, &sbuf) != 0)
return map_nt_error_from_unix(errno);
} else {
if(SMB_VFS_FSTAT(fsp, &sbuf) != 0)
@@ -3730,7 +3730,8 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
*/
if(fsp->is_directory) {
- if(SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf) != 0) {
+ if(vfs_stat_smb_fname(fsp->conn, fsp->fsp_name,
+ &sbuf) != 0) {
return map_nt_error_from_unix(errno);
}
} else {
@@ -3738,7 +3739,9 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
int sret;
if(fsp->fh->fd == -1)
- sret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf);
+ sret = vfs_stat_smb_fname(fsp->conn,
+ fsp->fsp_name,
+ &sbuf);
else
sret = SMB_VFS_FSTAT(fsp, &sbuf);
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 9544b845da..8cc865edeb 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -1007,8 +1007,9 @@ void reply_checkpath(struct smb_request *req)
}
if (!VALID_STAT(smb_fname->st) &&
- (SMB_VFS_STAT(conn, name, &smb_fname->st) != 0)) {
- DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
+ (SMB_VFS_STAT(conn, smb_fname) != 0)) {
+ DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
+ smb_fname_str_dbg(smb_fname), strerror(errno)));
status = map_nt_error_from_unix(errno);
goto path_err;
}
@@ -1020,17 +1021,8 @@ void reply_checkpath(struct smb_request *req)
}
reply_outbuf(req, 0, 0);
- out:
- TALLOC_FREE(smb_fname);
- END_PROFILE(SMBcheckpath);
- return;
path_err:
-
- TALLOC_FREE(smb_fname);
-
- END_PROFILE(SMBcheckpath);
-
/* We special case this - as when a Windows machine
is parsing a path is steps through the components
one at a time - if a component fails it expects
@@ -1047,10 +1039,15 @@ void reply_checkpath(struct smb_request *req)
*/
reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
ERRDOS, ERRbadpath);
- return;
+ goto out;
}
reply_nterror(req, status);
+
+ out:
+ TALLOC_FREE(smb_fname);
+ END_PROFILE(SMBcheckpath);
+ return;
}
/****************************************************************************
@@ -1104,8 +1101,10 @@ void reply_getatr(struct smb_request *req)
goto out;
}
if (!VALID_STAT(smb_fname->st) &&
- (SMB_VFS_STAT(conn, fname, &smb_fname->st) != 0)) {
- DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
+ (SMB_VFS_STAT(conn, smb_fname) != 0)) {
+ DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno)));
reply_unixerror(req, ERRDOS,ERRbadfile);
goto out;
}
@@ -1133,10 +1132,12 @@ void reply_getatr(struct smb_request *req)
SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
}
- DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
+ DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
+ smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
out:
TALLOC_FREE(smb_fname);
+ TALLOC_FREE(fname);
END_PROFILE(SMBgetatr);
return;
}
@@ -2243,8 +2244,7 @@ void reply_ctemp(struct smb_request *req)
goto out;
}
- SET_STAT_INVALID(smb_fname->st);
- SMB_VFS_STAT(conn, smb_fname->base_name, &smb_fname->st);
+ SMB_VFS_STAT(conn, smb_fname);
/* We should fail if file does not exist. */
status = SMB_VFS_CREATE_FILE(
@@ -2377,16 +2377,16 @@ static NTSTATUS do_unlink(connection_struct *conn,
return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
+ if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
+ return map_nt_error_from_unix(errno);
+ }
+
status = get_full_smb_filename(smb_fname, smb_fname, &fname);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
-
- if (SMB_VFS_LSTAT(conn, fname, &smb_fname->st) != 0) {
- return map_nt_error_from_unix(errno);
- }
-
fattr = dos_mode(conn, fname, &smb_fname->st);
+ TALLOC_FREE(fname);
if (dirtype & FILE_ATTRIBUTE_NORMAL) {
dirtype = aDIR|aARCH|aRONLY;
@@ -5259,6 +5259,8 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
while((dname = ReadDirName(dir_hnd, &offset, &st))) {
char *fullname = NULL;
+ struct smb_filename *smb_fname = NULL;
+ NTSTATUS status;
if (ISDOT(dname) || ISDOTDOT(dname)) {
continue;
@@ -5275,29 +5277,37 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
dname);
if (!fullname) {
errno = ENOMEM;
- ret = False;
- break;
+ goto err_break;
}
- if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
- ret = False;
- break;
+ status = create_synthetic_smb_fname(talloc_tos(), fullname,
+ NULL, NULL, &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err_break;
+ }
+
+ if(SMB_VFS_LSTAT(conn, smb_fname) != 0) {
+ goto err_break;
}
- if(st.st_ex_mode & S_IFDIR) {
+ if(smb_fname->st.st_ex_mode & S_IFDIR) {
if(!recursive_rmdir(ctx, conn, fullname)) {
- ret = False;
- break;
+ goto err_break;
}
if(SMB_VFS_RMDIR(conn,fullname) != 0) {
- ret = False;
- break;
+ goto err_break;
}
} else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
- ret = False;
- break;
+ goto err_break;
}
+ TALLOC_FREE(smb_fname);
+ TALLOC_FREE(fullname);
+ continue;
+ err_break:
+ TALLOC_FREE(smb_fname);
TALLOC_FREE(fullname);
+ ret = false;
+ break;
}
TALLOC_FREE(dir_hnd);
return ret;
@@ -5315,13 +5325,13 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
SMB_STRUCT_STAT st;
/* Might be a symlink. */
- if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
+ if(vfs_lstat_smb_fname(conn, directory, &st) != 0) {
return map_nt_error_from_unix(errno);
}
if (S_ISLNK(st.st_ex_mode)) {
/* Is what it points to a directory ? */
- if(SMB_VFS_STAT(conn, directory, &st) != 0) {
+ if(vfs_stat_smb_fname(conn, directory, &st) != 0) {
return map_nt_error_from_unix(errno);
}
if (!(S_ISDIR(st.st_ex_mode))) {
@@ -5398,7 +5408,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
break;
}
- if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
+ if(vfs_lstat_smb_fname(conn,fullname, &st) != 0) {
break;
}
if(st.st_ex_mode & S_IFDIR) {
@@ -5817,10 +5827,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
- /*
- * Have vfs_object_exist also fill sbuf1
- */
- dst_exists = vfs_object_exist(conn, newname, &sbuf1);
+ dst_exists = vfs_stat_smb_fname(conn, newname, &sbuf1) == 0;
if(!replace_if_exists && dst_exists) {
DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
@@ -5846,9 +5853,10 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
} else {
int ret = -1;
if (fsp->posix_open) {
- ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
+ ret = vfs_lstat_smb_fname(conn,fsp->fsp_name,&sbuf);
} else {
- ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
+
+ ret = vfs_stat_smb_fname(conn,fsp->fsp_name,&sbuf);
}
if (ret == -1) {
return map_nt_error_from_unix(errno);
@@ -6005,7 +6013,6 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
if (!src_has_wild) {
files_struct *fsp;
- char *fname_src = NULL;
char *fname_dst = NULL;
/*
@@ -6063,24 +6070,17 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
smb_fname_dst->base_name = fname_dst_mod;
}
- status = get_full_smb_filename(ctx, smb_fname_src, &fname_src);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
- }
-
ZERO_STRUCT(smb_fname_src->st);
if (posix_pathnames) {
- SMB_VFS_LSTAT(conn, fname_src, &smb_fname_src->st);
+ SMB_VFS_LSTAT(conn, smb_fname_src);
} else {
- SMB_VFS_STAT(conn, fname_src, &smb_fname_src->st);
+ SMB_VFS_STAT(conn, smb_fname_src);
}
if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
create_options |= FILE_DIRECTORY_FILE;
}
- TALLOC_FREE(fname_src);
-
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
@@ -6108,7 +6108,6 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
status = get_full_smb_filename(ctx, smb_fname_dst, &fname_dst);
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(fname_src);
goto out;
}
@@ -6159,7 +6158,6 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
files_struct *fsp = NULL;
- char *fname_src = NULL;
char *fname_dst = NULL;
char *destname = NULL;
bool sysdir_entry = False;
@@ -6212,20 +6210,13 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
TALLOC_FREE(smb_fname_dst->base_name);
smb_fname_dst->base_name = destname;
- status = get_full_smb_filename(ctx, smb_fname_src, &fname_src);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
- }
-
ZERO_STRUCT(smb_fname_src->st);
if (posix_pathnames) {
- SMB_VFS_LSTAT(conn, fname_src, &smb_fname_src->st);
+ SMB_VFS_LSTAT(conn, smb_fname_src);
} else {
- SMB_VFS_STAT(conn, fname_src, &smb_fname_src->st);
+ SMB_VFS_STAT(conn, smb_fname_src);
}
- TALLOC_FREE(fname_src);
-
create_options = 0;
if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
@@ -6416,7 +6407,6 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
{
struct smb_filename *smb_fname_dst_tmp = NULL;
char *fname_src = NULL;
- char *fname_dst = NULL;
SMB_OFF_T ret=-1;
files_struct *fsp1,*fsp2;
uint32 dosattrs;
@@ -6502,17 +6492,10 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
TALLOC_FREE(fname_src);
- status = get_full_smb_filename(talloc_tos(), smb_fname_dst_tmp, &fname_dst);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
- }
-
- if (SMB_VFS_STAT(conn, fname_dst, &smb_fname_dst_tmp->st) == -1) {
+ if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
ZERO_STRUCTP(&smb_fname_dst_tmp->st);
}
- TALLOC_FREE(fname_dst);
-
/* Open the dst file for writing. */
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
@@ -7509,9 +7492,9 @@ void reply_setattrE(struct smb_request *req)
int ret = -1;
if (fsp->posix_open) {
- ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
+ ret = vfs_lstat_smb_fname(conn, fsp->fsp_name, &sbuf);
} else {
- ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
+ ret = vfs_stat_smb_fname(conn, fsp->fsp_name, &sbuf);
}
if (ret == -1) {
status = map_nt_error_from_unix(errno);
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 508f71b44e..0124b2b047 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -643,7 +643,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
NTSTATUS *pstatus)
{
connection_struct *conn;
- SMB_STRUCT_STAT st;
+ struct smb_filename *smb_fname_cpath = NULL;
fstring dev;
int ret;
char addr[INET6_ADDRSTRLEN];
@@ -651,7 +651,6 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
NTSTATUS status;
fstrcpy(dev, pdev);
- SET_STAT_INVALID(st);
if (NT_STATUS_IS_ERR(*pstatus = share_sanity_checks(snum, dev))) {
return NULL;
@@ -990,14 +989,21 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
/* Any error exit after here needs to call the disconnect hook. */
on_err_call_dis_hook = true;
+ status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
+ NULL, NULL, &smb_fname_cpath);
+ if (!NT_STATUS_IS_OK(status)) {
+ *pstatus = status;
+ goto err_root_exit;
+ }
+
/* win2000 does not check the permissions on the directory
during the tree connect, instead relying on permission
check during individual operations. To match this behaviour
I have disabled this chdir check (tridge) */
/* the alternative is just to check the directory exists */
- if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
- !S_ISDIR(st.st_ex_mode)) {
- if (ret == 0 && !S_ISDIR(st.st_ex_mode)) {
+ if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
+ !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
+ if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
DEBUG(0,("'%s' is not a directory, when connecting to "
"[%s]\n", conn->connectpath,
lp_servicename(snum)));
@@ -1059,7 +1065,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
return(conn);
err_root_exit:
-
+ TALLOC_FREE(smb_fname_cpath);
change_to_root_user();
if (on_err_call_dis_hook) {
/* Call VFS disconnect hook */
diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c
index 2f7d16790d..daed9f8225 100644
--- a/source3/smbd/statcache.c
+++ b/source3/smbd/statcache.c
@@ -274,7 +274,7 @@ bool stat_cache_lookup(connection_struct *conn,
"-> [%s]\n", chk_name, translated_path ));
DO_PROFILE_INC(statcache_hits);
- if (SMB_VFS_STAT(conn, translated_path, pst) != 0) {
+ if (vfs_stat_smb_fname(conn, translated_path, pst) != 0) {
/* Discard this entry - it doesn't exist in the filesystem. */
memcache_delete(smbd_memcache(), STAT_CACHE,
data_blob_const(chk_name, strlen(chk_name)));
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index ca90c5ae69..a7d5c427d3 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -1395,14 +1395,17 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
}
if (INFO_LEVEL_IS_UNIX(info_level)) {
- if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
+ if (vfs_lstat_smb_fname(conn, pathreal,
+ &sbuf) != 0) {
DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
pathreal,strerror(errno)));
TALLOC_FREE(pathreal);
TALLOC_FREE(fname);
continue;
}
- } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
+ } else if (!VALID_STAT(sbuf) &&
+ vfs_stat_smb_fname(conn, pathreal,
+ &sbuf) != 0) {
/* Needed to show the msdfs symlinks as
* directories */
@@ -2626,7 +2629,7 @@ static void call_trans2qfsinfo(connection_struct *conn,
DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
- if(SMB_VFS_STAT(conn,".",&st)!=0) {
+ if(vfs_stat_smb_fname(conn,".",&st)!=0) {
DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
reply_doserror(req, ERRSRV, ERRinvdevice);
return;
@@ -3871,13 +3874,13 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
char *lock_data = NULL;
bool ms_dfs_link = false;
TALLOC_CTX *ctx = talloc_tos();
+ NTSTATUS status = NT_STATUS_OK;
if (!params) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
return;
}
- ZERO_STRUCT(sbuf);
ZERO_STRUCT(write_time_ts);
if (tran_call == TRANSACT2_QFILEINFO) {
@@ -3915,6 +3918,13 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
return;
}
+ status = create_synthetic_smb_fname_split(talloc_tos(), fname,
+ NULL, &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ return;
+ }
+
if(fsp->fake_file_handle) {
/*
* This is actually for the QUOTA_FAKE_FILE --metze
@@ -3931,18 +3941,25 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
if (INFO_LEVEL_IS_UNIX(info_level)) {
/* Always do lstat for UNIX calls. */
- if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
- DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
+ if (SMB_VFS_LSTAT(conn, smb_fname)) {
+ DEBUG(3,("call_trans2qfilepathinfo: "
+ "SMB_VFS_LSTAT of %s failed "
+ "(%s)\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno)));
reply_unixerror(req,ERRDOS,ERRbadpath);
return;
}
- } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
- DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
+ } else if (SMB_VFS_STAT(conn, smb_fname)) {
+ DEBUG(3,("call_trans2qfilepathinfo: "
+ "SMB_VFS_STAT of %s failed (%s)\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno)));
reply_unixerror(req, ERRDOS, ERRbadpath);
return;
}
- fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+ fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
get_file_infos(fileid, &delete_pending, &write_time_ts);
} else {
/*
@@ -3952,19 +3969,18 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
return;
}
- if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
- DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
+ if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
+ DEBUG(3, ("fstat of fnum %d failed (%s)\n",
+ fsp->fnum, strerror(errno)));
reply_unixerror(req, ERRDOS, ERRbadfid);
return;
}
pos = fsp->fh->position_information;
- fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+ fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
get_file_infos(fileid, &delete_pending, &write_time_ts);
}
} else {
- NTSTATUS status = NT_STATUS_OK;
-
/* qpathinfo */
if (total_params < 7) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -4005,41 +4021,50 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
return;
}
- sbuf = smb_fname->st;
-
+ /* If this is a stream, check if there is a delete_pending. */
if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
- && is_ntfs_stream_name(fname)) {
- char *base;
- SMB_STRUCT_STAT bsbuf;
-
- status = split_ntfs_stream_name(talloc_tos(), fname,
- &base, NULL);
+ && is_ntfs_stream_smb_fname(smb_fname)) {
+ struct smb_filename *smb_fname_base = NULL;
+
+ /* Create an smb_filename with stream_name == NULL. */
+ status =
+ create_synthetic_smb_fname(talloc_tos(),
+ smb_fname->base_name,
+ NULL, NULL,
+ &smb_fname_base);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("create_file_unixpath: "
- "split_ntfs_stream_name failed: %s\n",
- nt_errstr(status)));
reply_nterror(req, status);
return;
}
- SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
-
if (INFO_LEVEL_IS_UNIX(info_level)) {
/* Always do lstat for UNIX calls. */
- if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
- DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
+ if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
+ DEBUG(3,("call_trans2qfilepathinfo: "
+ "SMB_VFS_LSTAT of %s failed "
+ "(%s)\n",
+ smb_fname_str_dbg(smb_fname_base),
+ strerror(errno)));
+ TALLOC_FREE(smb_fname_base);
reply_unixerror(req,ERRDOS,ERRbadpath);
return;
}
} else {
- if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
- DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
+ if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
+ DEBUG(3,("call_trans2qfilepathinfo: "
+ "fileinfo of %s failed "
+ "(%s)\n",
+ smb_fname_str_dbg(smb_fname_base),
+ strerror(errno)));
+ TALLOC_FREE(smb_fname_base);
reply_unixerror(req,ERRDOS,ERRbadpath);
return;
}
}
- fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
+ fileid = vfs_file_id_from_sbuf(conn,
+ &smb_fname_base->st);
+ TALLOC_FREE(smb_fname_base);
get_file_infos(fileid, &delete_pending, NULL);
if (delete_pending) {
reply_nterror(req, NT_STATUS_DELETE_PENDING);
@@ -4049,23 +4074,32 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
if (INFO_LEVEL_IS_UNIX(info_level)) {
/* Always do lstat for UNIX calls. */
- if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
- DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
+ if (SMB_VFS_LSTAT(conn, smb_fname)) {
+ DEBUG(3,("call_trans2qfilepathinfo: "
+ "SMB_VFS_LSTAT of %s failed (%s)\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno)));
reply_unixerror(req, ERRDOS, ERRbadpath);
return;
}
- } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
- ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
+ } else if (!VALID_STAT(smb_fname->st) &&
+ SMB_VFS_STAT(conn, smb_fname) &&
+ (info_level != SMB_INFO_IS_NAME_VALID)) {
+ ms_dfs_link = check_msdfs_link(conn, fname,
+ &smb_fname->st);
if (!ms_dfs_link) {
- DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
+ DEBUG(3,("call_trans2qfilepathinfo: "
+ "SMB_VFS_STAT of %s failed (%s)\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno)));
reply_unixerror(req, ERRDOS, ERRbadpath);
return;
}
}
- fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+ fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
get_file_infos(fileid, &delete_pending, &write_time_ts);
if (delete_pending) {
reply_nterror(req, NT_STATUS_DELETE_PENDING);
@@ -4073,6 +4107,9 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
}
}
+ /* Set sbuf for use below. */
+ sbuf = smb_fname->st;
+
if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
reply_nterror(req, NT_STATUS_INVALID_LEVEL);
return;
@@ -4511,7 +4548,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
case SMB_FILE_STREAM_INFORMATION: {
unsigned int num_streams;
struct stream_struct *streams;
- NTSTATUS status;
DEBUG(10,("call_trans2qfilepathinfo: "
"SMB_FILE_STREAM_INFORMATION\n"));
@@ -4738,7 +4774,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
case SMB_QUERY_POSIX_LOCK:
{
- NTSTATUS status = NT_STATUS_INVALID_LEVEL;
uint64_t count;
uint64_t offset;
uint32 lock_pid;
@@ -6024,7 +6059,7 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn,
TALLOC_FREE(parent);
}
- if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
+ if (vfs_stat_smb_fname(conn, fname, psbuf) != 0) {
status = map_nt_error_from_unix(errno);
SMB_VFS_UNLINK(conn,fname);
return status;
@@ -6742,8 +6777,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
return;
}
- ZERO_STRUCT(sbuf);
-
if (tran_call == TRANSACT2_SETFILEINFO) {
if (total_params < 4) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -6763,6 +6796,13 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
return;
}
+ status = create_synthetic_smb_fname_split(talloc_tos(), fname,
+ NULL, &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ return;
+ }
+
if(fsp->is_directory || fsp->fh->fd == -1) {
/*
* This is actually a SETFILEINFO on a directory
@@ -6771,14 +6811,21 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
*/
if (INFO_LEVEL_IS_UNIX(info_level)) {
/* Always do lstat for UNIX calls. */
- if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
- DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
+ if (SMB_VFS_LSTAT(conn, smb_fname)) {
+ DEBUG(3,("call_trans2setfilepathinfo: "
+ "SMB_VFS_LSTAT of %s failed "
+ "(%s)\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno)));
reply_unixerror(req,ERRDOS,ERRbadpath);
return;
}
} else {
- if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
- DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
+ if (SMB_VFS_STAT(conn, smb_fname) != 0) {
+ DEBUG(3,("call_trans2setfilepathinfo: "
+ "fileinfo of %s failed (%s)\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno)));
reply_unixerror(req,ERRDOS,ERRbadpath);
return;
}
@@ -6809,8 +6856,10 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
return;
}
- if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
- DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
+ if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
+ DEBUG(3,("call_trans2setfilepathinfo: fstat "
+ "of fnum %d failed (%s)\n", fsp->fnum,
+ strerror(errno)));
reply_unixerror(req, ERRDOS, ERRbadfid);
return;
}
@@ -6847,23 +6896,28 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
return;
}
- sbuf = smb_fname->st;
-
if (INFO_LEVEL_IS_UNIX(info_level)) {
/*
* For CIFS UNIX extensions the target name may not exist.
*/
/* Always do lstat for UNIX calls. */
- SMB_VFS_LSTAT(conn,fname,&sbuf);
-
- } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
- DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
+ SMB_VFS_LSTAT(conn, smb_fname);
+
+ } else if (!VALID_STAT(smb_fname->st) &&
+ SMB_VFS_STAT(conn, smb_fname)) {
+ DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
+ "%s failed (%s)\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno)));
reply_unixerror(req, ERRDOS, ERRbadpath);
return;
}
}
+ /* Set sbuf for use below. */
+ sbuf = smb_fname->st;
+
if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
reply_nterror(req, NT_STATUS_INVALID_LEVEL);
return;
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 385454e587..2b4124bf7b 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -339,71 +339,18 @@ bool smbd_vfs_init(connection_struct *conn)
}
/*******************************************************************
- Check if directory exists.
-********************************************************************/
-
-bool vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *st)
-{
- SMB_STRUCT_STAT st2;
- bool ret;
-
- if (!st)
- st = &st2;
-
- if (SMB_VFS_STAT(conn,dname,st) != 0)
- return(False);
-
- ret = S_ISDIR(st->st_ex_mode);
- if(!ret)
- errno = ENOTDIR;
-
- return ret;
-}
-
-/*******************************************************************
- Check if an object exists in the vfs.
-********************************************************************/
-
-bool vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *sbuf)
-{
- SMB_STRUCT_STAT st;
-
- if (!sbuf)
- sbuf = &st;
-
- ZERO_STRUCTP(sbuf);
-
- if (SMB_VFS_STAT(conn,fname,sbuf) == -1)
- return(False);
- return True;
-}
-
-/*******************************************************************
Check if a file exists in the vfs.
********************************************************************/
NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
{
- char *fname = NULL;
- NTSTATUS status;
-
- status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
- }
-
- status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
- if (SMB_VFS_STAT(conn, fname, &smb_fname->st) == -1) {
- goto out;
- }
-
/* Only return OK if stat was successful and S_ISREG */
- if (S_ISREG(smb_fname->st.st_ex_mode)) {
- status = NT_STATUS_OK;
+ if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
+ S_ISREG(smb_fname->st.st_ex_mode)) {
+ return NT_STATUS_OK;
}
- out:
- TALLOC_FREE(fname);
- return status;
+
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
/****************************************************************************
@@ -791,10 +738,12 @@ int vfs_ChDir(connection_struct *conn, const char *path)
char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
{
char s[PATH_MAX+1];
- SMB_STRUCT_STAT st, st2;
- char *result;
+ char *result = NULL;
DATA_BLOB cache_value;
struct file_id key;
+ struct smb_filename *smb_fname_dot = NULL;
+ struct smb_filename *smb_fname_full = NULL;
+ NTSTATUS status;
*s = 0;
@@ -802,9 +751,14 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
goto nocache;
}
- SET_STAT_INVALID(st);
+ status = create_synthetic_smb_fname(ctx, ".", NULL, NULL,
+ &smb_fname_dot);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = map_errno_from_nt_status(status);
+ goto out;
+ }
- if (SMB_VFS_STAT(conn, ".",&st) == -1) {
+ if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
/*
* Known to fail for root: the directory may be NFS-mounted
* and exported with root_squash (so has no root access).
@@ -814,7 +768,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
goto nocache;
}
- key = vfs_file_id_from_sbuf(conn, &st);
+ key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
data_blob_const(&key, sizeof(key)),
@@ -825,17 +779,25 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
SMB_ASSERT((cache_value.length > 0)
&& (cache_value.data[cache_value.length-1] == '\0'));
- if ((SMB_VFS_STAT(conn, (char *)cache_value.data, &st2) == 0)
- && (st.st_ex_dev == st2.st_ex_dev) && (st.st_ex_ino == st2.st_ex_ino)
- && (S_ISDIR(st.st_ex_mode))) {
+ status = create_synthetic_smb_fname(ctx, (char *)cache_value.data,
+ NULL, NULL, &smb_fname_full);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = map_errno_from_nt_status(status);
+ goto out;
+ }
+
+ if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
+ (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
+ (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
+ (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
/*
* Ok, we're done
*/
- result = talloc_strdup(ctx, (char *)cache_value.data);
+ result = talloc_strdup(ctx, smb_fname_full->base_name);
if (result == NULL) {
errno = ENOMEM;
}
- return result;
+ goto out;
}
nocache:
@@ -849,11 +811,11 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
if (!SMB_VFS_GETWD(conn,s)) {
DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
strerror(errno)));
- return NULL;
+ goto out;
}
- if (lp_getwd_cache() && VALID_STAT(st)) {
- key = vfs_file_id_from_sbuf(conn, &st);
+ if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
+ key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
memcache_add(smbd_memcache(), GETWD_CACHE,
data_blob_const(&key, sizeof(key)),
@@ -864,6 +826,10 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
if (result == NULL) {
errno = ENOMEM;
}
+
+ out:
+ TALLOC_FREE(smb_fname_dot);
+ TALLOC_FREE(smb_fname_full);
return result;
}
@@ -997,7 +963,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
#ifdef S_ISLNK
if (!lp_symlinks(SNUM(conn))) {
SMB_STRUCT_STAT statbuf;
- if ( (SMB_VFS_LSTAT(conn,fname,&statbuf) != -1) &&
+ if ( (vfs_lstat_smb_fname(conn,fname,&statbuf) != -1) &&
(S_ISLNK(statbuf.st_ex_mode)) ) {
if (free_resolved_name) {
SAFE_FREE(resolved_name);