From f420f7550872bbae4175faffd5a68c172113f7c2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 8 Jan 2003 02:09:14 +0000 Subject: Fix open problem with changing attributes on an existing file - based on work by . Jeremy. (This used to be commit 465d86d95fbdeda423d1f4b06cee46c119a31447) --- source3/passdb/pdb_get_set.c | 1 - source3/smbd/open.c | 52 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index 5dfa8667fe..ed850b9f25 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -1114,4 +1114,3 @@ BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext) return True; } - diff --git a/source3/smbd/open.c b/source3/smbd/open.c index dcd901afaf..5c3359fc6b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -698,7 +698,8 @@ static void kernel_flock(files_struct *fsp, int deny_mode) } -static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t existing_mode, mode_t new_mode) +static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t existing_mode, + mode_t new_mode, mode_t *returned_mode) { uint32 old_dos_mode, new_dos_mode; SMB_STRUCT_STAT sbuf; @@ -711,22 +712,33 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex sbuf.st_mode = new_mode; new_dos_mode = dos_mode(conn, path, &sbuf); + /* + * We only set returned mode to be the same as new_mode if + * the file attributes need to be changed. + */ + + *returned_mode = (mode_t)0; + /* If we're mapping SYSTEM and HIDDEN ensure they match. */ if (lp_map_system(SNUM(conn))) { if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && !(new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) return False; + if (!(old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && (new_dos_mode & FILE_ATTRIBUTE_SYSTEM)) + *returned_mode = new_mode; } if (lp_map_hidden(SNUM(conn))) { if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) return False; + if (!(old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && (new_dos_mode & FILE_ATTRIBUTE_HIDDEN)) + *returned_mode = new_mode; } return True; } /**************************************************************************** - Open a file with a share mode. On output from this open we are guarenteeing - that + Open a file with a share mode. ****************************************************************************/ + files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action) @@ -736,9 +748,9 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S } /**************************************************************************** - Open a file with a share mode. On output from this open we are guarenteeing - that + Open a file with a share mode. ****************************************************************************/ + files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, uint32 desired_access, int share_mode,int ofun, mode_t mode,int oplock_request, @@ -760,6 +772,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ files_struct *fsp = NULL; int open_mode=0; uint16 port = 0; + mode_t new_mode = (mode_t)0; if (conn->printer) { /* printers are handled completely differently. Most of the passed parameters are @@ -819,7 +832,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ /* We only care about matching attributes on file exists and truncate. */ if (file_existed && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) { - if (!open_match_attributes(conn, fname, psbuf->st_mode, mode)) { + if (!open_match_attributes(conn, fname, psbuf->st_mode, mode, &new_mode)) { DEBUG(5,("open_file_shared: attributes missmatch for file %s (0%o, 0%o)\n", fname, psbuf->st_mode, mode )); file_free(fsp); @@ -1089,11 +1102,36 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", */ if (!file_existed && !def_acl && (conn->vfs_ops.fchmod_acl != NULL)) { + int saved_errno = errno; /* We might get ENOSYS in the next call.. */ + if (conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) errno = saved_errno; /* Ignore ENOSYS */ + + } else if (new_mode) { + + int ret = -1; + + /* Attributes need changing. File already existed. */ + + if (conn->vfs_ops.fchmod_acl != NULL) { + int saved_errno = errno; /* We might get ENOSYS in the next call.. */ + ret = conn->vfs_ops.fchmod_acl(fsp, fsp->fd, new_mode); + + if (ret == -1 && errno == ENOSYS) { + errno = saved_errno; /* Ignore ENOSYS */ + } else { + DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", + fname, (int)new_mode)); + ret = 0; /* Don't do the fchmod below. */ + } + } + + if ((ret == -1) && (conn->vfs_ops.fchmod(fsp, fsp->fd, new_mode) == -1)) + DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", + fname, (int)new_mode)); } - + unlock_share_entry_fsp(fsp); conn->num_files_open++; -- cgit