Beginnings of symbolic link support.

Cleanup of the code in many places.
Fixed bad bugs in dir_vnode_to_path(), and entry_ref_to_vnode().
Fixed some other bugs.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@509 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2002-07-28 18:41:07 +00:00
parent 951cb228e1
commit 7be577a363
4 changed files with 519 additions and 278 deletions
+20 -16
View File
@@ -34,6 +34,11 @@ static char *bootdir = NULL;
static off_t bootdir_len = 0;
static region_id bootdir_region = -1;
typedef enum {
STREAM_TYPE_FILE = S_IFREG,
STREAM_TYPE_DIR = S_IFDIR,
} stream_type;
struct bootfs_stream {
stream_type type;
union {
@@ -484,41 +489,38 @@ bootfs_sync(fs_cookie fs)
static int
bootfs_lookup(fs_cookie _fs, fs_vnode _dir, const char *name, vnode_id *id)
bootfs_lookup(fs_cookie _fs, fs_vnode _dir, const char *name, vnode_id *_id, int *_type)
{
struct bootfs *fs = (struct bootfs *)_fs;
struct bootfs_vnode *dir = (struct bootfs_vnode *)_dir;
struct bootfs_vnode *v;
struct bootfs_vnode *v1;
int err;
struct bootfs_vnode *vnode, *vdummy;
int status;
TRACE(("bootfs_lookup: entry dir 0x%x, name '%s'\n", dir, name));
if (dir->stream.type != STREAM_TYPE_DIR)
return ENOTDIR;
return B_NOT_A_DIRECTORY;
mutex_lock(&fs->lock);
// look it up
v = bootfs_find_in_dir(dir, name);
if (!v) {
err = ENOENT;
vnode = bootfs_find_in_dir(dir, name);
if (!vnode) {
status = B_ENTRY_NOT_FOUND;
goto err;
}
err = vfs_get_vnode(fs->id, v->id, (fs_vnode *)&v1);
if(err < 0) {
status = vfs_get_vnode(fs->id, vnode->id, (fs_vnode *)&vdummy);
if (status < 0)
goto err;
}
*id = v->id;
err = B_NO_ERROR;
*_id = vnode->id;
*_type = dir->stream.type;
err:
mutex_unlock(&fs->lock);
return err;
return status;
}
@@ -989,7 +991,7 @@ err:
static int
bootfs_write_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat, int stat_mask)
bootfs_write_stat(fs_cookie _fs, fs_vnode _v, const struct stat *stat, int stat_mask)
{
struct bootfs *fs = _fs;
struct bootfs_vnode *v = _v;
@@ -1026,6 +1028,8 @@ static struct fs_calls bootfs_calls = {
&bootfs_ioctl,
&bootfs_fsync,
NULL, // read_link
NULL, // symlink
&bootfs_unlink,
&bootfs_rename,
+31 -24
View File
@@ -34,6 +34,12 @@
# define INSANE(x)
#endif
typedef enum {
STREAM_TYPE_DIR = S_IFDIR,
STREAM_TYPE_DEVICE = S_IFCHR,
STREAM_TYPE_SYMLINK = S_IFLNK
} stream_type;
struct devfs_part_map {
off_t offset;
off_t size;
@@ -57,6 +63,9 @@ struct devfs_stream {
device_hooks *calls;
struct devfs_part_map *part_map;
} dev;
struct stream_symlink {
char *path;
} symlink;
} u;
};
@@ -502,25 +511,24 @@ devfs_sync(fs_cookie fs)
static int
devfs_lookup(fs_cookie _fs, fs_vnode _dir, const char *name, vnode_id *id)
devfs_lookup(fs_cookie _fs, fs_vnode _dir, const char *name, vnode_id *_id, int *_type)
{
struct devfs *fs = (struct devfs *)_fs;
struct devfs_vnode *dir = (struct devfs_vnode *)_dir;
struct devfs_vnode *vnode;
struct devfs_vnode *vdummy;
struct devfs_vnode *vnode, *vdummy;
int err;
TRACE(("devfs_lookup: entry dir %p, name '%s'\n", dir, name));
if (dir->stream.type != STREAM_TYPE_DIR)
return ENOTDIR;
return B_NOT_A_DIRECTORY;
mutex_lock(&fs->lock);
// look it up
vnode = devfs_find_in_dir(dir, name);
if (!vnode) {
err = ERR_NOT_FOUND;
err = B_ENTRY_NOT_FOUND;
goto err;
}
@@ -528,7 +536,8 @@ devfs_lookup(fs_cookie _fs, fs_vnode _dir, const char *name, vnode_id *id)
if (err < 0)
goto err;
*id = vnode->id;
*_id = vnode->id;
*_type = vnode->stream.type;
err:
mutex_unlock(&fs->lock);
@@ -967,33 +976,33 @@ devfs_unlink(fs_cookie _fs, fs_vnode _dir, const char *name)
{
struct devfs *fs = _fs;
struct devfs_vnode *dir = _dir;
struct devfs_vnode *v;
int res = B_NO_ERROR;
struct devfs_vnode *vnode;
int status = B_NO_ERROR;
mutex_lock(&fs->lock);
v = devfs_find_in_dir( dir, name );
if(!v) {
res = ERR_NOT_FOUND;
vnode = devfs_find_in_dir(dir, name);
if (!vnode) {
status = B_ENTRY_NOT_FOUND;
goto err;
}
// you can unlink partitions only
if( v->stream.type != STREAM_TYPE_DEVICE || !v->stream.u.dev.part_map ) {
res = EROFS;
if (vnode->stream.type != STREAM_TYPE_DEVICE || !vnode->stream.u.dev.part_map) {
status = EROFS;
goto err;
}
res = devfs_remove_from_dir( v->parent, v );
if( res )
status = devfs_remove_from_dir(vnode->parent, vnode);
if (status < 0)
goto err;
res = vfs_remove_vnode( fs->id, v->id );
status = vfs_remove_vnode(fs->id, vnode->id);
err:
mutex_unlock(&fs->lock);
return res;
return status;
}
@@ -1012,20 +1021,16 @@ devfs_read_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat)
TRACE(("devfs_rstat: vnode %p (%Ld), stat %p\n", vnode, vnode->id, stat));
stat->st_ino = vnode->id;
stat->st_mode = DEFFILEMODE;
stat->st_size = 0;
if (vnode->stream.type == STREAM_TYPE_DIR)
stat->st_mode |= S_IFDIR;
else
stat->st_mode |= S_IFCHR;
// ToDo: or should this be just DEFFILEMODE (0666 instead of 0644)?
stat->st_mode = vnode->stream.type | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
return 0;
}
static int
devfs_write_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat, int stat_mask)
devfs_write_stat(fs_cookie _fs, fs_vnode _v, const struct stat *stat, int stat_mask)
{
#if DEVFS_TRACE
struct devfs_vnode *v = _v;
@@ -1062,6 +1067,8 @@ static struct fs_calls devfs_calls = {
&devfs_ioctl,
&devfs_fsync,
NULL, // read_link
NULL, // symlink
&devfs_unlink,
&devfs_rename,
+210 -119
View File
@@ -27,12 +27,21 @@
#define TRACE(x)
#endif
typedef enum {
STREAM_TYPE_DIR = S_IFDIR,
STREAM_TYPE_SYMLINK = S_IFLNK,
} stream_type;
struct rootfs_stream {
// only type of stream supported by rootfs
stream_type type;
struct stream_dir {
struct rootfs_vnode *dir_head;
struct rootfs_cookie *jar_head;
} dir;
struct stream_symlink {
char *path;
int length;
} symlink;
};
struct rootfs_vnode {
@@ -67,13 +76,13 @@ struct rootfs_cookie {
static unsigned int
rootfs_vnode_hash_func(void *_v, const void *_key, unsigned int range)
{
struct rootfs_vnode *v = _v;
struct rootfs_vnode *vnode = _v;
const vnode_id *key = _key;
if(v != NULL)
return v->id % range;
else
return (*key) % range;
if (vnode != NULL)
return vnode->id % range;
return (*key) % range;
}
@@ -83,10 +92,10 @@ rootfs_vnode_compare_func(void *_v, const void *_key)
struct rootfs_vnode *v = _v;
const vnode_id *key = _key;
if(v->id == *key)
if (v->id == *key)
return 0;
else
return -1;
return -1;
}
@@ -124,14 +133,18 @@ rootfs_delete_vnode(struct rootfs *fs, struct rootfs_vnode *v, bool force_delete
return 0;
}
static void insert_cookie_in_jar(struct rootfs_vnode *dir, struct rootfs_cookie *cookie)
static void
insert_cookie_in_jar(struct rootfs_vnode *dir, struct rootfs_cookie *cookie)
{
cookie->next = dir->stream.dir.jar_head;
dir->stream.dir.jar_head = cookie;
cookie->prev = NULL;
}
static void remove_cookie_from_jar(struct rootfs_vnode *dir, struct rootfs_cookie *cookie)
static void
remove_cookie_from_jar(struct rootfs_vnode *dir, struct rootfs_cookie *cookie)
{
if(cookie->next)
cookie->next->prev = cookie->prev;
@@ -148,48 +161,52 @@ static void update_dircookies(struct rootfs_vnode *dir, struct rootfs_vnode *v)
{
struct rootfs_cookie *cookie;
for(cookie = dir->stream.dir.jar_head; cookie; cookie = cookie->next) {
if(cookie->ptr == v) {
for (cookie = dir->stream.dir.jar_head; cookie; cookie = cookie->next) {
if(cookie->ptr == v)
cookie->ptr = v->dir_next;
}
}
}
static struct rootfs_vnode *rootfs_find_in_dir(struct rootfs_vnode *dir, const char *path)
static struct rootfs_vnode *
rootfs_find_in_dir(struct rootfs_vnode *dir, const char *path)
{
struct rootfs_vnode *v;
if(!strcmp(path, "."))
if (!strcmp(path, "."))
return dir;
if(!strcmp(path, ".."))
if (!strcmp(path, ".."))
return dir->parent;
for(v = dir->stream.dir.dir_head; v; v = v->dir_next) {
if(strcmp(v->name, path) == 0) {
for (v = dir->stream.dir.dir_head; v; v = v->dir_next) {
if (strcmp(v->name, path) == 0)
return v;
}
}
return NULL;
}
static int rootfs_insert_in_dir(struct rootfs_vnode *dir, struct rootfs_vnode *v)
static int
rootfs_insert_in_dir(struct rootfs_vnode *dir, struct rootfs_vnode *v)
{
v->dir_next = dir->stream.dir.dir_head;
dir->stream.dir.dir_head = v;
return 0;
}
static int rootfs_remove_from_dir(struct rootfs_vnode *dir, struct rootfs_vnode *findit)
static int
rootfs_remove_from_dir(struct rootfs_vnode *dir, struct rootfs_vnode *findit)
{
struct rootfs_vnode *v;
struct rootfs_vnode *last_v;
for(v = dir->stream.dir.dir_head, last_v = NULL; v; last_v = v, v = v->dir_next) {
if(v == findit) {
for (v = dir->stream.dir.dir_head, last_v = NULL; v; last_v = v, v = v->dir_next) {
if (v == findit) {
/* make sure all dircookies dont point to this vnode */
update_dircookies(dir, v);
if(last_v)
if (last_v)
last_v->dir_next = v->dir_next;
else
dir->stream.dir.dir_head = v->dir_next;
@@ -228,9 +245,8 @@ rootfs_mount(fs_id id, const char *device, void *args, fs_cookie *_fs, vnode_id
fs->next_vnode_id = 0;
err = mutex_init(&fs->lock, "rootfs_mutex");
if(err < 0) {
if (err < 0)
goto err1;
}
fs->vnode_list_hash = hash_init(ROOTFS_HASH_SIZE, (addr)&v->all_next - (addr)v,
&rootfs_vnode_compare_func, &rootfs_vnode_hash_func);
@@ -313,38 +329,38 @@ rootfs_sync(fs_cookie fs)
static int
rootfs_lookup(fs_cookie _fs, fs_vnode _dir, const char *name, vnode_id *id)
rootfs_lookup(fs_cookie _fs, fs_vnode _dir, const char *name, vnode_id *_id, int *_type)
{
struct rootfs *fs = (struct rootfs *)_fs;
struct rootfs_vnode *dir = (struct rootfs_vnode *)_dir;
struct rootfs_vnode *v;
struct rootfs_vnode *vnode,*vdummy;
struct rootfs_vnode *v1;
int err;
int status;
TRACE(("rootfs_lookup: entry dir 0x%x, name '%s'\n", dir, name));
if (dir->stream.type != STREAM_TYPE_DIR)
return B_NOT_A_DIRECTORY;
mutex_lock(&fs->lock);
// look it up
v = rootfs_find_in_dir(dir, name);
if(!v) {
err = ENOENT;
vnode = rootfs_find_in_dir(dir, name);
if (!vnode) {
status = B_ENTRY_NOT_FOUND;
goto err;
}
err = vfs_get_vnode(fs->id, v->id, (fs_vnode *)&v1);
if(err < 0) {
status = vfs_get_vnode(fs->id, vnode->id, (fs_vnode *)&vdummy);
if (status < 0)
goto err;
}
*id = v->id;
err = B_NO_ERROR;
*_id = vnode->id;
*_type = vnode->stream.type;
err:
mutex_unlock(&fs->lock);
return err;
return status;
}
@@ -361,23 +377,23 @@ rootfs_get_vnode_name(fs_cookie _fs, fs_vnode _vnode, char *buffer, size_t buffe
static int
rootfs_get_vnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r)
rootfs_get_vnode(fs_cookie _fs, vnode_id id, fs_vnode *_vnode, bool reenter)
{
struct rootfs *fs = (struct rootfs *)_fs;
TRACE(("rootfs_getvnode: asking for vnode 0x%x 0x%x, r %d\n", id, r));
TRACE(("rootfs_getvnode: asking for vnode 0x%x 0x%x, r %d\n", id, reenter));
if (!r)
if (!reenter)
mutex_lock(&fs->lock);
*v = hash_lookup(fs->vnode_list_hash, &id);
*_vnode = hash_lookup(fs->vnode_list_hash, &id);
if (!r)
if (!reenter)
mutex_unlock(&fs->lock);
TRACE(("rootfs_getnvnode: looked it up at 0x%x\n", *v));
TRACE(("rootfs_getnvnode: looked it up at 0x%x\n", *_vnode));
if (*v)
if (*_vnode)
return B_NO_ERROR;
return ENOENT;
@@ -385,42 +401,39 @@ rootfs_get_vnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r)
static int
rootfs_put_vnode(fs_cookie _fs, fs_vnode _v, bool r)
rootfs_put_vnode(fs_cookie _fs, fs_vnode _vnode, bool reenter)
{
#if ROOTFS_TRACE
struct rootfs_vnode *v = (struct rootfs_vnode *)_v;
struct rootfs_vnode *vnode = (struct rootfs_vnode *)_vnode;
TRACE(("rootfs_putvnode: entry on vnode 0x%x 0x%x, r %d\n", v->id, r));
TRACE(("rootfs_putvnode: entry on vnode 0x%x 0x%x, r %d\n", vnode->id, reenter));
#endif
return 0; // whatever
}
static int
rootfs_remove_vnode(fs_cookie _fs, fs_vnode _v, bool r)
rootfs_remove_vnode(fs_cookie _fs, fs_vnode _vnode, bool reenter)
{
struct rootfs *fs = (struct rootfs *)_fs;
struct rootfs_vnode *v = (struct rootfs_vnode *)_v;
int err;
struct rootfs_vnode *vnode = (struct rootfs_vnode *)_vnode;
TRACE(("rootfs_removevnode: remove 0x%x (0x%x 0x%x), r %d\n", v, v->id, r));
TRACE(("rootfs_removevnode: remove 0x%x (0x%x 0x%x), r %d\n", vnode, vnode->id, reenter));
if(!r)
if (!reenter)
mutex_lock(&fs->lock);
if(v->dir_next) {
if (vnode->dir_next) {
// can't remove node if it's linked to the dir
panic("rootfs_removevnode: vnode %p asked to be removed is present in dir\n", v);
panic("rootfs_removevnode: vnode %p asked to be removed is present in dir\n", vnode);
}
rootfs_delete_vnode(fs, v, false);
rootfs_delete_vnode(fs, vnode, false);
err = 0;
if (!r)
if (!reenter)
mutex_unlock(&fs->lock);
return err;
return 0;
}
@@ -503,54 +516,51 @@ rootfs_create_dir(fs_cookie _fs, fs_vnode _dir, const char *name, int perms, vno
{
struct rootfs *fs = _fs;
struct rootfs_vnode *dir = _dir;
struct rootfs_vnode *new_vnode;
struct rootfs_stream *s;
int err = 0;
struct rootfs_vnode *vnode;
bool created_vnode = false;
int status = 0;
TRACE(("rootfs_create: dir 0x%x, name = '%s', stream_type = %d\n", dir, name, st));
TRACE(("rootfs_create_dir: dir 0x%x, name = '%s', stream_type = %d\n", dir, name, st));
mutex_lock(&fs->lock);
new_vnode = rootfs_find_in_dir(dir, name);
if (new_vnode == NULL) {
dprintf("rootfs_create: creating new vnode\n");
new_vnode = rootfs_create_vnode(fs);
if (new_vnode == NULL) {
err = ENOMEM;
goto err;
}
created_vnode = true;
new_vnode->name = kstrdup(name);
if (new_vnode->name == NULL) {
err = ENOMEM;
goto err1;
}
new_vnode->parent = dir;
rootfs_insert_in_dir(dir, new_vnode);
hash_insert(fs->vnode_list_hash, new_vnode);
s = &new_vnode->stream;
} else {
// we found the vnode
err = ERR_VFS_ALREADY_EXISTS;
vnode = rootfs_find_in_dir(dir, name);
if (vnode != NULL) {
status = B_FILE_EXISTS;
goto err;
}
new_vnode->stream.dir.dir_head = NULL;
new_vnode->stream.dir.jar_head = NULL;
dprintf("rootfs_create: creating new vnode\n");
vnode = rootfs_create_vnode(fs);
if (vnode == NULL) {
status = B_NO_MEMORY;
goto err;
}
created_vnode = true;
vnode->name = kstrdup(name);
if (vnode->name == NULL) {
status = B_NO_MEMORY;
goto err1;
}
vnode->stream.type = STREAM_TYPE_DIR;
vnode->parent = dir;
rootfs_insert_in_dir(dir, vnode);
hash_insert(fs->vnode_list_hash, vnode);
vnode->stream.dir.dir_head = NULL;
vnode->stream.dir.jar_head = NULL;
mutex_unlock(&fs->lock);
return 0;
err1:
if (created_vnode)
rootfs_delete_vnode(fs, new_vnode, false);
rootfs_delete_vnode(fs, vnode, false);
err:
mutex_unlock(&fs->lock);
return err;
return status;
}
@@ -563,9 +573,12 @@ rootfs_open_dir(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie)
TRACE(("rootfs_open: vnode 0x%x\n", vnode));
if (vnode->stream.type != STREAM_TYPE_DIR)
return B_BAD_VALUE;
cookie = kmalloc(sizeof(struct rootfs_cookie));
if (cookie == NULL)
return ENOMEM;
return B_NO_MEMORY;
mutex_lock(&fs->lock);
@@ -593,6 +606,7 @@ rootfs_read_dir(fs_cookie _fs, fs_vnode _vnode, file_cookie _cookie, struct dire
mutex_lock(&fs->lock);
if (cookie->ptr == NULL) {
// we're at the end of the directory
*_num = 0;
status = B_OK;
goto err;
@@ -666,44 +680,119 @@ rootfs_write_page(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t pos)
}
static int
rootfs_read_link(fs_cookie _fs, fs_vnode _link, char *buffer, size_t bufferSize)
{
struct rootfs *fs = _fs;
struct rootfs_vnode *link = _link;
if (link->stream.type != STREAM_TYPE_SYMLINK)
return B_BAD_VALUE;
if (bufferSize < link->stream.symlink.length)
return B_NAME_TOO_LONG;
memcpy(buffer, link->stream.symlink.path, link->stream.symlink.length + 1);
return link->stream.symlink.length;
}
static int
rootfs_symlink(fs_cookie _fs, fs_vnode _dir, const char *name, const char *path)
{
struct rootfs *fs = _fs;
struct rootfs_vnode *dir = _dir;
struct rootfs_vnode *vnode;
bool created_vnode = false;
int status = 0;
TRACE(("rootfs_symlink: dir 0x%x, name = '%s', path = %s\n", dir, name, path));
mutex_lock(&fs->lock);
vnode = rootfs_find_in_dir(dir, name);
if (vnode != NULL) {
status = B_FILE_EXISTS;
goto err;
}
dprintf("rootfs_create: creating new symlink\n");
vnode = rootfs_create_vnode(fs);
if (vnode == NULL) {
status = B_NO_MEMORY;
goto err;
}
created_vnode = true;
vnode->name = kstrdup(name);
if (vnode->name == NULL) {
status = B_NO_MEMORY;
goto err1;
}
vnode->stream.type = STREAM_TYPE_SYMLINK;
vnode->parent = dir;
rootfs_insert_in_dir(dir, vnode);
hash_insert(fs->vnode_list_hash, vnode);
vnode->stream.symlink.path = kstrdup(path);
if (vnode->stream.symlink.path == NULL) {
status = ENOMEM;
goto err1;
}
vnode->stream.symlink.length = strlen(path);
mutex_unlock(&fs->lock);
return 0;
err1:
if (created_vnode)
rootfs_delete_vnode(fs, vnode, false);
err:
mutex_unlock(&fs->lock);
return status;
}
static int
rootfs_unlink(fs_cookie _fs, fs_vnode _dir, const char *name)
{
struct rootfs *fs = _fs;
struct rootfs_vnode *dir = _dir;
struct rootfs_vnode *v;
int err;
struct rootfs_vnode *vnode;
int status;
TRACE(("rootfs_unlink: dir 0x%x (0x%x 0x%x), name '%s'\n", dir, dir->id, name));
mutex_lock(&fs->lock);
v = rootfs_find_in_dir(dir, name);
if(!v) {
err = ERR_VFS_PATH_NOT_FOUND;
vnode = rootfs_find_in_dir(dir, name);
if (!vnode) {
status = B_ENTRY_NOT_FOUND;
goto err;
}
// do some checking to see if we can delete it
if(!rootfs_is_dir_empty(v)) {
err = ERR_VFS_DIR_NOT_EMPTY;
// if the node is a directory, only delete it if it's empty
if (vnode->stream.type == STREAM_TYPE_DIR && !rootfs_is_dir_empty(vnode)) {
status = B_DIRECTORY_NOT_EMPTY;
goto err;
}
rootfs_remove_from_dir(dir, v);
rootfs_remove_from_dir(dir, vnode);
// schedule this vnode to be removed when it's ref goes to zero
vfs_remove_vnode(fs->id, v->id);
vfs_remove_vnode(fs->id, vnode->id);
err = 0;
status = 0;
err:
mutex_unlock(&fs->lock);
return err;
return status;
}
static int rootfs_rename(fs_cookie _fs, fs_vnode _olddir, const char *oldname, fs_vnode _newdir, const char *newname)
static int
rootfs_rename(fs_cookie _fs, fs_vnode _olddir, const char *oldname, fs_vnode _newdir, const char *newname)
{
struct rootfs *fs = _fs;
struct rootfs_vnode *olddir = _olddir;
@@ -717,23 +806,23 @@ static int rootfs_rename(fs_cookie _fs, fs_vnode _olddir, const char *oldname, f
mutex_lock(&fs->lock);
v1 = rootfs_find_in_dir(olddir, oldname);
if(!v1) {
if (!v1) {
err = ERR_VFS_PATH_NOT_FOUND;
goto err;
}
v2 = rootfs_find_in_dir(newdir, newname);
if(olddir == newdir) {
if (olddir == newdir) {
// rename to a different name in the same dir
if(v2) {
if (v2) {
// target node exists
err = ERR_VFS_ALREADY_EXISTS;
goto err;
}
// change the name on this node
if(strlen(oldname) >= strlen(newname)) {
if (strlen(oldname) >= strlen(newname)) {
// reuse the old name buffer
strcpy(v1->name, newname);
} else {
@@ -773,25 +862,25 @@ err:
return err;
}
static int rootfs_read_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat)
static int
rootfs_read_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat)
{
struct rootfs_vnode *v = _v;
struct rootfs_vnode *vnode = _v;
TRACE(("rootfs_rstat: vnode 0x%x (0x%x 0x%x), stat 0x%x\n", v, v->id, stat));
//dprintf("rootfs_rstat\n");
TRACE(("rootfs_rstat: vnode 0x%x (0x%x 0x%x), stat 0x%x\n", vnode, vnode->id, stat));
// stream exists, but we know to return size 0, since we can only hold directories
stat->st_ino = v->id;
stat->st_ino = vnode->id;
stat->st_size = 0;
stat->st_mode = (S_IFDIR | DEFFILEMODE);
stat->st_mode = vnode->stream.type | DEFFILEMODE;
return 0;
}
static int
rootfs_write_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat, int stat_mask)
rootfs_write_stat(fs_cookie _fs, fs_vnode _v, const struct stat *stat, int stat_mask)
{
#if ROOTFS_TRACE
struct rootfs *fs = _fs;
@@ -829,6 +918,8 @@ static struct fs_calls rootfs_calls = {
&rootfs_ioctl,
&rootfs_fsync,
&rootfs_read_link,
&rootfs_symlink,
&rootfs_unlink,
&rootfs_rename,
+258 -119
View File
@@ -527,31 +527,42 @@ find_fs(const char *fs_name)
static status_t
entry_ref_to_vnode(fs_id fsID,vnode_id directoryID,const char *name,struct vnode **_vnode)
{
struct vnode *directory;
struct vnode *directory, *vnode;
vnode_id id;
int status;
int type;
status = get_vnode(fsID,directoryID,&directory,false);
if (status < 0)
return status;
status = FS_CALL(directory,fs_lookup)(directory->mount->cookie,directory->private_node,name,&id);
dec_vnode_ref_count(directory, false);
status = FS_CALL(directory,fs_lookup)(directory->mount->cookie,
directory->private_node, name, &id, &type);
put_vnode(directory);
if (status < 0)
return status;
return get_vnode(fsID,id,_vnode,false);
mutex_lock(&vfs_vnode_mutex);
vnode = lookup_vnode(fsID, id);
mutex_unlock(&vfs_vnode_mutex);
if (vnode == NULL) {
// fs_lookup() should have left the vnode referenced, so chances
// are good that this will never happen
panic("entry_ref_to_vnode: could not lookup vnode (fsid 0x%x vnid 0x%Lx)\n", fsID, id);
return B_ENTRY_NOT_FOUND;
}
*_vnode = vnode;
return B_OK;
}
static int
path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
{
char *nextPath;
struct vnode *vnode;
struct vnode *nextVnode;
vnode_id vnid;
int err = 0;
if (!path)
@@ -573,6 +584,11 @@ path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
}
for (;;) {
struct vnode *nextVnode;
vnode_id vnodeID;
char *nextPath;
int type;
PRINT(("path_to_vnode: top of loop. p = %p, *p = %c, p = '%s'\n", path, *path, path));
// done?
@@ -581,7 +597,8 @@ path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
break;
}
// walk to find the next component
// walk to find the next path component ("path" will point to a single
// path component), and filter out multiple slashes
for (nextPath = path + 1;*nextPath != '\0' && *nextPath != '/';nextPath++);
if (*nextPath == '/') {
@@ -602,30 +619,35 @@ path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
}
}
// tell the filesystem to parse this path
err = FS_CALL(vnode,fs_lookup)(vnode->mount->cookie, vnode->private_node, path, &vnid);
// tell the filesystem to get the vnode of this path component
err = FS_CALL(vnode,fs_lookup)(vnode->mount->cookie, vnode->private_node, path, &vnodeID, &type);
if (err < 0) {
dec_vnode_ref_count(vnode, false);
put_vnode(vnode);
goto out;
}
// lookup the vnode, the call to fs_lookup should have caused a get_vnode to be called
// from inside the filesystem, thus the vnode would have to be in the list and it's
// ref count incremented at this point
mutex_lock(&vfs_vnode_mutex);
nextVnode = lookup_vnode(vnode->fs_id, vnid);
mutex_unlock(&vfs_vnode_mutex);
if (S_ISLNK(type)) {
// ToDo: we have to resolve the link here
nextVnode = NULL;
} else {
// lookup the vnode, the call to fs_lookup should have caused a get_vnode to be called
// from inside the filesystem, thus the vnode would have to be in the list and it's
// ref count incremented at this point
mutex_lock(&vfs_vnode_mutex);
nextVnode = lookup_vnode(vnode->fs_id, vnodeID);
mutex_unlock(&vfs_vnode_mutex);
}
if (!nextVnode) {
// pretty screwed up here
panic("path_to_vnode: could not lookup vnode (fsid 0x%x vnid 0x%Lx)\n", vnode->fs_id, vnid);
panic("path_to_vnode: could not lookup vnode (fsid 0x%x vnid 0x%Lx)\n", vnode->fs_id, vnodeID);
err = ERR_VFS_PATH_NOT_FOUND;
dec_vnode_ref_count(vnode, false);
put_vnode(vnode);
goto out;
}
// decrease the ref count on the old dir we just looked up into
dec_vnode_ref_count(vnode, false);
put_vnode(vnode);
path = nextPath;
vnode = nextVnode;
@@ -634,7 +656,7 @@ path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
if (vnode->covered_by) {
nextVnode = vnode->covered_by;
inc_vnode_ref_count(nextVnode);
dec_vnode_ref_count(vnode, false);
put_vnode(vnode);
vnode = nextVnode;
}
}
@@ -662,11 +684,12 @@ path_to_dir_vnode(char *path, struct vnode **_vnode, char *filename, bool kernel
strcpy(path, ".");
} else {
// replace the filename portion of the path with a '.'
strcpy(filename, p+1);
strcpy(filename, ++p);
if (p[1] != '\0'){
p[1] = '.';
p[2] = '\0';
// ToDo: this could write behind the array limit
if (p[0] != '\0'){
p[0] = '.';
p[1] = '\0';
}
}
return path_to_vnode(path, _vnode, kernel);
@@ -712,10 +735,24 @@ dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize)
// the name buffer is also used for fs_read_dir()
char nameBuffer[sizeof(struct dirent) + B_FILE_NAME_LENGTH];
char *name = &((struct dirent *)nameBuffer)->d_name[0];
vnode_id parentId, id;
struct vnode *parentVnode;
vnode_id parentID, id;
int type;
// lookup the parent vnode
status = FS_CALL(vnode,fs_lookup)(vnode->mount->cookie,vnode->private_node,"..",&parentId);
status = FS_CALL(vnode,fs_lookup)(vnode->mount->cookie,vnode->private_node,"..",&parentID,&type);
if (status < B_OK)
goto out;
mutex_lock(&vfs_vnode_mutex);
parentVnode = lookup_vnode(vnode->fs_id, parentID);
mutex_unlock(&vfs_vnode_mutex);
if (parentVnode == NULL) {
panic("dir_vnode_to_path: could not lookup vnode (fsid 0x%x vnid 0x%Lx)\n", vnode->fs_id, parentID);
status = B_ENTRY_NOT_FOUND;
goto out;
}
// Does the file system support getting the name of a vnode?
// If so, get it here...
@@ -728,27 +765,25 @@ dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize)
// release the current vnode, we only need its parent from now on
put_vnode(vnode);
vnode = parentVnode;
if (status < B_OK)
return status;
goto out;
// 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;
if (parentId == vnode->id) {
// we have reached the root level directory of this file system
break;
if (maxLevel-- < 0) {
status = ELOOP;
goto out;
}
// Get the parent vnode. The parent of the vnode may have already
// changed, though, which would result in an incorrect path
status = get_vnode(vnode->mount->id,parentId,&vnode,0);
if (status < B_OK)
return status;
if (parentID == id) {
// we have reached the root level directory of this file system
// which means we have constructed the full path
break;
}
if (!FS_CALL(vnode,fs_get_vnode_name)) {
// If we don't got the vnode's name yet, we have to search for it
@@ -771,10 +806,8 @@ dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize)
FS_CALL(vnode,fs_close_dir)(vnode->mount->cookie,vnode->private_node,cookie);
}
if (status < B_OK) {
put_vnode(vnode);
return status;
}
if (status < B_OK)
goto out;
}
// add the name infront of the current path
@@ -782,8 +815,8 @@ dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize)
length = strlen(name);
insert -= length;
if (insert <= 0) {
put_vnode(vnode);
return ENOBUFS;
status = ENOBUFS;
goto out;
}
memcpy(path + insert, name, length);
path[--insert] = '/';
@@ -791,13 +824,54 @@ dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize)
// add the mountpoint
length = strlen(vnode->mount->mount_point);
if (bufferSize - (sizeof(path) - insert) < length + 1)
return ENOBUFS;
if (bufferSize - (sizeof(path) - insert) < length + 1) {
status = ENOBUFS;
goto out;
}
memcpy(buffer, vnode->mount->mount_point, length);
if (insert != sizeof(path))
memcpy(buffer + length, path + insert, sizeof(path) - insert);
out:
put_vnode(vnode);
return status;
}
static status_t
check_path(char *to)
{
int32 length = 0;
// check length of every path component
while (*to) {
char *begin;
if (*to == '/')
to++, length++;
begin = to;
while (*to != '/' && *to)
to++, length++;
if (to - begin > B_FILE_NAME_LENGTH)
return B_NAME_TOO_LONG;
}
if (length == 0)
return B_ENTRY_NOT_FOUND;
// complete path if there is a slash at the end
if (*(to - 1) == '/') {
if (length > SYS_MAX_PATH_LEN - 2)
return B_NAME_TOO_LONG;
to[0] = '.';
to[1] = '\0';
}
return B_OK;
}
@@ -810,14 +884,13 @@ int
vfs_get_vnode(fs_id fsID, vnode_id vnodeID, fs_vnode *_fsNode)
{
struct vnode *vnode;
int err;
err = get_vnode(fsID, vnodeID, &vnode, true);
if (err < 0)
return err;
int status = get_vnode(fsID, vnodeID, &vnode, true);
if (status < 0)
return status;
*_fsNode = vnode->private_node;
return B_NO_ERROR;
return B_OK;
}
@@ -833,7 +906,7 @@ vfs_put_vnode(fs_id fsID, vnode_id vnodeID)
if (vnode)
dec_vnode_ref_count(vnode, true);
return B_NO_ERROR;
return B_OK;
}
@@ -1868,6 +1941,29 @@ common_sync(int fd, bool kernel)
}
static int
common_symlink(char *path, const char *toPath, bool kernel)
{
// path validity checks have to be in the calling function!
char name[B_FILE_NAME_LENGTH];
struct vnode *vnode;
int status;
status = path_to_dir_vnode(path, &vnode, name, kernel);
if (status < B_OK)
return status;
if (FS_CALL(vnode,fs_symlink) != NULL)
status = FS_CALL(vnode,fs_symlink)(vnode->mount->cookie, vnode->private_node, name, toPath);
else
status = EROFS;
put_vnode(vnode);
return status;
}
static int
common_unlink(char *path, bool kernel)
{
@@ -1928,19 +2024,19 @@ err:
static int
common_write_stat(char *path, struct stat *stat, int stat_mask, bool kernel)
common_write_stat(char *path, const struct stat *stat, int statMask, bool kernel)
{
struct vnode *vnode;
int status;
FUNCTION(("vfs_write_stat: path '%s', stat 0x%p, stat_mask %d, kernel %d\n", path, stat, stat_mask, kernel));
FUNCTION(("vfs_write_stat: path '%s', stat 0x%p, stat_mask %d, kernel %d\n", path, stat, statMask, kernel));
status = path_to_vnode(path, &vnode, kernel);
if (status < 0)
return status;
if (FS_CALL(vnode,fs_write_stat))
status = FS_CALL(vnode,fs_write_stat)(vnode->mount->cookie, vnode->private_node, stat, stat_mask);
status = FS_CALL(vnode,fs_write_stat)(vnode->mount->cookie, vnode->private_node, stat, statMask);
else
status = EROFS;
@@ -2070,29 +2166,27 @@ err:
static int
fs_unmount(char *path, bool kernel)
{
struct vnode *v;
struct fs_mount *mount;
struct vnode *vnode;
int err;
FUNCTION(("vfs_unmount: entry. path = '%s', kernel %d\n", path, kernel));
err = path_to_vnode(path, &v, kernel);
if (err < 0) {
err = ERR_VFS_PATH_NOT_FOUND;
goto err;
}
err = path_to_vnode(path, &vnode, kernel);
if (err < 0)
return ERR_VFS_PATH_NOT_FOUND;
mutex_lock(&vfs_mount_op_mutex);
mount = find_mount(v->fs_id);
mount = find_mount(vnode->fs_id);
if (!mount)
panic("vfs_unmount: fsid_to_mount failed on root vnode @%p of mount\n", v);
panic("vfs_unmount: fsid_to_mount failed on root vnode @%p of mount\n", vnode);
if (mount->root_vnode != v) {
if (mount->root_vnode != vnode) {
// not mountpoint
dec_vnode_ref_count(v, false);
dec_vnode_ref_count(vnode, false);
err = ERR_VFS_NOT_MOUNTPOINT;
goto err1;
goto err;
}
/* grab the vnode master mutex to keep someone from creating a vnode
@@ -2102,24 +2196,24 @@ fs_unmount(char *path, bool kernel)
/* simulate the root vnode having it's refcount decremented */
mount->root_vnode->ref_count -= 2;
/* cycle through the list of vnodes associated with this mount and
make sure all of them are not busy or have refs on them */
err = 0;
for (v = mount->vnodes_head; v; v = v->mount_next) {
if (v->busy || v->ref_count != 0) {
// cycle through the list of vnodes associated with this mount and
// make sure all of them are not busy or have refs on them
for (vnode = mount->vnodes_head; vnode != NULL; vnode = vnode->mount_next) {
if (vnode->busy || vnode->ref_count != 0) {
mount->root_vnode->ref_count += 2;
mutex_unlock(&vfs_vnode_mutex);
dec_vnode_ref_count(mount->root_vnode, false);
err = EBUSY;
goto err1;
goto err;
}
}
/* we can safely continue, mark all of the vnodes busy and this mount
structure in unmounting state */
for (v = mount->vnodes_head; v; v = v->mount_next)
if (v != mount->root_vnode)
v->busy = true;
for (vnode = mount->vnodes_head; vnode; vnode = vnode->mount_next)
if (vnode != mount->root_vnode)
vnode->busy = true;
mount->unmounting = true;
mutex_unlock(&vfs_vnode_mutex);
@@ -2148,9 +2242,8 @@ fs_unmount(char *path, bool kernel)
return 0;
err1:
mutex_unlock(&vfs_mount_op_mutex);
err:
mutex_unlock(&vfs_mount_op_mutex);
return err;
}
@@ -2210,7 +2303,7 @@ error:
static int
fs_write_info(dev_t device, struct fs_info *info, int mask)
fs_write_info(dev_t device, const struct fs_info *info, int mask)
{
struct fs_mount *mount;
int status;
@@ -2264,7 +2357,7 @@ set_cwd(char *path, bool kernel)
struct stat stat;
int rc;
FUNCTION(("vfs_set_cwd: path=\'%s\'\n", path));
FUNCTION(("vfs_set_cwd: path = \'%s\'\n", path));
// Get vnode for passed path, and bail if it failed
rc = path_to_vnode(path, &vnode, kernel);
@@ -2309,7 +2402,7 @@ err:
int
sys_mount(const char *path, const char *device, const char *fs_name, void *args)
{
char buf[SYS_MAX_PATH_LEN+1];
char buf[SYS_MAX_PATH_LEN + 1];
strncpy(buf, path, SYS_MAX_PATH_LEN);
buf[SYS_MAX_PATH_LEN] = 0;
@@ -2321,7 +2414,7 @@ sys_mount(const char *path, const char *device, const char *fs_name, void *args)
int
sys_unmount(const char *path)
{
char buf[SYS_MAX_PATH_LEN+1];
char buf[SYS_MAX_PATH_LEN + 1];
strncpy(buf, path, SYS_MAX_PATH_LEN);
buf[SYS_MAX_PATH_LEN] = 0;
@@ -2415,7 +2508,7 @@ sys_create_entry_ref(dev_t device, ino_t inode, const char *name, int omode, int
int
sys_create(const char *path, int omode, int perms)
{
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';
@@ -2439,7 +2532,7 @@ sys_create_dir_entry_ref(dev_t device, ino_t inode, const char *name, int perms)
int
sys_create_dir(const char *path, int perms)
{
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;
@@ -2448,10 +2541,31 @@ sys_create_dir(const char *path, int perms)
}
int
sys_symlink(const char *userPath, const char *userToPath)
{
char path[SYS_MAX_PATH_LEN + 1];
char toPath[SYS_MAX_PATH_LEN + 1];
int status;
strncpy(path, userPath, SYS_MAX_PATH_LEN);
path[SYS_MAX_PATH_LEN] = '\0';
strncpy(toPath, userToPath, SYS_MAX_PATH_LEN);
toPath[SYS_MAX_PATH_LEN] = '\0';
status = check_path(toPath);
if (status < B_OK)
return status;
return common_symlink(path, toPath, true);
}
int
sys_unlink(const char *path)
{
char buf[SYS_MAX_PATH_LEN+1];
char buf[SYS_MAX_PATH_LEN + 1];
strncpy(buf, path, SYS_MAX_PATH_LEN);
buf[SYS_MAX_PATH_LEN] = 0;
@@ -2463,8 +2577,8 @@ sys_unlink(const char *path)
int
sys_rename(const char *oldpath, const char *newpath)
{
char buf1[SYS_MAX_PATH_LEN+1];
char buf2[SYS_MAX_PATH_LEN+1];
char buf1[SYS_MAX_PATH_LEN + 1];
char buf2[SYS_MAX_PATH_LEN + 1];
strncpy(buf1, oldpath, SYS_MAX_PATH_LEN);
buf1[SYS_MAX_PATH_LEN] = 0;
@@ -2554,20 +2668,16 @@ sys_setcwd(const char *_path)
int
user_mount(const char *upath, const char *udevice, const char *ufs_name, void *args)
{
char path[SYS_MAX_PATH_LEN+1];
char fs_name[SYS_MAX_OS_NAME_LEN+1];
char device[SYS_MAX_PATH_LEN+1];
char path[SYS_MAX_PATH_LEN + 1];
char fs_name[SYS_MAX_OS_NAME_LEN + 1];
char device[SYS_MAX_PATH_LEN + 1];
int rc;
if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP)
if (!CHECK_USER_ADDRESS(upath)
|| !CHECK_USER_ADDRESS(ufs_name)
|| !CHECK_USER_ADDRESS(udevice))
return B_BAD_ADDRESS;
if ((addr)ufs_name >= KERNEL_BASE && (addr)ufs_name <= KERNEL_TOP)
return ERR_VM_BAD_USER_MEMORY;
if (udevice != NULL && (addr)udevice >= KERNEL_BASE && (addr)udevice <= KERNEL_TOP)
return ERR_VM_BAD_USER_MEMORY;
rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN);
if (rc < 0)
return rc;
@@ -2593,7 +2703,7 @@ user_mount(const char *upath, const char *udevice, const char *ufs_name, void *a
int
user_unmount(const char *upath)
{
char path[SYS_MAX_PATH_LEN+1];
char path[SYS_MAX_PATH_LEN + 1];
int rc;
rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN);
@@ -2633,16 +2743,16 @@ user_open_entry_ref(dev_t device, ino_t inode, const char *uname, int omode)
int
user_open(const char *upath, int omode)
{
char path[SYS_MAX_PATH_LEN];
char path[SYS_MAX_PATH_LEN + 1];
int rc;
if (!CHECK_USER_ADDRESS(upath))
return ERR_VM_BAD_USER_MEMORY;
rc = user_strncpy(path, upath, sizeof(path) - 1);
rc = user_strncpy(path, upath, sizeof(path));
if (rc < 0)
return rc;
path[sizeof(path) - 1] = 0;
path[sizeof(path)] = 0;
return file_open(path, omode, false);
}
@@ -2676,16 +2786,16 @@ user_open_dir_entry_ref(dev_t device, ino_t inode, const char *uname)
int
user_open_dir(const char *upath)
{
char path[SYS_MAX_PATH_LEN];
char path[SYS_MAX_PATH_LEN + 1];
int status;
if (!CHECK_USER_ADDRESS(upath))
return ERR_VM_BAD_USER_MEMORY;
status = user_strncpy(path, upath, sizeof(path) - 1);
status = user_strncpy(path, upath, sizeof(path));
if (status < 0)
return status;
path[sizeof(path) - 1] = 0;
path[sizeof(path)] = 0;
return dir_open(path, false);
}
@@ -2719,16 +2829,16 @@ user_create_entry_ref(dev_t device, ino_t inode, const char *uname, int omode, i
int
user_create(const char *upath, int omode, int perms)
{
char path[SYS_MAX_PATH_LEN];
int rc;
char path[SYS_MAX_PATH_LEN + 1];
int status;
if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP)
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, SYS_MAX_PATH_LEN);
if (status < 0)
return status;
path[SYS_MAX_PATH_LEN] = '\0';
return file_create(path, omode, perms, false);
}
@@ -2755,25 +2865,54 @@ user_create_dir_entry_ref(dev_t device, ino_t inode, const char *uname, int perm
int
user_create_dir(const char *upath, int perms)
{
char path[SYS_MAX_PATH_LEN];
int rc;
char path[SYS_MAX_PATH_LEN + 1];
int status;
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, SYS_MAX_PATH_LEN);
if (status < 0)
return status;
path[SYS_MAX_PATH_LEN] = '\0';
return dir_create(path, perms, false);
}
int
user_symlink(const char *userPath, const char *userToPath)
{
char path[SYS_MAX_PATH_LEN + 1];
char toPath[SYS_MAX_PATH_LEN + 1];
int status;
if (!CHECK_USER_ADDRESS(userPath)
|| !CHECK_USER_ADDRESS(userToPath))
return B_BAD_ADDRESS;
status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN);
if (status < 0)
return status;
path[SYS_MAX_PATH_LEN] = '\0';
status = user_strncpy(toPath, userToPath, SYS_MAX_PATH_LEN);
if (status < 0)
return status;
toPath[SYS_MAX_PATH_LEN] = '\0';
status = check_path(toPath);
if (status < B_OK)
return status;
return common_symlink(path, toPath, false);
}
int
user_unlink(const char *upath)
{
char path[SYS_MAX_PATH_LEN+1];
char path[SYS_MAX_PATH_LEN + 1];
int rc;
if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP)
@@ -2791,8 +2930,8 @@ user_unlink(const char *upath)
int
user_rename(const char *uoldpath, const char *unewpath)
{
char oldpath[SYS_MAX_PATH_LEN+1];
char newpath[SYS_MAX_PATH_LEN+1];
char oldpath[SYS_MAX_PATH_LEN + 1];
char newpath[SYS_MAX_PATH_LEN + 1];
int rc;
if ((addr)uoldpath >= KERNEL_BASE && (addr)uoldpath <= KERNEL_TOP)