summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorTim Prouty <tprouty@samba.org>2009-07-06 14:36:16 -0700
committerTim Prouty <tprouty@samba.org>2009-07-06 15:38:41 -0700
commit99bd4fda0cd97eb211549a511a2ff6153c2bde2d (patch)
treedb1e4d3424b6bd1215a341f727ef94c748244454 /source3/smbd
parent0f6e10886f3f778fe301ee981873f29d295d39c5 (diff)
downloadsamba-99bd4fda0cd97eb211549a511a2ff6153c2bde2d.tar.gz
samba-99bd4fda0cd97eb211549a511a2ff6153c2bde2d.tar.bz2
samba-99bd4fda0cd97eb211549a511a2ff6153c2bde2d.zip
s3: Plumb smb_filename around SMB_VFS_CHFLAGS
SMB_VFS_CHFLAGS isn't actually getting the smb_filename struct for now since it only operates on the basefile. This is the strategy for all path-based operations that will never actually operate on a stream. By clarifying the meaning of path based operations that don't take an smb_filename struct, modules that implement streams such as vfs_onefs no longer need to implement SMB_VFS_CHFLAGS to ensure it's only called on the base_name.
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/dosmode.c93
-rw-r--r--source3/smbd/fileio.c20
-rw-r--r--source3/smbd/nttrans.c14
-rw-r--r--source3/smbd/open.c68
-rw-r--r--source3/smbd/reply.c2
-rw-r--r--source3/smbd/trans2.c17
6 files changed, 115 insertions, 99 deletions
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 03ac0897ef..2006b75d52 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -429,15 +429,14 @@ static bool get_stat_dos_flags(connection_struct *conn,
****************************************************************************/
static bool set_stat_dos_flags(connection_struct *conn,
- const char *fname,
- SMB_STRUCT_STAT *sbuf,
- uint32_t dosmode,
- bool *attributes_changed)
+ const struct smb_filename *smb_fname,
+ uint32_t dosmode,
+ bool *attributes_changed)
{
uint32_t new_flags = 0;
int error = 0;
- SMB_ASSERT(sbuf && VALID_STAT(*sbuf));
+ SMB_ASSERT(VALID_STAT(smb_fname->st));
SMB_ASSERT(attributes_changed);
*attributes_changed = false;
@@ -446,23 +445,25 @@ static bool set_stat_dos_flags(connection_struct *conn,
return false;
}
- DEBUG(5, ("Setting stat dos attributes for %s.\n", fname));
+ DEBUG(5, ("Setting stat dos attributes for %s.\n",
+ smb_fname_str_dbg(smb_fname)));
- new_flags = (sbuf->st_ex_flags & ~UF_DOS_FLAGS) |
+ new_flags = (smb_fname->st.st_ex_flags & ~UF_DOS_FLAGS) |
dos_attributes_to_stat_dos_flags(dosmode);
/* Return early if no flags changed. */
- if (new_flags == sbuf->st_ex_flags)
+ if (new_flags == smb_fname->st.st_ex_flags)
return true;
DEBUG(5, ("Setting stat dos attributes=0x%x, prev=0x%x\n", new_flags,
- sbuf->st_ex_flags));
+ smb_fname->st.st_ex_flags));
/* Set new flags with chflags. */
- error = SMB_VFS_CHFLAGS(conn, fname, new_flags);
+ error = SMB_VFS_CHFLAGS(conn, smb_fname->base_name, new_flags);
if (error) {
DEBUG(0, ("Failed setting new stat dos attributes (0x%x) on "
- "file %s! errno=%d\n", new_flags, fname, errno));
+ "file %s! errno=%d\n", new_flags,
+ smb_fname_str_dbg(smb_fname), errno));
return false;
}
@@ -545,52 +546,56 @@ uint32 dos_mode(connection_struct *conn, const char *path, const SMB_STRUCT_STAT
chmod a file - but preserve some bits.
********************************************************************/
-int file_set_dosmode(connection_struct *conn, const char *fname,
- uint32 dosmode, SMB_STRUCT_STAT *st,
- const char *parent_dir,
- bool newfile)
+int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
+ uint32 dosmode, const char *parent_dir, bool newfile)
{
- SMB_STRUCT_STAT st1;
int mask=0;
mode_t tmp;
mode_t unixmode;
int ret = -1, lret = -1;
uint32_t old_mode;
+ char *fname = NULL;
+ NTSTATUS status;
/* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
dosmode &= (SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE);
- DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
+ DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n",
+ dosmode, smb_fname_str_dbg(smb_fname)));
- if (st == NULL) {
- SET_STAT_INVALID(st1);
- st = &st1;
- }
-
- if (!VALID_STAT(*st)) {
- if (vfs_stat_smb_fname(conn,fname,st))
+ if (!VALID_STAT(smb_fname->st)) {
+ if (SMB_VFS_STAT(conn, smb_fname))
return(-1);
}
- unixmode = st->st_ex_mode;
+ unixmode = smb_fname->st.st_ex_mode;
- get_acl_group_bits(conn, fname, &st->st_ex_mode);
+ get_acl_group_bits(conn, smb_fname->base_name,
+ &smb_fname->st.st_ex_mode);
- if (S_ISDIR(st->st_ex_mode))
+ if (S_ISDIR(smb_fname->st.st_ex_mode))
dosmode |= aDIR;
else
dosmode &= ~aDIR;
- old_mode = dos_mode(conn,fname,st);
+ status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = map_errno_from_nt_status(status);
+ return -1;
+ }
+
+ old_mode = dos_mode(conn, fname, &smb_fname->st);
if (dosmode & FILE_ATTRIBUTE_OFFLINE) {
if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) {
lret = SMB_VFS_SET_OFFLINE(conn, fname);
if (lret == -1) {
- DEBUG(0, ("set_dos_mode: client has asked to set "
- "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was "
- "an error while setting it or it is not supported.\n",
- parent_dir, fname));
+ DEBUG(0, ("set_dos_mode: client has asked to "
+ "set FILE_ATTRIBUTE_OFFLINE to "
+ "%s/%s but there was an error while "
+ "setting it or it is not "
+ "supported.\n", parent_dir,
+ smb_fname_str_dbg(smb_fname)));
}
}
}
@@ -599,7 +604,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
old_mode &= ~FILE_ATTRIBUTE_OFFLINE;
if (old_mode == dosmode) {
- st->st_ex_mode = unixmode;
+ smb_fname->st.st_ex_mode = unixmode;
return(0);
}
@@ -607,26 +612,26 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
{
bool attributes_changed;
- if (set_stat_dos_flags(conn, fname, st, dosmode,
+ if (set_stat_dos_flags(conn, smb_fname, dosmode,
&attributes_changed))
{
if (!newfile && attributes_changed) {
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
}
- st->st_ex_mode = unixmode;
+ smb_fname->st.st_ex_mode = unixmode;
return 0;
}
}
#endif
/* Store the DOS attributes in an EA by preference. */
- if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
+ if (set_ea_dos_attribute(conn, fname, &smb_fname->st, dosmode)) {
if (!newfile) {
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
}
- st->st_ex_mode = unixmode;
+ smb_fname->st.st_ex_mode = unixmode;
return 0;
}
@@ -648,10 +653,10 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
if (!MAP_HIDDEN(conn))
mask |= S_IXOTH;
- unixmode |= (st->st_ex_mode & mask);
+ unixmode |= (smb_fname->st.st_ex_mode & mask);
/* if we previously had any r bits set then leave them alone */
- if ((tmp = st->st_ex_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
+ if ((tmp = smb_fname->st.st_ex_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
unixmode |= tmp;
}
@@ -659,7 +664,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
/* if we previously had any w bits set then leave them alone
whilst adding in the new w bits, if the new mode is not rdonly */
if (!IS_DOS_READONLY(dosmode)) {
- unixmode |= (st->st_ex_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
+ unixmode |= (smb_fname->st.st_ex_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
}
ret = SMB_VFS_CHMOD(conn, fname, unixmode);
@@ -668,7 +673,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
}
- st->st_ex_mode = unixmode;
+ smb_fname->st.st_ex_mode = unixmode;
return 0;
}
@@ -693,8 +698,8 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
* break batch oplocks open by others. JRA.
*/
files_struct *fsp;
- if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, fname, st,
- &fsp)))
+ if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, fname,
+ &smb_fname->st, &fsp)))
return -1;
become_root();
ret = SMB_VFS_FCHMOD(fsp, unixmode);
@@ -705,7 +710,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
}
if (ret == 0) {
- st->st_ex_mode = unixmode;
+ smb_fname->st.st_ex_mode = unixmode;
}
}
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index 5cc3d4b88b..caaebf6217 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -294,10 +294,22 @@ ssize_t write_file(struct smb_request *req,
if ((lp_store_dos_attributes(SNUM(fsp->conn)) ||
MAP_ARCHIVE(fsp->conn)) &&
!IS_DOS_ARCHIVE(dosmode)) {
- file_set_dosmode(fsp->conn,fsp->fsp_name,
- dosmode | aARCH,&st,
- NULL,
- false);
+ struct smb_filename *smb_fname = NULL;
+ NTSTATUS status;
+
+ status = create_synthetic_smb_fname_split(
+ talloc_tos(), fsp->fsp_name, &st,
+ &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno =
+ map_errno_from_nt_status(status);
+ return -1;
+ }
+
+ file_set_dosmode(fsp->conn, smb_fname,
+ dosmode | aARCH, NULL, false);
+ st = smb_fname->st;
+ TALLOC_FREE(smb_fname);
}
/*
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index add0b40f2e..b970ffc05e 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1219,7 +1219,6 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
uint32 attrs)
{
char *oldname = NULL;
- char *newname = NULL;
files_struct *fsp1,*fsp2;
uint32 fattr;
int info;
@@ -1328,20 +1327,15 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
status = close_file(NULL, fsp2, NORMAL_CLOSE);
- status = get_full_smb_filename(ctx, smb_fname_dst, &newname);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
- }
-
/* Grrr. We have to do this as open_file_ntcreate adds aARCH when it
creates the file. This isn't the correct thing to do in the copy
case. JRA */
- if (!parent_dirname(talloc_tos(), newname, &parent, NULL)) {
+ if (!parent_dirname(talloc_tos(), smb_fname_dst->base_name, &parent,
+ NULL)) {
status = NT_STATUS_NO_MEMORY;
goto out;
}
- file_set_dosmode(conn, newname, fattr, &smb_fname_dst->st, parent,
- false);
+ file_set_dosmode(conn, smb_fname_dst, fattr, parent, false);
TALLOC_FREE(parent);
if (ret < (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
@@ -1356,8 +1350,6 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
}
TALLOC_FREE(oldname);
- TALLOC_FREE(newname);
-
return status;
}
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index df31365675..926c0ecaa7 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -2195,14 +2195,10 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
if (lp_map_archive(SNUM(conn)) ||
lp_store_dos_attributes(SNUM(conn))) {
if (!posix_open) {
- SMB_STRUCT_STAT tmp_sbuf;
- SET_STAT_INVALID(tmp_sbuf);
- if (file_set_dosmode(
- conn, fname,
+ if (file_set_dosmode(conn, smb_fname,
new_dos_attributes | aARCH,
- &tmp_sbuf, parent_dir,
- true) == 0) {
- unx_mode = tmp_sbuf.st_ex_mode;
+ parent_dir, true) == 0) {
+ unx_mode = smb_fname->st.st_ex_mode;
}
}
}
@@ -2338,9 +2334,8 @@ NTSTATUS close_file_fchmod(struct smb_request *req, files_struct *fsp)
}
static NTSTATUS mkdir_internal(connection_struct *conn,
- const char *name,
- uint32 file_attributes,
- SMB_STRUCT_STAT *psbuf)
+ struct smb_filename *smb_dname,
+ uint32 file_attributes)
{
mode_t mode;
char *parent_dir;
@@ -2353,12 +2348,13 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
return NT_STATUS_ACCESS_DENIED;
}
- status = check_name(conn, name);
+ status = check_name(conn, smb_dname->base_name);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- if (!parent_dirname(talloc_tos(), name, &parent_dir, NULL)) {
+ if (!parent_dirname(talloc_tos(), smb_dname->base_name, &parent_dir,
+ NULL)) {
return NT_STATUS_NO_MEMORY;
}
@@ -2366,39 +2362,39 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
posix_open = true;
mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
} else {
- mode = unix_mode(conn, aDIR, name, parent_dir);
+ mode = unix_mode(conn, aDIR, smb_dname->base_name, parent_dir);
}
- if (SMB_VFS_MKDIR(conn, name, mode) != 0) {
+ if (SMB_VFS_MKDIR(conn, smb_dname->base_name, mode) != 0) {
return map_nt_error_from_unix(errno);
}
/* Ensure we're checking for a symlink here.... */
/* We don't want to get caught by a symlink racer. */
- if (vfs_lstat_smb_fname(conn, name, psbuf) == -1) {
+ if (SMB_VFS_LSTAT(conn, smb_dname) == -1) {
DEBUG(2, ("Could not stat directory '%s' just created: %s\n",
- name, strerror(errno)));
+ smb_fname_str_dbg(smb_dname), strerror(errno)));
return map_nt_error_from_unix(errno);
}
- if (!S_ISDIR(psbuf->st_ex_mode)) {
+ if (!S_ISDIR(smb_dname->st.st_ex_mode)) {
DEBUG(0, ("Directory just '%s' created is not a directory\n",
- name));
+ smb_fname_str_dbg(smb_dname)));
return NT_STATUS_ACCESS_DENIED;
}
if (lp_store_dos_attributes(SNUM(conn))) {
if (!posix_open) {
- file_set_dosmode(conn, name,
- file_attributes | aDIR, NULL,
- parent_dir,
- true);
+ file_set_dosmode(conn, smb_dname,
+ file_attributes | aDIR,
+ parent_dir, true);
}
}
if (lp_inherit_perms(SNUM(conn))) {
- inherit_access_posix_acl(conn, parent_dir, name, mode);
+ inherit_access_posix_acl(conn, parent_dir,
+ smb_dname->base_name, mode);
}
if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
@@ -2408,19 +2404,23 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
* Consider bits automagically set by UNIX, i.e. SGID bit from parent
* dir.
*/
- if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_ex_mode)) {
- SMB_VFS_CHMOD(conn, name,
- psbuf->st_ex_mode | (mode & ~psbuf->st_ex_mode));
+ if ((mode & ~(S_IRWXU|S_IRWXG|S_IRWXO)) &&
+ (mode & ~smb_dname->st.st_ex_mode)) {
+ SMB_VFS_CHMOD(conn, smb_dname->base_name,
+ (smb_dname->st.st_ex_mode |
+ (mode & ~smb_dname->st.st_ex_mode)));
}
}
/* Change the owner if required. */
if (lp_inherit_owner(SNUM(conn))) {
- change_dir_owner_to_parent(conn, parent_dir, name, psbuf);
+ change_dir_owner_to_parent(conn, parent_dir,
+ smb_dname->base_name,
+ &smb_dname->st);
}
notify_fname(conn, NOTIFY_ACTION_ADDED, FILE_NOTIFY_CHANGE_DIR_NAME,
- name);
+ smb_dname->base_name);
return NT_STATUS_OK;
}
@@ -2503,10 +2503,8 @@ static NTSTATUS open_directory(connection_struct *conn,
/* If directory exists error. If directory doesn't
* exist create. */
- status = mkdir_internal(conn,
- smb_dname->base_name,
- file_attributes,
- &smb_dname->st);
+ status = mkdir_internal(conn, smb_dname,
+ file_attributes);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(2, ("open_directory: unable to create "
@@ -2525,10 +2523,8 @@ static NTSTATUS open_directory(connection_struct *conn,
* exist create.
*/
- status = mkdir_internal(conn,
- smb_dname->base_name,
- file_attributes,
- &smb_dname->st);
+ status = mkdir_internal(conn, smb_dname,
+ file_attributes);
if (NT_STATUS_IS_OK(status)) {
info = FILE_WAS_CREATED;
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index e37cdcb6b4..4a5610e5e1 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -1216,7 +1216,7 @@ void reply_setatr(struct smb_request *req)
else
mode &= ~aDIR;
- if (file_set_dosmode(conn, fname, mode, &smb_fname->st, NULL,
+ if (file_set_dosmode(conn, smb_fname, mode, NULL,
false) != 0) {
reply_unixerror(req, ERRDOS, ERRnoaccess);
goto out;
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index dfb682ee21..2c74c8f49e 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -5063,15 +5063,26 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
/* check the mode isn't different, before changing it */
if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
+ struct smb_filename *smb_fname = NULL;
+ NTSTATUS status;
+
+ status = create_synthetic_smb_fname_split(talloc_tos(), fname,
+ psbuf, &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
fname, (unsigned int)dosmode ));
- if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
+ if(file_set_dosmode(conn, smb_fname, dosmode, NULL, false)) {
DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
fname, strerror(errno)));
+ TALLOC_FREE(smb_fname);
return map_nt_error_from_unix(errno);
}
+ *psbuf = smb_fname->st;
+ TALLOC_FREE(smb_fname);
}
return NT_STATUS_OK;
}
@@ -6320,7 +6331,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
return status;
}
- id = vfs_file_id_from_sbuf(conn, psbuf);
+ id = vfs_file_id_from_sbuf(conn, &sbuf);
for(all_fsps = file_find_di_first(id); all_fsps;
all_fsps = file_find_di_next(all_fsps)) {
/*
@@ -6349,7 +6360,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
false);
if (modify_mtime) {
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
- FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
+ FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
}
return status;
}