Commit 471782ae authored by Alexandre Julliard's avatar Alexandre Julliard

server: Allow opening a directory with write access (based on a patch

by Mike McCormack).
parent cf675c11
...@@ -1327,6 +1327,7 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce ...@@ -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 closed_fd *closed_fd;
struct fd *fd; struct fd *fd;
const char *unlink_name = ""; const char *unlink_name = "";
int rw_mode;
if (!(fd = alloc_fd_object())) return NULL; 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 ...@@ -1336,6 +1337,7 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce
release_object( fd ); release_object( fd );
return NULL; return NULL;
} }
/* create the directory if needed */ /* create the directory if needed */
if ((options & FILE_DIRECTORY_FILE) && (flags & O_CREAT)) 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 ...@@ -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); 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(); /* if we tried to open a directory for write access, retry read-only */
goto error; 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->unix_fd = fd->unix_fd;
closed_fd->unlink[0] = 0; closed_fd->unlink[0] = 0;
fstat( fd->unix_fd, &st ); fstat( fd->unix_fd, &st );
......
...@@ -141,7 +141,7 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int ...@@ -141,7 +141,7 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
{ {
struct object *obj = NULL; struct object *obj = NULL;
struct fd *fd; struct fd *fd;
int flags, rw_mode; int flags;
char *name; char *name;
mode_t mode; mode_t mode;
...@@ -168,17 +168,6 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int ...@@ -168,17 +168,6 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
access = generic_file_map_access( access ); 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 */ /* 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 ); fd = open_fd( name, flags | O_NONBLOCK | O_LARGEFILE, &mode, access, sharing, options );
if (!fd) goto done; if (!fd) goto done;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment