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,
options = 0;
if (attributes & FILE_FLAG_BACKUP_SEMANTICS)
options |= FILE_OPEN_FOR_BACKUP_INTENT;
else
options |= FILE_NON_DIRECTORY_FILE;
if (attributes & FILE_FLAG_DELETE_ON_CLOSE)
options |= FILE_DELETE_ON_CLOSE;
if (!(attributes & FILE_FLAG_OVERLAPPED))
......
......@@ -26,6 +26,7 @@
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
......@@ -43,6 +44,10 @@
#include "process.h"
#include "request.h"
#include "winbase.h"
#include "winreg.h"
#include "winternl.h"
/* Because of the stupid Posix locking semantics, we need to keep
* track of all file descriptors referencing a given file, and not
* close a single one until all the locks are gone (sigh).
......@@ -415,7 +420,10 @@ static void inode_destroy( struct object *obj )
/* make sure it is still the same file */
struct stat st;
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 );
}
......@@ -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 */
/* on error the fd object is released */
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 closed_fd *closed_fd;
const char *unlink_name = "";
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) )))
{
release_object( fd );
......@@ -931,7 +941,20 @@ struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode,
fstat( fd->unix_fd, &st );
*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 );
......@@ -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,
* otherwise we wouldn't have failed to allocate a new inode
*/
release_object( fd );
free( closed_fd );
return NULL;
goto error;
}
fd->inode = inode;
fd->closed = closed_fd;
......@@ -957,15 +978,19 @@ struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode,
}
else
{
free( closed_fd );
if (unlink_name[0]) /* we can't unlink special files */
{
release_object( fd );
set_error( STATUS_INVALID_PARAMETER );
return NULL;
goto error;
}
free( closed_fd );
}
return fd;
error:
release_object( fd );
free( closed_fd );
return NULL;
}
/* create an fd for an anonymous file */
......
......@@ -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 */
if (!(file->fd = alloc_fd( &file_fd_ops, &file->obj )) ||
!(file->fd = open_fd( file->fd, name, flags | O_NONBLOCK | O_LARGEFILE,
&mode, access, sharing,
(options & FILE_DELETE_ON_CLOSE) ? name : "" )))
&mode, access, sharing, options )))
{
free( name );
release_object( file );
......@@ -176,13 +175,6 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
}
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 */
if (S_ISCHR(mode) && is_serial_fd( file->fd ))
{
......
......@@ -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 *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,
int unix_fd, struct object *user );
extern void *get_fd_user( struct fd *fd );
......
......@@ -3082,6 +3082,7 @@ static const char *get_status_name( unsigned int status )
NAME(DIRECTORY_NOT_EMPTY),
NAME(DISK_FULL),
NAME(DLL_NOT_FOUND),
NAME(FILE_IS_A_DIRECTORY),
NAME(FILE_LOCK_CONFLICT),
NAME(INVALID_FILE_FOR_SECTION),
NAME(INVALID_HANDLE),
......@@ -3089,6 +3090,7 @@ static const char *get_status_name( unsigned int status )
NAME(KEY_DELETED),
NAME(MEDIA_WRITE_PROTECTED),
NAME(MUTANT_NOT_OWNED),
NAME(NOT_A_DIRECTORY),
NAME(NOT_IMPLEMENTED),
NAME(NOT_REGISTRY_FILE),
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