1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-22 22:04:08 +03:00

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.
This commit is contained in:
Tim Prouty 2009-07-06 14:36:16 -07:00
parent 0f6e10886f
commit 99bd4fda0c
10 changed files with 117 additions and 128 deletions

View File

@ -6238,10 +6238,8 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname,
uint32 dos_mode_msdfs(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf);
int dos_attributes_to_stat_dos_flags(uint32_t dosmode);
uint32 dos_mode(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf);
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);
int file_ntimes(connection_struct *conn, const char *fname,
struct smb_file_time *ft, const SMB_STRUCT_STAT *psbuf);
bool set_sticky_write_time_path(connection_struct *conn, const char *fname,

View File

@ -74,9 +74,6 @@ int onefs_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname);
int onefs_unlink(vfs_handle_struct *handle, const char *path);
int onefs_chflags(vfs_handle_struct *handle, const char *path,
unsigned int flags);
NTSTATUS onefs_streaminfo(vfs_handle_struct *handle,
struct files_struct *fsp,
const char *fname,

View File

@ -544,26 +544,6 @@ int onefs_vtimes_streams(vfs_handle_struct *handle, const char *fname,
return ret;
}
int onefs_chflags(vfs_handle_struct *handle, const char *path,
unsigned int flags)
{
char *base = NULL;
char *stream = NULL;
if (!NT_STATUS_IS_OK(onefs_split_ntfs_stream_name(talloc_tos(), path,
&base, &stream))) {
DEBUG(10, ("onefs_split_ntfs_stream_name failed\n"));
errno = ENOMEM;
return -1;
}
/*
* Only set the attributes on the base file. ifs_createfile handles
* file creation attribute semantics.
*/
return SMB_VFS_NEXT_CHFLAGS(handle, base, flags);
}
/*
* Streaminfo enumeration functionality
*/

View File

@ -290,8 +290,6 @@ static vfs_op_tuple onefs_ops[] = {
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(onefs_ntimes), SMB_VFS_OP_NTIMES,
SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(onefs_chflags), SMB_VFS_OP_CHFLAGS,
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(onefs_file_id_create), SMB_VFS_OP_FILE_ID_CREATE,
SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(onefs_streaminfo), SMB_VFS_OP_STREAMINFO,

View File

@ -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;
}
}

View File

@ -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);
}
/*

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}