Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - kcc-4/lib/usys/stat.c
There are 9 other files named stat.c in the archive. Click here to see a list.
/* [SRI-NIC]SS:<C.LIB.UIO>STAT.C.76, 24-Aug-86 12:23:30, Edit by IAN
   xstat extended stat for T20
   [SRI-NIC]SS:<C.LIB.UIO>STAT.C.42,  3-Jun-86 14:37:53, Edit by IAN
   updated etc
   <KCC.LIB>STAT.C.35, 29-Aug-85 11:23:49, Edit by WHP4
   restructure slightly so fstat() uses fds, not jfns */

/*
** stat(name, buf)
** char *name;
** struct stat *buf;
**
** Greg Satz / Stanford University / 12-Sep-84
** TENEX additions by Ken Harrenstien, SRI 1-Jun-85
*/

#include "c-env.h"
#include "errno.h"
#include "sys/types.h"
#include "sys/file.h"
#include "sys/usysio.h"
#include "sys/usysig.h"
#include "sys/stat.h"
#if SYS_T20+SYS_10X
#include "jsys.h"
#include "sys/time.h"	/* For tadl_to_utime() to convert file times */

extern void _rljfn();
extern int _gtjfn();
static int _stat(), _xstat();
static int t2u_pro(), _gdsts(), _gfust();
#endif

/*
 *	stat(name, buf)
 */

int stat(name, buf)
char *name;
struct stat *buf;
{
#if SYS_T20+SYS_10X
    int jfn, i;

    USYS_BEG();
    if ((jfn = _gtjfn(name, O_RDONLY)) == 0)
	USYS_RETERR(ENOENT);
    i = _stat(jfn, buf);
    _rljfn(jfn);
    USYS_RET(i);
#else /* T20+10X */
#error stat() not supported for this system.
#endif /* Not T20+10X */
}

int xstat(name, buf)
char *name;
struct xstat *buf;
{
#if SYS_T20+SYS_10X
    int jfn, i;

    if ((jfn = _gtjfn(name, O_RDONLY)) == 0)
	USYS_RETERR(ENOENT);
    i = _xstat(jfn, buf);
    _rljfn(jfn);
    USYS_RET(i);
#else /* T20+10X */
#error xstat() not supported for this system.
#endif /* Not T20+10X */
}

int fstat(fd, buf)
int fd;
struct stat *buf;
{
    int ufx;

    USYS_BEG();
    if (fd < 0 || fd >= OPEN_MAX || !(ufx = _uioufx[fd]))
	USYS_RETERR(EBADF);
#if SYS_T20+SYS_10X
    USYS_RETVOLATILE(_stat(_uioch[ufx], buf));
#else /* T20+10X */
#error fstat() not supported for this system.
#endif /* not T20+10X */
}

int xfstat(fd, buf)
int fd;
struct xstat *buf;
{
    int ufx;

    if (fd < 0 || fd >= OPEN_MAX || !(ufx = _uioufx[fd]))
	USYS_RETERR(EBADF);
#if SYS_T20+SYS_10X
    USYS_RETVOLATILE(_xstat(_uioch[ufx], buf));
#else
#error xfstat() not supported for this system.
#endif
}
/*
 *	_stat(jfn, buf) - worker routine for stat() and fstat()
 *	_xstat(jfn, xbuf) - do above plus device dependent stuff
 */

static int _stat(jfn, buf)
int jfn;
struct stat *buf;
{
#if SYS_T20+SYS_10X
    int i, time, fdb[_FBLEN];
    char name[FILEPART_SIZE];
    unsigned protection;

    if (jfn == _PRIIN) _get_pio(&jfn, 0);	/* in case redirected */
    else if (jfn == _PRIOU) _get_pio(0, &jfn);
    _gt_all_fdb(jfn, fdb);			/* get the whole FDB */
    buf->st_dev = _dvtype(jfn);
    buf->st_ino = fdb[_FBADR];			/* disk address */
    buf->st_mode = 0;
    protection = fdb[_FBCTL];
    buf->st_mode |= ((protection & FB_DIR) ? S_IFDIR : S_IFREG);
    protection = fdb[_FBPRT];			/* protection */
    i = (protection & T20_OWNER_MASK) >> T20_OWNER_OFFSET;
    buf->st_mode |= (t2u_pro(i) >> UNIX_OWNER_OFFSET);
    i = (protection & T20_GROUP_MASK) >> T20_GROUP_OFFSET;
    buf->st_mode |= (t2u_pro(i) >> UNIX_GROUP_OFFSET);
    i = (protection & T20_WORLD_MASK) >> T20_WORLD_OFFSET;
    buf->st_mode |= (t2u_pro(i) >> UNIX_WORLD_OFFSET);
    buf->st_nlink = 1;				/* can it be anything else? */
#if SYS_10X
    i = fdb[_FBUSE];
    buf->st_uid = ((unsigned) i >> 18);		/* Get LH (directory #) */
#endif
#if SYS_T20
    _gfust(jfn, _GFAUT, name);
    buf->st_uid = _rcusr(name);
#endif
    buf->st_gid = 0;			/* for now */
    buf->st_rdev = 0;			/* no major/minor devices on tops */
    buf->st_size = fdb[_FBSIZ];
    buf->st_atime = tadl_to_utime(fdb[_FBREF]);
    buf->st_mtime = fdb[_FBCRE];
    time = fdb[_FBCRV];
    if (buf->st_mtime < time)
	buf->st_mtime = time;
    time = fdb[_FBWRT];
    if (buf->st_mtime < time)
	buf->st_mtime = time;
    buf->st_mtime = tadl_to_utime(buf->st_mtime);
    buf->st_ctime = buf->st_mtime;
    return 0;				/* success */
#else /* T20+10X */
    return -1;				/* Not implemented elsewhere yet */
#endif /* Not T20+10X */
}

static int _xstat(jfn, buf)
int jfn;
struct xstat *buf;
{
#if SYS_T20+SYS_10X
    int ablock[5];
    if (jfn == _PRIIN) _get_pio(&jfn, 0);	/* in case redirected */
    else if (jfn == _PRIOU) _get_pio(0, &jfn);
    if (_stat(jfn, &buf->st))			/* get primary stuff */
	return -1;				/* failed! */
    switch (buf->st.st_dev) {			/* device-dependant stuff */
	case ST_DEV_DSK:
	    buf->xst_version = _gtfdb(jfn, _FBGEN) >> 18;
	    buf->xst_pagcnt = _gtfdb(jfn, _FBBYV) & RH; break;
	case ST_DEV_TCP:
	    _gdsts(jfn, &buf->xst_state, &buf->xst_fhost, &buf->xst_fport);
    }
    return 0;
#else
    return -1;
#endif
}

#if SYS_T20+SYS_10X
/*
 *	get primary JFNs for ourself
 */


int _get_pio(i, o)
int *i, *o;
{
    int ac[5];

    ac[1] = _FHSLF;		/* "Self" process handle */
    if (jsys(GPJFN, ac)) {
	if (i) *i = ((unsigned) ac[2]) >> 18;
	if (o) *o = ac[2] & RH;
	return 1;
    } else return 0;
}

/*
 *	Takes TOPS-20 protections right justified and returns Unix protections
 *	right justified.
 */

static int t2u_pro(prot)
unsigned prot;
{
    int i = 0;

    if (prot & FP_READ)		i |= S_IREAD;
    if (prot & FP_WRITE)	i |= S_IWRITE;
    if (prot & FP_EXECUTE)	i |= S_IEXEC;
    return i;
}

/*
 *	_GTFDB() - read (and return) a word from a file's fdb
 *	this routine is exported, don't make it static!
 */

int _gtfdb(jfn, word)
int jfn, word;
{
    int temp, arg_block[5];

    arg_block[1] = jfn;
    arg_block[2] = (1 << 18) + word;
    arg_block[3] = 3;				/* put the value in AC3 */
    return (jsys(GTFDB, arg_block)) ? arg_block[3] : 0;
}

static int _gt_all_fdb(jfn, block)
int jfn, *block;
{
    int ablock[5];

    ablock[1] = jfn;
    ablock[2] = (_FBLEN << 18);		/* all words, start at 0 (RH) */
    ablock[3] = (int) block;		/* put them here */
    return jsys(GTFDB, ablock);
}

/*
 *	_gdsts(jfn, a, b, c) - get device status stuff.
 *	int jfn, *a, *b, *c;
 *
 *		Stores the ACs returned by GDSTS%
 */

static int _gdsts(jfn, a, b, c)
int jfn, *a, *b, *c;
{
    int ablock[5];

    ablock[1] = jfn;
    if (!jsys(GDSTS, ablock)) return 0;
    if (a) *a = ablock[2];
    if (b) *b = ablock[3];
    if (c) *c = ablock[4];
    return 1;
}

/*
 *	Get device characteristics
 */

int _dvtype(jfn)
int jfn;
{
    unsigned ablock[5];

    ablock[1] = jfn;
    return (jsys(DVCHR, ablock)) ? ((ablock[2] >> DV_TYP_S) & DV_TYP_M) : -1;
}

/*
 *	Get file user
 */

static int _gfust(jfn, func, name)
int jfn, func;
char *name;
{
    int ablock[5];

    ablock[1] = (func << 18) | jfn;
    ablock[2] = (-1 << 18) | (unsigned) name;
    return jsys(GFUST, ablock);
}

/*
 *	Return username number for given user name
 */

int _rcusr(name)
char *name;
{
    int ablock[5];

    ablock[1] = RC_EMO;
    ablock[2] = (int) (name - 1);
    if (!jsys(RCUSR, ablock) || (ablock[1] & RC_NOM))  /* jsys error */
	return -1;
    return ablock[3];
}
#endif /* T20+10X */