path_to_vnode() should now be able to resolve symbolic links (not tested
yet) - up to 16 symlinks are allowed in one path (following BeOS' restriction). git-svn-id: file:///srv/svn/repos/haiku/trunk/current@518 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
5e949b7dfc
commit
847248db20
@ -53,6 +53,8 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <fs_info.h>
|
#include <fs_info.h>
|
||||||
|
|
||||||
|
#define MAX_SYM_LINKS 16
|
||||||
|
|
||||||
// Passed in buffers from user-space shouldn't be in the kernel
|
// Passed in buffers from user-space shouldn't be in the kernel
|
||||||
#define CHECK_USER_ADDRESS(x) \
|
#define CHECK_USER_ADDRESS(x) \
|
||||||
((addr)(x) < KERNEL_BASE || (addr)(x) > KERNEL_TOP)
|
((addr)(x) < KERNEL_BASE || (addr)(x) > KERNEL_TOP)
|
||||||
@ -560,30 +562,14 @@ entry_ref_to_vnode(fs_id fsID,vnode_id directoryID,const char *name,struct vnode
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
|
vnode_path_to_vnode(struct vnode *vnode, char *path, struct vnode **_vnode, int count)
|
||||||
{
|
{
|
||||||
struct vnode *vnode;
|
int status = 0;
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
if (!path)
|
if (!path)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
// figure out if we need to start at root or at cwd
|
while (true) {
|
||||||
if (*path == '/') {
|
|
||||||
while (*++path == '/')
|
|
||||||
;
|
|
||||||
vnode = root_vnode;
|
|
||||||
inc_vnode_ref_count(vnode);
|
|
||||||
} else {
|
|
||||||
struct io_context *context = get_current_io_context(kernel);
|
|
||||||
|
|
||||||
mutex_lock(&context->io_mutex);
|
|
||||||
vnode = context->cwd;
|
|
||||||
inc_vnode_ref_count(vnode);
|
|
||||||
mutex_unlock(&context->io_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
struct vnode *nextVnode;
|
struct vnode *nextVnode;
|
||||||
vnode_id vnodeID;
|
vnode_id vnodeID;
|
||||||
char *nextPath;
|
char *nextPath;
|
||||||
@ -592,10 +578,8 @@ path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
|
|||||||
PRINT(("path_to_vnode: top of loop. p = %p, *p = %c, p = '%s'\n", path, *path, path));
|
PRINT(("path_to_vnode: top of loop. p = %p, *p = %c, p = '%s'\n", path, *path, path));
|
||||||
|
|
||||||
// done?
|
// done?
|
||||||
if (*path == '\0') {
|
if (*path == '\0')
|
||||||
err = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
// walk to find the next path component ("path" will point to a single
|
// walk to find the next path component ("path" will point to a single
|
||||||
// path component), and filter out multiple slashes
|
// path component), and filter out multiple slashes
|
||||||
@ -620,30 +604,24 @@ path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tell the filesystem to get the vnode of this path component
|
// 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);
|
status = FS_CALL(vnode,fs_lookup)(vnode->mount->cookie, vnode->private_node, path, &vnodeID, &type);
|
||||||
if (err < 0) {
|
if (status < 0) {
|
||||||
put_vnode(vnode);
|
put_vnode(vnode);
|
||||||
goto out;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// 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
|
// from inside the filesystem, thus the vnode would have to be in the list and it's
|
||||||
// ref count incremented at this point
|
// ref count incremented at this point
|
||||||
mutex_lock(&vfs_vnode_mutex);
|
mutex_lock(&vfs_vnode_mutex);
|
||||||
nextVnode = lookup_vnode(vnode->fs_id, vnodeID);
|
nextVnode = lookup_vnode(vnode->fs_id, vnodeID);
|
||||||
mutex_unlock(&vfs_vnode_mutex);
|
mutex_unlock(&vfs_vnode_mutex);
|
||||||
}
|
|
||||||
|
|
||||||
if (!nextVnode) {
|
if (!nextVnode) {
|
||||||
// pretty screwed up here
|
// pretty screwed up here
|
||||||
panic("path_to_vnode: could not lookup vnode (fsid 0x%x vnid 0x%Lx)\n", vnode->fs_id, vnodeID);
|
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;
|
|
||||||
put_vnode(vnode);
|
put_vnode(vnode);
|
||||||
goto out;
|
return ERR_VFS_PATH_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
// decrease the ref count on the old dir we just looked up into
|
// decrease the ref count on the old dir we just looked up into
|
||||||
@ -652,6 +630,39 @@ path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
|
|||||||
path = nextPath;
|
path = nextPath;
|
||||||
vnode = nextVnode;
|
vnode = nextVnode;
|
||||||
|
|
||||||
|
// If the new node is a symbolic link, resolve it
|
||||||
|
if (S_ISLNK(type)) {
|
||||||
|
char *buffer;
|
||||||
|
|
||||||
|
if (count + 1 > MAX_SYM_LINKS) {
|
||||||
|
put_vnode(vnode);
|
||||||
|
return B_LINK_LIMIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = kmalloc(SYS_MAX_PATH_LEN);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
put_vnode(vnode);
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = FS_CALL(vnode,fs_read_link)(vnode->mount->cookie, vnode->private_node, buffer, SYS_MAX_PATH_LEN);
|
||||||
|
if (status < B_OK) {
|
||||||
|
put_vnode(vnode);
|
||||||
|
kfree(buffer);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = vnode_path_to_vnode(vnode, buffer, &nextVnode, count + 1);
|
||||||
|
|
||||||
|
put_vnode(vnode);
|
||||||
|
kfree(buffer);
|
||||||
|
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
vnode = nextVnode;
|
||||||
|
}
|
||||||
|
|
||||||
// see if we hit a mount point
|
// see if we hit a mount point
|
||||||
if (vnode->covered_by) {
|
if (vnode->covered_by) {
|
||||||
nextVnode = vnode->covered_by;
|
nextVnode = vnode->covered_by;
|
||||||
@ -662,9 +673,36 @@ path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
*_vnode = vnode;
|
*_vnode = vnode;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
|
||||||
return err;
|
static int
|
||||||
|
path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
|
||||||
|
{
|
||||||
|
struct vnode *start;
|
||||||
|
int linkCount = 0;
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
// figure out if we need to start at root or at cwd
|
||||||
|
if (*path == '/') {
|
||||||
|
while (*++path == '/')
|
||||||
|
;
|
||||||
|
start = root_vnode;
|
||||||
|
inc_vnode_ref_count(start);
|
||||||
|
} else {
|
||||||
|
struct io_context *context = get_current_io_context(kernel);
|
||||||
|
|
||||||
|
mutex_lock(&context->io_mutex);
|
||||||
|
start = context->cwd;
|
||||||
|
inc_vnode_ref_count(start);
|
||||||
|
mutex_unlock(&context->io_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vnode_path_to_vnode(start, path, _vnode, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1756,7 +1794,7 @@ dir_create_entry_ref(fs_id fsID, vnode_id parentID, const char *name, int perms,
|
|||||||
vnode_id newID;
|
vnode_id newID;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
FUNCTION(("dir_create_entry_ref(dev = %ld, ino = %Ld, name = '%s', perms = %d)\n", fdID, parentID, name, perms));
|
FUNCTION(("dir_create_entry_ref(dev = %d, ino = %Ld, name = '%s', perms = %d)\n", fsID, parentID, name, perms));
|
||||||
|
|
||||||
status = get_vnode(fsID, parentID, &vnode, kernel);
|
status = get_vnode(fsID, parentID, &vnode, kernel);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
|
Loading…
Reference in New Issue
Block a user