/* * vfs_get_root - Given a device name (stdin, stdout, etc.), hand * back an appropriate inode. */ int vfs_get_root(const char *devname, struct inode **node_store) { assert(devname != NULL); int ret = -E_NO_DEV; if (!list_empty(&vdev_list)) { lock_vdev_list(); { list_entry_t *list = &vdev_list, *le = list; while ((le = list_next(le)) != list) { vfs_dev_t *vdev = le2vdev(le, vdev_link); if (strcmp(devname, vdev->devname) == 0) { struct inode *found = NULL; if (vdev->fs != NULL) { found = fsop_get_root(vdev->fs); } else if (!vdev->mountable) { vop_ref_inc(vdev->devnode); found = vdev->devnode; } if (found != NULL) { ret = 0, *node_store = found; } else { ret = -E_NA_DEV; } break; } } } unlock_vdev_list(); } return ret; }
/* * Common code to pull the device name, if any, off the front of a * path and choose the inode to begin the name lookup relative to. */ static int get_device(char *path, char **subpath, struct inode **node_store) { int i, slash = -1, colon = -1; /* * Locate the first colon or slash. */ for (i = 0; path[i] != '\0'; i ++) { if (path[i] == ':') { colon = i; break; } if (path[i] == '/') { slash = i; break; } } if (colon < 0 && slash != 0) { /* * * No colon before a slash, so no device name specified, and the slash isn't leading * or is also absent, so this is a relative path or just a bare filename. Start from * the current directory, and use the whole thing as the subpath. * */ *subpath = path; return vfs_get_curdir(node_store); } if (colon > 0) { /* device:path - get root of device's filesystem */ path[colon] = '\0'; /* device:/path - skip slash, treat as device:path */ while (path[++ colon] == '/'); *subpath = path + colon; return vfs_get_root(path, node_store); } /* * * we have either /path or :path * /path is a path relative to the root of the "boot filesystem" * :path is a path relative to the root of the current filesystem * */ int ret; if (*path == '/') { if ((ret = vfs_get_bootfs(node_store)) != 0) { return ret; } } else { assert(*path == ':'); struct inode *node; if ((ret = vfs_get_curdir(&node)) != 0) { return ret; } /* The current directory may not be a device, so it must have a fs. */ assert(node->in_fs != NULL); *node_store = fsop_get_root(node->in_fs); vop_ref_dec(node); } /* ///... or :/... */ while (*(++ path) == '/'); *subpath = path; return 0; }
/* * Given a device name (lhd0, emu0, somevolname, null, etc.), hand * back an appropriate inode. */ int vfs_get_root(const char *devname, struct inode **node_store) { assert(devname != NULL); int ret = -E_NO_DEV; if (!list_empty(&vdev_list)) { lock_vdev_list(); { list_entry_t *list = &vdev_list, *le = list; while ((le = list_next(le)) != list) { vfs_dev_t *vdev = le2vdev(le, vdev_link); if (strcmp(devname, vdev->devname) == 0) { struct inode *found = NULL; /* * If this device has a mounted filesystem, and * DEVNAME names either the filesystem or the device, * return the root of the filesystem. * * If it has no mounted filesystem, it's mountable, * and DEVNAME names the device, return -E_NA_DEV. */ if (vdev->fs != NULL) { found = fsop_get_root(vdev->fs); } else if (!vdev->mountable) { vop_ref_inc(vdev->devnode); found = vdev->devnode; } if (found != NULL) { /* * If DEVNAME names the device, and we get here, it * must have no fs and not be mountable. In this case, * we return the inode of device itself--node_store. */ ret = 0, *node_store = found; } else { /* * If we got here, the device specified by devname doesn't exist. */ ret = -E_NA_DEV; } break; } /* * If none of the above tests matched, we didn't name * any of the names of this device, so go on to the * next one. */ } } unlock_vdev_list(); } return ret; }