/* * nwfs_create call * Create a regular file. On entry the directory to contain the file being * created is locked. We must release before we return. * * nwfs_create(struct vnode *a_dvp, struct vnode **a_vpp, * struct componentname *a_cnpl, struct vattr *a_vap) */ static int nwfs_create(struct vop_old_create_args *ap) { struct vnode *dvp = ap->a_dvp; struct vattr *vap = ap->a_vap; struct vnode **vpp=ap->a_vpp; struct componentname *cnp = ap->a_cnp; struct vnode *vp = NULL; int error = 0, fmode; struct vattr vattr; struct nwnode *np; struct ncp_open_info no; struct nwmount *nmp=VTONWFS(dvp); ncpfid fid; NCPVNDEBUG("\n"); *vpp = NULL; if (vap->va_type == VSOCK) return (EOPNOTSUPP); if ((error = VOP_GETATTR(dvp, &vattr))) { return (error); } fmode = AR_READ | AR_WRITE; /* if (vap->va_vaflags & VA_EXCLUSIVE) fmode |= AR_DENY_READ | AR_DENY_WRITE;*/ error = ncp_open_create_file_or_subdir(nmp,dvp,cnp->cn_namelen,cnp->cn_nameptr, OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE, 0, fmode, &no, cnp->cn_td, cnp->cn_cred); if (!error) { error = ncp_close_file(NWFSTOCONN(nmp), &no.fh, cnp->cn_td,cnp->cn_cred); fid.f_parent = VTONW(dvp)->n_fid.f_id; fid.f_id = no.fattr.dirEntNum; error = nwfs_nget(VTOVFS(dvp), fid, &no.fattr, dvp, &vp); if (!error) { np = VTONW(vp); np->opened = 0; *vpp = vp; } } return (error); }
/* * nwfs_mkdir call * * nwfs_mkdir(struct vnode *a_dvp, struct vnode **a_vpp, * struct componentname *a_cnp, struct vattr *a_vap) */ static int nwfs_mkdir(struct vop_old_mkdir_args *ap) { struct vnode *dvp = ap->a_dvp; /* struct vattr *vap = ap->a_vap;*/ struct componentname *cnp = ap->a_cnp; int len=cnp->cn_namelen; struct ncp_open_info no; struct vnode *newvp = NULL; ncpfid fid; int error = 0; struct vattr vattr; char *name=cnp->cn_nameptr; if ((error = VOP_GETATTR(dvp, &vattr))) { return (error); } if ((name[0] == '.') && ((len == 1) || ((len == 2) && (name[1] == '.')))) { return EEXIST; } if (ncp_open_create_file_or_subdir(VTONWFS(dvp),dvp, cnp->cn_namelen, cnp->cn_nameptr,OC_MODE_CREATE, aDIR, 0xffff, &no, cnp->cn_td, cnp->cn_cred) != 0) { error = EACCES; } else { error = 0; } if (!error) { fid.f_parent = VTONW(dvp)->n_fid.f_id; fid.f_id = no.fattr.dirEntNum; error = nwfs_nget(VTOVFS(dvp), fid, &no.fattr, dvp, &newvp); if (!error) { newvp->v_type = VDIR; *ap->a_vpp = newvp; } } return (error); }
static int nwfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred) { struct nwmount *nmp = VTONWFS(vp); int error, count, i; struct dirent dp; struct nwnode *np = VTONW(vp); struct nw_entry_info fattr; struct vnode *newvp; struct componentname cn; ncpfid fid; np = VTONW(vp); NCPVNDEBUG("dirname='%s'\n",np->n_name); if (uio->uio_resid < DE_SIZE || (uio->uio_offset < 0)) return (EINVAL); error = 0; count = 0; i = uio->uio_offset / DE_SIZE; /* offset in directory */ if (i == 0) { error = ncp_initsearch(vp, uio->uio_td, cred); if (error) { NCPVNDEBUG("cannot initialize search, error=%d",error); return( error ); } } for (; uio->uio_resid >= DE_SIZE; i++) { bzero((char *) &dp, DE_SIZE); dp.d_reclen = DE_SIZE; switch (i) { case 0: /* `.' */ case 1: /* `..' */ dp.d_fileno = (i == 0) ? np->n_fid.f_id : np->n_parent.f_id; if (!dp.d_fileno) dp.d_fileno = NWFS_ROOT_INO; dp.d_namlen = i + 1; dp.d_name[0] = '.'; dp.d_name[1] = '.'; dp.d_name[i + 1] = '\0'; dp.d_type = DT_DIR; break; default: error = ncp_search_for_file_or_subdir(nmp, &np->n_seq, &fattr, uio->uio_td, cred); if (error && error < 0x80) break; dp.d_fileno = fattr.dirEntNum; dp.d_type = (fattr.attributes & aDIR) ? DT_DIR : DT_REG; dp.d_namlen = fattr.nameLen; bcopy(fattr.entryName, dp.d_name, dp.d_namlen); dp.d_name[dp.d_namlen] = '\0'; #if 0 if (error && eofflag) { /* *eofflag = 1;*/ break; } #endif break; } if (nwfs_fastlookup && !error && i > 1) { fid.f_id = fattr.dirEntNum; fid.f_parent = np->n_fid.f_id; error = nwfs_nget(vp->v_mount, fid, &fattr, vp, &newvp); if (!error) { VTONW(newvp)->n_ctime = VTONW(newvp)->n_vattr.va_ctime.tv_sec; cn.cn_nameptr = dp.d_name; cn.cn_namelen = dp.d_namlen; cache_enter(vp, newvp, &cn); vput(newvp); } else error = 0; } if (error >= 0x80) { error = 0; break; } if ((error = uiomove(&dp, DE_SIZE, uio))) break; } uio->uio_offset = i * DE_SIZE; return (error); }
/* Return locked vnode to root of a filesystem */ static int nwfs_root(struct mount *mp, struct vnode **vpp) { struct vnode *vp; struct nwmount *nmp; struct nwnode *np; struct ncp_conn *conn; struct nw_entry_info fattr; struct thread *td = curthread; /* XXX */ struct ucred *cred; int error, nsf, opt; u_char vol; KKASSERT(td->td_proc); cred = td->td_proc->p_ucred; nmp = VFSTONWFS(mp); conn = NWFSTOCONN(nmp); if (nmp->n_root) { *vpp = NWTOV(nmp->n_root); while (vget(*vpp, LK_EXCLUSIVE) != 0) /* XXX */ ; return 0; } error = ncp_lookup_volume(conn, nmp->m.mounted_vol, &vol, &nmp->n_rootent.f_id, td, cred); if (error) return ENOENT; nmp->n_volume = vol; error = ncp_get_namespaces(conn, vol, &nsf, td, cred); if (error) return ENOENT; if (nsf & NW_NSB_OS2) { NCPVODEBUG("volume %s has os2 namespace\n",nmp->m.mounted_vol); if ((nmp->m.flags & NWFS_MOUNT_NO_OS2) == 0) { nmp->name_space = NW_NS_OS2; nmp->m.nls.opt &= ~NWHP_DOS; } } opt = nmp->m.nls.opt; nsf = opt & (NWHP_UPPER | NWHP_LOWER); if (opt & NWHP_DOS) { if (nsf == (NWHP_UPPER | NWHP_LOWER)) { nmp->m.nls.opt &= ~(NWHP_LOWER | NWHP_UPPER); } else if (nsf == 0) { nmp->m.nls.opt |= NWHP_LOWER; } } else { if (nsf == (NWHP_UPPER | NWHP_LOWER)) { nmp->m.nls.opt &= ~(NWHP_LOWER | NWHP_UPPER); } } if (nmp->m.root_path[0]) { nmp->m.root_path[0]--; error = ncp_obtain_info(nmp, nmp->n_rootent.f_id, -nmp->m.root_path[0], nmp->m.root_path, &fattr, td, cred); if (error) { NCPFATAL("Invalid root path specified\n"); return ENOENT; } nmp->n_rootent.f_parent = fattr.dirEntNum; nmp->m.root_path[0]++; error = ncp_obtain_info(nmp, nmp->n_rootent.f_id, -nmp->m.root_path[0], nmp->m.root_path, &fattr, td, cred); if (error) { NCPFATAL("Invalid root path specified\n"); return ENOENT; } nmp->n_rootent.f_id = fattr.dirEntNum; } else { error = ncp_obtain_info(nmp, nmp->n_rootent.f_id, 0, NULL, &fattr, td, cred); if (error) { NCPFATAL("Can't obtain volume info\n"); return ENOENT; } fattr.nameLen = strlen(strcpy(fattr.entryName, NWFS_ROOTVOL)); nmp->n_rootent.f_parent = nmp->n_rootent.f_id; } error = nwfs_nget(mp, nmp->n_rootent, &fattr, NULL, &vp); if (error) return (error); vsetflags(vp, VROOT); np = VTONW(vp); if (nmp->m.root_path[0] == 0) np->n_flag |= NVOLUME; nmp->n_root = np; /* error = VOP_GETATTR(vp, &vattr); if (error) { vput(vp); NCPFATAL("Can't get root directory entry\n"); return error; }*/ *vpp = vp; return (0); }
/* * How to keep the brain busy ... * Currently lookup routine can make two lookup for vnode. This can be * avoided by reorg the code. * * nwfs_lookup(struct vnode *a_dvp, struct vnode **a_vpp, * struct componentname *a_cnp) */ int nwfs_lookup(struct vop_old_lookup_args *ap) { struct componentname *cnp = ap->a_cnp; struct vnode *dvp = ap->a_dvp; struct vnode **vpp = ap->a_vpp; int flags = cnp->cn_flags; struct vnode *vp; struct nwmount *nmp; struct mount *mp = dvp->v_mount; struct nwnode *dnp, *npp; struct nw_entry_info fattr, *fap; ncpfid fid; int nameiop=cnp->cn_nameiop; int lockparent, wantparent, error = 0, notfound; struct thread *td = cnp->cn_td; char _name[cnp->cn_namelen+1]; bcopy(cnp->cn_nameptr,_name,cnp->cn_namelen); _name[cnp->cn_namelen]=0; if (dvp->v_type != VDIR) return (ENOTDIR); if ((flags & CNP_ISDOTDOT) && (dvp->v_flag & VROOT)) { kprintf("nwfs_lookup: invalid '..'\n"); return EIO; } NCPVNDEBUG("%d '%s' in '%s' id=d\n", nameiop, _name, VTONW(dvp)->n_name/*, VTONW(dvp)->n_name*/); if ((mp->mnt_flag & MNT_RDONLY) && nameiop != NAMEI_LOOKUP) return (EROFS); if ((error = VOP_EACCESS(dvp, VEXEC, cnp->cn_cred))) return (error); lockparent = flags & CNP_LOCKPARENT; wantparent = flags & (CNP_LOCKPARENT | CNP_WANTPARENT); nmp = VFSTONWFS(mp); dnp = VTONW(dvp); /* kprintf("dvp %d:%d:%d\n", (int)mp, (int)dvp->v_flag & VROOT, (int)flags & CNP_ISDOTDOT); */ error = ncp_pathcheck(cnp->cn_nameptr, cnp->cn_namelen, &nmp->m.nls, (nameiop == NAMEI_CREATE || nameiop == NAMEI_RENAME) && (nmp->m.nls.opt & NWHP_NOSTRICT) == 0); if (error) return ENOENT; error = 0; *vpp = NULLVP; fap = NULL; if (flags & CNP_ISDOTDOT) { if (NWCMPF(&dnp->n_parent, &nmp->n_rootent)) { fid = nmp->n_rootent; fap = NULL; notfound = 0; } else { error = nwfs_lookupnp(nmp, dnp->n_parent, td, &npp); if (error) { return error; } fid = dnp->n_parent; fap = &fattr; /*np = *npp;*/ notfound = ncp_obtain_info(nmp, npp->n_dosfid, 0, NULL, fap, td, cnp->cn_cred); } } else { fap = &fattr; notfound = ncp_lookup(dvp, cnp->cn_namelen, cnp->cn_nameptr, fap, td, cnp->cn_cred); fid.f_id = fap->dirEntNum; if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { fid.f_parent = dnp->n_fid.f_parent; } else fid.f_parent = dnp->n_fid.f_id; NCPVNDEBUG("call to ncp_lookup returned=%d\n",notfound); } if (notfound && notfound < 0x80 ) return (notfound); /* hard error */ if (notfound) { /* entry not found */ /* Handle RENAME or CREATE case... */ if ((nameiop == NAMEI_CREATE || nameiop == NAMEI_RENAME) && wantparent) { if (!lockparent) vn_unlock(dvp); return (EJUSTRETURN); } return ENOENT; }/* else { NCPVNDEBUG("Found entry %s with id=%d\n", fap->entryName, fap->dirEntNum); }*/ /* handle DELETE case ... */ if (nameiop == NAMEI_DELETE) { /* delete last component */ error = VOP_EACCESS(dvp, VWRITE, cnp->cn_cred); if (error) return (error); if (NWCMPF(&dnp->n_fid, &fid)) { /* we found ourselfs */ vref(dvp); *vpp = dvp; return 0; } error = nwfs_nget(mp, fid, fap, dvp, &vp); if (error) return (error); *vpp = vp; if (!lockparent) vn_unlock(dvp); return (0); } if (nameiop == NAMEI_RENAME && wantparent) { error = VOP_EACCESS(dvp, VWRITE, cnp->cn_cred); if (error) return (error); if (NWCMPF(&dnp->n_fid, &fid)) return EISDIR; error = nwfs_nget(mp, fid, fap, dvp, &vp); if (error) return (error); *vpp = vp; if (!lockparent) vn_unlock(dvp); return (0); } if (flags & CNP_ISDOTDOT) { vn_unlock(dvp); /* race to get the inode */ error = nwfs_nget(mp, fid, NULL, NULL, &vp); if (error) { vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); return (error); } if (lockparent) { error = vn_lock(dvp, LK_EXCLUSIVE | LK_FAILRECLAIM); if (error) { vput(vp); return (error); } } *vpp = vp; } else if (NWCMPF(&dnp->n_fid, &fid)) { vref(dvp); *vpp = dvp; } else { error = nwfs_nget(mp, fid, fap, dvp, &vp); if (error) return (error); *vpp = vp; NCPVNDEBUG("lookup: getnewvp!\n"); if (!lockparent) vn_unlock(dvp); } #if 0 /* XXX MOVE TO NREMOVE */ if ((cnp->cn_flags & CNP_MAKEENTRY)) { VTONW(*vpp)->n_ctime = VTONW(*vpp)->n_vattr.va_ctime.tv_sec; /* XXX */ } #endif return (0); }
static int nwfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred) { struct nwmount *nmp = VTONWFS(vp); int error, i; struct nwnode *np; struct nw_entry_info fattr; struct vnode *newvp; ncpfid fid; ino_t d_ino; size_t d_namlen; const char *d_name; uint8_t d_type; np = VTONW(vp); NCPVNDEBUG("dirname='%s'\n",np->n_name); if (uio->uio_offset < 0 || uio->uio_offset > INT_MAX) return (EINVAL); error = 0; i = (int)uio->uio_offset; /* offset in directory */ if (i == 0) { error = ncp_initsearch(vp, uio->uio_td, cred); if (error) { NCPVNDEBUG("cannot initialize search, error=%d",error); return( error ); } } for (; !error && uio->uio_resid > 0; i++) { switch (i) { case 0: /* `.' */ d_ino = np->n_fid.f_id; if (d_ino == 0) d_ino = NWFS_ROOT_INO; d_namlen = 1; d_name = "."; d_type = DT_DIR; break; case 1: /* `..' */ d_ino = np->n_parent.f_id; if (d_ino == 0) d_ino = NWFS_ROOT_INO; d_namlen = 2; d_name = ".."; d_type = DT_DIR; break; default: error = ncp_search_for_file_or_subdir(nmp, &np->n_seq, &fattr, uio->uio_td, cred); if (error && error < 0x80) goto done; d_ino = fattr.dirEntNum; d_type = (fattr.attributes & aDIR) ? DT_DIR : DT_REG; d_namlen = fattr.nameLen; d_name = fattr.entryName; #if 0 if (error && eofflag) { /* *eofflag = 1;*/ break; } #endif break; } if (nwfs_fastlookup && !error && i > 1) { fid.f_id = fattr.dirEntNum; fid.f_parent = np->n_fid.f_id; error = nwfs_nget(vp->v_mount, fid, &fattr, vp, &newvp); if (!error) { VTONW(newvp)->n_ctime = VTONW(newvp)->n_vattr.va_ctime.tv_sec; vput(newvp); } else error = 0; } if (error >= 0x80) { error = 0; break; } if (vop_write_dirent(&error, uio, d_ino, d_type, d_namlen, d_name)) break; } done: uio->uio_offset = i; return (error); }