int sysvbfs_create(void *arg) { struct vop_create_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; struct vattr *a_vap; } */ *a = arg; struct sysvbfs_node *bnode = a->a_dvp->v_data; struct sysvbfs_mount *bmp = bnode->bmp; struct bfs *bfs = bmp->bfs; struct mount *mp = bmp->mountp; struct bfs_dirent *dirent; struct bfs_fileattr attr; struct vattr *va = a->a_vap; kauth_cred_t cr = a->a_cnp->cn_cred; int err = 0; DPRINTF("%s: %s\n", __func__, a->a_cnp->cn_nameptr); KDASSERT(a->a_vap->va_type == VREG); attr.uid = kauth_cred_geteuid(cr); attr.gid = kauth_cred_getegid(cr); attr.mode = va->va_mode; if ((err = bfs_file_create(bfs, a->a_cnp->cn_nameptr, 0, 0, &attr)) != 0) { DPRINTF("%s: bfs_file_create failed.\n", __func__); goto unlock_exit; } if (!bfs_dirent_lookup_by_name(bfs, a->a_cnp->cn_nameptr, &dirent)) panic("no dirent for created file."); if ((err = sysvbfs_vget(mp, dirent->inode, a->a_vpp)) != 0) { DPRINTF("%s: sysvbfs_vget failed.\n", __func__); goto unlock_exit; } bnode = (*a->a_vpp)->v_data; bnode->update_ctime = true; bnode->update_mtime = true; bnode->update_atime = true; unlock_exit: /* unlock parent directory */ vput(a->a_dvp); /* locked at sysvbfs_lookup(); */ return err; }
int sysvbfs_lookup(void *arg) { struct vop_lookup_v2_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; } */ *a = arg; struct vnode *v = a->a_dvp; struct sysvbfs_node *bnode = v->v_data; struct bfs *bfs = bnode->bmp->bfs; /* my filesystem */ struct vnode *vpp = NULL; struct bfs_dirent *dirent = NULL; struct componentname *cnp = a->a_cnp; int nameiop = cnp->cn_nameiop; const char *name = cnp->cn_nameptr; int namelen = cnp->cn_namelen; int error; DPRINTF("%s: %s op=%d %d\n", __func__, name, nameiop, cnp->cn_flags); *a->a_vpp = NULL; KASSERT((cnp->cn_flags & ISDOTDOT) == 0); if ((error = VOP_ACCESS(a->a_dvp, VEXEC, cnp->cn_cred)) != 0) { return error; /* directory permission. */ } /* Deny last component write operation on a read-only mount */ if ((cnp->cn_flags & ISLASTCN) && (v->v_mount->mnt_flag & MNT_RDONLY) && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) return EROFS; if (namelen == 1 && name[0] == '.') { /* "." */ vref(v); *a->a_vpp = v; } else { /* Regular file */ if (!bfs_dirent_lookup_by_name(bfs, cnp->cn_nameptr, &dirent)) { if (nameiop != CREATE && nameiop != RENAME) { DPRINTF("%s: no such a file. (1)\n", __func__); return ENOENT; } if ((error = VOP_ACCESS(v, VWRITE, cnp->cn_cred)) != 0) return error; return EJUSTRETURN; } /* Allocate v-node */ if ((error = sysvbfs_vget(v->v_mount, dirent->inode, &vpp)) != 0) { DPRINTF("%s: can't get vnode.\n", __func__); return error; } VOP_UNLOCK(vpp); *a->a_vpp = vpp; } return 0; }