summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2003-01-08 02:09:18 +0000
committerJeremy Allison <jra@samba.org>2003-01-08 02:09:18 +0000
commit7f4177aa9e85c5d801aefabf39e08e40bce04f7d (patch)
tree210abeb356695b154e2102f0be6312de95813aa6 /source3/smbd
parentd034ba5ce18fb7f62060a6eab7b3563c5ff7b859 (diff)
downloadsamba-7f4177aa9e85c5d801aefabf39e08e40bce04f7d.tar.gz
samba-7f4177aa9e85c5d801aefabf39e08e40bce04f7d.tar.bz2
samba-7f4177aa9e85c5d801aefabf39e08e40bce04f7d.zip
Fix open problem with changing attributes on an existing file - based
on work by <steve@griffin.sio2.nl>. Jeremy. (This used to be commit 1cff725e37d04e25d2cd5523683b35c82d5040fa)
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/open.c53
1 files changed, 45 insertions, 8 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index d5521f7f47..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++;
@@ -1281,7 +1319,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST
files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf)
{
extern struct current_user current_user;
- BOOL got_stat = False;
files_struct *fsp = NULL;
if (!VALID_STAT(*psbuf))