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:
parent
ba94874630
commit
63c5cc0aa1
|
@ -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
|
||||
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_lookup,
|
||||
&bootfs_get_vnode_name,
|
||||
|
||||
&bootfs_getvnode,
|
||||
&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
|
||||
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_lookup,
|
||||
&devfs_get_vnode_name,
|
||||
|
||||
&devfs_get_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
|
||||
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_lookup,
|
||||
&rootfs_get_vnode_name,
|
||||
|
||||
&rootfs_get_vnode,
|
||||
&rootfs_put_vnode,
|
||||
|
|
|
@ -23,9 +23,10 @@
|
|||
#include <Errors.h>
|
||||
#include <kerrors.h>
|
||||
#include <atomic.h>
|
||||
#include <OS.h>
|
||||
#include <fd.h>
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
#include <rootfs.h>
|
||||
|
||||
#include <string.h>
|
||||
|
@ -46,6 +47,10 @@
|
|||
# define FUNCTION(x) ;
|
||||
#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 *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_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 = {
|
||||
"file",
|
||||
file_read,
|
||||
|
@ -369,7 +376,7 @@ lookup_vnode(fs_id fsid, vnode_id vnid)
|
|||
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
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)
|
||||
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)
|
|||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// XXX -- Warning: horrible hack, just ahead!
|
||||
//
|
||||
// the following code implements a version of vnode_to_path()
|
||||
// which takes an arbitrary vnode and generates the full file path string.
|
||||
// this is used by vfs_get_cwd() so that the user shell can implement 'pwd'
|
||||
//
|
||||
// however...
|
||||
//
|
||||
// the method used is to peek into the private vnodes of the filesystem modules.
|
||||
// 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...
|
||||
//
|
||||
/** 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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
int vnode_to_path(struct vnode *, char *, int);
|
||||
|
||||
|
||||
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)
|
||||
status_t
|
||||
dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize)
|
||||
{
|
||||
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;
|
||||
|
||||
inc_vnode_ref_count(vnode);
|
||||
|
||||
path[--insert] = '\0';
|
||||
|
||||
//
|
||||
// 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;
|
||||
while (true) {
|
||||
char name[B_FILE_NAME_LENGTH];
|
||||
vnode_id parentId;
|
||||
|
||||
char *mpoint = v->mount->mount_point;
|
||||
int mpointlen = strlen (mpoint);
|
||||
|
||||
char rpath[SYS_MAX_NAME_LEN]; // buffer to hold relative path
|
||||
int i = sizeof rpath; // current insertion point
|
||||
int rpathlen = 0;
|
||||
int len;
|
||||
// lookup the parent vnode
|
||||
status = FS_CALL(vnode,fs_lookup)(vnode->mount->cookie,vnode->priv_vnode,"..",&parentId);
|
||||
|
||||
//
|
||||
// generate relative path:
|
||||
// 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) {
|
||||
//
|
||||
if (g->name[0]) {
|
||||
len = strlen (g->name);
|
||||
i -= len;
|
||||
memcpy (rpath+i, g->name, len);
|
||||
rpathlen += len;
|
||||
}
|
||||
if (g->parent) {
|
||||
if (g->parent->id == g->id)
|
||||
// hit mount point
|
||||
break;
|
||||
|
||||
rpath[--i] = '/';
|
||||
++rpathlen;
|
||||
}
|
||||
// release the current vnode, we only need its parent from now on
|
||||
put_vnode(vnode);
|
||||
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
// don't go deeper as 'maxLevel' to prevent circular loops
|
||||
if (maxLevel-- < 0)
|
||||
return ELOOP;
|
||||
|
||||
if (parentId == vnode->vnid) {
|
||||
// we have reached the root level directory of this file system
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
//
|
||||
// copy results to output buffer
|
||||
//
|
||||
strcpy (buf, mpoint);
|
||||
if (rpathlen > 0)
|
||||
strcat (buf, rpath+i);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
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;
|
||||
|
||||
memcpy(buffer, vnode->mount->mount_point, length);
|
||||
memcpy(buffer + length, path + insert, sizeof(path) - insert);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// XXX - end of the vnode_to_path() hack
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/** Sets up a new io_control structure, and inherits the properties
|
||||
* 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
|
||||
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));
|
||||
|
||||
if (cwd)
|
||||
//
|
||||
// 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 dir_vnode_to_path(cwd, buffer, size);
|
||||
|
||||
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)
|
||||
return ERR_VM_BAD_USER_MEMORY;
|
||||
|
||||
if (udevice) {
|
||||
if((addr)udevice >= KERNEL_BASE && (addr)udevice <= 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)
|
||||
|
@ -2027,12 +2011,11 @@ user_mount(const char *upath, const char *udevice, const char *ufs_name, void *a
|
|||
|
||||
if (udevice) {
|
||||
rc = user_strncpy(device, udevice, SYS_MAX_PATH_LEN);
|
||||
if(rc < 0)
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
device[SYS_MAX_PATH_LEN] = 0;
|
||||
} else {
|
||||
} else
|
||||
device[0] = 0;
|
||||
}
|
||||
|
||||
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
|
||||
user_getcwd(char *buf, size_t size)
|
||||
user_getcwd(char *buffer, size_t size)
|
||||
{
|
||||
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
|
||||
if((addr)buf >= KERNEL_BASE && (addr)buf <= KERNEL_TOP)
|
||||
return NULL; //ERR_VM_BAD_USER_MEMORY;
|
||||
if ((addr)buffer >= KERNEL_BASE && (addr)buffer <= KERNEL_TOP)
|
||||
return ERR_VM_BAD_USER_MEMORY;
|
||||
|
||||
// Call vfs to get current working directory
|
||||
rc = vfs_get_cwd(path, SYS_MAX_PATH_LEN-1, false);
|
||||
if(rc < 0)
|
||||
return rc;
|
||||
status = vfs_get_cwd(path, sizeof(path), false);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
// Copy back the result
|
||||
rc2 = user_strncpy(buf, path, size);
|
||||
if(rc2 < 0)
|
||||
return rc2;
|
||||
if (user_strncpy(buffer, path, size) < 0)
|
||||
return ERR_VM_BAD_USER_MEMORY;
|
||||
|
||||
return rc;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue