/* * Given a locked directory vnode, iterate over the names in the directory * and use ufs_extattr_lookup() to retrieve locked vnodes of potential * attribute files. Then invoke ufs_extattr_enable_with_open() on each * to attempt to start the attribute. Leaves the directory locked on * exit. */ static int ufs_extattr_iterate_directory(struct ufsmount *ump, struct vnode *dvp, int attrnamespace, struct thread *td) { struct vop_readdir_args vargs; struct dirent *dp, *edp; struct vnode *attr_vp; struct uio auio; struct iovec aiov; char *dirbuf; int error, eofflag = 0; if (dvp->v_type != VDIR) return (ENOTDIR); dirbuf = malloc(DIRBLKSIZ, M_TEMP, M_WAITOK); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_SYSSPACE; auio.uio_td = td; auio.uio_offset = 0; vargs.a_gen.a_desc = NULL; vargs.a_vp = dvp; vargs.a_uio = &auio; vargs.a_cred = td->td_ucred; vargs.a_eofflag = &eofflag; vargs.a_ncookies = NULL; vargs.a_cookies = NULL; while (!eofflag) { auio.uio_resid = DIRBLKSIZ; aiov.iov_base = dirbuf; aiov.iov_len = DIRBLKSIZ; error = ufs_readdir(&vargs); if (error) { printf("ufs_extattr_iterate_directory: ufs_readdir " "%d\n", error); return (error); } /* * XXXRW: While in UFS, we always get DIRBLKSIZ returns from * the directory code on success, on other file systems this * may not be the case. For portability, we should check the * read length on return from ufs_readdir(). */ edp = (struct dirent *)&dirbuf[DIRBLKSIZ]; for (dp = (struct dirent *)dirbuf; dp < edp; ) { #if (BYTE_ORDER == LITTLE_ENDIAN) dp->d_type = dp->d_namlen; dp->d_namlen = 0; #else dp->d_type = 0; #endif if (dp->d_reclen == 0) break; error = ufs_extattr_lookup(dvp, UE_GETDIR_LOCKPARENT, dp->d_name, &attr_vp, td); if (error) { printf("ufs_extattr_iterate_directory: lookup " "%s %d\n", dp->d_name, error); } else if (attr_vp == dvp) { vrele(attr_vp); } else if (attr_vp->v_type != VREG) { vput(attr_vp); } else { error = ufs_extattr_enable_with_open(ump, attr_vp, attrnamespace, dp->d_name, td); vrele(attr_vp); if (error) { printf("ufs_extattr_iterate_directory: " "enable %s %d\n", dp->d_name, error); } else if (bootverbose) { printf("UFS autostarted EA %s\n", dp->d_name); } } dp = (struct dirent *) ((char *)dp + dp->d_reclen); if (dp >= edp) break; } } free(dirbuf, M_TEMP); return (0); }
/* * Given a locked directory vnode, iterate over the names in the directory * and use ufs_extattr_lookup() to retrieve locked vnodes of potential * attribute files. Then invoke ufs_extattr_enable_with_open() on each * to attempt to start the attribute. Leaves the directory locked on * exit. */ static int ufs_extattr_iterate_directory(struct ufsmount *ump, struct vnode *dvp, int attrnamespace, struct thread *td) { struct vop_readdir_args vargs; struct dirent *dp, *edp; struct vnode *attr_vp; struct uio auio; struct iovec aiov; char *dirbuf; int error, eofflag = 0; if (dvp->v_type != VDIR) return (ENOTDIR); dirbuf = malloc(DIRBLKSIZ, M_TEMP, M_WAITOK); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_SYSSPACE; auio.uio_td = td; auio.uio_offset = 0; vargs.a_gen.a_desc = NULL; vargs.a_vp = dvp; vargs.a_uio = &auio; vargs.a_cred = td->td_ucred; vargs.a_eofflag = &eofflag; vargs.a_ncookies = NULL; vargs.a_cookies = NULL; while (!eofflag) { auio.uio_resid = DIRBLKSIZ; aiov.iov_base = dirbuf; aiov.iov_len = DIRBLKSIZ; error = ufs_readdir(&vargs); if (error) { printf("ufs_extattr_iterate_directory: ufs_readdir " "%d\n", error); return (error); } edp = (struct dirent *)&dirbuf[DIRBLKSIZ - auio.uio_resid]; for (dp = (struct dirent *)dirbuf; dp < edp; ) { if (dp->d_reclen == 0) break; error = ufs_extattr_lookup(dvp, UE_GETDIR_LOCKPARENT, dp->d_name, &attr_vp, td); if (error) { printf("ufs_extattr_iterate_directory: lookup " "%s %d\n", dp->d_name, error); } else if (attr_vp == dvp) { vrele(attr_vp); } else if (attr_vp->v_type != VREG) { vput(attr_vp); } else { error = ufs_extattr_enable_with_open(ump, attr_vp, attrnamespace, dp->d_name, td); vrele(attr_vp); if (error) { printf("ufs_extattr_iterate_directory: " "enable %s %d\n", dp->d_name, error); } else if (bootverbose) { printf("UFS autostarted EA %s\n", dp->d_name); } } dp = (struct dirent *) ((char *)dp + dp->d_reclen); if (dp >= edp) break; } } free(dirbuf, M_TEMP); return (0); }
/* * Given a locked directory vnode, iterate over the names in the directory * and use ufs_extattr_lookup() to retrieve locked vnodes of potential * attribute files. Then invoke ufs_extattr_enable_with_open() on each * to attempt to start the attribute. Leaves the directory locked on * exit. */ static int ufs_extattr_iterate_directory(struct ufsmount *ump, struct vnode *dvp, int attrnamespace, struct proc *p) { struct vop_readdir_args vargs; struct dirent *dp, *edp; struct vnode *attr_vp; struct uio auio; struct iovec aiov; char *dirbuf; int error, eofflag = 0; if (dvp->v_type != VDIR) return (ENOTDIR); MALLOC(dirbuf, char *, DIRBLKSIZ, M_TEMP, M_WAITOK); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_SYSSPACE; auio.uio_procp = p; auio.uio_offset = 0; vargs.a_desc = NULL; vargs.a_vp = dvp; vargs.a_uio = &auio; vargs.a_cred = p->p_ucred; vargs.a_eofflag = &eofflag; vargs.a_ncookies = NULL; vargs.a_cookies = NULL; while (!eofflag) { auio.uio_resid = DIRBLKSIZ; aiov.iov_base = dirbuf; aiov.iov_len = DIRBLKSIZ; error = ufs_readdir(&vargs); if (error) { printf("ufs_extattr_iterate_directory: ufs_readdir " "%d\n", error); return (error); } edp = (struct dirent *)&dirbuf[DIRBLKSIZ]; for (dp = (struct dirent *)dirbuf; dp < edp; ) { #if (BYTE_ORDER == LITTLE_ENDIAN) dp->d_type = dp->d_namlen; dp->d_namlen = 0; #else dp->d_type = 0; #endif if (dp->d_reclen == 0) break; error = ufs_extattr_lookup(dvp, UE_GETDIR_LOCKPARENT, dp->d_name, &attr_vp, p); if (error) { printf("ufs_extattr_iterate_directory: lookup " "%s %d\n", dp->d_name, error); } else if (attr_vp == dvp) { vrele(attr_vp); } else if (attr_vp->v_type != VREG) { /* * Eventually, this will be uncommented, but in the mean time, the ".." * entry causes unnecessary console warnings. printf("ufs_extattr_iterate_directory: " "%s not VREG\n", dp->d_name); */ vput(attr_vp); } else { error = ufs_extattr_enable_with_open(ump, attr_vp, attrnamespace, dp->d_name, p); vrele(attr_vp); if (error) { printf("ufs_extattr_iterate_directory: " "enable %s %d\n", dp->d_name, error); } else { /* * While it's nice to have some visual output here, skip for the time-being. * Probably should be enabled by -v at boot. printf("Autostarted %s\n", dp->d_name); */ printf("Autostarted %s\n", dp->d_name); /* XXX - debug*/ } } dp = (struct dirent *) ((char *)dp + dp->d_reclen); if (dp >= edp) break; } } FREE(dirbuf, M_TEMP); return (0); }