asmlinkage long sys_chroot(const char * filename) { int error; struct nameidata nd; char *name; name = getname(filename); error = PTR_ERR(name); if (IS_ERR(name)) goto out; path_init(name, LOOKUP_POSITIVE | LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); error = path_walk(name, &nd); putname(name); if (error) goto out; error = permission(nd.dentry->d_inode,MAY_EXEC); if (error) goto dput_and_out; error = -EPERM; if (!capable(CAP_SYS_CHROOT)) goto dput_and_out; set_fs_root(current->fs, nd.mnt, nd.dentry); set_fs_altroot(); error = 0; dput_and_out: path_release(&nd); out: return error; }
int dm_path_to_fshdl( char *path, /* any path name */ void *hanp, /* user's data buffer */ size_t *hlenp) /* set to size of data copied */ { /* REFERENCED */ dm_fsreg_t *fsrp; xfs_handle_t handle; vnode_t *vp; size_t hlen; int error; int lc; /* lock cookie */ struct nameidata nd; struct inode *inode; size_t len; char *name; /* XXX get things straightened out so getname() works here? */ len = strnlen_user(path, 2000); name = kmem_alloc(len, KM_SLEEP); if (copy_from_user(name, path, len)) return(EFAULT); error = 0; if (path_init(name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &nd)) error = path_walk(name, &nd); if (error) return error; kmem_free(name, len); ASSERT(nd.dentry); ASSERT(nd.dentry->d_inode); inode = igrab(nd.dentry->d_inode); path_release(&nd); /* we need the vnode */ vp = LINVFS_GET_VP(inode); if (!vp || !vp->v_vfsp->vfs_altfsid) { /* we're not in XFS anymore, Toto */ iput(inode); return EINVAL; } error = dm_vp_to_handle(vp, &handle); iput(inode);/*was VN_RELE(vp);*/ if (error) return(error); if ((fsrp = dm_find_fsreg_and_lock((fsid_t*)&handle.ha_fsid, &lc)) == NULL) return(EBADF); mutex_spinunlock(&fsrp->fr_lock, lc); hlen = FSHSIZE; if(copy_to_user(hanp, &handle, (int)hlen)) return(EFAULT); return(put_user(hlen,hlenp)); }
asmlinkage long sys_chdir(const char * filename) { int error; struct nameidata nd; char *name; name = getname(filename); error = PTR_ERR(name); if (IS_ERR(name)) goto out; error = 0; if (path_init(name,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd)) error = path_walk(name, &nd); putname(name); if (error) goto out; error = permission(nd.dentry->d_inode,MAY_EXEC); if (error) goto dput_and_out; set_fs_pwd(current->fs, nd.mnt, nd.dentry); dput_and_out: path_release(&nd); out: return error; }
/* Lookup name and return vnode for same. */ int osi_lookupname_internal(char *aname, int followlink, struct vfsmount **mnt, struct dentry **dpp) { int code; struct nameidata nd; int flags = LOOKUP_POSITIVE; code = ENOENT; if (followlink) flags |= LOOKUP_FOLLOW; if (path_init(aname, flags, &nd)) code = path_walk(aname, &nd); if (!code) { #if defined(STRUCT_NAMEIDATA_HAS_PATH) *dpp = dget(nd.path.dentry); if (mnt) *mnt = mntget(nd.path.mnt); path_put(&nd.path); #else *dpp = dget(nd.dentry); if (mnt) *mnt = mntget(nd.mnt); path_release(&nd); #endif } return code; }
/* XXX: this function is utterly bogus. Every use of it is racy and the prototype is stupid. You have been warned. --hch. */ hwgfs_handle_t hwgfs_find_handle( hwgfs_handle_t base, const char *name, unsigned int major, /* IGNORED */ unsigned int minor, /* IGNORED */ char type, /* IGNORED */ int traverse_symlinks) { struct dentry *dentry = NULL; struct nameidata nd; int error; BUG_ON(*name=='/'); memset(&nd, 0, sizeof(nd)); nd.mnt = mntget(hwgfs_vfsmount); nd.dentry = dget(base ? base : hwgfs_vfsmount->mnt_sb->s_root); nd.flags = (traverse_symlinks ? LOOKUP_FOLLOW : 0); error = path_walk(name, &nd); if (likely(!error)) { dentry = nd.dentry; path_release(&nd); /* stale data from here! */ } return dentry; }
/* On success, returns with parent_inode->i_sem taken. */ static int hwgfs_decode( hwgfs_handle_t dir, const char *name, int is_dir, struct inode **parent_inode, struct dentry **dentry) { struct nameidata nd; int error; if (!dir) dir = hwgfs_vfsmount->mnt_sb->s_root; memset(&nd, 0, sizeof(nd)); nd.flags = LOOKUP_PARENT; nd.mnt = mntget(hwgfs_vfsmount); nd.dentry = dget(dir); error = walk_parents_mkdir(&name, &nd, is_dir); if (unlikely(error)) return error; error = path_walk(name, &nd); if (unlikely(error)) return error; *dentry = lookup_create(&nd, is_dir); if (IS_ERR(*dentry)) return PTR_ERR(*dentry); *parent_inode = (*dentry)->d_parent->d_inode; return 0; }
static struct file *do_open(char *name, int flags) { struct nameidata nd; int error; nd.mnt = do_kern_mount("nfsd", 0, "nfsd", NULL); if (IS_ERR(nd.mnt)) return (struct file *)nd.mnt; nd.dentry = dget(nd.mnt->mnt_root); nd.last_type = LAST_ROOT; nd.flags = 0; nd.depth = 0; error = path_walk(name, &nd); if (error) return ERR_PTR(error); if (flags == O_RDWR) error = may_open(&nd,MAY_READ|MAY_WRITE,FMODE_READ|FMODE_WRITE); else error = may_open(&nd, MAY_WRITE, FMODE_WRITE); if (!error) return dentry_open(nd.dentry, nd.mnt, flags); path_release(&nd); return ERR_PTR(error); }
// Deletes a file. // int unlink(const char *path) { int r; struct Inode *dirino, *ino; struct Direntry *de; if ((r = path_walk(path, &dirino, &de, 0)) < 0) goto done; if ((r = inode_open(de->de_inum, &ino)) < 0) goto closedirino; if (ino->i_ftype == FTYPE_DIR) { r = -E_IS_DIR; goto closeino; } // clear directory entry de->de_inum = 0; --ino->i_refcount; bcache_ipc(de, BCREQ_FLUSH); bcache_ipc(ino, BCREQ_FLUSH); r = 0; closeino: inode_close(ino); closedirino: inode_close(dirino); done: return r; }
static inline int translucent_is_whiteout2(char *path) { int i_Ret; struct nameidata n; path_init(path, 0, &n); i_Ret=path_walk(path, &n); if(i_Ret) return 0; i_Ret=translucent_is_whiteout(&n); path_release(&n); return i_Ret; }
static int a_path_walk(const char *pathname, int flags, struct nameidata *nd) { int error; error = 0; if (path_init(pathname, flags, nd)) error = path_walk(pathname, nd); return error; }
int presto_walk(const char *name, struct nameidata *nd) { int err; /* we do not follow symlinks to support symlink operations correctly. The vfs should always hand us resolved dentries so we should not be required to use LOOKUP_FOLLOW. At the reintegrating end, lento again should be working with the resolved pathname and not the symlink. SHP XXX: This code implies that direct symlinks do not work. SHP */ unsigned int flags = LOOKUP_POSITIVE; ENTRY; err = 0; if (path_init(name, flags, nd)) err = path_walk(name, nd); return err; }
static int walk_parents_mkdir( const char **path, struct nameidata *nd, int is_dir) { char *slash; char buf[strlen(*path)+1]; int error; while ((slash = strchr(*path, '/')) != NULL) { int len = slash - *path; memcpy(buf, *path, len); buf[len] = '\0'; error = path_walk(buf, nd); if (unlikely(error)) return error; nd->dentry = lookup_create(nd, is_dir); nd->flags |= LOOKUP_PARENT; if (IS_ERR(nd->dentry)) return PTR_ERR(nd->dentry); if (!nd->dentry->d_inode) error = vfs_mkdir(nd->dentry->d_parent->d_inode, nd->dentry, 0755); up(&nd->dentry->d_parent->d_inode->i_sem); if (unlikely(error)) return error; *path += len + 1; } return 0; }
// Open a file (or directory). // // Returns: // The file descriptor index on success // -E_BAD_PATH if the path is too long (>= MAXPATHLEN) // -E_BAD_PATH if an intermediate path component is not a directory // -E_MAX_FD if no more file descriptors // -E_NOT_FOUND if the file (or a path component) was not found // (and others) int open(const char *path, int mode) { // Find an unused file descriptor page using fd_find_unused // and allocate a page there (PTE_P|PTE_U|PTE_W|PTE_SHARE). // // LAB 5: Your code here int r; struct Fd *fd; if((r = fd_find_unused(&fd)) < 0 || (r = sys_page_alloc(0, fd, PTE_P|PTE_U|PTE_W|PTE_SHARE)) < 0) goto err1; // Check the pathname. Error if too long. // Use path_walk to find the corresponding directory entry. // If '(mode & O_CREAT) == 0' (Exercise 4), // Return -E_NOT_FOUND if the file is not found. // Otherwise, use inode_open to open the inode. // If '(mode & O_CREAT) != 0' (Exercise 7), // Create the file if it doesn't exist yet. // Allocate a new inode, initialize its fields, and // reference that inode from the new directory entry. // Flush any blocks you change. // Directories can be opened, but only as read-only: // return -E_IS_DIR if '(mode & O_ACCMODE) != O_RDONLY'. // // Check for errors. On error, make sure you clean up any // allocated objects. // // The root directory is a special case -- if you aren't careful, // you will deadlock when the root directory is opened. (Why?) // // LAB 5: Your code here. int i; for(i = 0; i < MAXNAMELEN && path[i]; i++); if(i == MAXNAMELEN) { r = -E_BAD_PATH; goto err2; } struct Inode *dirino; struct Direntry *de; if((r = path_walk(path, &dirino, &de, mode & O_CREAT))) goto err2; struct Inode *fileino; if(!(mode & O_CREAT)) { if(de == &super->s_root) fileino = dirino; else if((r = inode_open(de->de_inum, &fileino)) < 0) goto err3; if(fileino->i_ftype == FTYPE_DIR && ( mode & O_ACCMODE) != O_RDONLY) { r = -E_IS_DIR; goto err4; } } else { if((r = inode_alloc(&fileino)) < 0) goto err3; fileino->i_ftype = FTYPE_REG; fileino->i_refcount = 1; fileino->i_size = 0; memset(&fileino->i_direct, 0, NDIRECT * sizeof (blocknum_t)); de->de_inum = fileino->i_inum; bcache_ipc(fileino, BCREQ_FLUSH); bcache_ipc(dirino, BCREQ_FLUSH); } // If '(mode & O_TRUNC) != 0' and the open mode is not read-only, // set the file's length to 0. Flush any blocks you change. // // LAB 5: Your code here (Exercise 8). if((mode & O_TRUNC)) { inode_set_size(fileino, 0); } // The open has succeeded. // Fill in all parts of the 'fd' appropriately. Use 'devfile.dev_id'. // Copy the file's pathname into 'fd->fd_file.open_path' to improve // error messages later. // You must account for the open file reference in the inode as well. // Clean up any open inodes. // // LAB 5: Your code here (Exercise 4). fd->fd_dev_id = devfile.dev_id; fd->fd_offset = 0; fd->fd_omode = mode; fd->fd_file.inum = fileino->i_inum; strcpy(fd->fd_file.open_path, path); fileino->i_opencount++; inode_close(dirino); inode_close(fileino); return fd2num(fd); err4: inode_close(fileino); err3: inode_close(dirino); err2: sys_page_unmap(thisenv->env_id, fd); err1: return r; }
static void do_dir_line (tux_req_t *req, int cachemiss) { struct linux_dirent64 *dirp, *dirp0; char string0[MAX_OBJECTNAME_LEN+200], *tmp; int len, curroff, total, str_len = 0; int err, flag = cachemiss ? 0 : LOOKUP_ATOMIC; struct nameidata base = { }; struct dentry *dentry = NULL; struct inode *inode = NULL; struct vfsmount *mnt = NULL; if (req->proto->check_req_err(req, cachemiss)) return; tmp = NULL; dirp0 = req->dirp0; curroff = req->curroff; total = req->total; dirp = (struct linux_dirent64 *)((char *)dirp0 + curroff); if (!dirp->d_name || !dirp->d_name[0]) goto next_dir; /* * Hide .xxxxx files: */ if (dirp->d_name[0] == '.') goto next_dir; Dprintk("<%s T:%d (off:%Ld) (len:%d)>\n", dirp->d_name, dirp->d_type, dirp->d_off, dirp->d_reclen); if (tux_hide_unreadable) { switch (dirp->d_type) { default: goto next_dir; case DT_UNKNOWN: case DT_REG: case DT_DIR: case DT_LNK: /* valid entries - fall through. */ ; } } len = strlen(dirp->d_name); if (len >= MAX_OBJECTNAME_LEN) { dirp->d_name[MAX_OBJECTNAME_LEN] = 0; len = MAX_OBJECTNAME_LEN-1; } if (!req->dentry) TUX_BUG(); base.flags = flag; base.last_type = LAST_ROOT; base.dentry = dget(req->dentry); base.mnt = mntget(req->cwd_mnt); switch_docroot(req); err = path_walk(dirp->d_name, &base); Dprintk("path_walk() returned %d.\n", err); if (err) { if (err == -EWOULDBLOCKIO) { add_tux_atom(req, do_dir_line); queue_cachemiss(req); return; } goto next_dir; } dentry = base.dentry; mnt = base.mnt; if (!dentry) TUX_BUG(); if (IS_ERR(dentry)) TUX_BUG(); inode = dentry->d_inode; if (!inode) TUX_BUG(); if (!dirp->d_type) dirp->d_type = get_d_type(dentry); if (tux_hide_unreadable) { umode_t mode; mode = inode->i_mode; if (mode & tux_mode_forbidden) goto out_dput; if (!(mode & tux_mode_allowed)) goto out_dput; err = permission(inode, MAY_READ, NULL); if (err) goto out_dput; if (dirp->d_type == DT_DIR) { err = permission(inode, MAY_EXEC, NULL); if (err) goto out_dput; } } tmp = req->proto->print_dir_line(req, string0, dirp->d_name, len, dirp->d_type, dentry, inode); if (tmp) str_len = tmp-string0; out_dput: dput(dentry); mntput(mnt); next_dir: curroff += dirp->d_reclen; if (tmp && (tmp != string0)) Dprintk("writing line (len: %d): <%s>\n", strlen(string0), string0); if (curroff < total) { req->dirp0 = dirp0; req->curroff = curroff; add_tux_atom(req, do_dir_line); } else { kfree(dirp0); req->dirp0 = NULL; req->curroff = 0; // falls back to the list_directory atom } if (tmp && (tmp != string0)) __send_async_message(req, string0, 200, str_len, 0); else add_req_to_workqueue(req); }