Added sys/user calls for the open/create entry_ref/node_ref functions.

Added functions to retrieve set the fs_info structure (i.e. used to get the
partition's name); not implemented yet in the internal file systems.
Implemented the dir_create_entry_ref() function.
Re-ordered some parameters for the fs calls to be more consistent.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@396 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2002-07-23 14:10:12 +00:00
parent c9d3e51155
commit b9f8590233
4 changed files with 285 additions and 56 deletions

View File

@ -381,7 +381,7 @@ bootfs_create_vnode_tree(struct bootfs *fs, struct bootfs_vnode *root)
static int
bootfs_mount(fs_cookie *_fs, fs_id id, const char *device, void *args, vnode_id *root_vnid)
bootfs_mount(fs_id id, const char *device, void *args, fs_cookie *_fs, vnode_id *root_vnid)
{
struct bootfs *fs;
struct bootfs_vnode *v;
@ -535,12 +535,12 @@ bootfs_get_vnode_name(fs_cookie _fs, fs_vnode _vnode, char *buffer, size_t buffe
static int
bootfs_getvnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r)
bootfs_get_vnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r)
{
struct bootfs *fs = (struct bootfs *)_fs;
int err;
TRACE(("bootfs_getvnode: asking for vnode 0x%x 0x%x, r %d\n", id, r));
TRACE(("bootfs_get_vnode: asking for vnode 0x%x 0x%x, r %d\n", id, r));
if(!r)
mutex_lock(&fs->lock);
@ -550,7 +550,7 @@ bootfs_getvnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r)
if(!r)
mutex_unlock(&fs->lock);
TRACE(("bootfs_getnvnode: looked it up at 0x%x\n", *v));
TRACE(("bootfs_get_vnode: looked it up at 0x%x\n", *v));
if(*v)
return 0;
@ -560,32 +560,32 @@ bootfs_getvnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r)
static int
bootfs_putvnode(fs_cookie _fs, fs_vnode _v, bool r)
bootfs_put_vnode(fs_cookie _fs, fs_vnode _v, bool r)
{
struct bootfs_vnode *v = (struct bootfs_vnode *)_v;
TRACE(("bootfs_putvnode: entry on vnode 0x%x 0x%x, r %d\n", v->id, r));
TRACE(("bootfs_put_vnode: entry on vnode 0x%x 0x%x, r %d\n", v->id, r));
return 0; // whatever
}
static int
bootfs_removevnode(fs_cookie _fs, fs_vnode _v, bool r)
bootfs_remove_vnode(fs_cookie _fs, fs_vnode _v, bool reenter)
{
struct bootfs *fs = (struct bootfs *)_fs;
struct bootfs_vnode *v = (struct bootfs_vnode *)_v;
struct bootfs_vnode dummy;
int err;
TRACE(("bootfs_removevnode: remove 0x%x (0x%x 0x%x), r %d\n", v, v->id, r));
TRACE(("bootfs_remove_vnode: remove 0x%x (0x%x 0x%x), r %d\n", v, v->id, r));
if(!r)
if (!reenter)
mutex_lock(&fs->lock);
if(v->dir_next) {
if (v->dir_next) {
// can't remove node if it's linked to the dir
panic("bootfs_removevnode: vnode %p asked to be removed is present in dir\n", v);
panic("bootfs_remove_vnode: vnode %p asked to be removed is present in dir\n", v);
}
bootfs_delete_vnode(fs, v, false);
@ -593,7 +593,7 @@ bootfs_removevnode(fs_cookie _fs, fs_vnode _v, bool r)
err = 0;
err:
if (!r)
if (!reenter)
mutex_unlock(&fs->lock);
return err;
@ -601,14 +601,14 @@ err:
static int
bootfs_create(fs_cookie _fs, fs_vnode _dir, file_cookie *_cookie, vnode_id *new_vnid, const char *name, int omode, int perms)
bootfs_create(fs_cookie _fs, fs_vnode _dir, const char *name, int omode, int perms, file_cookie *_cookie, vnode_id *new_vnid)
{
return EROFS;
}
static int
bootfs_open(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie, int oflags)
bootfs_open(fs_cookie _fs, fs_vnode _v, int oflags, file_cookie *_cookie)
{
struct bootfs *fs = _fs;
struct bootfs_vnode *vnode = _v;
@ -879,7 +879,7 @@ bootfs_ioctl(fs_cookie _fs, fs_vnode _v, file_cookie _cookie, ulong op, void *bu
static int
bootfs_canpage(fs_cookie _fs, fs_vnode _v)
bootfs_can_page(fs_cookie _fs, fs_vnode _v)
{
struct bootfs_vnode *v = _v;
@ -893,7 +893,7 @@ bootfs_canpage(fs_cookie _fs, fs_vnode _v)
static ssize_t
bootfs_readpage(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t pos)
bootfs_read_page(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t pos)
{
struct bootfs *fs = _fs;
struct bootfs_vnode *v = _v;
@ -912,7 +912,7 @@ bootfs_readpage(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t pos)
memcpy(vecs->vec[i].iov_base, v->stream.u.file.start + pos, copy_len);
if(copy_len < vecs->vec[i].iov_len)
if (copy_len < vecs->vec[i].iov_len)
memset((char *)vecs->vec[i].iov_base + copy_len, 0, vecs->vec[i].iov_len - copy_len);
pos += vecs->vec[i].iov_len;
@ -924,7 +924,7 @@ bootfs_readpage(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t pos)
static ssize_t
bootfs_writepage(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t pos)
bootfs_write_page(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t pos)
{
struct bootfs *fs = _fs;
struct bootfs_vnode *v = _v;
@ -1007,18 +1007,20 @@ bootfs_write_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat, int stat_mask)
static struct fs_calls bootfs_calls = {
&bootfs_mount,
&bootfs_unmount,
NULL,
NULL,
&bootfs_sync,
&bootfs_lookup,
&bootfs_get_vnode_name,
&bootfs_getvnode,
&bootfs_putvnode,
&bootfs_removevnode,
&bootfs_get_vnode,
&bootfs_put_vnode,
&bootfs_remove_vnode,
&bootfs_canpage,
&bootfs_readpage,
&bootfs_writepage,
&bootfs_can_page,
&bootfs_read_page,
&bootfs_write_page,
/* common */
&bootfs_ioctl,

View File

@ -396,7 +396,7 @@ err2:
static int
devfs_mount(fs_cookie *_fs, fs_id id, const char *devfs, void *args, vnode_id *root_vnid)
devfs_mount(fs_id id, const char *devfs, void *args, fs_cookie *_fs, vnode_id *root_vnid)
{
struct devfs *fs;
struct devfs_vnode *v;
@ -612,14 +612,14 @@ devfs_remove_vnode(fs_cookie _fs, fs_vnode _v, bool reenter)
static int
devfs_create(fs_cookie _fs, fs_vnode _dir, file_cookie *_cookie, vnode_id *new_vnid, const char *name, int omode, int perms)
devfs_create(fs_cookie _fs, fs_vnode _dir, const char *name, int omode, int perms, file_cookie *_cookie, vnode_id *new_vnid)
{
return EROFS;
}
static int
devfs_open(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie, int oflags)
devfs_open(fs_cookie _fs, fs_vnode _v, int oflags, file_cookie *_cookie)
{
struct devfs *fs = _fs;
struct devfs_vnode *vnode = _v;
@ -1043,6 +1043,8 @@ devfs_write_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat, int stat_mask)
static struct fs_calls devfs_calls = {
&devfs_mount,
&devfs_unmount,
NULL,
NULL,
&devfs_sync,
&devfs_lookup,

View File

@ -212,7 +212,7 @@ rootfs_is_dir_empty(struct rootfs_vnode *dir)
static int
rootfs_mount(fs_cookie *_fs, fs_id id, const char *device, void *args, vnode_id *root_vnid)
rootfs_mount(fs_id id, const char *device, void *args, fs_cookie *_fs, vnode_id *root_vnid)
{
struct rootfs *fs;
struct rootfs_vnode *v;
@ -425,14 +425,14 @@ rootfs_remove_vnode(fs_cookie _fs, fs_vnode _v, bool r)
static int
rootfs_create(fs_cookie _fs, fs_vnode _dir, file_cookie *_cookie, vnode_id *new_vnid, const char *name, int omode, int perms)
rootfs_create(fs_cookie _fs, fs_vnode _dir, const char *name, int omode, int perms, file_cookie *_cookie, vnode_id *new_vnid)
{
return EINVAL;
}
static int
rootfs_open(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie, int oflags)
rootfs_open(fs_cookie _fs, fs_vnode _v, int oflags, file_cookie *_cookie)
{
// allow to open the file, but it can't be done anything with it
return B_OK;
@ -810,6 +810,8 @@ rootfs_write_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat, int stat_mask)
static struct fs_calls rootfs_calls = {
&rootfs_mount,
&rootfs_unmount,
NULL,
NULL,
&rootfs_sync,
&rootfs_lookup,

View File

@ -51,6 +51,11 @@
#ifndef B_FILE_NAME_LENGTH
# define B_FILE_NAME_LENGTH 256
#endif
#include <fs_info.h>
// Passed in buffers from user-space shouldn't be in the kernel
#define CHECK_USER_ADDRESS(x) \
((addr)(x) < KERNEL_BASE || (addr)(x) > KERNEL_TOP)
struct vnode {
struct vnode *next;
@ -673,12 +678,15 @@ path_to_dir_vnode(char *path, struct vnode **_vnode, char *filename, bool kernel
* file system doesn't support this call, it will fall back to iterating
* through the parent directory to get the name of the child.
*
* To detect circular loops, it supports a maximum tree depth
* To protect against circular loops, it supports a maximum tree depth
* of 256 levels.
*
* Note that the path may not be correct the time this function returns!
* It doesn't use any locking to prevent returning the correct path, as
* paths aren't safe anyway: the path to a file can change at any time.
*
* It might be a good idea, though, to check if the returned path exists
* in the calling function (it's not done here because of efficiency)
*/
static status_t
@ -724,6 +732,9 @@ dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize)
if (status < B_OK)
return status;
// ToDo: add an explicit check for loops in about 10 levels to do
// real loop detection
// don't go deeper as 'maxLevel' to prevent circular loops
if (maxLevel-- < 0)
return ELOOP;
@ -1443,7 +1454,7 @@ create_vnode(struct vnode *directory, const char *name, int omode, int perms, bo
if (FS_CALL(directory,fs_create) == NULL)
return EROFS;
status = FS_CALL(directory,fs_create)(directory->mount->cookie, directory->private_node, &cookie, &newID, name, omode, perms);
status = FS_CALL(directory,fs_create)(directory->mount->cookie, directory->private_node, name, omode, perms, &cookie, &newID);
if (status < B_OK)
return status;
@ -1479,7 +1490,7 @@ open_vnode(struct vnode *vnode, int omode, bool kernel)
file_cookie cookie;
int status;
status = FS_CALL(vnode,fs_open)(vnode->mount->cookie, vnode->private_node, &cookie, omode);
status = FS_CALL(vnode,fs_open)(vnode->mount->cookie, vnode->private_node, omode, &cookie);
if (status < 0)
return status;
@ -1665,12 +1676,35 @@ file_seek(struct file_descriptor *descriptor, off_t pos, int seekType)
}
static int
dir_create_entry_ref(fs_id fsID, vnode_id parentID, const char *name, int perms, bool kernel)
{
struct vnode *vnode;
vnode_id newID;
int status;
FUNCTION(("dir_create_entry_ref(dev = %ld, ino = %Ld, name = '%s', perms = %d)\n", fdID, parentID, name, perms));
status = get_vnode(fsID, parentID, &vnode, kernel);
if (status < B_OK)
return status;
if (FS_CALL(vnode, fs_create_dir))
status = FS_CALL(vnode, fs_create_dir)(vnode->mount->cookie, vnode->private_node, name, perms, &newID);
else
status = EROFS;
put_vnode(vnode);
return status;
}
static int
dir_create(char *path, int perms, bool kernel)
{
char filename[SYS_MAX_NAME_LEN];
struct vnode *vnode;
vnode_id vnid;
vnode_id newID;
int status;
FUNCTION(("dir_create: path '%s', perms %d, kernel %d\n", path, perms, kernel));
@ -1680,7 +1714,7 @@ dir_create(char *path, int perms, bool kernel)
return status;
if (FS_CALL(vnode,fs_create_dir))
status = FS_CALL(vnode,fs_create_dir)(vnode->mount->cookie, vnode->private_node, filename, perms, &vnid);
status = FS_CALL(vnode,fs_create_dir)(vnode->mount->cookie, vnode->private_node, filename, perms, &newID);
else
status = EROFS;
@ -1961,7 +1995,7 @@ fs_mount(char *path, const char *device, const char *fs_name, void *args, bool k
goto err3;
}
err = mount->fs->calls->fs_mount(&mount->cookie, mount->id, device, NULL, &root_id);
err = mount->fs->calls->fs_mount(mount->id, device, NULL, &mount->cookie, &root_id);
if (err < 0) {
err = ERR_VFS_GENERAL;
goto err3;
@ -1988,7 +2022,7 @@ fs_mount(char *path, const char *device, const char *fs_name, void *args, bool k
mount->covers_vnode = covered_vnode;
// mount it
err = mount->fs->calls->fs_mount(&mount->cookie, mount->id, device, NULL, &root_id);
err = mount->fs->calls->fs_mount(mount->id, device, NULL, &mount->cookie, &root_id);
if (err < 0)
goto err4;
}
@ -2146,6 +2180,60 @@ fs_sync(void)
}
static int
fs_read_info(dev_t device, struct fs_info *info)
{
struct fs_mount *mount;
int status;
mutex_lock(&vfs_mount_mutex);
mount = find_mount(device);
if (mount == NULL) {
status = EINVAL;
goto error;
}
if (mount->fs->calls->fs_read_fs_info)
status = mount->fs->calls->fs_read_fs_info(mount->cookie, info);
else
status = EOPNOTSUPP;
// fill in other info the file system doesn't know about
info->dev = mount->id;
info->root = mount->root_vnode->id;
error:
mutex_unlock(&vfs_mount_mutex);
return status;
}
static int
fs_write_info(dev_t device, struct fs_info *info, int mask)
{
struct fs_mount *mount;
int status;
mutex_lock(&vfs_mount_mutex);
mount = find_mount(device);
if (mount == NULL) {
status = EINVAL;
goto error;
}
if (mount->fs->calls->fs_write_fs_info)
status = mount->fs->calls->fs_write_fs_info(mount->cookie, info, mask);
else
status = EROFS;
error:
mutex_unlock(&vfs_mount_mutex);
return status;
}
static int
get_cwd(char *buffer, size_t size, bool kernel)
{
@ -2249,22 +2337,53 @@ sys_sync(void)
}
int
sys_open_entry_ref(dev_t device, ino_t inode, const char *name, int omode)
{
char nameCopy[B_FILE_NAME_LENGTH];
strncpy(nameCopy, name, sizeof(nameCopy) - 1);
nameCopy[sizeof(nameCopy) - 1] = '\0';
return file_open_entry_ref(device, inode, nameCopy, omode, true);
}
int
sys_open(const char *path, int omode)
{
char buffer[SYS_MAX_PATH_LEN+1];
char pathCopy[SYS_MAX_PATH_LEN + 1];
strncpy(buffer, path, SYS_MAX_PATH_LEN);
buffer[SYS_MAX_PATH_LEN] = 0;
strncpy(pathCopy, path, SYS_MAX_PATH_LEN);
pathCopy[SYS_MAX_PATH_LEN] = 0;
return file_open(buffer, omode, true);
return file_open(pathCopy, omode, true);
}
int
sys_open_dir_node_ref(dev_t device, ino_t inode)
{
return dir_open_node_ref(device, inode, true);
}
int
sys_open_dir_entry_ref(dev_t device, ino_t inode, const char *name)
{
char nameCopy[B_FILE_NAME_LENGTH];
strncpy(nameCopy, name, sizeof(nameCopy) - 1);
nameCopy[sizeof(nameCopy) - 1] = '\0';
return dir_open_entry_ref(device, inode, nameCopy, true);
}
int
sys_open_dir(const char *path)
{
char buffer[SYS_MAX_PATH_LEN+1];
char buffer[SYS_MAX_PATH_LEN + 1];
strncpy(buffer, path, SYS_MAX_PATH_LEN);
buffer[SYS_MAX_PATH_LEN] = 0;
@ -2280,18 +2399,43 @@ sys_fsync(int fd)
}
int
sys_create_entry_ref(dev_t device, ino_t inode, const char *name, int omode, int perms)
{
char nameCopy[B_FILE_NAME_LENGTH];
int status;
strncpy(nameCopy, name, sizeof(nameCopy) - 1);
nameCopy[sizeof(nameCopy) - 1] = '\0';
return file_create_entry_ref(device, inode, nameCopy, omode, perms, true);
}
int
sys_create(const char *path, int omode, int perms)
{
char buffer[SYS_MAX_PATH_LEN+1];
strncpy(buffer, path, SYS_MAX_PATH_LEN);
buffer[SYS_MAX_PATH_LEN] = 0;
buffer[SYS_MAX_PATH_LEN] = '\0';
return file_create(buffer, omode, perms, true);
}
int
sys_create_dir_entry_ref(dev_t device, ino_t inode, const char *name, int perms)
{
char nameCopy[B_FILE_NAME_LENGTH];
strncpy(nameCopy, name, sizeof(nameCopy) - 1);
nameCopy[sizeof(nameCopy) - 1] = '\0';
return dir_create_entry_ref(device, inode, nameCopy, perms, true);
}
int
sys_create_dir(const char *path, int perms)
{
@ -2416,7 +2560,7 @@ user_mount(const char *upath, const char *udevice, const char *ufs_name, void *a
int rc;
if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP)
return ERR_VM_BAD_USER_MEMORY;
return B_BAD_ADDRESS;
if ((addr)ufs_name >= KERNEL_BASE && (addr)ufs_name <= KERNEL_TOP)
return ERR_VM_BAD_USER_MEMORY;
@ -2468,37 +2612,80 @@ user_sync(void)
}
int
user_open_entry_ref(dev_t device, ino_t inode, const char *uname, int omode)
{
char name[B_FILE_NAME_LENGTH];
int status;
if (!CHECK_USER_ADDRESS(uname))
return ERR_VM_BAD_USER_MEMORY;
status = user_strncpy(name, uname, sizeof(name) - 1);
if (status < B_OK)
return status;
name[sizeof(name) - 1] = '\0';
return file_open_entry_ref(device, inode, name, omode, false);
}
int
user_open(const char *upath, int omode)
{
char path[SYS_MAX_PATH_LEN];
int rc;
if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP)
if (!CHECK_USER_ADDRESS(upath))
return ERR_VM_BAD_USER_MEMORY;
rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN-1);
rc = user_strncpy(path, upath, sizeof(path) - 1);
if (rc < 0)
return rc;
path[SYS_MAX_PATH_LEN-1] = 0;
path[sizeof(path) - 1] = 0;
return file_open(path, omode, false);
}
int
user_open_dir_node_ref(dev_t device, ino_t inode)
{
return dir_open_node_ref(device, inode, false);
}
int
user_open_dir_entry_ref(dev_t device, ino_t inode, const char *uname)
{
char name[B_FILE_NAME_LENGTH];
int status;
if (!CHECK_USER_ADDRESS(uname))
return ERR_VM_BAD_USER_MEMORY;
status = user_strncpy(name, uname, sizeof(name) - 1);
if (status < B_OK)
return status;
name[sizeof(name) - 1] = '\0';
return dir_open_entry_ref(device, inode, name, false);
}
int
user_open_dir(const char *upath)
{
char path[SYS_MAX_PATH_LEN];
int rc;
int status;
if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP)
if (!CHECK_USER_ADDRESS(upath))
return ERR_VM_BAD_USER_MEMORY;
rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN-1);
if (rc < 0)
return rc;
path[SYS_MAX_PATH_LEN-1] = 0;
status = user_strncpy(path, upath, sizeof(path) - 1);
if (status < 0)
return status;
path[sizeof(path) - 1] = 0;
return dir_open(path, false);
}
@ -2511,6 +2698,24 @@ user_fsync(int fd)
}
int
user_create_entry_ref(dev_t device, ino_t inode, const char *uname, int omode, int perms)
{
char name[B_FILE_NAME_LENGTH];
int status;
if (!CHECK_USER_ADDRESS(uname))
return ERR_VM_BAD_USER_MEMORY;
status = user_strncpy(name, uname, sizeof(name) - 1);
if (status < 0)
return status;
name[sizeof(name) - 1] = '\0';
return file_create_entry_ref(device, inode, name, omode, perms, false);
}
int
user_create(const char *upath, int omode, int perms)
{
@ -2523,25 +2728,43 @@ user_create(const char *upath, int omode, int perms)
rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN - 1);
if (rc < 0)
return rc;
path[SYS_MAX_PATH_LEN - 1] = 0;
path[SYS_MAX_PATH_LEN - 1] = '\0';
return file_create(path, omode, perms, false);
}
int
user_create_dir_entry_ref(dev_t device, ino_t inode, const char *uname, int perms)
{
char name[B_FILE_NAME_LENGTH];
int status;
if (!CHECK_USER_ADDRESS(uname))
return ERR_VM_BAD_USER_MEMORY;
status = user_strncpy(name, uname, sizeof(name) - 1);
if (status < 0)
return status;
name[sizeof(name) - 1] = '\0';
return dir_create_entry_ref(device, inode, name, perms, false);
}
int
user_create_dir(const char *upath, int perms)
{
char path[SYS_MAX_PATH_LEN];
int rc;
if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP)
if (!CHECK_USER_ADDRESS(upath))
return ERR_VM_BAD_USER_MEMORY;
rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN - 1);
if (rc < 0)
return rc;
path[SYS_MAX_PATH_LEN - 1] = 0;
path[SYS_MAX_PATH_LEN - 1] = '\0';
return dir_create(path, perms, false);
}