mirror of
https://github.com/samba-team/samba.git
synced 2025-03-26 18:50:30 +03:00
s3: Plumb smb_filename through dos_mode() and related funtions
This commit is contained in:
parent
69c8795b67
commit
1a1d10d22f
@ -6237,9 +6237,10 @@ bool smbd_setup_mdns_registration(struct tevent_context *ev,
|
||||
mode_t unix_mode(connection_struct *conn, int dosmode,
|
||||
const struct smb_filename *smb_fname,
|
||||
const char *inherit_from_dir);
|
||||
uint32 dos_mode_msdfs(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf);
|
||||
uint32 dos_mode_msdfs(connection_struct *conn,
|
||||
const struct smb_filename *smb_fname);
|
||||
int dos_attributes_to_stat_dos_flags(uint32_t dosmode);
|
||||
uint32 dos_mode(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf);
|
||||
uint32 dos_mode(connection_struct *conn, const struct smb_filename *smb_fname);
|
||||
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 struct smb_filename *smb_fname,
|
||||
@ -6596,8 +6597,8 @@ bool map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func
|
||||
uint32 *pcreate_disposition,
|
||||
uint32 *pcreate_options);
|
||||
NTSTATUS open_file_fchmod(struct smb_request *req, connection_struct *conn,
|
||||
const char *fname,
|
||||
SMB_STRUCT_STAT *psbuf, files_struct **result);
|
||||
struct smb_filename *smb_fname,
|
||||
files_struct **result);
|
||||
NTSTATUS close_file_fchmod(struct smb_request *req, files_struct *fsp);
|
||||
NTSTATUS create_directory(connection_struct *conn, struct smb_request *req,
|
||||
struct smb_filename *smb_dname);
|
||||
@ -6718,7 +6719,8 @@ NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info,
|
||||
SEC_DESC **ppdesc);
|
||||
NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
|
||||
uint32_t security_info, SEC_DESC **ppdesc);
|
||||
int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid);
|
||||
int try_chown(connection_struct *conn, struct smb_filename *smb_fname,
|
||||
uid_t uid, gid_t gid);
|
||||
NTSTATUS append_parent_acl(files_struct *fsp,
|
||||
const SEC_DESC *pcsd,
|
||||
SEC_DESC **pp_new_sd);
|
||||
|
@ -743,12 +743,22 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp,
|
||||
}
|
||||
if (((newUID != (uid_t)-1) && (sbuf.st_ex_uid != newUID)) ||
|
||||
((newGID != (gid_t)-1) && (sbuf.st_ex_gid != newGID))) {
|
||||
if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) {
|
||||
struct smb_filename *smb_fname = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
status = create_synthetic_smb_fname_split(talloc_tos(),
|
||||
fsp->fsp_name, NULL, &smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
if(try_chown(fsp->conn, smb_fname, newUID, newGID)) {
|
||||
DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n",
|
||||
fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID,
|
||||
strerror(errno)));
|
||||
TALLOC_FREE(smb_fname);
|
||||
return map_nt_error_from_unix(errno);
|
||||
}
|
||||
TALLOC_FREE(smb_fname);
|
||||
|
||||
DEBUG(10,("chown %s, %u, %u succeeded.\n",
|
||||
fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID));
|
||||
|
@ -591,8 +591,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn,
|
||||
if (!posix_open) {
|
||||
new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;
|
||||
if (file_existed) {
|
||||
existing_dos_attributes = dos_mode(conn, fname,
|
||||
&smb_fname->st);
|
||||
existing_dos_attributes = dos_mode(conn, smb_fname);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -876,6 +876,8 @@ bool get_dir_entry(TALLOC_CTX *ctx,
|
||||
mask_match_search(filename,mask,False) ||
|
||||
mangle_mask_match(conn,filename,mask)) {
|
||||
char mname[13];
|
||||
struct smb_filename *smb_fname = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
if (!mangle_is_8_3(filename, False, conn->params)) {
|
||||
if (!name_to_8_3(filename,mname,False,
|
||||
@ -905,51 +907,47 @@ bool get_dir_entry(TALLOC_CTX *ctx,
|
||||
return False;
|
||||
}
|
||||
|
||||
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, &sbuf,
|
||||
&smb_fname);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
TALLOC_FREE(pathreal);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
TALLOC_FREE(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!VALID_STAT(smb_fname->st)) {
|
||||
if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
|
||||
DEBUG(5,("Couldn't stat 1 [%s]. Error "
|
||||
"= %s\n", pathreal,
|
||||
"= %s\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
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);
|
||||
*mode = dos_mode(conn, smb_fname);
|
||||
|
||||
if (!dir_check_ftype(conn,*mode,dirtype)) {
|
||||
DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype));
|
||||
TALLOC_FREE(pathreal);
|
||||
TALLOC_FREE(smb_fname);
|
||||
TALLOC_FREE(filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
*size = sbuf.st_ex_size;
|
||||
*date = sbuf.st_ex_mtime;
|
||||
*size = smb_fname->st.st_ex_size;
|
||||
*date = smb_fname->st.st_ex_mtime;
|
||||
|
||||
if (ask_sharemode) {
|
||||
struct timespec write_time_ts;
|
||||
struct file_id fileid;
|
||||
|
||||
fileid = vfs_file_id_from_sbuf(conn, &sbuf);
|
||||
fileid = vfs_file_id_from_sbuf(conn,
|
||||
&smb_fname->st);
|
||||
get_file_infos(fileid, NULL, &write_time_ts);
|
||||
if (!null_timespec(write_time_ts)) {
|
||||
*date = write_time_ts;
|
||||
@ -959,7 +957,7 @@ bool get_dir_entry(TALLOC_CTX *ctx,
|
||||
DEBUG(3,("get_dir_entry mask=[%s] found %s "
|
||||
"fname=%s (%s)\n",
|
||||
mask,
|
||||
pathreal,
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
dname,
|
||||
filename));
|
||||
|
||||
@ -969,7 +967,7 @@ bool get_dir_entry(TALLOC_CTX *ctx,
|
||||
*pp_fname_out = filename;
|
||||
|
||||
DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff);
|
||||
TALLOC_FREE(pathreal);
|
||||
TALLOC_FREE(smb_fname);
|
||||
}
|
||||
|
||||
if (!found)
|
||||
|
@ -158,45 +158,38 @@ mode_t unix_mode(connection_struct *conn, int dosmode,
|
||||
Change a unix mode to a dos mode.
|
||||
****************************************************************************/
|
||||
|
||||
static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf)
|
||||
static uint32 dos_mode_from_sbuf(connection_struct *conn,
|
||||
const struct smb_filename *smb_fname)
|
||||
{
|
||||
int result = 0;
|
||||
enum mapreadonly_options ro_opts = (enum mapreadonly_options)lp_map_readonly(SNUM(conn));
|
||||
|
||||
if (ro_opts == MAP_READONLY_YES) {
|
||||
/* Original Samba method - map inverse of user "w" bit. */
|
||||
if ((sbuf->st_ex_mode & S_IWUSR) == 0) {
|
||||
if ((smb_fname->st.st_ex_mode & S_IWUSR) == 0) {
|
||||
result |= aRONLY;
|
||||
}
|
||||
} else if (ro_opts == MAP_READONLY_PERMISSIONS) {
|
||||
struct smb_filename *smb_fname = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
status = create_synthetic_smb_fname_split(talloc_tos(), path,
|
||||
sbuf, &smb_fname);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
/* Check actual permissions for read-only. */
|
||||
if (!can_write_to_file(conn, smb_fname)) {
|
||||
result |= aRONLY;
|
||||
}
|
||||
/* Check actual permissions for read-only. */
|
||||
if (!can_write_to_file(conn, smb_fname)) {
|
||||
result |= aRONLY;
|
||||
}
|
||||
TALLOC_FREE(smb_fname);
|
||||
} /* Else never set the readonly bit. */
|
||||
|
||||
if (MAP_ARCHIVE(conn) && ((sbuf->st_ex_mode & S_IXUSR) != 0))
|
||||
if (MAP_ARCHIVE(conn) && ((smb_fname->st.st_ex_mode & S_IXUSR) != 0))
|
||||
result |= aARCH;
|
||||
|
||||
if (MAP_SYSTEM(conn) && ((sbuf->st_ex_mode & S_IXGRP) != 0))
|
||||
if (MAP_SYSTEM(conn) && ((smb_fname->st.st_ex_mode & S_IXGRP) != 0))
|
||||
result |= aSYSTEM;
|
||||
|
||||
if (MAP_HIDDEN(conn) && ((sbuf->st_ex_mode & S_IXOTH) != 0))
|
||||
if (MAP_HIDDEN(conn) && ((smb_fname->st.st_ex_mode & S_IXOTH) != 0))
|
||||
result |= aHIDDEN;
|
||||
|
||||
if (S_ISDIR(sbuf->st_ex_mode))
|
||||
if (S_ISDIR(smb_fname->st.st_ex_mode))
|
||||
result = aDIR | (result & aRONLY);
|
||||
|
||||
result |= set_sparse_flag(sbuf);
|
||||
result |= set_link_read_only_flag(sbuf);
|
||||
result |= set_sparse_flag(&smb_fname->st);
|
||||
result |= set_link_read_only_flag(&smb_fname->st);
|
||||
|
||||
DEBUG(8,("dos_mode_from_sbuf returning "));
|
||||
|
||||
@ -214,7 +207,9 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, cons
|
||||
Get DOS attributes from an EA.
|
||||
****************************************************************************/
|
||||
|
||||
static bool get_ea_dos_attribute(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf, uint32 *pattr)
|
||||
static bool get_ea_dos_attribute(connection_struct *conn,
|
||||
const struct smb_filename *smb_fname,
|
||||
uint32 *pattr)
|
||||
{
|
||||
ssize_t sizeret;
|
||||
fstring attrstr;
|
||||
@ -227,7 +222,9 @@ static bool get_ea_dos_attribute(connection_struct *conn, const char *path, cons
|
||||
/* Don't reset pattr to zero as we may already have filename-based attributes we
|
||||
need to preserve. */
|
||||
|
||||
sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr));
|
||||
sizeret = SMB_VFS_GETXATTR(conn, smb_fname->base_name,
|
||||
SAMBA_XATTR_DOS_ATTRIB, attrstr,
|
||||
sizeof(attrstr));
|
||||
if (sizeret == -1) {
|
||||
if (errno == ENOSYS
|
||||
#if defined(ENOTSUP)
|
||||
@ -235,23 +232,28 @@ static bool get_ea_dos_attribute(connection_struct *conn, const char *path, cons
|
||||
#else
|
||||
) {
|
||||
#endif
|
||||
DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
|
||||
path, strerror(errno) ));
|
||||
DEBUG(1,("get_ea_dos_attributes: Cannot get attribute "
|
||||
"from EA on file %s: Error = %s\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
strerror(errno)));
|
||||
set_store_dos_attributes(SNUM(conn), False);
|
||||
}
|
||||
return False;
|
||||
}
|
||||
/* Null terminate string. */
|
||||
attrstr[sizeret] = 0;
|
||||
DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path, attrstr));
|
||||
DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n",
|
||||
smb_fname_str_dbg(smb_fname), attrstr));
|
||||
|
||||
if (sizeret < 2 || attrstr[0] != '0' || attrstr[1] != 'x' ||
|
||||
sscanf(attrstr, "%x", &dosattr) != 1) {
|
||||
DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path, attrstr));
|
||||
DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on "
|
||||
"file %s - %s\n", smb_fname_str_dbg(smb_fname),
|
||||
attrstr));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (S_ISDIR(sbuf->st_ex_mode)) {
|
||||
if (S_ISDIR(smb_fname->st.st_ex_mode)) {
|
||||
dosattr |= aDIR;
|
||||
}
|
||||
*pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK);
|
||||
@ -273,7 +275,9 @@ static bool get_ea_dos_attribute(connection_struct *conn, const char *path, cons
|
||||
Set DOS attributes in an EA.
|
||||
****************************************************************************/
|
||||
|
||||
static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode)
|
||||
static bool set_ea_dos_attribute(connection_struct *conn,
|
||||
struct smb_filename *smb_fname,
|
||||
uint32 dosmode)
|
||||
{
|
||||
fstring attrstr;
|
||||
files_struct *fsp = NULL;
|
||||
@ -284,7 +288,9 @@ static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_
|
||||
}
|
||||
|
||||
snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK);
|
||||
if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) {
|
||||
if (SMB_VFS_SETXATTR(conn, smb_fname->base_name,
|
||||
SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr),
|
||||
0) == -1) {
|
||||
if((errno != EPERM) && (errno != EACCES)) {
|
||||
if (errno == ENOSYS
|
||||
#if defined(ENOTSUP)
|
||||
@ -292,8 +298,10 @@ static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_
|
||||
#else
|
||||
) {
|
||||
#endif
|
||||
DEBUG(1,("set_ea_dos_attributes: Cannot set attribute EA on file %s: Error = %s\n",
|
||||
path, strerror(errno) ));
|
||||
DEBUG(1,("set_ea_dos_attributes: Cannot set "
|
||||
"attribute EA on file %s: Error = %s\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
strerror(errno) ));
|
||||
set_store_dos_attributes(SNUM(conn), False);
|
||||
}
|
||||
return False;
|
||||
@ -313,18 +321,21 @@ static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_
|
||||
* are not violating security in doing the setxattr.
|
||||
*/
|
||||
|
||||
if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, path, sbuf,
|
||||
if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, smb_fname,
|
||||
&fsp)))
|
||||
return ret;
|
||||
become_root();
|
||||
if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) {
|
||||
if (SMB_VFS_SETXATTR(conn, smb_fname->base_name,
|
||||
SAMBA_XATTR_DOS_ATTRIB, attrstr,
|
||||
strlen(attrstr), 0) == 0) {
|
||||
ret = True;
|
||||
}
|
||||
unbecome_root();
|
||||
close_file_fchmod(NULL, fsp);
|
||||
return ret;
|
||||
}
|
||||
DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr, path));
|
||||
DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr,
|
||||
smb_fname_str_dbg(smb_fname)));
|
||||
return True;
|
||||
}
|
||||
|
||||
@ -332,25 +343,25 @@ static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_
|
||||
Change a unix mode to a dos mode for an ms dfs link.
|
||||
****************************************************************************/
|
||||
|
||||
uint32 dos_mode_msdfs(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *psbuf)
|
||||
uint32 dos_mode_msdfs(connection_struct *conn,
|
||||
const struct smb_filename *smb_fname)
|
||||
{
|
||||
SMB_STRUCT_STAT sbuf = *psbuf;
|
||||
uint32 result = 0;
|
||||
|
||||
DEBUG(8,("dos_mode_msdfs: %s\n", path));
|
||||
DEBUG(8,("dos_mode_msdfs: %s\n", smb_fname_str_dbg(smb_fname)));
|
||||
|
||||
if (!VALID_STAT(sbuf)) {
|
||||
if (!VALID_STAT(smb_fname->st)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First do any modifications that depend on the path name. */
|
||||
/* hide files with a name starting with a . */
|
||||
if (lp_hide_dot_files(SNUM(conn))) {
|
||||
const char *p = strrchr_m(path,'/');
|
||||
const char *p = strrchr_m(smb_fname->base_name, '/');
|
||||
if (p) {
|
||||
p++;
|
||||
} else {
|
||||
p = path;
|
||||
p = smb_fname->base_name;
|
||||
}
|
||||
|
||||
/* Only . and .. are not hidden. */
|
||||
@ -360,11 +371,12 @@ uint32 dos_mode_msdfs(connection_struct *conn, const char *path, const SMB_STRUC
|
||||
}
|
||||
}
|
||||
|
||||
result |= dos_mode_from_sbuf(conn, path, &sbuf);
|
||||
result |= dos_mode_from_sbuf(conn, smb_fname);
|
||||
|
||||
/* Optimization : Only call is_hidden_path if it's not already
|
||||
hidden. */
|
||||
if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
|
||||
if (!(result & aHIDDEN) &&
|
||||
IS_HIDDEN_PATH(conn, smb_fname->base_name)) {
|
||||
result |= aHIDDEN;
|
||||
}
|
||||
|
||||
@ -410,34 +422,34 @@ int dos_attributes_to_stat_dos_flags(uint32_t dosmode)
|
||||
****************************************************************************/
|
||||
|
||||
static bool get_stat_dos_flags(connection_struct *conn,
|
||||
const char *fname,
|
||||
const SMB_STRUCT_STAT *sbuf,
|
||||
const struct smb_filename *smb_fname,
|
||||
uint32_t *dosmode)
|
||||
{
|
||||
SMB_ASSERT(sbuf && VALID_STAT(*sbuf));
|
||||
SMB_ASSERT(VALID_STAT(smb_fname->st));
|
||||
SMB_ASSERT(dosmode);
|
||||
|
||||
if (!lp_store_dos_attributes(SNUM(conn))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG(5, ("Getting stat dos attributes for %s.\n", fname));
|
||||
DEBUG(5, ("Getting stat dos attributes for %s.\n",
|
||||
smb_fname_str_dbg(smb_fname)));
|
||||
|
||||
if (sbuf->st_ex_flags & UF_DOS_ARCHIVE)
|
||||
if (smb_fname->st.st_ex_flags & UF_DOS_ARCHIVE)
|
||||
*dosmode |= aARCH;
|
||||
if (sbuf->st_ex_flags & UF_DOS_HIDDEN)
|
||||
if (smb_fname->st.st_ex_flags & UF_DOS_HIDDEN)
|
||||
*dosmode |= aHIDDEN;
|
||||
if (sbuf->st_ex_flags & UF_DOS_RO)
|
||||
if (smb_fname->st.st_ex_flags & UF_DOS_RO)
|
||||
*dosmode |= aRONLY;
|
||||
if (sbuf->st_ex_flags & UF_DOS_SYSTEM)
|
||||
if (smb_fname->st.st_ex_flags & UF_DOS_SYSTEM)
|
||||
*dosmode |= aSYSTEM;
|
||||
if (sbuf->st_ex_flags & UF_DOS_NOINDEX)
|
||||
if (smb_fname->st.st_ex_flags & UF_DOS_NOINDEX)
|
||||
*dosmode |= FILE_ATTRIBUTE_NONINDEXED;
|
||||
if (S_ISDIR(sbuf->st_ex_mode))
|
||||
if (S_ISDIR(smb_fname->st.st_ex_mode))
|
||||
*dosmode |= aDIR;
|
||||
|
||||
*dosmode |= set_sparse_flag(sbuf);
|
||||
*dosmode |= set_link_read_only_flag(sbuf);
|
||||
*dosmode |= set_sparse_flag(smb_fname->st);
|
||||
*dosmode |= set_link_read_only_flag(smb_fname->st);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -494,26 +506,26 @@ static bool set_stat_dos_flags(connection_struct *conn,
|
||||
Change a unix mode to a dos mode.
|
||||
****************************************************************************/
|
||||
|
||||
uint32 dos_mode(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *psbuf)
|
||||
uint32 dos_mode(connection_struct *conn, const struct smb_filename *smb_fname)
|
||||
{
|
||||
SMB_STRUCT_STAT sbuf = *psbuf;
|
||||
SMB_STRUCT_STAT sbuf;
|
||||
uint32 result = 0;
|
||||
bool offline, used_stat_dos_flags = false;
|
||||
|
||||
DEBUG(8,("dos_mode: %s\n", path));
|
||||
DEBUG(8,("dos_mode: %s\n", smb_fname_str_dbg(smb_fname)));
|
||||
|
||||
if (!VALID_STAT(sbuf)) {
|
||||
if (!VALID_STAT(smb_fname->st)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First do any modifications that depend on the path name. */
|
||||
/* hide files with a name starting with a . */
|
||||
if (lp_hide_dot_files(SNUM(conn))) {
|
||||
const char *p = strrchr_m(path,'/');
|
||||
const char *p = strrchr_m(smb_fname->base_name,'/');
|
||||
if (p) {
|
||||
p++;
|
||||
} else {
|
||||
p = path;
|
||||
p = smb_fname->base_name;
|
||||
}
|
||||
|
||||
/* Only . and .. are not hidden. */
|
||||
@ -524,25 +536,27 @@ uint32 dos_mode(connection_struct *conn, const char *path, const SMB_STRUCT_STAT
|
||||
}
|
||||
|
||||
#ifdef HAVE_STAT_DOS_FLAGS
|
||||
used_stat_dos_flags = get_stat_dos_flags(conn, path, &sbuf, &result);
|
||||
used_stat_dos_flags = get_stat_dos_flags(conn, smb_fname, &result);
|
||||
#endif
|
||||
if (!used_stat_dos_flags) {
|
||||
/* Get the DOS attributes from an EA by preference. */
|
||||
if (get_ea_dos_attribute(conn, path, &sbuf, &result)) {
|
||||
result |= set_sparse_flag(&sbuf);
|
||||
if (get_ea_dos_attribute(conn, smb_fname, &result)) {
|
||||
result |= set_sparse_flag(&smb_fname->st);
|
||||
} else {
|
||||
result |= dos_mode_from_sbuf(conn, path, &sbuf);
|
||||
result |= dos_mode_from_sbuf(conn, smb_fname);
|
||||
}
|
||||
}
|
||||
|
||||
offline = SMB_VFS_IS_OFFLINE(conn, path, &sbuf);
|
||||
sbuf = smb_fname->st;
|
||||
offline = SMB_VFS_IS_OFFLINE(conn, smb_fname->base_name, &sbuf);
|
||||
if (S_ISREG(sbuf.st_ex_mode) && offline) {
|
||||
result |= FILE_ATTRIBUTE_OFFLINE;
|
||||
}
|
||||
|
||||
/* Optimization : Only call is_hidden_path if it's not already
|
||||
hidden. */
|
||||
if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
|
||||
if (!(result & aHIDDEN) &&
|
||||
IS_HIDDEN_PATH(conn, smb_fname->base_name)) {
|
||||
result |= aHIDDEN;
|
||||
}
|
||||
|
||||
@ -572,8 +586,6 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
|
||||
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);
|
||||
@ -596,17 +608,11 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
|
||||
else
|
||||
dosmode &= ~aDIR;
|
||||
|
||||
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);
|
||||
old_mode = dos_mode(conn, smb_fname);
|
||||
|
||||
if (dosmode & FILE_ATTRIBUTE_OFFLINE) {
|
||||
if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) {
|
||||
lret = SMB_VFS_SET_OFFLINE(conn, fname);
|
||||
lret = SMB_VFS_SET_OFFLINE(conn, smb_fname->base_name);
|
||||
if (lret == -1) {
|
||||
DEBUG(0, ("set_dos_mode: client has asked to "
|
||||
"set FILE_ATTRIBUTE_OFFLINE to "
|
||||
@ -635,19 +641,20 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
|
||||
{
|
||||
if (!newfile && attributes_changed) {
|
||||
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES,
|
||||
smb_fname->base_name);
|
||||
}
|
||||
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, &smb_fname->st, dosmode)) {
|
||||
if (set_ea_dos_attribute(conn, smb_fname, dosmode)) {
|
||||
if (!newfile) {
|
||||
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES,
|
||||
smb_fname->base_name);
|
||||
}
|
||||
smb_fname->st.st_ex_mode = unixmode;
|
||||
return 0;
|
||||
@ -685,11 +692,12 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
|
||||
unixmode |= (smb_fname->st.st_ex_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
|
||||
}
|
||||
|
||||
ret = SMB_VFS_CHMOD(conn, fname, unixmode);
|
||||
ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
|
||||
if (ret == 0) {
|
||||
if(!newfile || (lret != -1)) {
|
||||
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES,
|
||||
smb_fname->base_name);
|
||||
}
|
||||
smb_fname->st.st_ex_mode = unixmode;
|
||||
return 0;
|
||||
@ -716,8 +724,8 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
|
||||
* break batch oplocks open by others. JRA.
|
||||
*/
|
||||
files_struct *fsp;
|
||||
if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, fname,
|
||||
&smb_fname->st, &fsp)))
|
||||
if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, smb_fname,
|
||||
&fsp)))
|
||||
return -1;
|
||||
become_root();
|
||||
ret = SMB_VFS_FCHMOD(fsp, unixmode);
|
||||
@ -725,7 +733,8 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
|
||||
close_file_fchmod(NULL, fsp);
|
||||
if (!newfile) {
|
||||
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES,
|
||||
smb_fname->base_name);
|
||||
}
|
||||
if (ret == 0) {
|
||||
smb_fname->st.st_ex_mode = unixmode;
|
||||
|
@ -284,32 +284,28 @@ ssize_t write_file(struct smb_request *req,
|
||||
}
|
||||
|
||||
if (!fsp->modified) {
|
||||
SMB_STRUCT_STAT st;
|
||||
struct smb_filename *smb_fname = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
fsp->modified = True;
|
||||
|
||||
if (SMB_VFS_FSTAT(fsp, &st) == 0) {
|
||||
status = create_synthetic_smb_fname_split(talloc_tos(),
|
||||
fsp->fsp_name, NULL,
|
||||
&smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
errno = map_errno_from_nt_status(status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SMB_VFS_FSTAT(fsp, &smb_fname->st) == 0) {
|
||||
int dosmode;
|
||||
trigger_write_time_update(fsp);
|
||||
dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st);
|
||||
dosmode = dos_mode(fsp->conn, smb_fname);
|
||||
if ((lp_store_dos_attributes(SNUM(fsp->conn)) ||
|
||||
MAP_ARCHIVE(fsp->conn)) &&
|
||||
!IS_DOS_ARCHIVE(dosmode)) {
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -318,10 +314,12 @@ ssize_t write_file(struct smb_request *req,
|
||||
*/
|
||||
|
||||
if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !wcp) {
|
||||
setup_write_cache(fsp, st.st_ex_size);
|
||||
setup_write_cache(fsp,
|
||||
smb_fname->st.st_ex_size);
|
||||
wcp = fsp->wcp;
|
||||
}
|
||||
}
|
||||
TALLOC_FREE(smb_fname);
|
||||
}
|
||||
|
||||
#ifdef WITH_PROFILE
|
||||
|
@ -620,7 +620,7 @@ void reply_ntcreate_and_X(struct smb_request *req)
|
||||
}
|
||||
|
||||
file_len = smb_fname->st.st_ex_size;
|
||||
fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
|
||||
fattr = dos_mode(conn, smb_fname);
|
||||
if (fattr == 0) {
|
||||
fattr = FILE_ATTRIBUTE_NORMAL;
|
||||
}
|
||||
@ -704,7 +704,7 @@ void reply_ntcreate_and_X(struct smb_request *req)
|
||||
}
|
||||
|
||||
DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n",
|
||||
fsp->fnum, fsp->fsp_name));
|
||||
fsp->fnum, smb_fname_str_dbg(smb_fname)));
|
||||
|
||||
chain_reply(req);
|
||||
out:
|
||||
@ -1111,7 +1111,7 @@ static void call_nt_transact_create(connection_struct *conn,
|
||||
}
|
||||
|
||||
file_len = smb_fname->st.st_ex_size;
|
||||
fattr = dos_mode(conn, fsp->fsp_name, &smb_fname->st);
|
||||
fattr = dos_mode(conn, smb_fname);
|
||||
if (fattr == 0) {
|
||||
fattr = FILE_ATTRIBUTE_NORMAL;
|
||||
}
|
||||
@ -1194,7 +1194,8 @@ static void call_nt_transact_create(connection_struct *conn,
|
||||
SIVAL(p,0,perms);
|
||||
}
|
||||
|
||||
DEBUG(5,("call_nt_transact_create: open name = %s\n", fsp->fsp_name));
|
||||
DEBUG(5,("call_nt_transact_create: open name = %s\n",
|
||||
smb_fname_str_dbg(smb_fname)));
|
||||
|
||||
/* Send the required number of replies */
|
||||
send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0);
|
||||
@ -1236,7 +1237,6 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
|
||||
struct smb_filename *smb_fname_dst,
|
||||
uint32 attrs)
|
||||
{
|
||||
char *oldname = NULL;
|
||||
files_struct *fsp1,*fsp2;
|
||||
uint32 fattr;
|
||||
int info;
|
||||
@ -1255,13 +1255,8 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = get_full_smb_filename(ctx, smb_fname_src, &oldname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Ensure attributes match. */
|
||||
fattr = dos_mode(conn, oldname, &smb_fname_src->st);
|
||||
fattr = dos_mode(conn, smb_fname_src);
|
||||
if ((fattr & ~attrs) & (aHIDDEN | aSYSTEM)) {
|
||||
status = NT_STATUS_NO_SUCH_FILE;
|
||||
goto out;
|
||||
@ -1367,7 +1362,6 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
|
||||
smb_fname_str_dbg(smb_fname_dst)));
|
||||
}
|
||||
|
||||
TALLOC_FREE(oldname);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1567,8 +1567,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
|
||||
if (!posix_open) {
|
||||
new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;
|
||||
if (file_existed) {
|
||||
existing_dos_attributes = dos_mode(conn, fname,
|
||||
&smb_fname->st);
|
||||
existing_dos_attributes = dos_mode(conn, smb_fname);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2265,14 +2264,13 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
|
||||
****************************************************************************/
|
||||
|
||||
NTSTATUS open_file_fchmod(struct smb_request *req, connection_struct *conn,
|
||||
const char *fname,
|
||||
SMB_STRUCT_STAT *psbuf, files_struct **result)
|
||||
struct smb_filename *smb_fname,
|
||||
files_struct **result)
|
||||
{
|
||||
struct smb_filename *smb_fname = NULL;
|
||||
files_struct *fsp = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
if (!VALID_STAT(*psbuf)) {
|
||||
if (!VALID_STAT(smb_fname->st)) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
@ -2281,12 +2279,6 @@ NTSTATUS open_file_fchmod(struct smb_request *req, connection_struct *conn,
|
||||
return status;
|
||||
}
|
||||
|
||||
status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
|
||||
&smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
NULL, /* req */
|
||||
@ -2303,10 +2295,7 @@ NTSTATUS open_file_fchmod(struct smb_request *req, connection_struct *conn,
|
||||
NULL, /* sd */
|
||||
NULL, /* ea_list */
|
||||
&fsp, /* result */
|
||||
NULL); /* psbuf */
|
||||
|
||||
*psbuf = smb_fname->st;
|
||||
TALLOC_FREE(smb_fname);
|
||||
NULL); /* pinfo */
|
||||
|
||||
/*
|
||||
* This is not a user visible file open.
|
||||
|
@ -2560,36 +2560,23 @@ static bool current_user_in_group(gid_t gid)
|
||||
****************************************************************************/
|
||||
|
||||
static bool acl_group_override(connection_struct *conn,
|
||||
const SMB_STRUCT_STAT *psbuf,
|
||||
const char *fname)
|
||||
const struct smb_filename *smb_fname)
|
||||
{
|
||||
struct smb_filename *smb_fname = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
if ((errno != EPERM) && (errno != EACCES)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* file primary group == user primary or supplementary group */
|
||||
if (lp_acl_group_control(SNUM(conn)) &&
|
||||
current_user_in_group(psbuf->st_ex_gid)) {
|
||||
current_user_in_group(smb_fname->st.st_ex_gid)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
|
||||
&smb_fname);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* user has writeable permission */
|
||||
if (lp_dos_filemode(SNUM(conn)) &&
|
||||
can_write_to_file(conn, smb_fname)) {
|
||||
TALLOC_FREE(smb_fname);
|
||||
return true;
|
||||
}
|
||||
TALLOC_FREE(smb_fname);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -2615,6 +2602,14 @@ static bool set_canon_ace_list(files_struct *fsp,
|
||||
SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS);
|
||||
bool needs_mask = False;
|
||||
mode_t mask_perms = 0;
|
||||
struct smb_filename *smb_fname = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name,
|
||||
psbuf, &smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if defined(POSIX_ACL_NEEDS_MASK)
|
||||
/* HP-UX always wants to have a mask (called "class" there). */
|
||||
@ -2632,7 +2627,7 @@ static bool set_canon_ace_list(files_struct *fsp,
|
||||
default_ace ? "default" : "file", strerror(errno) ));
|
||||
}
|
||||
*pacl_set_support = False;
|
||||
return False;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if( DEBUGLVL( 10 )) {
|
||||
@ -2772,7 +2767,8 @@ static bool set_canon_ace_list(files_struct *fsp,
|
||||
*/
|
||||
|
||||
if(default_ace || fsp->is_directory || fsp->fh->fd == -1) {
|
||||
if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) {
|
||||
if (SMB_VFS_SYS_ACL_SET_FILE(conn, smb_fname->base_name,
|
||||
the_acl_type, the_acl) == -1) {
|
||||
/*
|
||||
* Some systems allow all the above calls and only fail with no ACL support
|
||||
* when attempting to apply the acl. HPUX with HFS is an example of this. JRA.
|
||||
@ -2781,14 +2777,18 @@ static bool set_canon_ace_list(files_struct *fsp,
|
||||
*pacl_set_support = False;
|
||||
}
|
||||
|
||||
if (acl_group_override(conn, psbuf, fsp->fsp_name)) {
|
||||
if (acl_group_override(conn, smb_fname)) {
|
||||
int sret;
|
||||
|
||||
DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n",
|
||||
fsp->fsp_name ));
|
||||
DEBUG(5,("set_canon_ace_list: acl group "
|
||||
"control on and current user in file "
|
||||
"%s primary group.\n",
|
||||
smb_fname_str_dbg(smb_fname)));
|
||||
|
||||
become_root();
|
||||
sret = SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl);
|
||||
sret = SMB_VFS_SYS_ACL_SET_FILE(conn,
|
||||
smb_fname->base_name, the_acl_type,
|
||||
the_acl);
|
||||
unbecome_root();
|
||||
if (sret == 0) {
|
||||
ret = True;
|
||||
@ -2796,9 +2796,13 @@ static bool set_canon_ace_list(files_struct *fsp,
|
||||
}
|
||||
|
||||
if (ret == False) {
|
||||
DEBUG(2,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n",
|
||||
the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file",
|
||||
fsp->fsp_name, strerror(errno) ));
|
||||
DEBUG(2,("set_canon_ace_list: "
|
||||
"sys_acl_set_file type %s failed for "
|
||||
"file %s (%s).\n",
|
||||
the_acl_type == SMB_ACL_TYPE_DEFAULT ?
|
||||
"directory default" : "file",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
strerror(errno)));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@ -2812,11 +2816,13 @@ static bool set_canon_ace_list(files_struct *fsp,
|
||||
*pacl_set_support = False;
|
||||
}
|
||||
|
||||
if (acl_group_override(conn, psbuf, fsp->fsp_name)) {
|
||||
if (acl_group_override(conn, smb_fname)) {
|
||||
int sret;
|
||||
|
||||
DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n",
|
||||
fsp->fsp_name ));
|
||||
DEBUG(5,("set_canon_ace_list: acl group "
|
||||
"control on and current user in file "
|
||||
"%s primary group.\n",
|
||||
smb_fname_str_dbg(smb_fname)));
|
||||
|
||||
become_root();
|
||||
sret = SMB_VFS_SYS_ACL_SET_FD(fsp, the_acl);
|
||||
@ -2827,8 +2833,11 @@ static bool set_canon_ace_list(files_struct *fsp,
|
||||
}
|
||||
|
||||
if (ret == False) {
|
||||
DEBUG(2,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n",
|
||||
fsp->fsp_name, strerror(errno) ));
|
||||
DEBUG(2,("set_canon_ace_list: "
|
||||
"sys_acl_set_file failed for file %s "
|
||||
"(%s).\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
strerror(errno) ));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@ -2841,6 +2850,7 @@ static bool set_canon_ace_list(files_struct *fsp,
|
||||
if (the_acl != NULL) {
|
||||
SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);
|
||||
}
|
||||
TALLOC_FREE(smb_fname);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -3405,11 +3415,11 @@ NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
|
||||
then allow chown to the currently authenticated user.
|
||||
****************************************************************************/
|
||||
|
||||
int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
|
||||
int try_chown(connection_struct *conn, struct smb_filename *smb_fname,
|
||||
uid_t uid, gid_t gid)
|
||||
{
|
||||
int ret;
|
||||
files_struct *fsp;
|
||||
SMB_STRUCT_STAT st;
|
||||
|
||||
if(!CAN_WRITE(conn)) {
|
||||
return -1;
|
||||
@ -3417,7 +3427,7 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
|
||||
|
||||
/* Case (1). */
|
||||
/* try the direct way first */
|
||||
ret = SMB_VFS_CHOWN(conn, fname, uid, gid);
|
||||
ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid, gid);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
||||
@ -3436,7 +3446,8 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
|
||||
|
||||
become_root();
|
||||
/* Keep the current file gid the same - take ownership doesn't imply group change. */
|
||||
ret = SMB_VFS_CHOWN(conn, fname, uid, (gid_t)-1);
|
||||
ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid,
|
||||
(gid_t)-1);
|
||||
unbecome_root();
|
||||
return ret;
|
||||
}
|
||||
@ -3457,11 +3468,11 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vfs_stat_smb_fname(conn,fname,&st)) {
|
||||
if (SMB_VFS_STAT(conn, smb_fname)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, fname, &st, &fsp))) {
|
||||
if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, smb_fname, &fsp))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -3507,8 +3518,8 @@ NTSTATUS append_parent_acl(files_struct *fsp,
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
status = create_synthetic_smb_fname_split(mem_ctx, parent_name, NULL,
|
||||
&smb_dname);
|
||||
status = create_synthetic_smb_fname(mem_ctx, parent_name, NULL, NULL,
|
||||
&smb_dname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto fail;
|
||||
}
|
||||
@ -3530,16 +3541,16 @@ NTSTATUS append_parent_acl(files_struct *fsp,
|
||||
&parent_fsp, /* result */
|
||||
&info); /* pinfo */
|
||||
|
||||
TALLOC_FREE(smb_fname);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
TALLOC_FREE(smb_dname);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = SMB_VFS_GET_NT_ACL(parent_fsp->conn, parent_fsp->fsp_name,
|
||||
status = SMB_VFS_GET_NT_ACL(parent_fsp->conn, smb_dname->base_name,
|
||||
DACL_SECURITY_INFORMATION, &parent_sd );
|
||||
|
||||
close_file(NULL, parent_fsp, NORMAL_CLOSE);
|
||||
TALLOC_FREE(smb_dname);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
@ -3686,7 +3697,6 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
|
||||
connection_struct *conn = fsp->conn;
|
||||
uid_t user = (uid_t)-1;
|
||||
gid_t grp = (gid_t)-1;
|
||||
SMB_STRUCT_STAT sbuf;
|
||||
DOM_SID file_owner_sid;
|
||||
DOM_SID file_grp_sid;
|
||||
canon_ace *file_ace_list = NULL;
|
||||
@ -3697,12 +3707,21 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
|
||||
bool set_acl_as_root = false;
|
||||
bool acl_set_support = false;
|
||||
bool ret = false;
|
||||
struct smb_filename *smb_fname = NULL;
|
||||
|
||||
DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name ));
|
||||
status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name,
|
||||
NULL, &smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
DEBUG(10,("set_nt_acl: called for file %s\n",
|
||||
smb_fname_str_dbg(smb_fname)));
|
||||
|
||||
if (!CAN_WRITE(conn)) {
|
||||
DEBUG(10,("set acl rejected on read-only share\n"));
|
||||
return NT_STATUS_MEDIA_WRITE_PROTECTED;
|
||||
status = NT_STATUS_MEDIA_WRITE_PROTECTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3710,15 +3729,19 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
|
||||
*/
|
||||
|
||||
if(fsp->is_directory || fsp->fh->fd == -1) {
|
||||
if(vfs_stat_smb_fname(fsp->conn,fsp->fsp_name, &sbuf) != 0)
|
||||
return map_nt_error_from_unix(errno);
|
||||
if(SMB_VFS_STAT(fsp->conn, smb_fname) != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if(SMB_VFS_FSTAT(fsp, &sbuf) != 0)
|
||||
return map_nt_error_from_unix(errno);
|
||||
if(SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the original element we check against. */
|
||||
orig_mode = sbuf.st_ex_mode;
|
||||
orig_mode = smb_fname->st.st_ex_mode;
|
||||
|
||||
/*
|
||||
* Unpack the user/group/world id's.
|
||||
@ -3726,7 +3749,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
|
||||
|
||||
status = unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3735,18 +3758,24 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
|
||||
* Noticed by Simo.
|
||||
*/
|
||||
|
||||
if (((user != (uid_t)-1) && (sbuf.st_ex_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_ex_gid != grp))) {
|
||||
if (((user != (uid_t)-1) && (smb_fname->st.st_ex_uid != user)) ||
|
||||
(( grp != (gid_t)-1) && (smb_fname->st.st_ex_gid != grp))) {
|
||||
|
||||
DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
|
||||
fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
|
||||
smb_fname_str_dbg(smb_fname), (unsigned int)user,
|
||||
(unsigned int)grp ));
|
||||
|
||||
if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) {
|
||||
DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n",
|
||||
fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) ));
|
||||
if(try_chown(fsp->conn, smb_fname, user, grp) == -1) {
|
||||
DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error "
|
||||
"= %s.\n", smb_fname_str_dbg(smb_fname),
|
||||
(unsigned int)user, (unsigned int)grp,
|
||||
strerror(errno)));
|
||||
if (errno == EPERM) {
|
||||
return NT_STATUS_INVALID_OWNER;
|
||||
status = NT_STATUS_INVALID_OWNER;
|
||||
goto out;
|
||||
}
|
||||
return map_nt_error_from_unix(errno);
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3755,27 +3784,25 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
|
||||
*/
|
||||
|
||||
if(fsp->is_directory) {
|
||||
if(vfs_stat_smb_fname(fsp->conn, fsp->fsp_name,
|
||||
&sbuf) != 0) {
|
||||
return map_nt_error_from_unix(errno);
|
||||
if(SMB_VFS_STAT(fsp->conn, smb_fname) != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
|
||||
int sret;
|
||||
|
||||
if(fsp->fh->fd == -1)
|
||||
sret = vfs_stat_smb_fname(fsp->conn,
|
||||
fsp->fsp_name,
|
||||
&sbuf);
|
||||
sret = SMB_VFS_STAT(fsp->conn, smb_fname);
|
||||
else
|
||||
sret = SMB_VFS_FSTAT(fsp, &sbuf);
|
||||
sret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
|
||||
|
||||
if(sret != 0)
|
||||
return map_nt_error_from_unix(errno);
|
||||
}
|
||||
|
||||
/* Save the original element we check against. */
|
||||
orig_mode = sbuf.st_ex_mode;
|
||||
orig_mode = smb_fname->st.st_ex_mode;
|
||||
|
||||
/* If we successfully chowned, we know we must
|
||||
* be able to set the acl, so do it as root.
|
||||
@ -3783,21 +3810,24 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
|
||||
set_acl_as_root = true;
|
||||
}
|
||||
|
||||
create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid);
|
||||
create_file_sids(&smb_fname->st, &file_owner_sid, &file_grp_sid);
|
||||
|
||||
acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid,
|
||||
&file_ace_list, &dir_ace_list, security_info_sent, psd);
|
||||
acl_perms = unpack_canon_ace(fsp, &smb_fname->st, &file_owner_sid,
|
||||
&file_grp_sid, &file_ace_list,
|
||||
&dir_ace_list, security_info_sent, psd);
|
||||
|
||||
/* Ignore W2K traverse DACL set. */
|
||||
if (!file_ace_list && !dir_ace_list) {
|
||||
return NT_STATUS_OK;
|
||||
status = NT_STATUS_OK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!acl_perms) {
|
||||
DEBUG(3,("set_nt_acl: cannot set permissions\n"));
|
||||
free_canon_ace_list(file_ace_list);
|
||||
free_canon_ace_list(dir_ace_list);
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
status = NT_STATUS_ACCESS_DENIED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3807,7 +3837,8 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
|
||||
if(!(security_info_sent & DACL_SECURITY_INFORMATION) || (psd->dacl == NULL)) {
|
||||
free_canon_ace_list(file_ace_list);
|
||||
free_canon_ace_list(dir_ace_list);
|
||||
return NT_STATUS_OK;
|
||||
status = NT_STATUS_OK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3819,15 +3850,19 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
|
||||
if (set_acl_as_root) {
|
||||
become_root();
|
||||
}
|
||||
ret = set_canon_ace_list(fsp, file_ace_list, False, &sbuf, &acl_set_support);
|
||||
ret = set_canon_ace_list(fsp, file_ace_list, false,
|
||||
&smb_fname->st, &acl_set_support);
|
||||
if (set_acl_as_root) {
|
||||
unbecome_root();
|
||||
}
|
||||
if (acl_set_support && ret == false) {
|
||||
DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) ));
|
||||
DEBUG(3,("set_nt_acl: failed to set file acl on file "
|
||||
"%s (%s).\n", smb_fname_str_dbg(smb_fname),
|
||||
strerror(errno)));
|
||||
free_canon_ace_list(file_ace_list);
|
||||
free_canon_ace_list(dir_ace_list);
|
||||
return map_nt_error_from_unix(errno);
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3836,15 +3871,21 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
|
||||
if (set_acl_as_root) {
|
||||
become_root();
|
||||
}
|
||||
ret = set_canon_ace_list(fsp, dir_ace_list, True, &sbuf, &acl_set_support);
|
||||
ret = set_canon_ace_list(fsp, dir_ace_list, true,
|
||||
&smb_fname->st,
|
||||
&acl_set_support);
|
||||
if (set_acl_as_root) {
|
||||
unbecome_root();
|
||||
}
|
||||
if (ret == false) {
|
||||
DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) ));
|
||||
DEBUG(3,("set_nt_acl: failed to set default "
|
||||
"acl on directory %s (%s).\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
strerror(errno) ));
|
||||
free_canon_ace_list(file_ace_list);
|
||||
free_canon_ace_list(dir_ace_list);
|
||||
return map_nt_error_from_unix(errno);
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
int sret = -1;
|
||||
@ -3856,18 +3897,24 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
|
||||
if (set_acl_as_root) {
|
||||
become_root();
|
||||
}
|
||||
sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name);
|
||||
sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn,
|
||||
smb_fname->base_name);
|
||||
if (set_acl_as_root) {
|
||||
unbecome_root();
|
||||
}
|
||||
if (sret == -1) {
|
||||
if (acl_group_override(conn, &sbuf, fsp->fsp_name)) {
|
||||
DEBUG(5,("set_nt_acl: acl group control on and "
|
||||
"current user in file %s primary group. Override delete_def_acl\n",
|
||||
fsp->fsp_name ));
|
||||
if (acl_group_override(conn, smb_fname)) {
|
||||
DEBUG(5,("set_nt_acl: acl group "
|
||||
"control on and current user "
|
||||
"in file %s primary group. "
|
||||
"Override delete_def_acl\n",
|
||||
smb_fname_str_dbg(smb_fname)));
|
||||
|
||||
become_root();
|
||||
sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name);
|
||||
sret =
|
||||
SMB_VFS_SYS_ACL_DELETE_DEF_FILE(
|
||||
conn,
|
||||
smb_fname->base_name);
|
||||
unbecome_root();
|
||||
}
|
||||
|
||||
@ -3875,7 +3922,8 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
|
||||
DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno)));
|
||||
free_canon_ace_list(file_ace_list);
|
||||
free_canon_ace_list(dir_ace_list);
|
||||
return map_nt_error_from_unix(errno);
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3904,41 +3952,54 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
|
||||
if (!convert_canon_ace_to_posix_perms( fsp, file_ace_list, &posix_perms)) {
|
||||
free_canon_ace_list(file_ace_list);
|
||||
free_canon_ace_list(dir_ace_list);
|
||||
DEBUG(3,("set_nt_acl: failed to convert file acl to posix permissions for file %s.\n",
|
||||
fsp->fsp_name ));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
DEBUG(3,("set_nt_acl: failed to convert file acl to "
|
||||
"posix permissions for file %s.\n",
|
||||
smb_fname_str_dbg(smb_fname)));
|
||||
status = NT_STATUS_ACCESS_DENIED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (orig_mode != posix_perms) {
|
||||
int sret = -1;
|
||||
|
||||
DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n",
|
||||
fsp->fsp_name, (unsigned int)posix_perms ));
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
(unsigned int)posix_perms));
|
||||
|
||||
if (set_acl_as_root) {
|
||||
become_root();
|
||||
}
|
||||
sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms);
|
||||
sret = SMB_VFS_CHMOD(conn, smb_fname->base_name,
|
||||
posix_perms);
|
||||
if (set_acl_as_root) {
|
||||
unbecome_root();
|
||||
}
|
||||
if(sret == -1) {
|
||||
if (acl_group_override(conn, &sbuf, fsp->fsp_name)) {
|
||||
DEBUG(5,("set_nt_acl: acl group control on and "
|
||||
"current user in file %s primary group. Override chmod\n",
|
||||
fsp->fsp_name ));
|
||||
if (acl_group_override(conn, smb_fname)) {
|
||||
DEBUG(5,("set_nt_acl: acl group "
|
||||
"control on and current user "
|
||||
"in file %s primary group. "
|
||||
"Override chmod\n",
|
||||
smb_fname_str_dbg(smb_fname)));
|
||||
|
||||
become_root();
|
||||
sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms);
|
||||
sret =
|
||||
SMB_VFS_CHMOD(conn,
|
||||
smb_fname->base_name,
|
||||
posix_perms);
|
||||
unbecome_root();
|
||||
}
|
||||
|
||||
if (sret == -1) {
|
||||
DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n",
|
||||
fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) ));
|
||||
DEBUG(3,("set_nt_acl: chmod %s, 0%o "
|
||||
"failed. Error = %s.\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
(unsigned int)posix_perms,
|
||||
strerror(errno)));
|
||||
free_canon_ace_list(file_ace_list);
|
||||
free_canon_ace_list(dir_ace_list);
|
||||
return map_nt_error_from_unix(errno);
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3947,7 +4008,10 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
|
||||
free_canon_ace_list(file_ace_list);
|
||||
free_canon_ace_list(dir_ace_list);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
status = NT_STATUS_OK;
|
||||
out:
|
||||
TALLOC_FREE(smb_fname);
|
||||
return status;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -1091,7 +1091,7 @@ void reply_getatr(struct smb_request *req)
|
||||
req->flags2 & FLAGS2_DFS_PATHNAMES,
|
||||
fname,
|
||||
&smb_fname,
|
||||
&fname);
|
||||
NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
|
||||
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
|
||||
@ -1110,7 +1110,7 @@ void reply_getatr(struct smb_request *req)
|
||||
goto out;
|
||||
}
|
||||
|
||||
mode = dos_mode(conn, fname, &smb_fname->st);
|
||||
mode = dos_mode(conn, smb_fname);
|
||||
size = smb_fname->st.st_ex_size;
|
||||
|
||||
if (ask_sharemode) {
|
||||
@ -1747,7 +1747,7 @@ void reply_open(struct smb_request *req)
|
||||
req->flags2 & FLAGS2_DFS_PATHNAMES,
|
||||
fname,
|
||||
&smb_fname,
|
||||
&fname);
|
||||
NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
|
||||
reply_botherror(req,
|
||||
@ -1760,8 +1760,9 @@ void reply_open(struct smb_request *req)
|
||||
}
|
||||
|
||||
if (!map_open_params_to_ntcreate(
|
||||
fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
|
||||
&share_mode, &create_disposition, &create_options)) {
|
||||
smb_fname->base_name, deny_mode, OPENX_FILE_EXISTS_OPEN,
|
||||
&access_mask, &share_mode, &create_disposition,
|
||||
&create_options)) {
|
||||
reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
|
||||
goto out;
|
||||
}
|
||||
@ -1793,7 +1794,7 @@ void reply_open(struct smb_request *req)
|
||||
}
|
||||
|
||||
size = smb_fname->st.st_ex_size;
|
||||
fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
|
||||
fattr = dos_mode(conn, smb_fname);
|
||||
|
||||
/* Deal with other possible opens having a modified
|
||||
write time. JRA. */
|
||||
@ -1916,7 +1917,7 @@ void reply_open_and_X(struct smb_request *req)
|
||||
req->flags2 & FLAGS2_DFS_PATHNAMES,
|
||||
fname,
|
||||
&smb_fname,
|
||||
&fname);
|
||||
NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
|
||||
reply_botherror(req,
|
||||
@ -1929,7 +1930,7 @@ void reply_open_and_X(struct smb_request *req)
|
||||
}
|
||||
|
||||
if (!map_open_params_to_ntcreate(
|
||||
fname, deny_mode, smb_ofun, &access_mask,
|
||||
smb_fname->base_name, deny_mode, smb_ofun, &access_mask,
|
||||
&share_mode, &create_disposition, &create_options)) {
|
||||
reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
|
||||
goto out;
|
||||
@ -1980,7 +1981,7 @@ void reply_open_and_X(struct smb_request *req)
|
||||
SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
|
||||
}
|
||||
|
||||
fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
|
||||
fattr = dos_mode(conn, smb_fname);
|
||||
mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
|
||||
if (fattr & aDIR) {
|
||||
close_file(req, fsp, ERROR_CLOSE);
|
||||
@ -2354,13 +2355,22 @@ void reply_ctemp(struct smb_request *req)
|
||||
static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
|
||||
uint16 dirtype, SMB_STRUCT_STAT *pst)
|
||||
{
|
||||
struct smb_filename *smb_fname = NULL;
|
||||
NTSTATUS status;
|
||||
uint32 fmode;
|
||||
|
||||
if (!CAN_WRITE(conn)) {
|
||||
return NT_STATUS_MEDIA_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
fmode = dos_mode(conn, fsp->fsp_name, pst);
|
||||
status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name,
|
||||
pst, &smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
fmode = dos_mode(conn, smb_fname);
|
||||
TALLOC_FREE(smb_fname);
|
||||
if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
|
||||
return NT_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
@ -2395,13 +2405,14 @@ static NTSTATUS do_unlink(connection_struct *conn,
|
||||
struct smb_filename *smb_fname,
|
||||
uint32 dirtype)
|
||||
{
|
||||
char *fname = NULL;
|
||||
uint32 fattr;
|
||||
files_struct *fsp;
|
||||
uint32 dirtype_orig = dirtype;
|
||||
NTSTATUS status;
|
||||
|
||||
DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
|
||||
DEBUG(10,("do_unlink: %s, dirtype = %d\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
dirtype));
|
||||
|
||||
if (!CAN_WRITE(conn)) {
|
||||
return NT_STATUS_MEDIA_WRITE_PROTECTED;
|
||||
@ -2411,12 +2422,7 @@ static NTSTATUS do_unlink(connection_struct *conn,
|
||||
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;
|
||||
}
|
||||
fattr = dos_mode(conn, fname, &smb_fname->st);
|
||||
TALLOC_FREE(fname);
|
||||
fattr = dos_mode(conn, smb_fname);
|
||||
|
||||
if (dirtype & FILE_ATTRIBUTE_NORMAL) {
|
||||
dirtype = aDIR|aARCH|aRONLY;
|
||||
@ -6578,7 +6584,6 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
|
||||
bool target_is_directory)
|
||||
{
|
||||
struct smb_filename *smb_fname_dst_tmp = NULL;
|
||||
char *fname_src = NULL;
|
||||
SMB_OFF_T ret=-1;
|
||||
files_struct *fsp1,*fsp2;
|
||||
uint32 dosattrs;
|
||||
@ -6655,14 +6660,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = get_full_smb_filename(talloc_tos(), smb_fname_src, &fname_src);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
dosattrs = dos_mode(conn, fname_src, &smb_fname_src->st);
|
||||
|
||||
TALLOC_FREE(fname_src);
|
||||
dosattrs = dos_mode(conn, smb_fname_src);
|
||||
|
||||
if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
|
||||
ZERO_STRUCTP(&smb_fname_dst_tmp->st);
|
||||
@ -7739,6 +7737,8 @@ void reply_getattrE(struct smb_request *req)
|
||||
int mode;
|
||||
files_struct *fsp;
|
||||
struct timespec create_ts;
|
||||
struct smb_filename *smb_fname = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
START_PROFILE(SMBgetattrE);
|
||||
|
||||
@ -7763,7 +7763,16 @@ void reply_getattrE(struct smb_request *req)
|
||||
return;
|
||||
}
|
||||
|
||||
mode = dos_mode(conn,fsp->fsp_name,&sbuf);
|
||||
status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name,
|
||||
&sbuf, &smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
reply_nterror(req, status);
|
||||
END_PROFILE(SMBgetattrE);
|
||||
return;
|
||||
}
|
||||
|
||||
mode = dos_mode(conn, smb_fname);
|
||||
TALLOC_FREE(smb_fname);
|
||||
|
||||
/*
|
||||
* Convert the times into dos times. Set create
|
||||
|
@ -353,6 +353,16 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
|
||||
sbuf = smb_fname->st;
|
||||
}
|
||||
|
||||
if (!smb_fname) {
|
||||
status = create_synthetic_smb_fname_split(talloc_tos(),
|
||||
result->fsp_name,
|
||||
&sbuf, &smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
tevent_req_nterror(req, status);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
smb2req->compat_chain_fsp = smbreq->chain_fsp;
|
||||
|
||||
state->out_oplock_level = 0;
|
||||
@ -369,8 +379,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
|
||||
state->out_allocation_size = sbuf.st_ex_blksize * sbuf.st_ex_blocks;
|
||||
state->out_end_of_file = sbuf.st_ex_size;
|
||||
state->out_file_attributes = dos_mode(result->conn,
|
||||
result->fsp_name,
|
||||
&sbuf);
|
||||
smb_fname);
|
||||
if (state->out_file_attributes == 0) {
|
||||
state->out_file_attributes = FILE_ATTRIBUTE_NORMAL;
|
||||
}
|
||||
|
@ -964,7 +964,7 @@ static void call_trans2open(connection_struct *conn,
|
||||
req->flags2 & FLAGS2_DFS_PATHNAMES,
|
||||
fname,
|
||||
&smb_fname,
|
||||
&fname);
|
||||
NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
|
||||
reply_botherror(req,
|
||||
@ -981,7 +981,8 @@ static void call_trans2open(connection_struct *conn,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
|
||||
if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
|
||||
open_ofun,
|
||||
&access_mask,
|
||||
&share_mode,
|
||||
&create_disposition,
|
||||
@ -1047,7 +1048,7 @@ static void call_trans2open(connection_struct *conn,
|
||||
}
|
||||
|
||||
size = get_file_size_stat(&smb_fname->st);
|
||||
fattr = dos_mode(conn, fsp->fsp_name, &smb_fname->st);
|
||||
fattr = dos_mode(conn, smb_fname);
|
||||
mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
|
||||
inode = smb_fname->st.st_ex_ino;
|
||||
if (fattr & aDIR) {
|
||||
@ -1388,6 +1389,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
|
||||
|
||||
if (got_match) {
|
||||
bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
|
||||
struct smb_filename *smb_fname = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
if (dont_descend && !isdots) {
|
||||
TALLOC_FREE(fname);
|
||||
@ -1412,25 +1415,40 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
|
||||
return False;
|
||||
}
|
||||
|
||||
/* A dirent from dptr_ReadDirName isn't a stream. */
|
||||
status = create_synthetic_smb_fname(ctx, pathreal,
|
||||
NULL, &sbuf,
|
||||
&smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
TALLOC_FREE(fname);
|
||||
}
|
||||
|
||||
if (INFO_LEVEL_IS_UNIX(info_level)) {
|
||||
if (vfs_lstat_smb_fname(conn, pathreal,
|
||||
&sbuf) != 0) {
|
||||
DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
|
||||
pathreal,strerror(errno)));
|
||||
if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
|
||||
DEBUG(5,("get_lanman2_dir_entry: "
|
||||
"Couldn't lstat [%s] (%s)\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
strerror(errno)));
|
||||
TALLOC_FREE(smb_fname);
|
||||
TALLOC_FREE(pathreal);
|
||||
TALLOC_FREE(fname);
|
||||
continue;
|
||||
}
|
||||
} else if (!VALID_STAT(sbuf) &&
|
||||
vfs_stat_smb_fname(conn, pathreal,
|
||||
&sbuf) != 0) {
|
||||
} else if (!VALID_STAT(smb_fname->st) &&
|
||||
SMB_VFS_STAT(conn, smb_fname) != 0) {
|
||||
/* Needed to show the msdfs symlinks as
|
||||
* directories */
|
||||
|
||||
ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
|
||||
ms_dfs_link =
|
||||
check_msdfs_link(conn,
|
||||
smb_fname->base_name,
|
||||
&smb_fname->st);
|
||||
if (!ms_dfs_link) {
|
||||
DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
|
||||
pathreal,strerror(errno)));
|
||||
DEBUG(5,("get_lanman2_dir_entry: "
|
||||
"Couldn't stat [%s] (%s)\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
strerror(errno)));
|
||||
TALLOC_FREE(smb_fname);
|
||||
TALLOC_FREE(pathreal);
|
||||
TALLOC_FREE(fname);
|
||||
continue;
|
||||
@ -1438,38 +1456,42 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
|
||||
}
|
||||
|
||||
if (ms_dfs_link) {
|
||||
mode = dos_mode_msdfs(conn,pathreal,&sbuf);
|
||||
mode = dos_mode_msdfs(conn, smb_fname);
|
||||
} else {
|
||||
mode = dos_mode(conn,pathreal,&sbuf);
|
||||
mode = dos_mode(conn, smb_fname);
|
||||
}
|
||||
|
||||
if (!dir_check_ftype(conn,mode,dirtype)) {
|
||||
DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
|
||||
TALLOC_FREE(smb_fname);
|
||||
TALLOC_FREE(pathreal);
|
||||
TALLOC_FREE(fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(mode & aDIR)) {
|
||||
file_size = get_file_size_stat(&sbuf);
|
||||
file_size = get_file_size_stat(&smb_fname->st);
|
||||
}
|
||||
allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
|
||||
allocation_size =
|
||||
SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
|
||||
|
||||
if (ask_sharemode) {
|
||||
struct timespec write_time_ts;
|
||||
struct file_id fileid;
|
||||
|
||||
ZERO_STRUCT(write_time_ts);
|
||||
fileid = vfs_file_id_from_sbuf(conn, &sbuf);
|
||||
fileid = vfs_file_id_from_sbuf(conn,
|
||||
&smb_fname->st);
|
||||
get_file_infos(fileid, NULL, &write_time_ts);
|
||||
if (!null_timespec(write_time_ts)) {
|
||||
update_stat_ex_mtime(&sbuf, write_time_ts);
|
||||
update_stat_ex_mtime(&smb_fname->st,
|
||||
write_time_ts);
|
||||
}
|
||||
}
|
||||
|
||||
mdate_ts = sbuf.st_ex_mtime;
|
||||
adate_ts = sbuf.st_ex_atime;
|
||||
create_date_ts = sbuf.st_ex_btime;
|
||||
mdate_ts = smb_fname->st.st_ex_mtime;
|
||||
adate_ts = smb_fname->st.st_ex_atime;
|
||||
create_date_ts = smb_fname->st.st_ex_btime;
|
||||
|
||||
if (lp_dos_filetime_resolution(SNUM(conn))) {
|
||||
dos_filetime_timespec(&create_date_ts);
|
||||
@ -1482,11 +1504,14 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
|
||||
adate = convert_timespec_to_time_t(adate_ts);
|
||||
|
||||
DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
|
||||
pathreal,fname));
|
||||
smb_fname_str_dbg(smb_fname), fname));
|
||||
|
||||
found = True;
|
||||
|
||||
dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
|
||||
sbuf = smb_fname->st;
|
||||
|
||||
TALLOC_FREE(smb_fname);
|
||||
}
|
||||
|
||||
if (!found)
|
||||
@ -4137,16 +4162,16 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
|
||||
DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
|
||||
fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
|
||||
|
||||
p = strrchr_m(fname,'/');
|
||||
p = strrchr_m(smb_fname->base_name,'/');
|
||||
if (!p)
|
||||
base_name = fname;
|
||||
base_name = smb_fname->base_name;
|
||||
else
|
||||
base_name = p+1;
|
||||
|
||||
if (ms_dfs_link) {
|
||||
mode = dos_mode_msdfs(conn,fname,&sbuf);
|
||||
mode = dos_mode_msdfs(conn, smb_fname);
|
||||
} else {
|
||||
mode = dos_mode(conn,fname,&sbuf);
|
||||
mode = dos_mode(conn, smb_fname);
|
||||
}
|
||||
if (!mode)
|
||||
mode = FILE_ATTRIBUTE_NORMAL;
|
||||
@ -5072,9 +5097,7 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
|
||||
DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
|
||||
|
||||
/* check the mode isn't different, before changing it */
|
||||
if ((dosmode != 0) && (dosmode != dos_mode(conn,
|
||||
smb_fname_base->base_name,
|
||||
&smb_fname_base->st))) {
|
||||
if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
|
||||
DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
|
||||
"0x%x\n", smb_fname_str_dbg(smb_fname_base),
|
||||
(unsigned int)dosmode));
|
||||
@ -5226,8 +5249,7 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
|
||||
const char *pdata,
|
||||
int total_data,
|
||||
files_struct *fsp,
|
||||
const char *fname,
|
||||
SMB_STRUCT_STAT *psbuf)
|
||||
const struct smb_filename *smb_fname)
|
||||
{
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
bool delete_on_close;
|
||||
@ -5242,11 +5264,11 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
|
||||
}
|
||||
|
||||
delete_on_close = (CVAL(pdata,0) ? True : False);
|
||||
dosmode = dos_mode(conn, fname, psbuf);
|
||||
dosmode = dos_mode(conn, smb_fname);
|
||||
|
||||
DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
|
||||
"delete_on_close = %u\n",
|
||||
fsp->fsp_name,
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
(unsigned int)dosmode,
|
||||
(unsigned int)delete_on_close ));
|
||||
|
||||
@ -6748,10 +6770,8 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
|
||||
struct smb_request *req,
|
||||
const char *pdata,
|
||||
int total_data,
|
||||
const char *fname,
|
||||
SMB_STRUCT_STAT *psbuf)
|
||||
struct smb_filename *smb_fname)
|
||||
{
|
||||
struct smb_filename *smb_fname = NULL;
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
files_struct *fsp = NULL;
|
||||
uint16 flags = 0;
|
||||
@ -6767,29 +6787,23 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
|
||||
|
||||
flags = SVAL(pdata,0);
|
||||
|
||||
if (!VALID_STAT(*psbuf)) {
|
||||
if (!VALID_STAT(smb_fname->st)) {
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
|
||||
!VALID_STAT_OF_DIR(*psbuf)) {
|
||||
!VALID_STAT_OF_DIR(smb_fname->st)) {
|
||||
return NT_STATUS_NOT_A_DIRECTORY;
|
||||
}
|
||||
|
||||
DEBUG(10,("smb_posix_unlink: %s %s\n",
|
||||
(flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
|
||||
fname));
|
||||
smb_fname_str_dbg(smb_fname)));
|
||||
|
||||
if (VALID_STAT_OF_DIR(*psbuf)) {
|
||||
if (VALID_STAT_OF_DIR(smb_fname->st)) {
|
||||
create_options |= FILE_DIRECTORY_FILE;
|
||||
}
|
||||
|
||||
status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
|
||||
&smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
req, /* req */
|
||||
@ -6808,9 +6822,6 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
|
||||
&fsp, /* result */
|
||||
&info); /* pinfo */
|
||||
|
||||
*psbuf = smb_fname->st;
|
||||
TALLOC_FREE(smb_fname);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
@ -6854,8 +6865,7 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
|
||||
&del,
|
||||
1,
|
||||
fsp,
|
||||
fname,
|
||||
psbuf);
|
||||
smb_fname);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
close_file(req, fsp, NORMAL_CLOSE);
|
||||
@ -7133,8 +7143,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
|
||||
pdata,
|
||||
total_data,
|
||||
fsp,
|
||||
fname,
|
||||
&sbuf);
|
||||
smb_fname);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -7270,8 +7279,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
|
||||
status = smb_posix_unlink(conn, req,
|
||||
pdata,
|
||||
total_data,
|
||||
fname,
|
||||
&sbuf);
|
||||
smb_fname);
|
||||
break;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user