From 0c7593bc675af151f3cc9f5419f15f33745285e4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 16:37:09 -0700 Subject: [PATCH 01/17] Code cleanup. uint32 -> uint32_t. Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 16 ++++++++-------- source3/smbd/proto.h | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 19b7675..3ea1b92 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -163,7 +163,7 @@ 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, +static uint32_t dos_mode_from_sbuf(connection_struct *conn, const struct smb_filename *smb_fname) { int result = 0; @@ -220,7 +220,7 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn, static bool get_ea_dos_attribute(connection_struct *conn, struct smb_filename *smb_fname, - uint32 *pattr) + uint32_t *pattr) { struct xattr_DOSATTRIB dosattrib; enum ndr_err_code ndr_err; @@ -348,7 +348,7 @@ static bool get_ea_dos_attribute(connection_struct *conn, static bool set_ea_dos_attribute(connection_struct *conn, struct smb_filename *smb_fname, - uint32 dosmode) + uint32_t dosmode) { struct xattr_DOSATTRIB dosattrib; enum ndr_err_code ndr_err; @@ -446,10 +446,10 @@ static bool set_ea_dos_attribute(connection_struct *conn, Change a unix mode to a dos mode for an ms dfs link. ****************************************************************************/ -uint32 dos_mode_msdfs(connection_struct *conn, +uint32_t dos_mode_msdfs(connection_struct *conn, const struct smb_filename *smb_fname) { - uint32 result = 0; + uint32_t result = 0; DEBUG(8,("dos_mode_msdfs: %s\n", smb_fname_str_dbg(smb_fname))); @@ -618,9 +618,9 @@ static bool set_stat_dos_flags(connection_struct *conn, if "store dos attributes" is true. ****************************************************************************/ -uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname) +uint32_t dos_mode(connection_struct *conn, struct smb_filename *smb_fname) { - uint32 result = 0; + uint32_t result = 0; bool offline, used_stat_dos_flags = false; DEBUG(8,("dos_mode: %s\n", smb_fname_str_dbg(smb_fname))); @@ -697,7 +697,7 @@ uint32 dos_mode(connection_struct *conn, 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) + uint32_t dosmode, const char *parent_dir, bool newfile) { int mask=0; mode_t tmp; diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 6d5bdba..1daed4c 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -260,12 +260,12 @@ 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, +uint32_t 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, struct smb_filename *smb_fname); +uint32_t dos_mode(connection_struct *conn, 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); + uint32_t dosmode, const char *parent_dir, bool newfile); NTSTATUS file_set_sparse(connection_struct *conn, struct files_struct *fsp, bool sparse); -- 1.8.2.1 From 37d7a53979634c1f628526f841ecfedf4dcf69cf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 16:38:05 -0700 Subject: [PATCH 02/17] Code cleanup. False -> false. True -> true. Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 3ea1b92..cb5c323 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -230,7 +230,7 @@ static bool get_ea_dos_attribute(connection_struct *conn, uint32_t dosattr; if (!lp_store_dos_attributes(SNUM(conn))) { - return False; + return false; } /* Don't reset pattr to zero as we may already have filename-based attributes we @@ -250,9 +250,9 @@ static bool get_ea_dos_attribute(connection_struct *conn, "from EA on file %s: Error = %s\n", smb_fname_str_dbg(smb_fname), strerror(errno))); - set_store_dos_attributes(SNUM(conn), False); + set_store_dos_attributes(SNUM(conn), false); } - return False; + return false; } blob.data = (uint8_t *)attrstr; @@ -338,7 +338,7 @@ static bool get_ea_dos_attribute(connection_struct *conn, DEBUG(8,("\n")); - return True; + return true; } /**************************************************************************** @@ -355,7 +355,7 @@ static bool set_ea_dos_attribute(connection_struct *conn, DATA_BLOB blob; if (!lp_store_dos_attributes(SNUM(conn))) { - return False; + return false; } ZERO_STRUCT(dosattrib); @@ -404,7 +404,7 @@ static bool set_ea_dos_attribute(connection_struct *conn, "attribute EA on file %s: Error = %s\n", smb_fname_str_dbg(smb_fname), strerror(errno) )); - set_store_dos_attributes(SNUM(conn), False); + set_store_dos_attributes(SNUM(conn), false); } return false; } -- 1.8.2.1 From 2626cd18dea242cbcbc9b3f0820a1d71345d8e73 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 16:39:32 -0700 Subject: [PATCH 03/17] Add parse_ea_dos_attribute(). Factor out the EA parsing code so it can be used from both pathname and file handle functions. Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index cb5c323..4cc5e90 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -213,6 +213,96 @@ static uint32_t dos_mode_from_sbuf(connection_struct *conn, return result; } +static bool parse_ea_dos_attribute(DATA_BLOB blob, + struct smb_filename *smb_fname, + uint32_t *pattr) +{ + struct xattr_DOSATTRIB dosattrib; + enum ndr_err_code ndr_err; + uint32_t dosattr; + + ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &dosattrib, + (ndr_pull_flags_fn_t)ndr_pull_xattr_DOSATTRIB); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(1,("parse_ea_dos_attribute: bad ndr decode " + "from EA on file %s: Error = %s\n", + smb_fname_str_dbg(smb_fname), + ndr_errstr(ndr_err))); + return false; + } + + DEBUG(10,("parse_ea_dos_attribute: %s attr = %s\n", + smb_fname_str_dbg(smb_fname), dosattrib.attrib_hex)); + + switch (dosattrib.version) { + case 0xFFFF: + dosattr = dosattrib.info.compatinfoFFFF.attrib; + break; + case 1: + dosattr = dosattrib.info.info1.attrib; + if (!null_nttime(dosattrib.info.info1.create_time)) { + struct timespec create_time = + nt_time_to_unix_timespec( + &dosattrib.info.info1.create_time); + + update_stat_ex_create_time(&smb_fname->st, + create_time); + + DEBUG(10,("parse_ea_dos_attribute: file %s case 1 " + "set btime %s\n", + smb_fname_str_dbg(smb_fname), + time_to_asc(convert_timespec_to_time_t( + create_time)) )); + } + break; + case 2: + dosattr = dosattrib.info.oldinfo2.attrib; + /* Don't know what flags to check for this case. */ + break; + case 3: + dosattr = dosattrib.info.info3.attrib; + if ((dosattrib.info.info3.valid_flags & XATTR_DOSINFO_CREATE_TIME) && + !null_nttime(dosattrib.info.info3.create_time)) { + struct timespec create_time = + nt_time_to_unix_timespec( + &dosattrib.info.info3.create_time); + + update_stat_ex_create_time(&smb_fname->st, + create_time); + + DEBUG(10,("parse_ea_dos_attribute: file %s case 3 " + "set btime %s\n", + smb_fname_str_dbg(smb_fname), + time_to_asc(convert_timespec_to_time_t( + create_time)) )); + } + break; + default: + DEBUG(1,("parse_ea_dos_attribute: Badly formed DOSATTRIB on " + "file %s\n", smb_fname_str_dbg(smb_fname))); + return false; + } + + if (S_ISDIR(smb_fname->st.st_ex_mode)) { + dosattr |= FILE_ATTRIBUTE_DIRECTORY; + } + /* FILE_ATTRIBUTE_SPARSE is valid on get but not on set. */ + *pattr = (uint32)(dosattr & (SAMBA_ATTRIBUTES_MASK|FILE_ATTRIBUTE_SPARSE)); + + DEBUG(8,("parse_ea_dos_attribute returning (0x%x)", dosattr)); + + if (dosattr & FILE_ATTRIBUTE_HIDDEN) DEBUG(8, ("h")); + if (dosattr & FILE_ATTRIBUTE_READONLY ) DEBUG(8, ("r")); + if (dosattr & FILE_ATTRIBUTE_SYSTEM) DEBUG(8, ("s")); + if (dosattr & FILE_ATTRIBUTE_DIRECTORY ) DEBUG(8, ("d")); + if (dosattr & FILE_ATTRIBUTE_ARCHIVE ) DEBUG(8, ("a")); + + DEBUG(8,("\n")); + + return true; +} + /**************************************************************************** Get DOS attributes from an EA. This can also pull the create time into the stat struct inside smb_fname. -- 1.8.2.1 From 2ded2d21a10542d9c04f76001e83202d1864ac97 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 16:41:10 -0700 Subject: [PATCH 04/17] Change get_ea_dos_attribute() to call parse_ea_dos_attribute(). Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 87 ++------------------------------------------------ 1 file changed, 3 insertions(+), 84 deletions(-) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 4cc5e90..3ecaa47 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -312,12 +312,9 @@ static bool get_ea_dos_attribute(connection_struct *conn, struct smb_filename *smb_fname, uint32_t *pattr) { - struct xattr_DOSATTRIB dosattrib; - enum ndr_err_code ndr_err; DATA_BLOB blob; ssize_t sizeret; fstring attrstr; - uint32_t dosattr; if (!lp_store_dos_attributes(SNUM(conn))) { return false; @@ -348,87 +345,9 @@ static bool get_ea_dos_attribute(connection_struct *conn, blob.data = (uint8_t *)attrstr; blob.length = sizeret; - ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &dosattrib, - (ndr_pull_flags_fn_t)ndr_pull_xattr_DOSATTRIB); - - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DEBUG(1,("get_ea_dos_attribute: bad ndr decode " - "from EA on file %s: Error = %s\n", - smb_fname_str_dbg(smb_fname), - ndr_errstr(ndr_err))); - return false; - } - - DEBUG(10,("get_ea_dos_attribute: %s attr = %s\n", - smb_fname_str_dbg(smb_fname), dosattrib.attrib_hex)); - - switch (dosattrib.version) { - case 0xFFFF: - dosattr = dosattrib.info.compatinfoFFFF.attrib; - break; - case 1: - dosattr = dosattrib.info.info1.attrib; - if (!null_nttime(dosattrib.info.info1.create_time)) { - struct timespec create_time = - nt_time_to_unix_timespec( - &dosattrib.info.info1.create_time); - - update_stat_ex_create_time(&smb_fname->st, - create_time); - - DEBUG(10,("get_ea_dos_attribute: file %s case 1 " - "set btime %s\n", - smb_fname_str_dbg(smb_fname), - time_to_asc(convert_timespec_to_time_t( - create_time)) )); - } - break; - case 2: - dosattr = dosattrib.info.oldinfo2.attrib; - /* Don't know what flags to check for this case. */ - break; - case 3: - dosattr = dosattrib.info.info3.attrib; - if ((dosattrib.info.info3.valid_flags & XATTR_DOSINFO_CREATE_TIME) && - !null_nttime(dosattrib.info.info3.create_time)) { - struct timespec create_time = - nt_time_to_unix_timespec( - &dosattrib.info.info3.create_time); - - update_stat_ex_create_time(&smb_fname->st, - create_time); - - DEBUG(10,("get_ea_dos_attribute: file %s case 3 " - "set btime %s\n", - smb_fname_str_dbg(smb_fname), - time_to_asc(convert_timespec_to_time_t( - create_time)) )); - } - break; - default: - DEBUG(1,("get_ea_dos_attribute: Badly formed DOSATTRIB on " - "file %s - %s\n", smb_fname_str_dbg(smb_fname), - attrstr)); - return false; - } - - if (S_ISDIR(smb_fname->st.st_ex_mode)) { - dosattr |= FILE_ATTRIBUTE_DIRECTORY; - } - /* FILE_ATTRIBUTE_SPARSE is valid on get but not on set. */ - *pattr = (uint32)(dosattr & (SAMBA_ATTRIBUTES_MASK|FILE_ATTRIBUTE_SPARSE)); - - DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr)); - - if (dosattr & FILE_ATTRIBUTE_HIDDEN) DEBUG(8, ("h")); - if (dosattr & FILE_ATTRIBUTE_READONLY ) DEBUG(8, ("r")); - if (dosattr & FILE_ATTRIBUTE_SYSTEM) DEBUG(8, ("s")); - if (dosattr & FILE_ATTRIBUTE_DIRECTORY ) DEBUG(8, ("d")); - if (dosattr & FILE_ATTRIBUTE_ARCHIVE ) DEBUG(8, ("a")); - - DEBUG(8,("\n")); - - return true; + return parse_ea_dos_attribute(blob, + smb_fname, + pattr); } /**************************************************************************** -- 1.8.2.1 From 66b4cb62c35300dca22eb4cc89b44674c5af09a5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 16:45:44 -0700 Subject: [PATCH 05/17] Add get_ea_dos_attribute_fsp(), get attribute from a handle. Re-uses common code from get_ea_dos_attribute(). Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 3ecaa47..795e07d 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -351,6 +351,53 @@ static bool get_ea_dos_attribute(connection_struct *conn, } /**************************************************************************** + Get DOS attributes from an EA from an fsp. + This can also pull the create time into the stat struct inside fsp->fsp_name. +****************************************************************************/ + +static bool get_ea_dos_attribute_fsp(files_struct *fsp, + uint32_t *pattr) +{ + DATA_BLOB blob; + ssize_t sizeret; + fstring attrstr; + + if (!lp_store_dos_attributes(SNUM(fsp->conn))) { + return false; + } + + /* Don't reset pattr to zero as we may already have filename-based attributes we + need to preserve. */ + + sizeret = SMB_VFS_FGETXATTR(fsp, + SAMBA_XATTR_DOS_ATTRIB, + attrstr, + sizeof(attrstr)); + if (sizeret == -1) { + if (errno == ENOSYS +#if defined(ENOTSUP) + || errno == ENOTSUP) { +#else + ) { +#endif + DEBUG(1,("get_ea_dos_attribute_fsp: Cannot get attribute " + "from EA on file %s: Error = %s\n", + smb_fname_str_dbg(fsp->fsp_name), + strerror(errno))); + set_store_dos_attributes(SNUM(fsp->conn), false); + } + return false; + } + + blob.data = (uint8_t *)attrstr; + blob.length = sizeret; + + return parse_ea_dos_attribute(blob, + fsp->fsp_name, + pattr); +} + +/**************************************************************************** Set DOS attributes in an EA. Also sets the create time. ****************************************************************************/ -- 1.8.2.1 From 4e114fd8de1aea206c9181d929b5139b7a90aaac Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 16:55:48 -0700 Subject: [PATCH 06/17] Make dos_mode() call dos_mode_internal() so I can re-use this code for handle fetch. Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 795e07d..f611e24 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -674,7 +674,8 @@ static bool set_stat_dos_flags(connection_struct *conn, if "store dos attributes" is true. ****************************************************************************/ -uint32_t dos_mode(connection_struct *conn, struct smb_filename *smb_fname) +static uint32_t dos_mode_internal(connection_struct *conn, + struct smb_filename *smb_fname) { uint32_t result = 0; bool offline, used_stat_dos_flags = false; @@ -745,6 +746,11 @@ uint32_t dos_mode(connection_struct *conn, struct smb_filename *smb_fname) return(result); } +uint32_t dos_mode(connection_struct *conn, struct smb_filename *smb_fname) +{ + return dos_mode_internal(conn, smb_fname); +} + /******************************************************************* chmod a file - but preserve some bits. If "store dos attributes" is also set it will store the create time -- 1.8.2.1 From 6d89ed0388d4e7956b60c5b55b1d2e7ca2a39083 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 17:00:06 -0700 Subject: [PATCH 07/17] Add in an fsp parameter to dos_mode_internal(). Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index f611e24..6541dd6 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -675,11 +675,16 @@ static bool set_stat_dos_flags(connection_struct *conn, ****************************************************************************/ static uint32_t dos_mode_internal(connection_struct *conn, + files_struct *fsp, struct smb_filename *smb_fname) { uint32_t result = 0; bool offline, used_stat_dos_flags = false; + if (fsp) { + SMB_ASSERT(fsp->fsp_name == smb_fname); + } + DEBUG(8,("dos_mode: %s\n", smb_fname_str_dbg(smb_fname))); if (!VALID_STAT(smb_fname->st)) { @@ -708,7 +713,15 @@ static uint32_t dos_mode_internal(connection_struct *conn, #endif if (!used_stat_dos_flags) { /* Get the DOS attributes from an EA by preference. */ - if (!get_ea_dos_attribute(conn, smb_fname, &result)) { + bool ret; + + if (fsp) { + ret = get_ea_dos_attribute_fsp(fsp, &result); + } else { + ret = get_ea_dos_attribute(conn, smb_fname, &result); + } + + if (ret == false) { result |= dos_mode_from_sbuf(conn, smb_fname); } } @@ -748,7 +761,7 @@ static uint32_t dos_mode_internal(connection_struct *conn, uint32_t dos_mode(connection_struct *conn, struct smb_filename *smb_fname) { - return dos_mode_internal(conn, smb_fname); + return dos_mode_internal(conn, NULL, smb_fname); } /******************************************************************* -- 1.8.2.1 From b8b24f7b24d4123a4ef89713d2058a50a546ebf6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 17:02:34 -0700 Subject: [PATCH 08/17] Add dos_mode_fsp() as a first class function. Will now replace uses of dos_mode() in situations where a handle is available. Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 5 +++++ source3/smbd/proto.h | 1 + 2 files changed, 6 insertions(+) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 6541dd6..0fb48d2 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -764,6 +764,11 @@ uint32_t dos_mode(connection_struct *conn, struct smb_filename *smb_fname) return dos_mode_internal(conn, NULL, smb_fname); } +uint32_t dos_mode_fsp(files_struct *fsp) +{ + return dos_mode_internal(fsp->conn, fsp, fsp->fsp_name); +} + /******************************************************************* chmod a file - but preserve some bits. If "store dos attributes" is also set it will store the create time diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 1daed4c..3e9a74d 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -264,6 +264,7 @@ uint32_t dos_mode_msdfs(connection_struct *conn, const struct smb_filename *smb_fname); int dos_attributes_to_stat_dos_flags(uint32_t dosmode); uint32_t dos_mode(connection_struct *conn, struct smb_filename *smb_fname); +uint32_t dos_mode_fsp(files_struct *fsp); int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, uint32_t dosmode, const char *parent_dir, bool newfile); NTSTATUS file_set_sparse(connection_struct *conn, -- 1.8.2.1 From 8feb5c41724148b022c60f5e4d47db76cd968af4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 17:12:23 -0700 Subject: [PATCH 09/17] Convert all possible dos_mode() calls to dos_mode_fsp() when a handle is present. Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 2 +- source3/smbd/fileio.c | 2 +- source3/smbd/nttrans.c | 4 ++-- source3/smbd/open.c | 4 ++++ source3/smbd/reply.c | 10 +++++----- source3/smbd/smb2_create.c | 3 +-- source3/smbd/trans2.c | 10 +++++++--- 7 files changed, 21 insertions(+), 14 deletions(-) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 0fb48d2..68b207b 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -998,7 +998,7 @@ NTSTATUS file_set_sparse(connection_struct *conn, return status; } - old_dosmode = dos_mode(conn, fsp->fsp_name); + old_dosmode = dos_mode_fsp(fsp); if (sparse && !(old_dosmode & FILE_ATTRIBUTE_SPARSE)) { new_dosmode = old_dosmode | FILE_ATTRIBUTE_SPARSE; diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 96eb24b..d80b882 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -292,7 +292,7 @@ void mark_file_modified(files_struct *fsp) return; } - dosmode = dos_mode(fsp->conn, fsp->fsp_name); + dosmode = dos_mode_fsp(fsp); if (IS_DOS_ARCHIVE(dosmode)) { return; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f5e5877..c85f191 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -650,7 +650,7 @@ void reply_ntcreate_and_X(struct smb_request *req) } p += 4; - fattr = dos_mode(conn, smb_fname); + fattr = dos_mode_fsp(fsp); if (fattr == 0) { fattr = FILE_ATTRIBUTE_NORMAL; } @@ -1278,7 +1278,7 @@ static void call_nt_transact_create(connection_struct *conn, } p += 8; - fattr = dos_mode(conn, smb_fname); + fattr = dos_mode_fsp(fsp); if (fattr == 0) { fattr = FILE_ATTRIBUTE_NORMAL; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0d9698a..b4e5e4a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2067,6 +2067,10 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, if (!posix_open) { new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; if (file_existed) { + /* + * We must still use pathname call here + * as the handle is not yet constructed. + */ existing_dos_attributes = dos_mode(conn, smb_fname); } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8790bd5..c9f4703 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1960,7 +1960,7 @@ void reply_open(struct smb_request *req) } size = smb_fname->st.st_ex_size; - fattr = dos_mode(conn, smb_fname); + fattr = dos_mode_fsp(fsp); /* Deal with other possible opens having a modified write time. JRA. */ @@ -2159,7 +2159,7 @@ void reply_open_and_X(struct smb_request *req) } } - fattr = dos_mode(conn, fsp->fsp_name); + fattr = dos_mode_fsp(fsp); mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime); if (fattr & FILE_ATTRIBUTE_DIRECTORY) { close_file(req, fsp, ERROR_CLOSE); @@ -2582,7 +2582,7 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) { /* Only bother to read the DOS attribute if we might deny the rename on the grounds of attribute missmatch. */ - uint32_t fmode = dos_mode(conn, fsp->fsp_name); + uint32_t fmode = dos_mode_fsp(fsp); if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) { return NT_STATUS_NO_SUCH_FILE; } @@ -7119,7 +7119,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, goto out; } - dosattrs = dos_mode(conn, smb_fname_src); + dosattrs = dos_mode_fsp(fsp1); if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) { ZERO_STRUCTP(&smb_fname_dst_tmp->st); @@ -8314,7 +8314,7 @@ void reply_getattrE(struct smb_request *req) return; } - mode = dos_mode(conn, fsp->fsp_name); + mode = dos_mode_fsp(fsp); /* * Convert the times into dos times. Set create diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index fe0c4e4..b317de7 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -1037,8 +1037,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, } else { state->out_create_action = info; } - state->out_file_attributes = dos_mode(result->conn, - result->fsp_name); + state->out_file_attributes = dos_mode_fsp(result); /* Deal with other possible opens having a modified write time. JRA. */ ZERO_STRUCT(write_time_ts); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 14a2e0f..90cdea5 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1249,7 +1249,7 @@ static void call_trans2open(connection_struct *conn, } size = get_file_size_stat(&smb_fname->st); - fattr = dos_mode(conn, smb_fname); + fattr = dos_mode_fsp(fsp); mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime); inode = smb_fname->st.st_ex_ino; if (fattr & FILE_ATTRIBUTE_DIRECTORY) { @@ -4389,7 +4389,11 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, fsp_fnum_dbg(fsp), info_level, max_data_bytes)); - mode = dos_mode(conn, smb_fname); + if (fsp) { + mode = dos_mode_fsp(fsp); + } else { + mode = dos_mode(conn, smb_fname); + } nlink = psbuf->st_ex_nlink; if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) { @@ -5974,7 +5978,7 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn, } delete_on_close = (CVAL(pdata,0) ? True : False); - dosmode = dos_mode(conn, smb_fname); + dosmode = dos_mode_fsp(fsp); DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, " "delete_on_close = %u\n", -- 1.8.2.1 From f744247129801ebba0db0536b278f40a0239f3b2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 17:14:03 -0700 Subject: [PATCH 10/17] Fix bad comment in code I'm intending to refactor. Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 68b207b..c37f1d2 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -434,7 +434,7 @@ static bool set_ea_dos_attribute(connection_struct *conn, (ndr_push_flags_fn_t)ndr_push_xattr_DOSATTRIB); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DEBUG(5, ("create_acl_blob: ndr_push_xattr_DOSATTRIB failed: %s\n", + DEBUG(5, ("set_ea_dos_attribute: ndr_push_xattr_DOSATTRIB failed: %s\n", ndr_errstr(ndr_err))); return false; } -- 1.8.2.1 From d060e5a2b4f41f327bb94168c3fd4603553cb633 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 17:19:50 -0700 Subject: [PATCH 11/17] Add create_ea_dos_attribute_blob() to create common code. Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index c37f1d2..ab4abf8 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -398,6 +398,52 @@ static bool get_ea_dos_attribute_fsp(files_struct *fsp, } /**************************************************************************** + Create an DOS EA blob. +****************************************************************************/ + +static bool create_ea_dos_attribute_blob(struct smb_filename *smb_fname, + uint32_t dosmode, + TALLOC_CTX *mem_ctx, + DATA_BLOB *p_blob_out) +{ + struct xattr_DOSATTRIB dosattrib; + enum ndr_err_code ndr_err; + DATA_BLOB blob; + + ZERO_STRUCT(dosattrib); + ZERO_STRUCT(blob); + + dosattrib.version = 3; + dosattrib.info.info3.valid_flags = XATTR_DOSINFO_ATTRIB| + XATTR_DOSINFO_CREATE_TIME; + dosattrib.info.info3.attrib = dosmode; + unix_timespec_to_nt_time(&dosattrib.info.info3.create_time, + smb_fname->st.st_ex_btime); + + DEBUG(10,("create_ea_dos_attribute_blob: set attribute 0x%x, btime = %s on file %s\n", + (unsigned int)dosmode, + time_to_asc(convert_timespec_to_time_t(smb_fname->st.st_ex_btime)), + smb_fname_str_dbg(smb_fname) )); + + ndr_err = ndr_push_struct_blob( + &blob, mem_ctx, &dosattrib, + (ndr_push_flags_fn_t)ndr_push_xattr_DOSATTRIB); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(5, ("create_ea_dos_attribute_blob: ndr_push_xattr_DOSATTRIB failed: %s\n", + ndr_errstr(ndr_err))); + return false; + } + + if (blob.data == NULL || blob.length == 0) { + return false; + } + + *p_blob_out = blob; + return true; +} + +/**************************************************************************** Set DOS attributes in an EA. Also sets the create time. ****************************************************************************/ -- 1.8.2.1 From 8f45459c85ace5f76959daa544f0ac15fd7ddbb9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 17:23:31 -0700 Subject: [PATCH 12/17] Make set_ea_dos_attribute() call create_ea_dos_attribute_blob(). Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index ab4abf8..22a367b 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -452,40 +452,16 @@ static bool set_ea_dos_attribute(connection_struct *conn, struct smb_filename *smb_fname, uint32_t dosmode) { - struct xattr_DOSATTRIB dosattrib; - enum ndr_err_code ndr_err; DATA_BLOB blob; if (!lp_store_dos_attributes(SNUM(conn))) { return false; } - ZERO_STRUCT(dosattrib); - ZERO_STRUCT(blob); - - dosattrib.version = 3; - dosattrib.info.info3.valid_flags = XATTR_DOSINFO_ATTRIB| - XATTR_DOSINFO_CREATE_TIME; - dosattrib.info.info3.attrib = dosmode; - unix_timespec_to_nt_time(&dosattrib.info.info3.create_time, - smb_fname->st.st_ex_btime); - - DEBUG(10,("set_ea_dos_attributes: set attribute 0x%x, btime = %s on file %s\n", - (unsigned int)dosmode, - time_to_asc(convert_timespec_to_time_t(smb_fname->st.st_ex_btime)), - smb_fname_str_dbg(smb_fname) )); - - ndr_err = ndr_push_struct_blob( - &blob, talloc_tos(), &dosattrib, - (ndr_push_flags_fn_t)ndr_push_xattr_DOSATTRIB); - - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DEBUG(5, ("set_ea_dos_attribute: ndr_push_xattr_DOSATTRIB failed: %s\n", - ndr_errstr(ndr_err))); - return false; - } - - if (blob.data == NULL || blob.length == 0) { + if (!create_ea_dos_attribute_blob(smb_fname, + dosmode, + talloc_tos(), + &blob)) { return false; } -- 1.8.2.1 From 895bd7176c08c34c82ad6a723d323969300d0e9a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 17:35:55 -0700 Subject: [PATCH 13/17] Add set_ea_dos_attribute_fsp() as a handle based call. Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 22a367b..608a85c 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -521,6 +521,80 @@ static bool set_ea_dos_attribute(connection_struct *conn, } /**************************************************************************** + Set DOS attributes in an EA from a handle. + Also sets the create time. +****************************************************************************/ + +static bool set_ea_dos_attribute_fsp(files_struct *fsp, + uint32_t dosmode) +{ + struct smb_filename *smb_fname = fsp->fsp_name; + int ret; + DATA_BLOB blob; + + if(!CAN_WRITE(fsp->conn)) { + return false; + } + + if (!lp_store_dos_attributes(SNUM(fsp->conn))) { + return false; + } + + if (!create_ea_dos_attribute_blob(smb_fname, + dosmode, + talloc_tos(), + &blob)) { + return false; + } + + + ret = SMB_VFS_FSETXATTR(fsp, + SAMBA_XATTR_DOS_ATTRIB, + blob.data, + blob.length, + 0); + + if (ret == -1) { + if((errno != EPERM) && (errno != EACCES)) { + if (errno == ENOSYS +#if defined(ENOTSUP) + || errno == ENOTSUP) { +#else + ) { +#endif + DEBUG(1,("set_ea_dos_attributes_fsp: Cannot set " + "attribute EA on file %s: Error = %s\n", + smb_fname_str_dbg(smb_fname), + strerror(errno) )); + set_store_dos_attributes(SNUM(fsp->conn), false); + } + return false; + } + + if(!lp_dos_filemode(SNUM(fsp->conn))) { + return false; + } + + /* We want DOS semantics, ie allow non owner with write permission to change the + bits on a file. Just like file_ntimes below. + */ + become_root(); + ret = SMB_VFS_FSETXATTR(fsp, + SAMBA_XATTR_DOS_ATTRIB, + blob.data, + blob.length, + 0); + unbecome_root(); + return ret; + } + + DEBUG(10,("set_ea_dos_attribute: set EA 0x%x on file %s\n", + (unsigned int)dosmode, + smb_fname_str_dbg(smb_fname))); + return true; +} + +/**************************************************************************** Change a unix mode to a dos mode for an ms dfs link. ****************************************************************************/ -- 1.8.2.1 From af371506fa448a8cd28e5b835be3ededce48f351 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 17:48:36 -0700 Subject: [PATCH 14/17] Add a wrapper function file_set_dosmode_internal() for use by handle based call. Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 608a85c..64b92dc 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -872,8 +872,11 @@ uint32_t dos_mode_fsp(files_struct *fsp) attribute also. ********************************************************************/ -int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, - uint32_t dosmode, const char *parent_dir, bool newfile) +static int file_set_dosmode_internal(connection_struct *conn, + struct smb_filename *smb_fname, + uint32_t dosmode, + const char *parent_dir, + bool newfile) { int mask=0; mode_t tmp; @@ -1054,6 +1057,11 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, return( ret ); } +int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, + uint32_t dosmode, const char *parent_dir, bool newfile) +{ + return file_set_dosmode_internal(conn, smb_fname, dosmode, parent_dir, newfile); +} NTSTATUS file_set_sparse(connection_struct *conn, files_struct *fsp, -- 1.8.2.1 From 177042cf3f5f6ba1c9350233859ac600350a96ee Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 18:08:53 -0700 Subject: [PATCH 15/17] Add fsp argument to file_set_dosmode_internal() and use the handle based calls. file_set_dosmode() passes NULL for fsp. Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 55 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 64b92dc..8b0b27b 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -873,6 +873,7 @@ uint32_t dos_mode_fsp(files_struct *fsp) ********************************************************************/ static int file_set_dosmode_internal(connection_struct *conn, + files_struct *fsp, struct smb_filename *smb_fname, uint32_t dosmode, const char *parent_dir, @@ -884,6 +885,11 @@ static int file_set_dosmode_internal(connection_struct *conn, int ret = -1, lret = -1; uint32_t old_mode; struct timespec new_create_timespec; + bool ok; + + if (fsp) { + SMB_ASSERT(fsp->fsp_name == smb_fname); + } /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */ dosmode &= (SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE); @@ -903,7 +909,11 @@ static int file_set_dosmode_internal(connection_struct *conn, new_create_timespec = smb_fname->st.st_ex_btime; - old_mode = dos_mode(conn, smb_fname); + if (fsp) { + old_mode = dos_mode_fsp(fsp); + } else { + old_mode = dos_mode(conn, smb_fname); + } if (dosmode & FILE_ATTRIBUTE_OFFLINE) { if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) { @@ -942,7 +952,13 @@ static int file_set_dosmode_internal(connection_struct *conn, } #endif /* Store the DOS attributes in an EA by preference. */ - if (set_ea_dos_attribute(conn, smb_fname, dosmode)) { + if (fsp) { + ok = set_ea_dos_attribute_fsp(fsp, dosmode); + } else { + ok = set_ea_dos_attribute(conn, smb_fname, dosmode); + } + + if (ok) { if (!newfile) { notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES, @@ -1008,7 +1024,11 @@ static int file_set_dosmode_internal(connection_struct *conn, return -1; } - ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode); + if (fsp) { + ret = SMB_VFS_FCHMOD(fsp, unixmode); + } else { + ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode); + } if (ret == 0) { if(!newfile || (lret != -1)) { notify_fname(conn, NOTIFY_ACTION_MODIFIED, @@ -1031,19 +1051,26 @@ static int file_set_dosmode_internal(connection_struct *conn, /* Check if we have write access. */ if (CAN_WRITE(conn)) { - /* - * We need to open the file with write access whilst - * still in our current user context. This ensures we - * are not violating security in doing the fchmod. - */ - files_struct *fsp; - if (!NT_STATUS_IS_OK(open_file_fchmod(conn, smb_fname, - &fsp))) - return -1; + bool opened_file = false; + if (fsp == NULL) { + /* + * We need to open the file with write access whilst + * still in our current user context. This ensures we + * are not violating security in doing the fchmod. + */ + if (!NT_STATUS_IS_OK(open_file_fchmod(conn, smb_fname, + &fsp))) { + return -1; + } + opened_file = true; + } become_root(); ret = SMB_VFS_FCHMOD(fsp, unixmode); unbecome_root(); - close_file(NULL, fsp, NORMAL_CLOSE); + if (opened_file) { + close_file(NULL, fsp, NORMAL_CLOSE); + fsp = NULL; + } if (!newfile) { notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES, @@ -1060,7 +1087,7 @@ static int file_set_dosmode_internal(connection_struct *conn, int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, uint32_t dosmode, const char *parent_dir, bool newfile) { - return file_set_dosmode_internal(conn, smb_fname, dosmode, parent_dir, newfile); + return file_set_dosmode_internal(conn, NULL, smb_fname, dosmode, parent_dir, newfile); } NTSTATUS file_set_sparse(connection_struct *conn, -- 1.8.2.1 From 3dba68ae7c7942637f014073eb38546f5ba8fa95 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 18:15:24 -0700 Subject: [PATCH 16/17] Add file_set_dosmode_fsp(). Signed-off-by: Jeremy Allison --- source3/smbd/dosmode.c | 13 +++++++++++++ source3/smbd/proto.h | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 8b0b27b..15bf5ef 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -1090,6 +1090,19 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, return file_set_dosmode_internal(conn, NULL, smb_fname, dosmode, parent_dir, newfile); } +int file_set_dosmode_fsp(files_struct *fsp, + uint32_t dosmode, + const char *parent_dir, + bool newfile) +{ + return file_set_dosmode_internal(fsp->conn, + fsp, + fsp->fsp_name, + dosmode, + parent_dir, + newfile); +} + NTSTATUS file_set_sparse(connection_struct *conn, files_struct *fsp, bool sparse) diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 3e9a74d..d6f1c6d 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -267,6 +267,10 @@ uint32_t dos_mode(connection_struct *conn, struct smb_filename *smb_fname); uint32_t dos_mode_fsp(files_struct *fsp); int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, uint32_t dosmode, const char *parent_dir, bool newfile); +int file_set_dosmode_fsp(files_struct *fsp, + uint32_t dosmode, + const char *parent_dir, + bool newfile); NTSTATUS file_set_sparse(connection_struct *conn, struct files_struct *fsp, bool sparse); -- 1.8.2.1 From 36b9f0a63af30c2297dab08a0da6383c24e2782c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Apr 2013 18:18:05 -0700 Subject: [PATCH 17/17] USe file_set_dosmode_fsp() when we have a handle. Signed-off-by: Jeremy Allison --- source3/smbd/fileio.c | 2 +- source3/smbd/open.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index d80b882..3c45f98 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -296,7 +296,7 @@ void mark_file_modified(files_struct *fsp) if (IS_DOS_ARCHIVE(dosmode)) { return; } - file_set_dosmode(fsp->conn, fsp->fsp_name, + file_set_dosmode_fsp(fsp, dosmode | FILE_ATTRIBUTE_ARCHIVE, NULL, false); } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b4e5e4a..0e7229c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2708,7 +2708,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { if (!posix_open) { - if (file_set_dosmode(conn, smb_fname, + if (file_set_dosmode_fsp(fsp, new_dos_attributes | FILE_ATTRIBUTE_ARCHIVE, parent_dir, true) == 0) { unx_mode = smb_fname->st.st_ex_mode; -- 1.8.2.1