Removed the big hack called vnode_to_path(), and replaced it with the real
thing dir_vnode_to_path(). But beware, it's not yet working correctly - will fix it later, I have no time anymore. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@315 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -522,6 +522,18 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
bootfs_get_vnode_name(fs_cookie _fs, fs_vnode _vnode, char *buffer, size_t bufferSize)
|
||||||
|
{
|
||||||
|
struct bootfs_vnode *vnode = (struct bootfs_vnode *)_vnode;
|
||||||
|
|
||||||
|
TRACE(("devfs_get_vnode_name: vnode = %p\n",vnode));
|
||||||
|
|
||||||
|
strlcpy(buffer,vnode->name,bufferSize);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bootfs_getvnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r)
|
bootfs_getvnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r)
|
||||||
{
|
{
|
||||||
@@ -998,6 +1010,7 @@ static struct fs_calls bootfs_calls = {
|
|||||||
&bootfs_sync,
|
&bootfs_sync,
|
||||||
|
|
||||||
&bootfs_lookup,
|
&bootfs_lookup,
|
||||||
|
&bootfs_get_vnode_name,
|
||||||
|
|
||||||
&bootfs_getvnode,
|
&bootfs_getvnode,
|
||||||
&bootfs_putvnode,
|
&bootfs_putvnode,
|
||||||
|
|||||||
@@ -536,6 +536,18 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
devfs_get_vnode_name(fs_cookie _fs, fs_vnode _vnode, char *buffer, size_t bufferSize)
|
||||||
|
{
|
||||||
|
struct devfs_vnode *vnode = (struct devfs_vnode *)_vnode;
|
||||||
|
|
||||||
|
TRACE(("devfs_get_vnode_name: vnode = %p\n",vnode));
|
||||||
|
|
||||||
|
strlcpy(buffer,vnode->name,bufferSize);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
devfs_get_vnode(fs_cookie _fs, vnode_id id, fs_vnode *_vnode, bool reenter)
|
devfs_get_vnode(fs_cookie _fs, vnode_id id, fs_vnode *_vnode, bool reenter)
|
||||||
{
|
{
|
||||||
@@ -1051,6 +1063,7 @@ static struct fs_calls devfs_calls = {
|
|||||||
&devfs_sync,
|
&devfs_sync,
|
||||||
|
|
||||||
&devfs_lookup,
|
&devfs_lookup,
|
||||||
|
&devfs_get_vnode_name,
|
||||||
|
|
||||||
&devfs_get_vnode,
|
&devfs_get_vnode,
|
||||||
&devfs_put_vnode,
|
&devfs_put_vnode,
|
||||||
|
|||||||
@@ -348,6 +348,18 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
rootfs_get_vnode_name(fs_cookie _fs, fs_vnode _vnode, char *buffer, size_t bufferSize)
|
||||||
|
{
|
||||||
|
struct rootfs_vnode *vnode = (struct rootfs_vnode *)_vnode;
|
||||||
|
|
||||||
|
TRACE(("devfs_get_vnode_name: vnode = %p\n",vnode));
|
||||||
|
|
||||||
|
strlcpy(buffer,vnode->name,bufferSize);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
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 *v, bool r)
|
||||||
{
|
{
|
||||||
@@ -801,6 +813,7 @@ static struct fs_calls rootfs_calls = {
|
|||||||
&rootfs_sync,
|
&rootfs_sync,
|
||||||
|
|
||||||
&rootfs_lookup,
|
&rootfs_lookup,
|
||||||
|
&rootfs_get_vnode_name,
|
||||||
|
|
||||||
&rootfs_get_vnode,
|
&rootfs_get_vnode,
|
||||||
&rootfs_put_vnode,
|
&rootfs_put_vnode,
|
||||||
|
|||||||
+113
-131
@@ -23,9 +23,10 @@
|
|||||||
#include <Errors.h>
|
#include <Errors.h>
|
||||||
#include <kerrors.h>
|
#include <kerrors.h>
|
||||||
#include <atomic.h>
|
#include <atomic.h>
|
||||||
#include <OS.h>
|
|
||||||
#include <fd.h>
|
#include <fd.h>
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
#include <rootfs.h>
|
#include <rootfs.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -46,6 +47,10 @@
|
|||||||
# define FUNCTION(x) ;
|
# define FUNCTION(x) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// ToDo: remove this and include StorageDefs.h once it's there...
|
||||||
|
#ifndef B_FILE_NAME_LENGTH
|
||||||
|
# define B_FILE_NAME_LENGTH 256
|
||||||
|
#endif
|
||||||
|
|
||||||
struct vnode {
|
struct vnode {
|
||||||
struct vnode *next;
|
struct vnode *next;
|
||||||
@@ -124,6 +129,8 @@ static int vfs_open_dir(char *path, bool kernel);
|
|||||||
static int vfs_create(char *path, int omode, int perms, bool kernel);
|
static int vfs_create(char *path, int omode, int perms, bool kernel);
|
||||||
static int vfs_create_dir(char *path, int perms, bool kernel);
|
static int vfs_create_dir(char *path, int perms, bool kernel);
|
||||||
|
|
||||||
|
static status_t dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize);
|
||||||
|
|
||||||
struct fd_ops file_ops = {
|
struct fd_ops file_ops = {
|
||||||
"file",
|
"file",
|
||||||
file_read,
|
file_read,
|
||||||
@@ -369,7 +376,7 @@ lookup_vnode(fs_id fsid, vnode_id vnid)
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_vnode(fs_id fsid, vnode_id vnid, struct vnode **outv, int r)
|
get_vnode(fs_id fsid, vnode_id vnid, struct vnode **outv, int reenter)
|
||||||
{
|
{
|
||||||
struct vnode *v;
|
struct vnode *v;
|
||||||
int err;
|
int err;
|
||||||
@@ -414,7 +421,7 @@ get_vnode(fs_id fsid, vnode_id vnid, struct vnode **outv, int r)
|
|||||||
|
|
||||||
add_vnode_to_mount_list(v, v->mount);
|
add_vnode_to_mount_list(v, v->mount);
|
||||||
|
|
||||||
err = FS_CALL(v,fs_get_vnode)(v->mount->cookie, vnid, &v->priv_vnode, r);
|
err = FS_CALL(v,fs_get_vnode)(v->mount->cookie, vnid, &v->priv_vnode, reenter);
|
||||||
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
remove_vnode_from_mount_list(v, v->mount);
|
remove_vnode_from_mount_list(v, v->mount);
|
||||||
@@ -724,121 +731,113 @@ path_to_dir_vnode(char *path, struct vnode **v, char *filename, bool kernel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
/** Gets the full path to a given directory vnode.
|
||||||
//
|
* It uses the fs_get_vnode_name() call to get the name of a vnode; if a
|
||||||
// XXX -- Warning: horrible hack, just ahead!
|
* file system doesn't support this call, it will fall back to iterating
|
||||||
//
|
* through the parent directory to get the name of the child.
|
||||||
// the following code implements a version of vnode_to_path()
|
*
|
||||||
// which takes an arbitrary vnode and generates the full file path string.
|
* To detect circular loops, it supports a maximum tree depth
|
||||||
// this is used by vfs_get_cwd() so that the user shell can implement 'pwd'
|
* of 256 levels.
|
||||||
//
|
*
|
||||||
// however...
|
* 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
|
||||||
// the method used is to peek into the private vnodes of the filesystem modules.
|
* paths aren't safe anyway: the path to a file can change at any time.
|
||||||
// this is *BAD MOJO* and only works because all of the current filesystems
|
*/
|
||||||
// were implemented with a common structure, mimicked by the struct below.
|
|
||||||
//
|
|
||||||
// the hack was required because the VFS layer, as it was forked from NewOS,
|
|
||||||
// did not have a means of acquiring the path info thru a standard method.
|
|
||||||
// Once we have our own proper implementation of the VFS layer, then the
|
|
||||||
// gross hack below can be removed...
|
|
||||||
//
|
|
||||||
|
|
||||||
int vnode_to_path(struct vnode *, char *, int);
|
status_t
|
||||||
|
dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize)
|
||||||
|
|
||||||
typedef struct generic_vnode {
|
|
||||||
struct generic_vnode *all_next;
|
|
||||||
vnode_id id;
|
|
||||||
char *name;
|
|
||||||
void *redir_vnode;
|
|
||||||
struct generic_vnode *parent;
|
|
||||||
struct generic_vnode *dir_next;
|
|
||||||
}
|
|
||||||
generic_vnode;
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
vnode_to_path(struct vnode *v, char *buf, int buflen)
|
|
||||||
{
|
{
|
||||||
int rc; // return code
|
/* this implementation is currently bound to SYS_MAX_PATH_LEN */
|
||||||
|
char path[SYS_MAX_PATH_LEN];
|
||||||
|
int32 insert = sizeof(path);
|
||||||
|
int32 maxLevel = 256;
|
||||||
|
int32 length;
|
||||||
|
status_t status;
|
||||||
|
|
||||||
if ((v == NULL) || (buf == NULL) || (buflen <= 0))
|
if (vnode == NULL || buffer == NULL)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
//
|
inc_vnode_ref_count(vnode);
|
||||||
// ask the filesystem containing the given vnode to fetch
|
|
||||||
// its local vnode structure for us (returned in v->priv_vnode).
|
|
||||||
// this fs vnode contains the leaf name and parent link required
|
|
||||||
//
|
|
||||||
rc = FS_CALL(v,fs_get_vnode)(v->mount->cookie, v->vnid, &v->priv_vnode, true);
|
|
||||||
if (rc < 0)
|
|
||||||
return rc;
|
|
||||||
else {
|
|
||||||
//
|
|
||||||
// construct the full path, which is:
|
|
||||||
// {mount_point}/{relative_path}
|
|
||||||
//
|
|
||||||
// the mount point has already been stored,
|
|
||||||
// but the relative path has to be generated on-the-fly
|
|
||||||
//
|
|
||||||
generic_vnode *g = (generic_vnode *) v->priv_vnode;
|
|
||||||
|
|
||||||
char *mpoint = v->mount->mount_point;
|
path[--insert] = '\0';
|
||||||
int mpointlen = strlen (mpoint);
|
|
||||||
|
|
||||||
char rpath[SYS_MAX_NAME_LEN]; // buffer to hold relative path
|
while (true) {
|
||||||
int i = sizeof rpath; // current insertion point
|
char name[B_FILE_NAME_LENGTH];
|
||||||
int rpathlen = 0;
|
vnode_id parentId;
|
||||||
int len;
|
|
||||||
|
|
||||||
//
|
// lookup the parent vnode
|
||||||
// generate relative path:
|
status = FS_CALL(vnode,fs_lookup)(vnode->mount->cookie,vnode->priv_vnode,"..",&parentId);
|
||||||
// start with given leaf vnode and back up to mount point,
|
|
||||||
// copying leaf names into buffer (right to left) as we go
|
|
||||||
//
|
|
||||||
rpath[--i] = '\0';
|
|
||||||
|
|
||||||
for (; g; g = g->parent) {
|
// release the current vnode, we only need its parent from now on
|
||||||
//
|
put_vnode(vnode);
|
||||||
if (g->name[0]) {
|
|
||||||
len = strlen (g->name);
|
if (status < B_OK)
|
||||||
i -= len;
|
return status;
|
||||||
memcpy (rpath+i, g->name, len);
|
|
||||||
rpathlen += len;
|
// don't go deeper as 'maxLevel' to prevent circular loops
|
||||||
}
|
if (maxLevel-- < 0)
|
||||||
if (g->parent) {
|
return ELOOP;
|
||||||
if (g->parent->id == g->id)
|
|
||||||
// hit mount point
|
if (parentId == vnode->vnid) {
|
||||||
|
// we have reached the root level directory of this file system
|
||||||
break;
|
break;
|
||||||
|
|
||||||
rpath[--i] = '/';
|
|
||||||
++rpathlen;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mpointlen + rpathlen) > buflen)
|
// 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;
|
||||||
|
|
||||||
|
// okay, we got the parent node, so we can now paste its name
|
||||||
|
// in front of our working path - but we don't know the name yet...
|
||||||
|
|
||||||
|
// does the file system support getting the name of a vnode?
|
||||||
|
if (FS_CALL(vnode,fs_get_vnode_name))
|
||||||
|
status = FS_CALL(vnode,fs_get_vnode_name)(vnode->mount->cookie,vnode->priv_vnode,name,sizeof(name));
|
||||||
|
else {
|
||||||
|
file_cookie cookie;
|
||||||
|
|
||||||
|
status = FS_CALL(vnode,fs_open_dir)(vnode->mount->cookie,vnode->priv_vnode,&cookie);
|
||||||
|
if (status >= B_OK) {
|
||||||
|
// ToDo: implement fall-back - iterate through the directory
|
||||||
|
// and find the correct entry...
|
||||||
|
// Does need some more stack space...
|
||||||
|
/* ... */
|
||||||
|
FS_CALL(vnode,fs_close_dir)(vnode->mount->cookie,vnode->priv_vnode,cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = B_ERROR;
|
||||||
|
}
|
||||||
|
if (status < B_OK) {
|
||||||
|
put_vnode(vnode);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the name infront of the current path
|
||||||
|
name[B_FILE_NAME_LENGTH - 1] = '\0';
|
||||||
|
length = strlen(name);
|
||||||
|
insert -= length;
|
||||||
|
if (insert <= 0) {
|
||||||
|
put_vnode(vnode);
|
||||||
|
return ENOBUFS;
|
||||||
|
}
|
||||||
|
memcpy(path + insert, name, length);
|
||||||
|
path[--insert] == '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the mountpoint
|
||||||
|
length = strlen(vnode->mount->mount_point);
|
||||||
|
if (bufferSize - (sizeof(path) - insert) < length + 1)
|
||||||
return ENOBUFS;
|
return ENOBUFS;
|
||||||
|
|
||||||
//
|
memcpy(buffer, vnode->mount->mount_point, length);
|
||||||
// copy results to output buffer
|
memcpy(buffer + length, path + insert, sizeof(path) - insert);
|
||||||
//
|
|
||||||
strcpy (buf, mpoint);
|
|
||||||
if (rpathlen > 0)
|
|
||||||
strcat (buf, rpath+i);
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// XXX - end of the vnode_to_path() hack
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
/** Sets up a new io_control structure, and inherits the properties
|
/** Sets up a new io_control structure, and inherits the properties
|
||||||
* of the parent io_control if it is given.
|
* of the parent io_control if it is given.
|
||||||
*/
|
*/
|
||||||
@@ -1623,10 +1622,6 @@ vfs_write_page(void *_v, iovecs *vecs, off_t pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// XXX -- Fixme: uses vnode_to_path() hack
|
|
||||||
//
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vfs_get_cwd(char *buffer, size_t size, bool kernel)
|
vfs_get_cwd(char *buffer, size_t size, bool kernel)
|
||||||
{
|
{
|
||||||
@@ -1636,16 +1631,7 @@ vfs_get_cwd(char *buffer, size_t size, bool kernel)
|
|||||||
FUNCTION(("vfs_get_cwd: buf %p, size %ld\n", buffer, size));
|
FUNCTION(("vfs_get_cwd: buf %p, size %ld\n", buffer, size));
|
||||||
|
|
||||||
if (cwd)
|
if (cwd)
|
||||||
//
|
return dir_vnode_to_path(cwd, buffer, size);
|
||||||
// vnode_to_path() takes the cwd vnode and computes
|
|
||||||
// a full path string from it, which is then copied
|
|
||||||
// into the given buffer.
|
|
||||||
//
|
|
||||||
// WARNING: the current version of this function
|
|
||||||
// utilizes a gross hack and will be removed and/or
|
|
||||||
// replaced in the future...
|
|
||||||
//
|
|
||||||
return vnode_to_path(cwd, buffer, size);
|
|
||||||
|
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
@@ -2010,10 +1996,8 @@ user_mount(const char *upath, const char *udevice, const char *ufs_name, void *a
|
|||||||
if ((addr)ufs_name >= KERNEL_BASE && (addr)ufs_name <= KERNEL_TOP)
|
if ((addr)ufs_name >= KERNEL_BASE && (addr)ufs_name <= KERNEL_TOP)
|
||||||
return ERR_VM_BAD_USER_MEMORY;
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
|
|
||||||
if (udevice) {
|
if (udevice != NULL && (addr)udevice >= KERNEL_BASE && (addr)udevice <= KERNEL_TOP)
|
||||||
if((addr)udevice >= KERNEL_BASE && (addr)udevice <= KERNEL_TOP)
|
|
||||||
return ERR_VM_BAD_USER_MEMORY;
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
}
|
|
||||||
|
|
||||||
rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN);
|
rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
@@ -2027,12 +2011,11 @@ user_mount(const char *upath, const char *udevice, const char *ufs_name, void *a
|
|||||||
|
|
||||||
if (udevice) {
|
if (udevice) {
|
||||||
rc = user_strncpy(device, udevice, SYS_MAX_PATH_LEN);
|
rc = user_strncpy(device, udevice, SYS_MAX_PATH_LEN);
|
||||||
if(rc < 0)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
device[SYS_MAX_PATH_LEN] = 0;
|
device[SYS_MAX_PATH_LEN] = 0;
|
||||||
} else {
|
} else
|
||||||
device[0] = 0;
|
device[0] = 0;
|
||||||
}
|
|
||||||
|
|
||||||
return vfs_mount(path, device, fs_name, args, false);
|
return vfs_mount(path, device, fs_name, args, false);
|
||||||
}
|
}
|
||||||
@@ -2248,28 +2231,27 @@ user_write_stat(const char *upath, struct stat *ustat, int stat_mask)
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
user_getcwd(char *buf, size_t size)
|
user_getcwd(char *buffer, size_t size)
|
||||||
{
|
{
|
||||||
char path[SYS_MAX_PATH_LEN];
|
char path[SYS_MAX_PATH_LEN];
|
||||||
int rc, rc2;
|
int status;
|
||||||
|
|
||||||
PRINT(("user_getcwd: buf %p, %ld\n", buf, size));
|
PRINT(("user_getcwd: buf %p, %ld\n", buffer, size));
|
||||||
|
|
||||||
// Check if userspace address is inside "shared" kernel space
|
// Check if userspace address is inside "shared" kernel space
|
||||||
if((addr)buf >= KERNEL_BASE && (addr)buf <= KERNEL_TOP)
|
if ((addr)buffer >= KERNEL_BASE && (addr)buffer <= KERNEL_TOP)
|
||||||
return NULL; //ERR_VM_BAD_USER_MEMORY;
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
|
|
||||||
// Call vfs to get current working directory
|
// Call vfs to get current working directory
|
||||||
rc = vfs_get_cwd(path, SYS_MAX_PATH_LEN-1, false);
|
status = vfs_get_cwd(path, sizeof(path), false);
|
||||||
if(rc < 0)
|
if (status < 0)
|
||||||
return rc;
|
return status;
|
||||||
|
|
||||||
// Copy back the result
|
// Copy back the result
|
||||||
rc2 = user_strncpy(buf, path, size);
|
if (user_strncpy(buffer, path, size) < 0)
|
||||||
if(rc2 < 0)
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
return rc2;
|
|
||||||
|
|
||||||
return rc;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user