2021-10-11 18:20:23 -03:00

233 lines
4.6 KiB
C

/* @(#)tmp_subr.c 1.1 92/07/30 SMI */
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <debug/debug.h>
#include <vm/anon.h>
#include <vm/seg_map.h>
#include <sys/time.h>
#include <sys/vnode.h>
#include <sys/vfs.h>
#include <sys/ucred.h>
#include <tmpfs/tmp.h>
#include <tmpfs/tmpnode.h>
newnode(t, mode, uid, gid)
struct tmpnode *t;
u_int mode;
uid_t uid;
gid_t gid;
{
t->tn_attr.va_mode = mode;
t->tn_attr.va_uid = uid;
t->tn_attr.va_gid = gid;
t->tn_attr.va_rdev = 0;
created(t);
}
created(t)
struct tmpnode *t;
{
modified(t);
t->tn_attr.va_ctime = t->tn_attr.va_mtime;
}
modified(t)
struct tmpnode *t;
{
accessed(t);
t->tn_attr.va_mtime = t->tn_attr.va_atime;
}
accessed(t)
struct tmpnode *t;
{
extern struct timeval time;
t->tn_attr.va_atime = time;
}
isparent(from, to)
struct tmpnode *from;
struct tmpnode *to;
{
int error;
struct tmpnode *prev_tp, *curr_tp;
struct ucred rootcred;
rootcred.cr_uid = 0;
curr_tp = to;
tmpnode_get(curr_tp);
while (from != curr_tp) {
error = tdirlookup(curr_tp, "..", &prev_tp, &rootcred);
if (error) {
tmpnode_put(curr_tp);
return (0);
}
if (curr_tp == prev_tp) { /* at root */
tmpnode_put(curr_tp);
tmpnode_put(prev_tp);
return (0);
}
tmpnode_put(curr_tp);
curr_tp = prev_tp;
}
tmpnode_put(curr_tp);
return (1);
}
#define MODESHIFT 3
taccess(tp, cred, access)
struct tmpnode *tp;
struct ucred *cred;
int access;
{
/*
* Superuser always gets access
*/
if (cred->cr_uid == 0)
return (0);
/*
* Check access based on owner, group and
* public permissions in tmpnode.
*/
if (cred->cr_uid != tp->tn_attr.va_uid) {
access >>= MODESHIFT;
if (ingroup(tp->tn_attr.va_gid, cred) == 0)
access >>= MODESHIFT;
}
if ((tp->tn_attr.va_mode & access) == access)
return (0);
return (EACCES);
}
ingroup(gid, cred)
gid_t gid;
struct ucred *cred;
{
int i;
if (gid == cred->cr_gid) {
return (1);
}
for (i = 0; i < NGROUPS && cred->cr_groups[i] != NOGROUP; i++) {
if (gid == cred->cr_groups[i]) {
return (1);
}
}
return (0);
}
/*
* alloc index numbers (inode #) for a new tmpfs file.
* vfs_getnum() does part of the job for us. hope no one hacks on it.
*/
long
tmpimapalloc(tm)
register struct tmount *tm;
{
register struct tmpimap *tmapp;
register int i, bitnum;
for (i = 0, tmapp = &tm->tm_inomap; tmapp;
i++, tmapp = tmapp->timap_next) {
if ((bitnum = vfs_getnum((char *)tmapp->timap_bits,
TMPIMAPSIZE)) != -1)
return ((i*TMPIMAPNODES)+bitnum);
if (tmapp->timap_next == (struct tmpimap *)NULL)
tmapp->timap_next = (struct tmpimap *)tmp_memalloc(tm,
sizeof (struct tmpimap));
}
return (-1);
}
/*
* free index number of a (being destroyed) tmpfs file
* vfs_putnum() does part of the job for us. hope no one hacks on it.
* XXX should free allocated tmpimap struct memory when files free up
*/
tmpimapfree(tm, number)
register struct tmount *tm;
register long number;
{
register int i;
register struct tmpimap *tmapp;
void vfs_putnum();
#ifdef TMPFSDEBUG
if (tmpfsdebug || tmpdirdebug)
printf("tmpimapfree: freeing tm %x number %d index %d\n", tm,
number, (number % TMPIMAPNODES));
#endif TMPFSDEBUG
for (i = 1, tmapp = &tm->tm_inomap; tmapp;
i++, tmapp = tmapp->timap_next) {
if (number < i*TMPIMAPNODES) { /* this is our map! */
vfs_putnum((char *)tmapp->timap_bits,
(int)(number % TMPIMAPNODES));
return (0);
}
}
return (-1);
}
/*
* tmpfs kernel memory allocation
* does some bookkeeping, calls kmem_zalloc() for the honey
*/
char *
tmp_memalloc(tm, size)
register struct tmount *tm;
register u_int size;
{
extern u_int tmpfs_maxkmem;
extern int tmp_kmemspace;
#ifdef TMPFSDEBUG
extern func_t caller();
#endif TMPFSDEBUG
#ifdef TMPFSDEBUG
if (tmpdebugalloc)
printf("tmp_memalloc: tm %x size %x\n", tm, size);
#endif TMPFSDEBUG
if ((tm->tm_kmemspace + size) < tmpfs_maxkmem) {
tm->tm_kmemspace += size;
tmp_kmemspace += size;
return (new_kmem_zalloc(size, KMEM_SLEEP));
}
#ifdef TMPFSDEBUG
if (tmpdebugerrs)
printf("tmp_memalloc: out of space. Called by %x\n", caller());
#endif TMPFSDEBUG
return (NULL);
}
/*
* tmpfs kernel memory freer
* does some bookkeeping, calls kmem_free()
*/
void
tmp_memfree(tm, cp, size)
register struct tmount *tm;
register char *cp;
register u_int size;
{
#ifdef TMPFSDEBUG
if (tmpdebugalloc)
printf("tmp_memfree: tm %x cp %x size %d\n", tm, cp, size);
#endif TMPFSDEBUG
if (tm->tm_kmemspace < size) {
panic("tmp_memfree()- bad memory bookkeeping");
}
kmem_free(cp, size);
tm->tm_kmemspace -= size;
tmp_kmemspace -= size;
}