From 8cd9636458e175d2e1b63a5211423cec04a6ce91 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 27 Dec 2006 10:57:59 +0000 Subject: r20356: Consolidate the calls to parent_dirname() per open to one. This involved passing the dirname as argument to a few routines instead of calling parent_dirname() deep down. Volker (This used to be commit 7977fd78652897bb7d4db1c21c5749043428f911) --- source3/smbd/dosmode.c | 27 +++++++++------ source3/smbd/nttrans.c | 3 +- source3/smbd/open.c | 86 ++++++++++++++++++++++++++++------------------- source3/smbd/posix_acls.c | 15 +++++---- source3/smbd/trans2.c | 5 +-- 5 files changed, 80 insertions(+), 56 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 260a8dadbd..1172fe3e6b 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -59,7 +59,7 @@ static uint32 set_offline_flag(connection_struct *conn, const char *const path) /**************************************************************************** Change a dos mode to a unix mode. Base permission for files: - if creating file and inheriting + if creating file and inheriting (i.e. parent_dir != NULL) apply read/write bits from parent directory. else everybody gets read bit set @@ -79,23 +79,26 @@ static uint32 set_offline_flag(connection_struct *conn, const char *const path) } ****************************************************************************/ -mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, BOOL creating_file) +mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, + const char *inherit_from_dir) { mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH); - mode_t dir_mode = 0; /* Mode of the parent directory if inheriting. */ + mode_t dir_mode = 0; /* Mode of the inherit_from directory if + * inheriting. */ if (!lp_store_dos_attributes(SNUM(conn)) && IS_DOS_READONLY(dosmode)) { result &= ~(S_IWUSR | S_IWGRP | S_IWOTH); } - if (fname && creating_file && lp_inherit_perms(SNUM(conn))) { - char *dname; + if (fname && (inherit_from_dir != NULL) + && lp_inherit_perms(SNUM(conn))) { SMB_STRUCT_STAT sbuf; - dname = parent_dirname(fname); - DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname)); - if (SMB_VFS_STAT(conn,dname,&sbuf) != 0) { - DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno))); + DEBUG(2, ("unix_mode(%s) inheriting from %s\n", fname, + inherit_from_dir)); + if (SMB_VFS_STAT(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! *** */ } @@ -429,7 +432,9 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) chmod a file - but preserve some bits. ********************************************************************/ -int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, SMB_STRUCT_STAT *st, BOOL creating_file) +int file_set_dosmode(connection_struct *conn, const char *fname, + uint32 dosmode, SMB_STRUCT_STAT *st, + const char *parent_dir) { SMB_STRUCT_STAT st1; int mask=0; @@ -462,7 +467,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, return 0; } - unixmode = unix_mode(conn,dosmode,fname, creating_file); + unixmode = unix_mode(conn,dosmode,fname, parent_dir); /* preserve the s bits */ mask |= (S_ISUID | S_ISGID); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 260a640dae..377ddbeec3 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1697,7 +1697,8 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new /* 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 */ - file_set_dosmode(conn, newname, fattr, &sbuf2, True); + file_set_dosmode(conn, newname, fattr, &sbuf2, + parent_dirname(newname)); if (ret < (SMB_OFF_T)sbuf1.st_size) { return NT_STATUS_DISK_FULL; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 59cd8030af..28170e9cd8 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -84,18 +84,18 @@ int fd_close(struct connection_struct *conn, Do this by fd if possible. ****************************************************************************/ -static void change_fd_owner_to_parent(connection_struct *conn, - files_struct *fsp) +static void change_file_owner_to_parent(connection_struct *conn, + const char *inherit_from_dir, + files_struct *fsp) { - const char *parent_path = parent_dirname(fsp->fsp_name); SMB_STRUCT_STAT parent_st; int ret; - ret = SMB_VFS_STAT(conn, parent_path, &parent_st); + ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st); if (ret == -1) { - DEBUG(0,("change_fd_owner_to_parent: failed to stat parent " + DEBUG(0,("change_file_owner_to_parent: failed to stat parent " "directory %s. Error was %s\n", - parent_path, strerror(errno) )); + inherit_from_dir, strerror(errno) )); return; } @@ -103,33 +103,33 @@ static void change_fd_owner_to_parent(connection_struct *conn, ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { - DEBUG(0,("change_fd_owner_to_parent: failed to fchown " + 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_uid, strerror(errno) )); } - DEBUG(10,("change_fd_owner_to_parent: changed new file %s to " + 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_uid )); } -static void change_owner_to_parent(connection_struct *conn, - const char *fname, - SMB_STRUCT_STAT *psbuf) +static void change_dir_owner_to_parent(connection_struct *conn, + const char *inherit_from_dir, + const char *fname, + SMB_STRUCT_STAT *psbuf) { pstring saved_dir; SMB_STRUCT_STAT sbuf; - const char *parent_path = parent_dirname(fname); SMB_STRUCT_STAT parent_st; int ret; - ret = SMB_VFS_STAT(conn, parent_path, &parent_st); + ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st); if (ret == -1) { - DEBUG(0,("change_owner_to_parent: failed to stat parent " + DEBUG(0,("change_dir_owner_to_parent: failed to stat parent " "directory %s. Error was %s\n", - parent_path, strerror(errno) )); + inherit_from_dir, strerror(errno) )); return; } @@ -141,21 +141,21 @@ static void change_owner_to_parent(connection_struct *conn, */ if (!vfs_GetWd(conn,saved_dir)) { - DEBUG(0,("change_owner_to_parent: failed to get " + DEBUG(0,("change_dir_owner_to_parent: failed to get " "current working directory\n")); return; } /* Chdir into the new path. */ if (vfs_ChDir(conn, fname) == -1) { - DEBUG(0,("change_owner_to_parent: failed to change " + DEBUG(0,("change_dir_owner_to_parent: failed to change " "current working directory to %s. Error " "was %s\n", fname, strerror(errno) )); goto out; } if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { - DEBUG(0,("change_owner_to_parent: failed to stat " + DEBUG(0,("change_dir_owner_to_parent: failed to stat " "directory '.' (%s) Error was %s\n", fname, strerror(errno))); goto out; @@ -165,7 +165,7 @@ static void change_owner_to_parent(connection_struct *conn, if (sbuf.st_dev != psbuf->st_dev || sbuf.st_ino != psbuf->st_ino || sbuf.st_mode != psbuf->st_mode ) { - DEBUG(0,("change_owner_to_parent: " + DEBUG(0,("change_dir_owner_to_parent: " "device/inode/mode on directory %s changed. " "Refusing to chown !\n", fname )); goto out; @@ -175,14 +175,14 @@ static void change_owner_to_parent(connection_struct *conn, ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { - DEBUG(10,("change_owner_to_parent: failed to chown " + 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_uid, strerror(errno) )); goto out; } - DEBUG(10,("change_owner_to_parent: changed ownership of new " + 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_uid )); @@ -197,6 +197,7 @@ static void change_owner_to_parent(connection_struct *conn, static NTSTATUS open_file(files_struct *fsp, connection_struct *conn, + const char *parent_dir, const char *fname, SMB_STRUCT_STAT *psbuf, int flags, @@ -297,12 +298,14 @@ static NTSTATUS open_file(files_struct *fsp, /* Inherit the ACL if required */ if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, fname, unx_mode); + inherit_access_acl(conn, parent_dir, fname, + unx_mode); } /* Change the owner if required. */ if (lp_inherit_owner(SNUM(conn))) { - change_fd_owner_to_parent(conn, fsp); + change_file_owner_to_parent(conn, parent_dir, + fsp); } } @@ -1124,6 +1127,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, uint32 open_access_mask = access_mask; NTSTATUS status; int ret_flock; + const char *parent_dir; if (conn->printer) { /* @@ -1140,9 +1144,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return print_fsp_open(conn, fname, result); } + if (!(parent_dir = talloc_strdup(tmp_talloc_ctx(), + parent_dirname(fname)))) { + return NT_STATUS_NO_MEMORY; + } + /* We add aARCH to this as this mode is only used if the file is * created new. */ - unx_mode = unix_mode(conn, new_dos_attributes | aARCH,fname, True); + unx_mode = unix_mode(conn, new_dos_attributes | aARCH, fname, + parent_dir); DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x " "access_mask=0x%x share_access=0x%x " @@ -1194,7 +1204,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* this is for OS/2 long file names - say we don't support them */ if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) { /* OS/2 Workplace shell fix may be main code stream in a later - * release. */ + * release. */ DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not " "supported.\n")); if (use_nt_status()) { @@ -1554,8 +1564,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, */ if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) && - (def_acl = directory_has_default_acl(conn, - parent_dirname(fname)))) { + (def_acl = directory_has_default_acl(conn, parent_dir))) { unx_mode = 0777; } @@ -1569,8 +1578,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, - access_mask, open_access_mask); + fsp_open = open_file(fsp, conn, parent_dir, fname, psbuf, flags|flags2, + unx_mode, access_mask, open_access_mask); if (!NT_STATUS_IS_OK(fsp_open)) { if (lck != NULL) { @@ -1658,7 +1667,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, fsp->fh->fd, share_access); if(ret_flock == -1 ){ - talloc_free(lck); + TALLOC_FREE(lck); fd_close(conn, fsp); file_free(fsp); @@ -1755,7 +1764,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, lp_store_dos_attributes(SNUM(conn))) { file_set_dosmode(conn, fname, new_dos_attributes | aARCH, NULL, - True); + parent_dir); } } @@ -1835,7 +1844,8 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname, /* note! we must use a non-zero desired access or we don't get a real file descriptor. Oh what a twisted web we weave. */ - status = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA,FILE_WRITE_DATA); + status = open_file(fsp, conn, NULL, fname, psbuf, O_WRONLY, 0, + FILE_WRITE_DATA, FILE_WRITE_DATA); /* * This is not a user visible file open. @@ -1868,6 +1878,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, { int ret= -1; mode_t mode; + const char *parent_dir; if(!CAN_WRITE(conn)) { DEBUG(5,("mkdir_internal: failing create on read-only share " @@ -1879,7 +1890,12 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, return map_nt_error_from_unix(errno); } - mode = unix_mode(conn, aDIR, name, True); + if (!(parent_dir = talloc_strdup(tmp_talloc_ctx(), + parent_dirname(name)))) { + return NT_STATUS_NO_MEMORY; + } + + mode = unix_mode(conn, aDIR, name, parent_dir); if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) { return map_nt_error_from_unix(errno); @@ -1901,7 +1917,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, } if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, name, mode); + inherit_access_acl(conn, parent_dir, name, mode); } /* @@ -1917,7 +1933,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, /* Change the owner if required. */ if (lp_inherit_owner(SNUM(conn))) { - change_owner_to_parent(conn, name, psbuf); + change_dir_owner_to_parent(conn, parent_dir, name, psbuf); } return NT_STATUS_OK; diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 75605ace8a..c5da33c9df 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1878,7 +1878,10 @@ static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode) int snum = SNUM(fsp->conn); mode_t and_bits = (mode_t)0; mode_t or_bits = (mode_t)0; - mode_t mode = interitable_mode ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name, False) : S_IRUSR; + mode_t mode = interitable_mode + ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name, + NULL ) + : S_IRUSR; if (fsp->is_directory) mode |= (S_IWUSR|S_IXUSR); @@ -3461,15 +3464,13 @@ int chmod_acl(connection_struct *conn, const char *name, mode_t mode) inherit this Access ACL to file name. ****************************************************************************/ -int inherit_access_acl(connection_struct *conn, const char *name, mode_t mode) +int inherit_access_acl(connection_struct *conn, const char *inherit_from_dir, + const char *name, mode_t mode) { - pstring dirname; - pstrcpy(dirname, parent_dirname(name)); - - if (directory_has_default_acl(conn, dirname)) + if (directory_has_default_acl(conn, inherit_from_dir)) return 0; - return copy_access_acl(conn, dirname, name, mode); + return copy_access_acl(conn, inherit_from_dir, name, mode); } /**************************************************************************** diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index e91cc7be06..9f22f65e34 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4300,8 +4300,9 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return(UNIXERROR(ERRDOS,ERRnoaccess)); if (lp_inherit_perms(SNUM(conn))) { - inherit_access_acl(conn, fname, - unixmode); + inherit_access_acl( + conn, parent_dirname(fname), + fname, unixmode); } SSVAL(params,0,0); -- cgit