static long exacct(int code, idtype_t idtype, id_t id, void *buf, size_t bufsize, int flags) { if (secpolicy_acct(CRED()) != 0) return (set_errno(EPERM)); if (exacct_zone_key == ZONE_KEY_UNINITIALIZED) return (set_errno(ENOTACTIVE)); switch (code) { case 0: return (getacct(idtype, id, buf, bufsize)); case 1: return (putacct(idtype, id, buf, bufsize, flags)); case 2: return (wracct(idtype, id, flags)); default: return (set_errno(EINVAL)); } }
/* * Perform process accounting functions. */ int sysacct(char *fname) { struct acct_globals *ag; struct vnode *vp; int error = 0; if (secpolicy_acct(CRED()) != 0) return (set_errno(EPERM)); ag = zone_getspecific(acct_zone_key, curproc->p_zone); ASSERT(ag != NULL); if (fname == NULL) { /* * Close the file and stop accounting. */ mutex_enter(&ag->aclock); vp = ag->acctvp; ag->acctvp = NULL; mutex_exit(&ag->aclock); if (vp) { error = VOP_CLOSE(vp, FWRITE, 1, (offset_t)0, CRED(), NULL); VN_RELE(vp); } return (error == 0 ? 0 : set_errno(error)); } /* * Either (a) open a new file and begin accounting -or- (b) * switch accounting from an old to a new file. * * (Open the file without holding aclock in case it * sleeps (holding the lock prevents process exit).) */ if ((error = vn_open(fname, UIO_USERSPACE, FWRITE, 0, &vp, (enum create)0, 0)) != 0) { /* SVID compliance */ if (error == EISDIR) error = EACCES; return (set_errno(error)); } if (vp->v_type != VREG) { error = EACCES; } else { mutex_enter(&acct_list_lock); if (acct_find(vp, B_FALSE)) { error = EBUSY; } else { mutex_enter(&ag->aclock); if (ag->acctvp) { vnode_t *oldvp; /* * close old acctvp, and point acct() * at new file by swapping vp and acctvp */ oldvp = ag->acctvp; ag->acctvp = vp; vp = oldvp; } else { /* * no existing file, start accounting .. */ ag->acctvp = vp; vp = NULL; } mutex_exit(&ag->aclock); } mutex_exit(&acct_list_lock); } if (vp) { (void) VOP_CLOSE(vp, FWRITE, 1, (offset_t)0, CRED(), NULL); VN_RELE(vp); } return (error == 0 ? 0 : set_errno(error)); }