From 471782ae29ff1191661fb4a5bdb92ed4d77d757f Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 25 Jan 2006 15:06:48 +0100 Subject: [PATCH] server: Allow opening a directory with write access (based on a patch by Mike McCormack). --- server/fd.c | 23 ++++++++++++++++++++--- server/file.c | 13 +------------ 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/server/fd.c b/server/fd.c index ba182f4ba0c..a142acdb8f2 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1327,6 +1327,7 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce struct closed_fd *closed_fd; struct fd *fd; const char *unlink_name = ""; + int rw_mode; if (!(fd = alloc_fd_object())) return NULL; @@ -1336,6 +1337,7 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce release_object( fd ); return NULL; } + /* create the directory if needed */ if ((options & FILE_DIRECTORY_FILE) && (flags & O_CREAT)) { @@ -1349,11 +1351,26 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce } flags &= ~(O_CREAT | O_EXCL | O_TRUNC); } - if ((fd->unix_fd = open( name, flags & ~O_TRUNC, *mode )) == -1) + + if ((access & FILE_UNIX_WRITE_ACCESS) && !(options & FILE_DIRECTORY_FILE)) + { + if (access & FILE_UNIX_READ_ACCESS) rw_mode = O_RDWR; + else rw_mode = O_WRONLY; + } + else rw_mode = O_RDONLY; + + if ((fd->unix_fd = open( name, rw_mode | (flags & ~O_TRUNC), *mode )) == -1) { - file_set_error(); - goto error; + /* if we tried to open a directory for write access, retry read-only */ + if (errno != EISDIR || + !(access & FILE_UNIX_WRITE_ACCESS) || + (fd->unix_fd = open( name, O_RDONLY | (flags & ~O_TRUNC), *mode )) == -1) + { + file_set_error(); + goto error; + } } + closed_fd->unix_fd = fd->unix_fd; closed_fd->unlink[0] = 0; fstat( fd->unix_fd, &st ); diff --git a/server/file.c b/server/file.c index bc8f63dd16a..f488c554367 100644 --- a/server/file.c +++ b/server/file.c @@ -141,7 +141,7 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int { struct object *obj = NULL; struct fd *fd; - int flags, rw_mode; + int flags; char *name; mode_t mode; @@ -168,17 +168,6 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int access = generic_file_map_access( access ); - rw_mode = 0; - if (access & FILE_UNIX_READ_ACCESS) rw_mode |= FILE_READ_DATA; - if (access & FILE_UNIX_WRITE_ACCESS) rw_mode |= FILE_WRITE_DATA; - switch(rw_mode) - { - case 0: break; - case FILE_READ_DATA: flags |= O_RDONLY; break; - case FILE_WRITE_DATA: flags |= O_WRONLY; break; - case FILE_READ_DATA|FILE_WRITE_DATA: flags |= O_RDWR; break; - } - /* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */ fd = open_fd( name, flags | O_NONBLOCK | O_LARGEFILE, &mode, access, sharing, options ); if (!fd) goto done; -- 2.11.4.GIT