|
|
coherent
/*
* system calls introduced by the 386 port
*
* Copyright (c) Ciaran O'Donnell, Bievres (FRANCE), 1991
*/
#include <sys/coherent.h>
#include <sys/buf.h>
#include <errno.h>
#include <canon.h>
#include <sys/con.h>
#include <fcntl.h>
#include <sys/fd.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/io.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/dir.h>
#include <sys/dirent.h>
#include <sys/utsname.h>
#include <sys/mount.h>
#include <ustat.h>
#include <sys/statfs.h>
utime(tp)
long *tp;
{
return timer.t_time;
}
/*
* Return an unique number.
*/
usysi86(f, arg1, arg2, arg3)
{
register MOUNT *mp;
register struct filsys *fsp;
switch (f) {
case SYI86UNEEK:
if ((mp=getment(rootdev, 1)) == NULL)
return;
fsp = &mp->m_super;
fsp->s_fmod = 1;
return (++fsp->s_unique);
case 40:
/*
* bit 2: floating point is present (80287/80387)
* bit 1: 80387 is present
*/
if (!useracc(arg1, sizeof(int))) {
SET_U_ERROR(EFAULT, "sysi386:40");
return;
}
putuwd(arg1, 0);
break;
}
}
ushmsys(func, arg1, arg2, arg3)
int func, arg1, arg2, arg3;
{
switch(func){
#if 0
case 0: return ushmat(arg1, arg2, arg3);
case 1: return ushmdt(arg1);
#endif
case 2: return ushmctl(arg1, arg2, arg3);
case 3: return ushmget(arg1, arg2, arg3);
default: u.u_error = EINVAL;
}
}
usemsys(func, arg1, arg2, arg3, arg4)
int func, arg1, arg2, arg3, arg4;
{
switch(func){
case 0: return usemctl(arg1, arg2, arg3, arg4);
case 1: return usemget(arg1, arg2, arg3);
case 2: return usemop(arg1, arg2, arg3);
default: u.u_error = EINVAL;
}
}
/*
* uname and ustat system calls.
*
* int uname(struct utsname *name)
* Before lcall instruction 4(%esp) contains name, 8(%esp) contains
* an unspecified value, and 12(%esp) contains the value 0.
*
* int ustat(int dev, struct ustat *buf)
* Before lcall instruction 4(%esp) contains buf (REVERSE order of argument)
* 8(%esp) contains dev, and 12(%esp) contains the value 0.
*/
uutssys(arg1, arg2, func)
{
switch(func) {
case 0: return uname(arg1);
case 2: return u_ustat(arg2, arg1);
default:u.u_error = EINVAL;
}
}
/*
* uname - get name of the current operating system.
*/
extern char version[]; /* Defined in main.c */
extern char release[]; /* Defined in main.c */
uname(name)
struct utsname *name;
{
register char *rcp; /**/
register int i; /* Counter, loop index */
register INODE *ip; /* /etc/uucpname inode */
BUF *bp; /* Read buffer */
char namebuf[SYS_NMLN]; /* System name */
int fl; /* File length*/
/* Check if *name is an available user area */
if (!useracc((char *) name, sizeof(struct utsname))) {
u.u_error = EFAULT;
return(0);
}
/* Find the size of the version number */
for (rcp = version, i = 0; *rcp != '\0' && i < SYS_NMLN; i++, rcp++)
;
/* Write version number to user area */
if (!kucopy(version, name->version, i))
return(0);
/* Find the size of the release number */
for (rcp = release, i = 0; *rcp != '\0' && i < SYS_NMLN; i++, rcp++)
;
/* Write release number to user area */
if (!kucopy(release, name->release, i))
return;
/* Write "machine" to user area */
if (!kucopy("i386", name->machine, 4))
return;
/* We supposed that system name and nodename are in /etc/uucpname */
if (ftoi("/etc/uucpname", 'r') != 0)
return(sys_unknown(name));
ip = u.u_cdiri;
if ((fl = ip->i_size) == 0) {
idetach(ip);
return(sys_unknown(name));
}
if (iaccess(ip, IPR) == 0) {
idetach(ip);
return;
}
if ((bp = vread(ip, (daddr_t) 0)) == NULL) {
brelease(bp);
idetach(ip);
return;
}
/* namebuf should be not more than SYS_NMLN - 1 characters long */
fl = (fl > SYS_NMLN) ? SYS_NMLN : fl;
kkcopy(bp->b_vaddr, namebuf, fl);
brelease(bp);
idetach(ip);
if (fl == 1 && namebuf[0] == '\n')
return(sys_unknown(name));
for (rcp = namebuf, i = 0; i < fl; rcp++) {
i++;
if (*rcp == '\n') {
*rcp = '\0';
break;
}
}
namebuf[i - 1] = '\0';
/* Write system name to user area */
if (!kucopy(namebuf, name->sysname, i))
return(0);
/* Write system name to user area */
if (!kucopy(namebuf, name->nodename, i))
return(0);
return 0;
}
/*
* sys_unknown - write name unknown to utsname struct
*/
char unknown[] = "UNKNOWN";
sys_unknown(name)
struct utsname *name;
{
if (!kucopy(unknown, name->sysname, sizeof(unknown)))
return;
if (!kucopy(unknown, name->nodename, sizeof(unknown)))
return;
}
/*
* u_ustat - get file system statistics. (Name ustat in use for stat s.c.)
*/
u_ustat(dev, buf)
dev_t dev;
struct ustat *buf;
{
register MOUNT *mp;
/* Check if buf is an available user area. */
/* B_READ | B_WRITE is not implemented yet. */
if (!useracc((char *) buf, sizeof(struct ustat))) {
u.u_error = EFAULT;
return;
}
/* Take mount filesystem, check if dev is mounted device */
for (mp = mountp; mp != NULL; mp = mp->m_next)
if (mp->m_dev == dev)
break;
if (mp == NULL) {
u.u_error = EINVAL;
return;
}
/* Pickup information from superblock */
/* Number of free blocks */
if (!kucopy(&(mp->m_super.s_tfree), &(buf->f_tfree),
sizeof(mp->m_super.s_tfree)))
return;
/* Number of free inodes */
if (!kucopy(&(mp->m_super.s_tinode), &(buf->f_tinode),
sizeof(mp->m_super.s_tinode)))
return;
/* File system name */
if (!kucopy(mp->m_super.s_fname, buf->f_fname,
sizeof(mp->m_super.s_fname)))
return;
/* File system pack name */
if (!kucopy(mp->m_super.s_fpack, buf->f_fpack,
sizeof(mp->m_super.s_fpack)))
return;
}
umsgsys(func, arg1, arg2, arg3, arg4, arg5)
{
switch (func) {
case 0: return umsgget(arg1, arg2);
case 1: return umsgctl(arg1, arg2, arg3);
case 2: return umsgrcv(arg1, arg2, arg3, arg4, arg5);
case 3: return umsgsnd(arg1, arg2, arg3, arg4);
default:u.u_error = EINVAL;
}
}
uulimit()
{
u.u_error = EINVAL;
}
/*
* Remove a directory.
*/
urmdir(path)
char *path;
{
register INODE *ip;
int isdirempty();
if (ftoi(path, 'r') != 0)
return;
ip = u.u_cdiri;
/* Check if path is a directory */
if ((ip->i_mode & IFMT) != IFDIR) {
idetach(ip);
SET_U_ERROR(ENOTDIR, "rmdir: no such file or directory");
return;
}
/* We have to check if directory is empty */
if (!isdirempty(ip)) {
idetach(ip);
SET_U_ERROR(EEXIST, "rmdir: directory is not empty");
return;
}
idetach(ip);
removedir(path);
return (u.u_error);
}
/*
* remove a directory entry.
* path is a pointer to user area.
*/
removedir(path)
char *path;
{
char buf[512];
char *cpbuf, /* to internal file_name buffer */
*cppath; /* to user file_name buffer */
/* Write path to a kernel buffer buf */
cpbuf = buf;
cppath = path;
while ((*cpbuf = getubd(cppath)) != '\0') {
cppath++;
if (++cpbuf >= &buf[sizeof(buf) - 3]) {
SET_U_ERROR(ENOENT, "rmdir: path too long");
return;
}
}
*cpbuf++ = '/';
*cpbuf++ = '.';
*cpbuf = '\0';
u.u_io.io_seg = IOSYS;
dunlink(buf);
*cpbuf++ = '.';
*cpbuf = '\0';
dunlink(buf);
u.u_io.io_seg = IOUSR;
dunlink(path);
return;
}
/*
* Unlink the given directory.
*/
dunlink(np)
char *np;
{
register INODE *ip;
register dev_t dev;
if (ftoi(np, 'u') != 0)
return;
ip = u.u_pdiri;
if (iaccess(ip, IPW) == 0) {
u.u_error = EACCES;
goto err;
}
dev = ip->i_dev;
if (diucheck(dev, u.u_cdirn) == 0)
goto err;
idirent(0);
idetach(ip);
if ((ip=iattach(dev, u.u_cdirn)) == NULL)
return;
if (ip->i_nlink > 0)
--ip->i_nlink;
icrt(ip); /* unlink - ctime */
err:
idetach(ip);
return (0);
}
/*
* This is a copy of iucheck. The only one difference is that that allows
* to remove a directory to a regular user.
*/
diucheck(dev, ino)
register dev_t dev;
register ino_t ino;
{
register INODE *ip;
INODE inode;
for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) {
if (ip->i_ino==ino && ip->i_dev==dev)
break;
}
if (ip < inodep) {
ip = &inode;
ip->i_dev = dev;
ip->i_ino = ino;
if (icopydm(ip) == 0)
return (0);
}
return (1);
}
/*
* Check if directory is empty.
*/
int isdirempty(ip)
register INODE *ip;
{
register char *cp;
int count;
BUF *bp;
for (count = 0; count < ip->i_size; count += 512) {
if ((bp = vread(ip, count)) == NULL)
break;
for (cp = (char *) bp->b_vaddr;
cp < (char *) bp->b_vaddr + BSIZE; cp += 16) {
if (*cp == '\0' && *(cp + 1) == '\0')
continue;
if (*(cp + 2) != '.')
goto bad;
if (*(cp + 3) == '\0')
continue;
if (*(cp + 3) != '.' || *(cp + 4) != '\0')
goto bad;
}
brelease(bp);
}
return 1;
bad:
brelease(bp);
return 0;
}
/*
* SysV compatible mkdir() system call.
*
* Create a directory of the given "path" and "mode", if possible.
* Creating the directory is straight forward. Trying to clean
* up in case we run out of inodes or freee blocks in the process
* is not trivial.
* This system call was implemented in very press time.
* Vlad 6-04-92
*/
umkdir(path, mode)
char *path;
int mode;
{
INODE *dmknod(); /* make directory node */
register INODE *pip; /* parent inode pointer */
register char *cp_path,
*cpb_path,
*cp_dot,
*cp_dotdot,
*cp_parent;
char bufpath[512],
bufdot[512],
bufdotdot[512],
bufparent[512];
int uid;
int error;
/*
* Create a local copies of "path" which we can use to build up
* the required directory links:
* path/. -- bufdot
* path/..-- bufdotdot
* Verify that the given path is not too long.
*/
cp_path = path;
cpb_path = bufpath;
cp_dot = bufdot;
cp_dotdot = bufdotdot;
cp_parent = bufparent;
while ((*cpb_path = getubd(cp_path)) != '\0') {
*cp_dot++ = *cp_dotdot++ = *cp_parent++ = *cpb_path;
++cp_path;
if (++cpb_path >= &bufpath[sizeof(bufpath) - 3]) {
SET_U_ERROR(ENOENT, "sys5: mkdir: path too long");
return;
}
}
while (--cp_parent >= bufparent) {
if (*cp_parent == '/') {
*++cp_parent = '\0';
break;
}
}
if (cp_parent < bufparent) {
*++cp_parent = '.';
*++cp_parent = '\0';
}
*cp_dotdot++ = *cp_dot++ = '/';
*cp_dotdot++ = *cp_dot++ = '.';
*cp_dotdot++ = '.';
*cp_dotdot = *cp_dot = '\0';
u.u_io.io_seg = IOSYS;
u.u_io.io_seg = IOUSR;
if ((pip = dmknod(path, mode)) == NULL) {
return;
}
u.u_io.io_seg = IOSYS;
/* Now we can switch our id to root. It allows to use existing
* functions.
*/
uid = u.u_uid;
u.u_uid = 0;
ulink(bufpath, bufdot);
if (u.u_error) {
error = u.u_error;
u.u_error = 0;
uunlink(bufpath);
u.u_error = 0;
u.u_io.io_seg = IOUSR;
u.u_uid = uid;
u.u_error = error;
return;
}
ulink(bufparent, bufdotdot);
if (u.u_error) {
error = u.u_error;
u.u_error = 0;
uunlink(bufdot);
printf("unlink %s errno is %d\n", bufdot, u.u_error);
u.u_error = 0;
uunlink(bufpath);
printf("unlink %s errno is %d\n", bufpath, u.u_error);
u.u_uid = uid;
u.u_io.io_seg = IOUSR;
u.u_error = error;
return;
}
u.u_io.io_seg = IOUSR;
return(0);
}
/*
* Create a directory.
* We cannot use original ulink because it makes the directories only for
* superuser.
*/
INODE *dmknod(np, mode)
char *np; /* Direcotory name */
int mode;
{
register INODE *ip, *pip;
register int type;
type = (mode & ~IFMT);
type |= S_IFDIR;
if (ftoi(np, 'c') != 0)
return NULL;
if ((ip=u.u_cdiri) != NULL) {
SET_U_ERROR(EEXIST, "sys5: path already exist")
idetach(ip);
return NULL;
}
if ((ip=imake(type, (dev_t) 0)) != NULL)
idetach(ip);
pip = u.u_pdiri; /* grab ptr to parent inode */
return pip;
}
/*
* Get directory entry in file system independent format.
*/
ugetdents(fd, bp, n)
int fd; /* File descriptor to an open directory */
char *bp; /* Buffer where entries should be read */
unsigned n; /* Number of bytes to be read */
{
struct direct r_dir;
unsigned bytes; /* Number of bytes */
struct dirent sd;
ino_t inode; /* Inode number */
unsigned short ofnm; /* Offset to file name in dirent */
char *cw,
*cr;
int minbuf; /* Minimum possible size of the bp */
int i, mod;
int entry;
char ends[3] = "";
int total = 0;
cw = &bp[0];
ofnm = sizeof(sd.d_ino) + sizeof(sd.d_off) + sizeof(sd.d_reclen);
/* Find minimum possible size of bp. It should be enough to contain the
* header of dirent, file name + '\0', and be on a sizeof(long)
* boundary.
*/
entry = ofnm + DIRSIZ + 1;
mod = entry % sizeof(long);
minbuf = entry + (mod ? sizeof(long) - mod : 0);
/* Is user buffer available? */
if (!useracc(bp, n) || n < minbuf) {
u.u_error = EFAULT;
return(0);
}
while(n - (cw - bp) >= minbuf) {
/* Read next entry from the directory.
* inode == 0 for rm(ed) entries
*/
do {
if ((bytes = dirio(fd, &r_dir, sizeof(struct direct),
&sd.d_off)) == 0) {
return(total);
}
inode = r_dir.d_ino;
} while (!inode);
/* Find the size of file name */
for (cr = r_dir.d_name, i = 0; *cr != '\0' && i < DIRSIZ;
i++, cr++)
;
/* Copy file name */
if (!kucopy(r_dir.d_name, cw + ofnm, i))
return(0);
/* Write '\0' */
putubd(cw + ofnm + i++, '\0');
/* Round up to long boundary */
if (mod = (ofnm + i) % sizeof(long))
if (!kucopy(ends, cw + ofnm + i, sizeof(long) - mod))
return(0);
sd.d_ino = r_dir.d_ino;
sd.d_reclen = ofnm + i; /* Size of directory entry */
if (mod)
sd.d_reclen += sizeof(long) - mod;
if (!kucopy(&sd, cw, ofnm))
return(0);
total += sd.d_reclen;
cw += sd.d_reclen;
}
return(total);
}
/*
* Read `n' bytes from the directory `fd' using the buffer `bp'.
*/
dirio(fd, bp, n, offset)
struct direct *bp;
unsigned n;
off_t *offset;
{
register FD *fdp;
register INODE *ip;
/* Check file descriptor */
if ((fdp = fdget(fd)) == NULL)
return (0);
if (((fdp->f_flag & IPR)) == 0) {
u.u_error = EBADF;
return (0);
}
ip = fdp->f_ip;
if ((ip->i_mode & IFMT) != IFDIR) {
u.u_error = EBADF;
return(0);
}
ilock(ip); /* We do not want file changes during the read */
u.u_io.io_seek = fdp->f_seek;
u.u_io.io.vbase = (vaddr_t) bp;
u.u_io.io_ioc = n;
u.u_io.io_flag = (fdp->f_flag & IPNDLY) ? IONDLY : 0;
iread(ip, &u.u_io);
iacc(ip); /* read - atime */
n -= u.u_io.io_ioc;
*offset = fdp->f_seek;
fdp->f_seek += n;
iunlock(ip);
return (n);
}
/*
* Get file system information by file name.
*/
ustatfs(path, stfs, len, fstyp)
char *path; /* File name */
struct statfs *stfs; /* Pointer to a user structure */
int len; /* Size of the structure */
int fstyp; /* File system type */
{
struct filsys *statmount(); /* Get mp for mounted device */
struct filsys *statunmount(); /* Get mp for unmounted device */
struct filsys *sb; /* Pointer to superblock */
int count = 0; /* Number of copied bytes */
short systype = 1; /* System type */
long bsize = BSIZE; /* Block size */
long frsize = 0; /* Fragment size */
/* Check if stfs is an available user area. */
if (!useracc((char *) stfs, len)) {
u.u_error = EFAULT;
return;
}
/* Filesystem type is 1 for 512 bytes blocks. */
count += sizeof(systype);
if (count > len)
return;
if (!kucopy(&(systype), &(stfs->f_fstyp), sizeof(systype)))
return;
/* Block size */
count += sizeof(bsize);
if (count > len)
return;
if (!kucopy(&(bsize), &(stfs->f_bsize), sizeof(bsize)))
return;
/* Fragment size. */
count += sizeof(int);
if (count > len)
return;
if (!kucopy(&(frsize), &(stfs->f_frsize), sizeof(frsize)))
return;
if (!fstyp) {
if ((sb = statmount(-1, path)) == NULL)
return;
devinfo(sb, stfs, len, &count);
} else {
if ((sb = statunmount(-1, path)) == NULL)
return;
devinfo(sb, stfs, len, &count);
kfree(sb);
}
return;
}
/*
* statmount - get superblock for mounted file system.
* fd - file descriptor or -1, path - file name or NULL.
*/
struct filsys *statmount(fd, path)
int fd;
char *path;
{
register INODE *ip; /* Structure inode */
register FD *fdp;
register MOUNT *mp; /* Pointer to device */
dev_t device; /* Mounted device */
/* Find the device */
if (path != NULL) { /* Find ip by file name */
if (ftoi(path, 'r') != 0)
return NULL;
ip = u.u_cdiri;
device = ip->i_dev;
idetach(ip);
} else { /* Find ip by file descriptor */
if ((fdp = fdget(fd)) == NULL)
return NULL;
if (((fdp->f_flag & IPR)) == 0) {
u.u_error = EBADF;
return NULL;
}
ip = fdp->f_ip;
device = ip->i_dev;
}
/* Take mount filesystem, check if dev is mounted device */
for (mp = mountp; mp != NULL; mp = mp->m_next)
if (mp->m_dev == device)
break;
if (mp == NULL) {
u.u_error = EINVAL;
return NULL;
}
return &mp->m_super;
}
/*
* devinfo() write system information to user area
*/
devinfo(sb, stfs, len, count)
struct filsys *sb; /* File name */
struct statfs *stfs; /* Pointer to a user structure */
int len; /* Size of the structure */
int *count;
{
long inode;
/* Total number of blocks */
*count += sizeof(sb->s_fsize);
if (*count > len)
return;
if (!kucopy(&(sb->s_fsize), &(stfs->f_blocks),
sizeof(sb->s_fsize)))
return;
/* Count of free blocks */
*count += sizeof(sb->s_tfree);
if (*count > len)
return;
if (!kucopy(&(sb->s_tfree), &(stfs->f_bfree),
sizeof(sb->s_tfree)))
return;
/* Total number of file inodes */
*count += sizeof(inode);
if (*count > len)
return;
inode = (long) (sb->s_isize - INODEI) * INOPB;
if (!kucopy(&inode, &(stfs->f_files), sizeof(inode)))
return;
/* Number of free inodes */
*count += sizeof(inode);
if (*count > len)
return;
inode = sb->s_tinode;
if (!kucopy(&inode, &(stfs->f_ffree), sizeof(inode)))
return;
/* Volume name */
*count += sizeof(sb->s_fname);
if (*count > len)
return;
if (!kucopy(sb->s_fname, stfs->f_fname,
sizeof(sb->s_fpack)))
return;
/* Pack name */
*count += sizeof(sb->s_fpack);
if (*count > len)
return;
if (!kucopy(sb->s_fpack, stfs->f_fpack,
sizeof(sb->s_fpack)))
return;
}
/*
* statunmount - get superblock for unmounted file system.
* fd - file descriptor or -1, path - file name or NULL.
*/
struct filsys *statunmount(fd, path)
int fd; /* File descriptor */
char *path; /* File name */
{
register INODE *ip;
register MOUNT *mp;
register dev_t rdev;
FD *fdp;
int mode;
BUF *bp;
struct filsys *sb;
/* Find the device */
if (path != NULL) { /* Find ip by file name */
if (ftoi(path, 'r') != 0)
return NULL;
ip = u.u_cdiri;
mode = ip->i_mode;
rdev = ip->i_a.i_rdev;
idetach(ip);
} else { /* Find ip by file descriptor */
if ((fdp = fdget(fd)) == NULL)
return NULL;
if (((fdp->f_flag & IPR)) == 0) {
u.u_error = EBADF;
return NULL;
}
ip = fdp->f_ip;
ilock(ip);
mode = ip->i_mode;
rdev = ip->i_a.i_rdev;
iunlock(ip);
}
/* Check for block special device */
if ((mode & IFMT) != IFBLK) {
u.u_error = ENOTBLK;
return NULL;
}
/* Check if device is mounted device */
for (mp = mountp; mp != NULL; mp = mp->m_next) {
if (mp->m_dev == rdev) {
u.u_error = EBUSY;
return NULL;
}
}
dopen(rdev, IPR, DFBLK);
if (u.u_error)
return NULL;
if ((bp = bread(rdev, (daddr_t) SUPERI, 1)) == NULL) {
dclose(rdev);
return NULL;
}
dclose(rdev);
if ((sb = kalloc(sizeof(struct filsys))) == NULL)
return (NULL);
kkcopy(bp->b_vaddr, sb, sizeof(struct filsys));
brelease(bp);
cansuper(sb); /* canonicalize supperblock */
if (tstf(sb) == 0) { /* check for consistency */
kfree(sb);
u.u_error = EINVAL;
return(NULL);
}
return(sb);
}
/*
* Get file system information by file descriptor
*/
ufstatfs(fildes, stfs, len, fstyp)
int fildes; /* File descriptor */
struct statfs *stfs; /* Pointer to a user structure */
int len; /* Size of the structure */
int fstyp; /* File system type */
{
struct filsys *statmount(); /* Get mp for mounted device */
struct filsys *statunmount(); /* Get mp for unmounted device */
struct filsys *sb; /* Pointer to superblock */
int count = 0; /* Number of copied bytes */
short systype = 1; /* System type */
long bsize = BSIZE; /* Block size */
long frsize = 0; /* Fragment size */
/* Check if stfs is an available user area. */
if (!useracc((char *) stfs, len)) {
u.u_error = EFAULT;
return;
}
/* Filesystem type is 1 for 512 bytes blocks. */
count += sizeof(systype);
if (count > len)
return;
if (!kucopy(&(systype), &(stfs->f_fstyp), sizeof(systype)))
return;
/* Block size */
count += sizeof(bsize);
if (count > len)
return;
if (!kucopy(&(bsize), &(stfs->f_bsize), sizeof(bsize)))
return;
/* Fragment size. */
count += sizeof(int);
if (count > len)
return;
if (!kucopy(&(frsize), &(stfs->f_frsize), sizeof(frsize)))
return;
if (!fstyp) {
if ((sb = statmount(fildes, NULL)) == NULL)
return;
devinfo(sb, stfs, len, &count);
} else {
if ((sb = statunmount(fildes, NULL)) == NULL)
return;
devinfo(sb, stfs, len, &count);
kfree(sb);
}
return;
}
/*
* Check superblock for consistency.
*/
tstf(fp)
register struct filsys *fp;
{
register daddr_t *dp;
register ino_t *ip;
register ino_t maxinode;
maxinode = (fp->s_isize - INODEI) * INOPB + 1;
if (fp->s_isize >= fp->s_fsize)
return (0);
if (fp->s_tfree < fp->s_nfree
|| fp->s_tfree >= fp->s_fsize - fp->s_isize + 1)
return (0);
if (fp->s_tinode < fp->s_ninode
|| fp->s_tinode >= maxinode-1)
return (0);
for (dp = &fp->s_free[0]; dp < &fp->s_free[fp->s_nfree]; dp += 1)
if (*dp < fp->s_isize || *dp >= fp->s_fsize)
return (0);
for (ip = &fp->s_inode[0]; ip < &fp->s_inode[fp->s_ninode]; ip += 1)
if (*ip < 1 || *ip > maxinode)
return (0);
return (1);
}
/* the following calls are not in the BCS */
uadmin()
{
u.u_error = EINVAL;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.