Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_FS_1_19910112
-
c/its/lib/usys/stat.c
There are 9 other files named stat.c in the archive. Click here to see a list.
/* -*-C-*-
* STAT - stat, fstat, xstat, xfstat
* Also provides _dvtype
*
* Edits for ITS: Copyright (C) 1988 Alan Bawden
*/
/* [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();
#elif SYS_ITS
#include "sysits.h"
#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, 0);
_rljfn(jfn);
USYS_RET(i);
#elif SYS_ITS
int fd, i;
USYS_BEG();
if ((fd = open(name, O_RDONLY, 0)) < 0)
USYS_RETERR(ENOENT);
/* Most device-independent way to avoid setting reference date: */
SYSCALL1("resrdt", _uioch[_uioufx[fd]]);
i = fstat(fd);
close(fd);
USYS_RET(i);
#else
#error stat() not supported for this system.
#endif /* Not T20+10X+ITS */
}
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, 0);
_rljfn(jfn);
USYS_RET(i);
#elif SYS_ITS
int fd, i;
USYS_BEG();
if ((fd = open(name, O_RDONLY, 0)) < 0)
USYS_RETERR(ENOENT);
/* Most device-independent way to avoid setting reference date: */
SYSCALL1("resrdt", _uioch[_uioufx[fd]]);
i = xfstat(fd);
close(fd);
USYS_RET(i);
#else
#error xstat() not supported for this system.
#endif /* Not T20+10X+ITS */
}
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+SYS_ITS
USYS_RETVOLATILE(_stat(_uioch[ufx], buf, ufx));
#else
#error fstat() not supported for this system.
#endif /* not T20+10X+ITS */
}
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+SYS_ITS
USYS_RETVOLATILE(_xstat(_uioch[ufx], buf, ufx));
#else
#error xfstat() not supported for this system.
#endif /* not T20+10X+ITS */
}
/*
* _stat(jfn, buf, ufx) - worker routine for stat() and fstat()
* _xstat(jfn, xbuf, ufx) - do above plus device dependent stuff
*/
static int
_stat(jfn, buf, ufx)
int jfn, ufx;
struct stat *buf;
{
#if SYS_T20+SYS_10X
int i, fdb[_FBLEN], bytsiz;
char name[FILEPART_SIZE];
unsigned protection;
int acs[5];
if (jfn == _PRIIN) _get_pio(&jfn, 0); /* in case redirected */
else if (jfn == _PRIOU) _get_pio(0, &jfn);
acs[1] = jfn;
acs[2] = _FBLEN << 18; /* get the whole FDB */
acs[3] = (int) fdb;
if (!jsys(GTFDB, acs))
return -1;
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_atime = tadl_to_utime(fdb[_FBREF]);
buf->st_mtime = tadl_to_utime(fdb[_FBWRT]);
buf->st_ctime = tadl_to_utime(fdb[_FBCRE]);
/* Set size vars. */
/* TOPS-20 has several stupid screws with respect to newly created files,
** or files being updated. Newly created files don't actually exist until
** they have been CLOSF%'d, so the FDB size information is all 0. open()
** attempts to circumvent this by doing a quick CLOSF/OPENF; however, then
** the update problem comes up, because TOPS-20 doesn't update the FDB
** size info until a CLOSF% is done after writing!! If we are writing the
** file ourselves, we look at our own info to see what's up.
*/
buf->st_size = fdb[_FBSIZ]; /* First try what FDB has */
bytsiz = (fdb[_FBBYV]>>24)&077; /* Get FDB bytesize */
buf->st_blksize = bytsiz ? ((36/bytsiz) * 512) : 0; /* # bytes in page */
buf->st_blocks = fdb[_FBBYV]&RH; /* # pages (blocks) in file */
if (ufx) { /* Have it open ourselves? */
if (bytsiz > _uiobsize[ufx]) { /* Yes, check bytesize info */
/* This takes care of 36-bit bytesize files */
buf->st_size = buf->st_size * (bytsiz/_uiobsize[ufx]);
bytsiz = _uiobsize[ufx];
}
if (buf->st_size < _uiopos[ufx]) /* If our len info is better */
buf->st_size = _uiopos[ufx]; /* update it! */
buf->st_blksize = (36/bytsiz) * 512; /* # bytes in page */
i = (buf->st_size + buf->st_blksize-1) / buf->st_blksize;
if (buf->st_blocks < i) /* If our page info better */
buf->st_blocks = i; /* # pages (blocks) in file */
}
return 0; /* success */
#else /* T20+10X */
return -1; /* Not implemented elsewhere yet */
#endif /* Not T20+10X */
}
static int _xstat(jfn, buf, ufx)
int jfn, ufx;
struct xstat *buf;
{
#if SYS_T20+SYS_10X
int fbbyv, 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, ufx)) /* 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;
fbbyv = _gtfdb(jfn, _FBBYV);
buf->xst_pagcnt = fbbyv & RH;
buf->xst_bytsiz = (fbbyv << FBBSZ_S) & FBBSZ_M;
break;
case ST_DEV_TCP:
_gdsts(jfn, &buf->xst_state, &buf->xst_fhost, &buf->xst_fport);
break;
}
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;
}
/*
* _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] = (int)(name-1);
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];
}
#elif SYS_ITS
/*
* Get device type
*/
int _dvtype(chan)
int chan;
{
unsigned status;
SYSCALL2_LOSE("status", chan, SC_VAL(&status)); /* can't fail */
switch (status & 077) {
case 000:
case 001:
case 002:
return _DVTTY;
case 060:
case 061:
return _DVUSR;
default:
return _DVDSK;
}
}
#endif