Commit 684b65cd authored by Alexandre Julliard's avatar Alexandre Julliard

Added support for FILE_DIRECTORY_FILE and FILE_NON_DIRECTORY_FILE open

options.
parent 5d617e8f
...@@ -204,6 +204,8 @@ HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing, ...@@ -204,6 +204,8 @@ HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
options = 0; options = 0;
if (attributes & FILE_FLAG_BACKUP_SEMANTICS) if (attributes & FILE_FLAG_BACKUP_SEMANTICS)
options |= FILE_OPEN_FOR_BACKUP_INTENT; options |= FILE_OPEN_FOR_BACKUP_INTENT;
else
options |= FILE_NON_DIRECTORY_FILE;
if (attributes & FILE_FLAG_DELETE_ON_CLOSE) if (attributes & FILE_FLAG_DELETE_ON_CLOSE)
options |= FILE_DELETE_ON_CLOSE; options |= FILE_DELETE_ON_CLOSE;
if (!(attributes & FILE_FLAG_OVERLAPPED)) if (!(attributes & FILE_FLAG_OVERLAPPED))
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <signal.h> #include <signal.h>
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -43,6 +44,10 @@ ...@@ -43,6 +44,10 @@
#include "process.h" #include "process.h"
#include "request.h" #include "request.h"
#include "winbase.h"
#include "winreg.h"
#include "winternl.h"
/* Because of the stupid Posix locking semantics, we need to keep /* Because of the stupid Posix locking semantics, we need to keep
* track of all file descriptors referencing a given file, and not * track of all file descriptors referencing a given file, and not
* close a single one until all the locks are gone (sigh). * close a single one until all the locks are gone (sigh).
...@@ -415,7 +420,10 @@ static void inode_destroy( struct object *obj ) ...@@ -415,7 +420,10 @@ static void inode_destroy( struct object *obj )
/* make sure it is still the same file */ /* make sure it is still the same file */
struct stat st; struct stat st;
if (!stat( fd->unlink, &st ) && st.st_dev == inode->dev && st.st_ino == inode->ino) if (!stat( fd->unlink, &st ) && st.st_dev == inode->dev && st.st_ino == inode->ino)
unlink( fd->unlink ); {
if (S_ISDIR(st.st_mode)) rmdir( fd->unlink );
else unlink( fd->unlink );
}
} }
free( fd ); free( fd );
} }
...@@ -907,13 +915,15 @@ static int check_sharing( struct fd *fd, unsigned int access, unsigned int shari ...@@ -907,13 +915,15 @@ static int check_sharing( struct fd *fd, unsigned int access, unsigned int shari
/* the fd must have been created with alloc_fd */ /* the fd must have been created with alloc_fd */
/* on error the fd object is released */ /* on error the fd object is released */
struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode, struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode,
unsigned int access, unsigned int sharing, const char *unlink_name ) unsigned int access, unsigned int sharing, unsigned int options )
{ {
struct stat st; struct stat st;
struct closed_fd *closed_fd; struct closed_fd *closed_fd;
const char *unlink_name = "";
assert( fd->unix_fd == -1 ); assert( fd->unix_fd == -1 );
if (options & FILE_DELETE_ON_CLOSE) unlink_name = name;
if (!(closed_fd = mem_alloc( sizeof(*closed_fd) + strlen(unlink_name) ))) if (!(closed_fd = mem_alloc( sizeof(*closed_fd) + strlen(unlink_name) )))
{ {
release_object( fd ); release_object( fd );
...@@ -931,7 +941,20 @@ struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode, ...@@ -931,7 +941,20 @@ struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode,
fstat( fd->unix_fd, &st ); fstat( fd->unix_fd, &st );
*mode = st.st_mode; *mode = st.st_mode;
if (S_ISREG(st.st_mode)) /* only bother with an inode for normal files */ /* check directory options */
if ((options & FILE_DIRECTORY_FILE) && !S_ISDIR(st.st_mode))
{
set_error( STATUS_NOT_A_DIRECTORY );
goto error;
}
if ((options & FILE_NON_DIRECTORY_FILE) && S_ISDIR(st.st_mode))
{
set_error( STATUS_FILE_IS_A_DIRECTORY );
goto error;
}
/* only bother with an inode for normal files and directories */
if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
{ {
struct inode *inode = get_inode( st.st_dev, st.st_ino ); struct inode *inode = get_inode( st.st_dev, st.st_ino );
...@@ -940,9 +963,7 @@ struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode, ...@@ -940,9 +963,7 @@ struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode,
/* we can close the fd because there are no others open on the same file, /* we can close the fd because there are no others open on the same file,
* otherwise we wouldn't have failed to allocate a new inode * otherwise we wouldn't have failed to allocate a new inode
*/ */
release_object( fd ); goto error;
free( closed_fd );
return NULL;
} }
fd->inode = inode; fd->inode = inode;
fd->closed = closed_fd; fd->closed = closed_fd;
...@@ -957,15 +978,19 @@ struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode, ...@@ -957,15 +978,19 @@ struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode,
} }
else else
{ {
free( closed_fd );
if (unlink_name[0]) /* we can't unlink special files */ if (unlink_name[0]) /* we can't unlink special files */
{ {
release_object( fd );
set_error( STATUS_INVALID_PARAMETER ); set_error( STATUS_INVALID_PARAMETER );
return NULL; goto error;
} }
free( closed_fd );
} }
return fd; return fd;
error:
release_object( fd );
free( closed_fd );
return NULL;
} }
/* create an fd for an anonymous file */ /* create an fd for an anonymous file */
......
...@@ -167,8 +167,7 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int ...@@ -167,8 +167,7 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
/* 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 */
if (!(file->fd = alloc_fd( &file_fd_ops, &file->obj )) || if (!(file->fd = alloc_fd( &file_fd_ops, &file->obj )) ||
!(file->fd = open_fd( file->fd, name, flags | O_NONBLOCK | O_LARGEFILE, !(file->fd = open_fd( file->fd, name, flags | O_NONBLOCK | O_LARGEFILE,
&mode, access, sharing, &mode, access, sharing, options )))
(options & FILE_DELETE_ON_CLOSE) ? name : "" )))
{ {
free( name ); free( name );
release_object( file ); release_object( file );
...@@ -176,13 +175,6 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int ...@@ -176,13 +175,6 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
} }
free( name ); free( name );
/* refuse to open a directory */
if (S_ISDIR(mode) && !(options & FILE_OPEN_FOR_BACKUP_INTENT))
{
set_error( STATUS_ACCESS_DENIED );
release_object( file );
return NULL;
}
/* check for serial port */ /* check for serial port */
if (S_ISCHR(mode) && is_serial_fd( file->fd )) if (S_ISCHR(mode) && is_serial_fd( file->fd ))
{ {
......
...@@ -46,7 +46,7 @@ struct fd_ops ...@@ -46,7 +46,7 @@ struct fd_ops
extern struct fd *alloc_fd( const struct fd_ops *fd_user_ops, struct object *user ); extern struct fd *alloc_fd( const struct fd_ops *fd_user_ops, struct object *user );
extern struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode, extern struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode,
unsigned int access, unsigned int sharing, const char *unlink_name ); unsigned int access, unsigned int sharing, unsigned int options );
extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops, extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops,
int unix_fd, struct object *user ); int unix_fd, struct object *user );
extern void *get_fd_user( struct fd *fd ); extern void *get_fd_user( struct fd *fd );
......
...@@ -3082,6 +3082,7 @@ static const char *get_status_name( unsigned int status ) ...@@ -3082,6 +3082,7 @@ static const char *get_status_name( unsigned int status )
NAME(DIRECTORY_NOT_EMPTY), NAME(DIRECTORY_NOT_EMPTY),
NAME(DISK_FULL), NAME(DISK_FULL),
NAME(DLL_NOT_FOUND), NAME(DLL_NOT_FOUND),
NAME(FILE_IS_A_DIRECTORY),
NAME(FILE_LOCK_CONFLICT), NAME(FILE_LOCK_CONFLICT),
NAME(INVALID_FILE_FOR_SECTION), NAME(INVALID_FILE_FOR_SECTION),
NAME(INVALID_HANDLE), NAME(INVALID_HANDLE),
...@@ -3089,6 +3090,7 @@ static const char *get_status_name( unsigned int status ) ...@@ -3089,6 +3090,7 @@ static const char *get_status_name( unsigned int status )
NAME(KEY_DELETED), NAME(KEY_DELETED),
NAME(MEDIA_WRITE_PROTECTED), NAME(MEDIA_WRITE_PROTECTED),
NAME(MUTANT_NOT_OWNED), NAME(MUTANT_NOT_OWNED),
NAME(NOT_A_DIRECTORY),
NAME(NOT_IMPLEMENTED), NAME(NOT_IMPLEMENTED),
NAME(NOT_REGISTRY_FILE), NAME(NOT_REGISTRY_FILE),
NAME(NO_DATA_DETECTED), NAME(NO_DATA_DETECTED),
......
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