server: Add support for opening files from a specified root directory.
This commit is contained in:
parent
d97149b708
commit
42806f32e9
|
@ -419,8 +419,7 @@ static void dir_destroy( struct object *obj )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dir *
|
struct dir *get_dir_obj( struct process *process, obj_handle_t handle, unsigned int access )
|
||||||
get_dir_obj( struct process *process, obj_handle_t handle, unsigned int access )
|
|
||||||
{
|
{
|
||||||
return (struct dir *)get_handle_obj( process, handle, access, &dir_ops );
|
return (struct dir *)get_handle_obj( process, handle, access, &dir_ops );
|
||||||
}
|
}
|
||||||
|
|
37
server/fd.c
37
server/fd.c
|
@ -1702,14 +1702,34 @@ void set_fd_user( struct fd *fd, const struct fd_ops *user_ops, struct object *u
|
||||||
fd->user = user;
|
fd->user = user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *dup_fd_name( struct fd *root, const char *name )
|
||||||
|
{
|
||||||
|
char *ret;
|
||||||
|
|
||||||
|
if (!root) return strdup( name );
|
||||||
|
if (!root->unix_name) return NULL;
|
||||||
|
|
||||||
|
/* skip . prefix */
|
||||||
|
if (name[0] == '.' && (!name[1] || name[1] == '/')) name++;
|
||||||
|
|
||||||
|
if ((ret = malloc( strlen(root->unix_name) + strlen(name) + 2 )))
|
||||||
|
{
|
||||||
|
strcpy( ret, root->unix_name );
|
||||||
|
if (name[0] && name[0] != '/') strcat( ret, "/" );
|
||||||
|
strcat( ret, name );
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* open() wrapper that returns a struct fd with no fd user set */
|
/* 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,
|
struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode, unsigned int access,
|
||||||
unsigned int sharing, unsigned int options )
|
unsigned int sharing, unsigned int options )
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
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 root_fd = -1;
|
||||||
int rw_mode;
|
int rw_mode;
|
||||||
|
|
||||||
if ((options & FILE_DELETE_ON_CLOSE) && !(access & DELETE))
|
if ((options & FILE_DELETE_ON_CLOSE) && !(access & DELETE))
|
||||||
|
@ -1728,6 +1748,17 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (root)
|
||||||
|
{
|
||||||
|
if ((root_fd = get_unix_fd( root )) == -1) goto error;
|
||||||
|
if (fchdir( root_fd ) == -1)
|
||||||
|
{
|
||||||
|
file_set_error();
|
||||||
|
root_fd = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 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))
|
||||||
{
|
{
|
||||||
|
@ -1749,8 +1780,7 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce
|
||||||
}
|
}
|
||||||
else rw_mode = O_RDONLY;
|
else rw_mode = O_RDONLY;
|
||||||
|
|
||||||
if (!(fd->unix_name = mem_alloc( strlen(name) + 1 ))) goto error;
|
fd->unix_name = dup_fd_name( root, name );
|
||||||
strcpy( fd->unix_name, name );
|
|
||||||
|
|
||||||
if ((fd->unix_fd = open( name, rw_mode | (flags & ~O_TRUNC), *mode )) == -1)
|
if ((fd->unix_fd = open( name, rw_mode | (flags & ~O_TRUNC), *mode )) == -1)
|
||||||
{
|
{
|
||||||
|
@ -1827,6 +1857,7 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce
|
||||||
error:
|
error:
|
||||||
release_object( fd );
|
release_object( fd );
|
||||||
free( closed_fd );
|
free( closed_fd );
|
||||||
|
if (root_fd != -1) fchdir( server_dir_fd ); /* go back to the server dir */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,9 +154,10 @@ static struct object *create_file_obj( struct fd *fd, unsigned int access, mode_
|
||||||
return &file->obj;
|
return &file->obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct object *create_file( const char *nameptr, data_size_t len, unsigned int access,
|
static struct object *create_file( struct fd *root, const char *nameptr, data_size_t len,
|
||||||
unsigned int sharing, int create, unsigned int options,
|
unsigned int access, unsigned int sharing, int create,
|
||||||
unsigned int attrs, const struct security_descriptor *sd )
|
unsigned int options, unsigned int attrs,
|
||||||
|
const struct security_descriptor *sd )
|
||||||
{
|
{
|
||||||
struct object *obj = NULL;
|
struct object *obj = NULL;
|
||||||
struct fd *fd;
|
struct fd *fd;
|
||||||
|
@ -164,6 +165,11 @@ static struct object *create_file( const char *nameptr, data_size_t len, unsigne
|
||||||
char *name;
|
char *name;
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
|
|
||||||
|
if (!len || ((nameptr[0] == '/') ^ !root))
|
||||||
|
{
|
||||||
|
set_error( STATUS_OBJECT_PATH_SYNTAX_BAD );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (!(name = mem_alloc( len + 1 ))) return NULL;
|
if (!(name = mem_alloc( len + 1 ))) return NULL;
|
||||||
memcpy( name, nameptr, len );
|
memcpy( name, nameptr, len );
|
||||||
name[len] = 0;
|
name[len] = 0;
|
||||||
|
@ -203,7 +209,7 @@ static struct object *create_file( const char *nameptr, data_size_t len, unsigne
|
||||||
access = generic_file_map_access( access );
|
access = generic_file_map_access( access );
|
||||||
|
|
||||||
/* 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( root, name, flags | O_NONBLOCK | O_LARGEFILE, &mode, access, sharing, options );
|
||||||
if (!fd) goto done;
|
if (!fd) goto done;
|
||||||
|
|
||||||
if (S_ISDIR(mode))
|
if (S_ISDIR(mode))
|
||||||
|
@ -628,6 +634,7 @@ struct file *grab_file_unless_removable( struct file *file )
|
||||||
DECL_HANDLER(create_file)
|
DECL_HANDLER(create_file)
|
||||||
{
|
{
|
||||||
struct object *file;
|
struct object *file;
|
||||||
|
struct fd *root_fd = NULL;
|
||||||
const struct object_attributes *objattr = get_req_data();
|
const struct object_attributes *objattr = get_req_data();
|
||||||
const struct security_descriptor *sd;
|
const struct security_descriptor *sd;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -644,19 +651,29 @@ DECL_HANDLER(create_file)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (objattr->rootdir)
|
||||||
|
{
|
||||||
|
struct dir *root;
|
||||||
|
|
||||||
|
if (!(root = get_dir_obj( current->process, objattr->rootdir, 0 ))) return;
|
||||||
|
root_fd = get_obj_fd( (struct object *)root );
|
||||||
|
release_object( root );
|
||||||
|
if (!root_fd) return;
|
||||||
|
}
|
||||||
|
|
||||||
sd = objattr->sd_len ? (const struct security_descriptor *)(objattr + 1) : NULL;
|
sd = objattr->sd_len ? (const struct security_descriptor *)(objattr + 1) : NULL;
|
||||||
|
|
||||||
name = (const char *)get_req_data() + sizeof(*objattr) + objattr->sd_len;
|
name = (const char *)get_req_data() + sizeof(*objattr) + objattr->sd_len;
|
||||||
name_len = get_req_data_size() - sizeof(*objattr) - objattr->sd_len;
|
name_len = get_req_data_size() - sizeof(*objattr) - objattr->sd_len;
|
||||||
|
|
||||||
reply->handle = 0;
|
reply->handle = 0;
|
||||||
if ((file = create_file( name, name_len, req->access,
|
if ((file = create_file( root_fd, name, name_len, req->access, req->sharing,
|
||||||
req->sharing, req->create, req->options,
|
req->create, req->options, req->attrs, sd )))
|
||||||
req->attrs, sd )))
|
|
||||||
{
|
{
|
||||||
reply->handle = alloc_handle( current->process, file, req->access, req->attributes );
|
reply->handle = alloc_handle( current->process, file, req->access, req->attributes );
|
||||||
release_object( file );
|
release_object( file );
|
||||||
}
|
}
|
||||||
|
if (root_fd) release_object( root_fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate a file handle for a Unix fd */
|
/* allocate a file handle for a Unix fd */
|
||||||
|
|
|
@ -54,8 +54,8 @@ struct fd_ops
|
||||||
extern struct fd *alloc_pseudo_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,
|
||||||
unsigned int options );
|
unsigned int options );
|
||||||
extern void set_no_fd_status( struct fd *fd, unsigned int status );
|
extern void set_no_fd_status( struct fd *fd, unsigned int status );
|
||||||
extern struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int access,
|
extern struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||||
unsigned int sharing, unsigned int options );
|
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, unsigned int options );
|
int unix_fd, struct object *user, unsigned int options );
|
||||||
extern struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sharing,
|
extern struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sharing,
|
||||||
|
@ -125,6 +125,7 @@ extern mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner
|
||||||
extern void do_change_notify( int unix_fd );
|
extern void do_change_notify( int unix_fd );
|
||||||
extern void sigio_callback(void);
|
extern void sigio_callback(void);
|
||||||
extern struct object *create_dir_obj( struct fd *fd, unsigned int access, mode_t mode );
|
extern struct object *create_dir_obj( struct fd *fd, unsigned int access, mode_t mode );
|
||||||
|
extern struct dir *get_dir_obj( struct process *process, obj_handle_t handle, unsigned int access );
|
||||||
|
|
||||||
/* completion */
|
/* completion */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue