break;
#endif
case SI_VMNT_TAB:
+ fetch_vmnt_paths();
src_addr = (vir_bytes) vmnt;
len = sizeof(struct vmnt) * NR_MNTS;
break;
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';
*/
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);
/* 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);
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);
}
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);
#include "threads.h"
#include "vmnt.h"
#include <assert.h>
+#include <string.h>
#include "fproc.h"
static int is_vmnt_locked(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 */
+ }
+ }
+}