server: Modify open_fd to create an fd without a user.
Create a set_fd_user function. Update create_file() to use the above functions.
This commit is contained in:
parent
433bbdf08a
commit
9a7124e815
36
server/fd.c
36
server/fd.c
|
@ -1224,14 +1224,14 @@ static inline void unmount_fd( struct fd *fd )
|
|||
}
|
||||
|
||||
/* allocate an fd object, without setting the unix fd yet */
|
||||
struct fd *alloc_fd( const struct fd_ops *fd_user_ops, struct object *user )
|
||||
static struct fd *alloc_fd_object(void)
|
||||
{
|
||||
struct fd *fd = alloc_object( &fd_ops );
|
||||
|
||||
if (!fd) return NULL;
|
||||
|
||||
fd->fd_ops = fd_user_ops;
|
||||
fd->user = user;
|
||||
fd->fd_ops = NULL;
|
||||
fd->user = NULL;
|
||||
fd->inode = NULL;
|
||||
fd->closed = NULL;
|
||||
fd->access = 0;
|
||||
|
@ -1311,17 +1311,24 @@ static int check_sharing( struct fd *fd, unsigned int access, unsigned int shari
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* open() wrapper using a struct fd */
|
||||
/* 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, unsigned int options )
|
||||
/* sets the user of an fd that previously had no user */
|
||||
void set_fd_user( struct fd *fd, const struct fd_ops *user_ops, struct object *user )
|
||||
{
|
||||
assert( fd->fd_ops == NULL );
|
||||
fd->fd_ops = user_ops;
|
||||
fd->user = user;
|
||||
}
|
||||
|
||||
/* open() wrapper that returns a struct fd with no fd user set */
|
||||
struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int access,
|
||||
unsigned int sharing, unsigned int options )
|
||||
{
|
||||
struct stat st;
|
||||
struct closed_fd *closed_fd;
|
||||
struct fd *fd;
|
||||
const char *unlink_name = "";
|
||||
|
||||
assert( fd->unix_fd == -1 );
|
||||
if (!(fd = alloc_fd_object())) return NULL;
|
||||
|
||||
if (options & FILE_DELETE_ON_CLOSE) unlink_name = name;
|
||||
if (!(closed_fd = mem_alloc( sizeof(*closed_fd) + strlen(unlink_name) )))
|
||||
|
@ -1337,9 +1344,7 @@ struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode,
|
|||
if (errno != EEXIST || (flags & O_EXCL))
|
||||
{
|
||||
file_set_error();
|
||||
release_object( fd );
|
||||
free( closed_fd );
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
|
||||
|
@ -1347,9 +1352,7 @@ struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode,
|
|||
if ((fd->unix_fd = open( name, flags & ~O_TRUNC, *mode )) == -1)
|
||||
{
|
||||
file_set_error();
|
||||
release_object( fd );
|
||||
free( closed_fd );
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
closed_fd->unix_fd = fd->unix_fd;
|
||||
closed_fd->unlink[0] = 0;
|
||||
|
@ -1420,10 +1423,11 @@ error:
|
|||
/* if the function fails the unix fd is closed */
|
||||
struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops, int unix_fd, struct object *user )
|
||||
{
|
||||
struct fd *fd = alloc_fd( fd_user_ops, user );
|
||||
struct fd *fd = alloc_fd_object();
|
||||
|
||||
if (fd)
|
||||
{
|
||||
set_fd_user( fd, fd_user_ops, user );
|
||||
fd->unix_fd = unix_fd;
|
||||
return fd;
|
||||
}
|
||||
|
|
|
@ -61,6 +61,8 @@ struct file
|
|||
unsigned int options; /* file options (FILE_DELETE_ON_CLOSE, FILE_SYNCHRONOUS...) */
|
||||
};
|
||||
|
||||
static unsigned int generic_file_map_access( unsigned int access );
|
||||
|
||||
static void file_dump( struct object *obj, int verbose );
|
||||
static struct fd *file_get_fd( struct object *obj );
|
||||
static unsigned int file_map_access( struct object *obj, unsigned int access );
|
||||
|
@ -120,12 +122,25 @@ static struct file *create_file_for_fd( int fd, unsigned int access, unsigned in
|
|||
return file;
|
||||
}
|
||||
|
||||
static struct object *create_file_obj( struct fd *fd, unsigned int access, unsigned int options )
|
||||
{
|
||||
struct file *file = alloc_object( &file_ops );
|
||||
|
||||
if (!file) return NULL;
|
||||
file->access = access;
|
||||
file->options = options;
|
||||
file->fd = fd;
|
||||
grab_object( fd );
|
||||
set_fd_user( fd, &file_fd_ops, &file->obj );
|
||||
return &file->obj;
|
||||
}
|
||||
|
||||
static struct object *create_file( const char *nameptr, size_t len, unsigned int access,
|
||||
unsigned int sharing, int create, unsigned int options,
|
||||
unsigned int attrs )
|
||||
{
|
||||
struct file *file;
|
||||
struct object *obj = NULL;
|
||||
struct fd *fd;
|
||||
int flags, rw_mode;
|
||||
char *name;
|
||||
mode_t mode;
|
||||
|
@ -142,7 +157,7 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
|
|||
case FILE_OPEN: flags = 0; break;
|
||||
case FILE_OPEN_IF: flags = O_CREAT; break;
|
||||
case FILE_OVERWRITE: flags = O_TRUNC; break;
|
||||
default: set_error( STATUS_INVALID_PARAMETER ); goto error;
|
||||
default: set_error( STATUS_INVALID_PARAMETER ); goto done;
|
||||
}
|
||||
|
||||
mode = (attrs & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666;
|
||||
|
@ -151,14 +166,11 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
|
|||
(!strcasecmp( name + len - 4, ".exe" ) || !strcasecmp( name + len - 4, ".com" )))
|
||||
mode |= 0111;
|
||||
|
||||
if (!(file = alloc_object( &file_ops ))) goto error;
|
||||
|
||||
file->access = file_map_access( &file->obj, access );
|
||||
file->options = options;
|
||||
access = generic_file_map_access( access );
|
||||
|
||||
rw_mode = 0;
|
||||
if (file->access & FILE_UNIX_READ_ACCESS) rw_mode |= FILE_READ_DATA;
|
||||
if (file->access & FILE_UNIX_WRITE_ACCESS) rw_mode |= FILE_WRITE_DATA;
|
||||
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;
|
||||
|
@ -168,29 +180,19 @@ 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, file->access, sharing, options )))
|
||||
{
|
||||
free( name );
|
||||
release_object( file );
|
||||
return NULL;
|
||||
}
|
||||
fd = open_fd( name, flags | O_NONBLOCK | O_LARGEFILE, &mode, access, sharing, options );
|
||||
if (!fd) goto done;
|
||||
|
||||
if (S_ISCHR(mode) && is_serial_fd( fd ))
|
||||
obj = create_serial( fd, options );
|
||||
else
|
||||
obj = create_file_obj( fd, access, options );
|
||||
|
||||
release_object( fd );
|
||||
|
||||
done:
|
||||
free( name );
|
||||
|
||||
/* check for serial port */
|
||||
if (S_ISCHR(mode) && is_serial_fd( file->fd ))
|
||||
{
|
||||
struct object *obj = create_serial( file->fd, file->options );
|
||||
release_object( file );
|
||||
return obj;
|
||||
}
|
||||
|
||||
return &file->obj;
|
||||
|
||||
error:
|
||||
free( name );
|
||||
return NULL;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/* check if two file objects point to the same file */
|
||||
|
@ -260,7 +262,7 @@ static struct fd *file_get_fd( struct object *obj )
|
|||
return (struct fd *)grab_object( file->fd );
|
||||
}
|
||||
|
||||
static unsigned int file_map_access( struct object *obj, unsigned int access )
|
||||
static unsigned int generic_file_map_access( unsigned int access )
|
||||
{
|
||||
if (access & GENERIC_READ) access |= FILE_GENERIC_READ;
|
||||
if (access & GENERIC_WRITE) access |= FILE_GENERIC_WRITE;
|
||||
|
@ -269,6 +271,11 @@ static unsigned int file_map_access( struct object *obj, unsigned int access )
|
|||
return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
|
||||
}
|
||||
|
||||
static unsigned int file_map_access( struct object *obj, unsigned int access )
|
||||
{
|
||||
return generic_file_map_access( access );
|
||||
}
|
||||
|
||||
static void file_destroy( struct object *obj )
|
||||
{
|
||||
struct file *file = (struct file *)obj;
|
||||
|
|
|
@ -46,13 +46,13 @@ struct fd_ops
|
|||
|
||||
/* file descriptor functions */
|
||||
|
||||
extern struct fd *alloc_fd( const struct fd_ops *fd_user_ops, struct object *user );
|
||||
extern struct fd *alloc_pseudo_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, unsigned int options );
|
||||
extern struct fd *open_fd( const char *name, int flags, mode_t *mode, 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 );
|
||||
extern void set_fd_user( struct fd *fd, const struct fd_ops *ops, struct object *user );
|
||||
extern int get_unix_fd( struct fd *fd );
|
||||
extern int is_same_file_fd( struct fd *fd1, struct fd *fd2 );
|
||||
extern void fd_poll_event( struct fd *fd, int event );
|
||||
|
|
Loading…
Reference in New Issue