static int linux_unlink_dircheck(const char *path) { struct nameidata nd; struct pathbuf *pb; int error; /* * Linux returns EISDIR if unlink(2) is called on a directory. * We return EPERM in such cases. To emulate correct behaviour, * check if the path points to directory and return EISDIR if this * is the case. * * XXX this should really not copy in the path buffer twice... */ error = pathbuf_copyin(path, &pb); if (error) { return error; } NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb); if (namei(&nd) == 0) { struct stat sb; if (vn_stat(nd.ni_vp, &sb) == 0 && S_ISDIR(sb.st_mode)) error = EISDIR; vput(nd.ni_vp); } pathbuf_destroy(pb); return error ? error : EPERM; }
int linux_newstat(struct proc *p, struct linux_newstat_args *args) { struct stat buf; struct nameidata nd; int error; caddr_t sg; sg = stackgap_init(); CHECKALTEXIST(p, &sg, args->path); #ifdef DEBUG printf("Linux-emul(%ld): newstat(%s, *)\n", (long)p->p_pid, args->path); #endif NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, args->path, p); error = namei(&nd); if (error) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); error = vn_stat(nd.ni_vp, &buf, p); vput(nd.ni_vp); if (error) return (error); return (newstat_copyout(&buf, args->buf)); }
/* * MPSAFE */ static int vn_statfile(struct file *fp, struct stat *sb, struct ucred *cred) { struct vnode *vp; int error; vp = (struct vnode *)fp->f_data; error = vn_stat(vp, sb, cred); return (error); }
/* * File table vnode stat routine. */ static int vn_statfile(file_t *fp, struct stat *sb) { struct vnode *vp = fp->f_data; int error; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); error = vn_stat(vp, sb); VOP_UNLOCK(vp); return error; }
static int verify_file(struct ucred *cred, struct vnode *vp) { char buffer[256]; char hash[SHA256_DIGEST_LENGTH > uECC_BYTES ? SHA256_DIGEST_LENGTH : uECC_BYTES]; char signature[2*uECC_BYTES]; int error, len; ssize_t resid; off_t i, size; SHA256_CTX ctx; struct stat stat; i = 0; error = vn_stat(vp, &stat, cred, NOCRED, curthread); size = stat.st_size; if (error) return (EPERM); len = sizeof(signature); error = vn_extattr_get(vp, IO_NODELOCKED, EXTATTR_NAMESPACE_SYSTEM, "signature", &len, signature, curthread); if (error) return (EPERM); #ifdef DEBUG printf("Signature: "); print_hex(signature, sizeof(signature)); #endif SHA256_Init(&ctx); while(i < size && !error) { len = size - i > sizeof(buffer) ? sizeof(buffer) : size - i; error = vn_rdwr(UIO_READ, vp, buffer, len, i, UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED, &resid, curthread); SHA256_Update(&ctx, buffer, len); i += len; } if (error) return (EPERM); SHA256_Final(hash, &ctx); #ifdef DEBUG printf("Hash: "); print_hex(hash, sizeof(hash)); #endif if (!uECC_verify(pubkey, hash, signature)) return (EPERM); return (0); }
int kern_file_size(struct file *fp, off_t *size) { struct vnode *vp = (struct vnode *)fp->f_data; struct stat sb; int rc; rc = vn_stat(vp, &sb, current_proc()); if (rc) { *size = 0; return rc; } *size = sb.st_size; return 0; }
/* * fhstat_args(struct fhandle *u_fhp, struct dfbsd12_stat *sb) * * MPALMOSTSAFE */ int sys_dfbsd12_fhstat(struct dfbsd12_fhstat_args *uap) { struct thread *td = curthread; struct dfbsd12_stat osb; struct stat sb; fhandle_t fh; struct mount *mp; struct vnode *vp; int error; /* * Must be super user */ error = priv_check(td, PRIV_ROOT); if (error) return (error); error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); if (error) return (error); get_mplock(); if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) { error = ESTALE; goto done; } if ((error = VFS_FHTOVP(mp, NULL, &fh.fh_fid, &vp))) goto done; error = vn_stat(vp, &sb, td->td_ucred); vput(vp); if (error) goto done; cvtstat(&osb, &sb); error = copyout(&osb, uap->sb, sizeof(osb)); done: rel_mplock(); return (error); }
int compat_30_netbsd32_fhstat(struct lwp *l, const struct compat_30_netbsd32_fhstat_args *uap, register_t *retval) { /* { syscallarg(const netbsd32_fhandlep_t) fhp; syscallarg(netbsd32_stat13p_t) sb; } */ struct stat sb; struct netbsd32_stat13 sb32; int error; struct compat_30_fhandle fh; struct mount *mp; struct vnode *vp; /* * Must be super user */ if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FILEHANDLE, 0, NULL, NULL, NULL))) return (error); if ((error = copyin(SCARG_P32(uap, fhp), &fh, sizeof(fh))) != 0) return (error); if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) return (ESTALE); if (mp->mnt_op->vfs_fhtovp == NULL) return EOPNOTSUPP; if ((error = VFS_FHTOVP(mp, (struct fid*)&fh.fh_fid, &vp))) return (error); error = vn_stat(vp, &sb); vput(vp); if (error) return (error); netbsd32_from___stat13(&sb, &sb32); error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb)); return (error); }
/* * File table wrapper for vn_stat */ int vn_statfile(struct file *fp, struct stat *sb, struct proc *p) { struct vnode *vp = (struct vnode *)fp->f_data; return vn_stat(vp, sb, p); }
int maruioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { ENTERSC(dev); DB("maruioctl(%d, %ld, %p, %d, %p)\n", dev, cmd, data, flag, p); switch (cmd) { case MARUIOCATTACH: { struct maru_ioc_attach *ma = (struct maru_ioc_attach *)data; int fd = ma->ma_kue_fd; struct filedesc *fdp = p->p_fd; struct file *fp; int err; struct stat st; struct kue_kapi *kapi; if (ma->ma_size < 512 * 16 * 32) EXITSC(EINVAL); if (fd>=fdp->fd_nfiles || (fp=fdp->fd_ofiles[fd]) == NULL) EXITSC(EBADF); if (fp->f_type != DTYPE_VNODE) EXITSC(ENOENT); /* some fool handed us a socket */ /* ok, so, this is cheating a little :) */ err = vn_stat((struct vnode *)fp->f_data, &st, p); if (err) EXITSC(err); /* pull in a pointer to the kue kernel api. we need * this hack in order to avoid nasty limitations in netbsd's * kernel linker: symbols from one module * are not linked against symbols from another, only * the kernel image. we splinter a little wood */ err = fp->f_ops->fo_ioctl(fp, KUEIOCGKAPI, (caddr_t)&kapi, p); DB("post ioctl"); if (err) EXITSC(err); DB("post ioctl:2"); /* now install our hooks of evil */ sc->sc_kapi = kapi; DB("post ioctl:3"); kapi->ka_read2_hook = maru_kue_read2_callback; DB("post ioctl:4"); kapi->ka_free_hook = maru_kue_free_callback; kapi->ka_write_hook = maru_kue_write_callback; disk_attach(&sc->sc_dkdev); memcpy(&sc->sc_size, &ma->ma_size, sizeof sc->sc_size); sc->sc_flags|=MUF_INITED; maru_getdisklabel(sc); } break; case DIOCGDINFO: maru_getdefaultlabel(sc, (struct disklabel*)data); break; case DIOCGPART: ((struct partinfo *)data)->disklab = sc->sc_dkdev.dk_label; ((struct partinfo *)data)->part = &sc->sc_dkdev.dk_label->d_partitions[DISKPART(dev)]; break; case DIOCWDINFO: case DIOCSDINFO: { int err; sc->sc_flags |= MUF_LABELING; /* marustrategy maybe called by writedisklabel() */ err = setdisklabel(sc->sc_dkdev.dk_label, (struct disklabel *)data, 0, sc->sc_dkdev.dk_cpulabel); if (!err) { if (cmd == DIOCWDINFO) err = writedisklabel(MARULABELDEV(dev), marustrategy, sc->sc_dkdev.dk_label, sc->sc_dkdev.dk_cpulabel); } sc->sc_flags &= ~MUF_LABELING; if (err) EXITSC(err); } break; case DIOCWLABEL: if (*(int *)data != 0) sc->sc_flags |= MUF_WLABEL; else sc->sc_flags &= ~MUF_WLABEL; break; case DIOCGDEFLABEL: maru_getdefaultlabel(sc, (struct disklabel*)data); break; default: return (ENOTTY); } EXITSC(0); }
/* ARGSUSED */ int compat_43_sys_lstat(struct lwp *l, const struct compat_43_sys_lstat_args *uap, register_t *retval) { /* { syscallarg(char *) path; syscallarg(struct ostat *) ub; } */ struct vnode *vp, *dvp; struct stat sb, sb1; struct stat43 osb; int error; struct pathbuf *pb; struct nameidata nd; int ndflags; error = pathbuf_copyin(SCARG(uap, path), &pb); if (error) { return error; } ndflags = NOFOLLOW | LOCKLEAF | LOCKPARENT | TRYEMULROOT; again: NDINIT(&nd, LOOKUP, ndflags, pb); if ((error = namei(&nd))) { if (error == EISDIR && (ndflags & LOCKPARENT) != 0) { /* * Should only happen on '/'. Retry without LOCKPARENT; * this is safe since the vnode won't be a VLNK. */ ndflags &= ~LOCKPARENT; goto again; } pathbuf_destroy(pb); return (error); } /* * For symbolic links, always return the attributes of its * containing directory, except for mode, size, and links. */ vp = nd.ni_vp; dvp = nd.ni_dvp; pathbuf_destroy(pb); if (vp->v_type != VLNK) { if ((ndflags & LOCKPARENT) != 0) { if (dvp == vp) vrele(dvp); else vput(dvp); } error = vn_stat(vp, &sb); vput(vp); if (error) return (error); } else { error = vn_stat(dvp, &sb); vput(dvp); if (error) { vput(vp); return (error); } error = vn_stat(vp, &sb1); vput(vp); if (error) return (error); sb.st_mode &= ~S_IFDIR; sb.st_mode |= S_IFLNK; sb.st_nlink = sb1.st_nlink; sb.st_size = sb1.st_size; sb.st_blocks = sb1.st_blocks; } cvtstat(&sb, &osb); error = copyout((void *)&osb, (void *)SCARG(uap, ub), sizeof (osb)); return (error); }
/* * module_load_plist_vfs: * * Load a plist located in the file system into memory. */ static int module_load_plist_vfs(const char *modpath, const bool nochroot, prop_dictionary_t *filedictp) { struct pathbuf *pb; struct nameidata nd; struct stat sb; void *base; char *proppath; const size_t plistsize = 8192; size_t resid; int error, pathlen; KASSERT(filedictp != NULL); base = NULL; proppath = PNBUF_GET(); strcpy(proppath, modpath); pathlen = strlen(proppath); if ((pathlen >= 6) && (strcmp(&proppath[pathlen - 5], ".kmod") == 0)) { strcpy(&proppath[pathlen - 5], ".plist"); } else if (pathlen < MAXPATHLEN - 6) { strcat(proppath, ".plist"); } else { error = ENOENT; goto out1; } /* XXX this makes an unnecessary extra copy of the path */ pb = pathbuf_create(proppath); if (pb == NULL) { error = ENOMEM; goto out1; } NDINIT(&nd, LOOKUP, FOLLOW | (nochroot ? NOCHROOT : 0), pb); error = vn_open(&nd, FREAD, 0); if (error != 0) { goto out2; } error = vn_stat(nd.ni_vp, &sb); if (error != 0) { goto out3; } if (sb.st_size >= (plistsize - 1)) { /* leave space for term \0 */ error = EFBIG; goto out3; } base = kmem_alloc(plistsize, KM_SLEEP); if (base == NULL) { error = ENOMEM; goto out3; } error = vn_rdwr(UIO_READ, nd.ni_vp, base, sb.st_size, 0, UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, curlwp); *((uint8_t *)base + sb.st_size) = '\0'; if (error == 0 && resid != 0) { error = EFBIG; } if (error != 0) { kmem_free(base, plistsize); base = NULL; goto out3; } *filedictp = prop_dictionary_internalize(base); if (*filedictp == NULL) { error = EINVAL; } kmem_free(base, plistsize); base = NULL; KASSERT(error == 0); out3: VOP_UNLOCK(nd.ni_vp); vn_close(nd.ni_vp, FREAD, kauth_cred_get()); out2: pathbuf_destroy(pb); out1: PNBUF_PUT(proppath); return error; }
static int devfs_fo_stat(struct file *fp, struct stat *sb, struct ucred *cred) { struct vnode *vp; struct vattr vattr; struct vattr *vap; u_short mode; cdev_t dev; int error; vp = (struct vnode *)fp->f_data; if (vp == NULL || vp->v_type == VBAD) return EBADF; error = vn_stat(vp, sb, cred); if (error) return (error); vap = &vattr; error = VOP_GETATTR(vp, vap); if (error) return (error); /* * Zero the spare stat fields */ sb->st_lspare = 0; sb->st_qspare1 = 0; sb->st_qspare2 = 0; /* * Copy from vattr table ... or not in case it's a cloned device */ if (vap->va_fsid != VNOVAL) sb->st_dev = vap->va_fsid; else sb->st_dev = vp->v_mount->mnt_stat.f_fsid.val[0]; sb->st_ino = vap->va_fileid; mode = vap->va_mode; mode |= S_IFCHR; sb->st_mode = mode; if (vap->va_nlink > (nlink_t)-1) sb->st_nlink = (nlink_t)-1; else sb->st_nlink = vap->va_nlink; sb->st_uid = vap->va_uid; sb->st_gid = vap->va_gid; sb->st_rdev = dev2udev(DEVFS_NODE(vp)->d_dev); sb->st_size = vap->va_bytes; sb->st_atimespec = vap->va_atime; sb->st_mtimespec = vap->va_mtime; sb->st_ctimespec = vap->va_ctime; /* * A VCHR and VBLK device may track the last access and last modified * time independantly of the filesystem. This is particularly true * because device read and write calls may bypass the filesystem. */ if (vp->v_type == VCHR || vp->v_type == VBLK) { dev = vp->v_rdev; if (dev != NULL) { if (dev->si_lastread) { sb->st_atimespec.tv_sec = time_second + (time_uptime - dev->si_lastread); sb->st_atimespec.tv_nsec = 0; } if (dev->si_lastwrite) { sb->st_atimespec.tv_sec = time_second + (time_uptime - dev->si_lastwrite); sb->st_atimespec.tv_nsec = 0; } } } /* * According to www.opengroup.org, the meaning of st_blksize is * "a filesystem-specific preferred I/O block size for this * object. In some filesystem types, this may vary from file * to file" * Default to PAGE_SIZE after much discussion. */ sb->st_blksize = PAGE_SIZE; sb->st_flags = vap->va_flags; error = priv_check_cred(cred, PRIV_VFS_GENERATION, 0); if (error) sb->st_gen = 0; else sb->st_gen = (u_int32_t)vap->va_gen; sb->st_blocks = vap->va_bytes / S_BLKSIZE; return (0); }