mtab: support moving mount points
Also fix canonical_path function; it fails to parse some paths
This commit is contained in:
parent
9f7fb97000
commit
179261a9b6
4 changed files with 71 additions and 4 deletions
|
@ -92,6 +92,7 @@ int do_getsysinfo()
|
|||
break;
|
||||
#endif
|
||||
case SI_VMNT_TAB:
|
||||
fetch_vmnt_paths();
|
||||
src_addr = (vir_bytes) vmnt;
|
||||
len = sizeof(struct vmnt) * NR_MNTS;
|
||||
break;
|
||||
|
|
|
@ -656,7 +656,8 @@ struct fproc *rfp;
|
|||
char temp_path[PATH_MAX];
|
||||
struct lookup resolve;
|
||||
|
||||
dir_vp = NULL;
|
||||
parent_dir = dir_vp = NULL;
|
||||
parent_vmp = dir_vmp = NULL;
|
||||
strlcpy(temp_path, orig_path, PATH_MAX);
|
||||
temp_path[PATH_MAX - 1] = '\0';
|
||||
|
||||
|
@ -678,6 +679,9 @@ struct fproc *rfp;
|
|||
*/
|
||||
strlcpy(orig_path, temp_path, NAME_MAX+1); /* Store file name */
|
||||
|
||||
/* If we're just crossing a mount point, our name has changed to '.' */
|
||||
if (!strcmp(orig_path, ".")) orig_path[0] = '\0';
|
||||
|
||||
/* check if the file is a symlink, if so resolve it */
|
||||
r = rdlink_direct(orig_path, temp_path, rfp);
|
||||
|
||||
|
@ -706,6 +710,10 @@ struct fproc *rfp;
|
|||
|
||||
/* check if we're at the root node of the file system */
|
||||
if (dir_vp->v_vmnt->m_root_node == dir_vp) {
|
||||
if (dir_vp->v_vmnt->m_mounted_on == NULL) {
|
||||
/* Bail out, we can't go any higher */
|
||||
break;
|
||||
}
|
||||
unlock_vnode(dir_vp);
|
||||
unlock_vmnt(dir_vmp);
|
||||
put_vnode(dir_vp);
|
||||
|
@ -769,18 +777,23 @@ struct fproc *rfp;
|
|||
unlock_vmnt(dir_vmp);
|
||||
put_vnode(dir_vp);
|
||||
dir_vp = parent_dir;
|
||||
dir_vmp = parent_vmp;
|
||||
parent_vmp = NULL;
|
||||
}
|
||||
|
||||
unlock_vmnt(dir_vmp);
|
||||
unlock_vnode(dir_vp);
|
||||
unlock_vmnt(parent_vmp);
|
||||
|
||||
put_vnode(dir_vp);
|
||||
|
||||
/* add the leading slash */
|
||||
len = strlen(orig_path);
|
||||
if (strlen(orig_path) >= PATH_MAX) return(ENAMETOOLONG);
|
||||
memmove(orig_path+1, orig_path, strlen(orig_path));
|
||||
memmove(orig_path+1, orig_path, len);
|
||||
orig_path[0] = '/';
|
||||
|
||||
/* remove trailing slash if there is any */
|
||||
if (len > 1 && orig_path[len] == '/') orig_path[len] = '\0';
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
|
|
@ -315,6 +315,7 @@ void init_vmnts(void);
|
|||
int lock_vmnt(struct vmnt *vp, tll_access_t locktype);
|
||||
void unlock_vmnt(struct vmnt *vp);
|
||||
void vmnt_unmap_by_endpt(endpoint_t proc_e);
|
||||
void fetch_vmnt_paths(void);
|
||||
|
||||
/* vnode.c */
|
||||
void check_vnode_locks(void);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "threads.h"
|
||||
#include "vmnt.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "fproc.h"
|
||||
|
||||
static int is_vmnt_locked(struct vmnt *vmp);
|
||||
|
@ -214,3 +215,54 @@ void unlock_vmnt(struct vmnt *vmp)
|
|||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* fetch_vmnt_paths *
|
||||
*===========================================================================*/
|
||||
void fetch_vmnt_paths(void)
|
||||
{
|
||||
struct vmnt *vmp;
|
||||
struct vnode *cur_wd;
|
||||
char orig_path[PATH_MAX];
|
||||
|
||||
cur_wd = fp->fp_wd;
|
||||
|
||||
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
|
||||
if (vmp->m_dev == NO_DEV)
|
||||
continue;
|
||||
if (vmp->m_fs_e == PFS_PROC_NR)
|
||||
continue;
|
||||
|
||||
strlcpy(orig_path, vmp->m_mount_path, PATH_MAX);
|
||||
|
||||
/* Find canonical path */
|
||||
if (canonical_path(vmp->m_mount_path, fp) != OK) {
|
||||
/* We failed to find it (moved somewhere else?). Let's try
|
||||
* again by starting at the node on which we are mounted:
|
||||
* pretend that node is our working directory and look for the
|
||||
* canonical path of the relative path to the mount point
|
||||
* (which should be in our 'working directory').
|
||||
*/
|
||||
char *mp;
|
||||
int len;
|
||||
|
||||
fp->fp_wd = vmp->m_mounted_on; /* Change our working dir */
|
||||
|
||||
/* Isolate the mount point name of the full path */
|
||||
len = strlen(vmp->m_mount_path);
|
||||
if (vmp->m_mount_path[len - 1] == '/') {
|
||||
vmp->m_mount_path[len - 1] = '\0';
|
||||
}
|
||||
mp = strrchr(vmp->m_mount_path, '/');
|
||||
strlcpy(vmp->m_mount_path, mp+1, NAME_MAX+1);
|
||||
|
||||
if (canonical_path(vmp->m_mount_path, fp) != OK) {
|
||||
/* Our second try failed too. Maybe an FS has crashed
|
||||
* and we're missing part of the tree. Revert path.
|
||||
*/
|
||||
strlcpy(vmp->m_mount_path, orig_path, PATH_MAX);
|
||||
}
|
||||
fp->fp_wd = cur_wd; /* Revert working dir */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue