/*
- * Copyright (c) 1982 Regents of the University of California.
+ * Copyright (c) 1982, 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
- * @(#)sys.c 6.3 (Berkeley) %G%
+ * @(#)sys.c 7.7 (Berkeley) %G%
*/
-#include "../h/param.h"
-#include "../h/inode.h"
-#include "../h/fs.h"
-#include "../h/dir.h"
+#include "param.h"
+#include "inode.h"
+#include "fs.h"
+#include "dir.h"
+#include "reboot.h"
#include "saio.h"
+#define isdigit(c) ((u_int)((c) - '0') <= 9)
+#define isspace(c) ((c) == ' ' || (c) == '\t')
+#define isupper(c) ((u_int)((c) - 'A') <= 'Z' - 'A')
+#define tolower(c) ((c) - 'A' + 'a')
+
ino_t dlook();
struct dirstuff {
struct iob *io;
};
+struct iob iob[NFILES];
+
static
openi(n, io)
register struct iob *io;
struct iob *file;
{
register char *q;
- char c;
+ char *dir, c;
int n;
- if (path==NULL || *path=='\0') {
+ if (path == NULL || *path == '\0') {
printf("null path\n");
return (0);
}
printf("can't read root inode\n");
return (0);
}
+ dir = path;
while (*path) {
while (*path == '/')
path++;
q++;
c = *q;
*q = '\0';
+ if (q == path) path = "." ; /* "/" means "/." */
- if ((n = dlook(path, file)) != 0) {
+ if ((n = dlook(path, file, dir)) != 0) {
if (c == '\0')
break;
if (openi(n, file) < 0)
path = q;
continue;
} else {
- printf("%s not found\n", path);
+ printf("%s: not found\n", path);
return (0);
}
}
return (n);
}
+#define NBUFS 4
+static char b[NBUFS][MAXBSIZE];
+static daddr_t blknos[NBUFS];
+
static daddr_t
sbmap(io, bn)
register struct iob *io;
}
static ino_t
-dlook(s, io)
+dlook(s, io, dir)
char *s;
register struct iob *io;
+ char *dir;
{
register struct direct *dp;
register struct inode *ip;
return (0);
ip = &io->i_ino;
if ((ip->i_mode&IFMT) != IFDIR) {
- printf("not a directory\n");
+ printf("%s: not a directory\n", dir);
return (0);
}
if (ip->i_size == 0) {
- printf("zero length directory\n");
+ printf("%s: zero length directory\n", dir);
return (0);
}
len = strlen(s);
lbn = lblkno(&io->i_fs, dirp->loc);
d = sbmap(io, lbn);
if(d == 0)
- return NULL;
+ return (NULL);
io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
io->i_ma = io->i_buf;
io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn);
if (devread(io) < 0) {
errno = io->i_error;
- printf("bn %D: read error\n", io->i_bn);
+ printf("bn %D: directory read error\n",
+ io->i_bn);
return (NULL);
}
}
{
register struct iob *io;
- if (ptr != 0) {
+#ifndef SMALL
+ if (ptr != L_SET) {
printf("Seek not from beginning of file\n");
errno = EOFFSET;
return (-1);
}
+#endif
fdesc -= 3;
if (fdesc < 0 || fdesc >= NFILES ||
((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
return (c);
}
-/* does this port?
-getw(fdesc)
- int fdesc;
-{
- register w,i;
- register char *cp;
- int val;
-
- for (i = 0, val = 0, cp = &val; i < sizeof(val); i++) {
- w = getc(fdesc);
- if (w < 0) {
- if (i == 0)
- return (-1);
- else
- return (val);
- }
- *cp++ = w;
- }
- return (val);
-}
-*/
int errno;
read(fdesc, buf, count)
int fdesc, count;
char *buf;
{
- register i;
+ register i, size;
register struct iob *file;
+ register struct fs *fs;
+ int lbn, off;
errno = 0;
if (fdesc >= 0 & fdesc <= 2) {
errno = EBADF;
return (-1);
}
+#ifndef SMALL
if ((file->i_flgs & F_FILE) == 0) {
file->i_cc = count;
file->i_ma = buf;
file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
i = devread(file);
- file->i_offset += count;
if (i < 0)
errno = file->i_error;
+ else
+ file->i_offset += i;
return (i);
- } else {
- if (file->i_offset+count > file->i_ino.i_size)
- count = file->i_ino.i_size - file->i_offset;
- if ((i = count) <= 0)
- return (0);
- do {
- *buf++ = getc(fdesc+3);
- } while (--i);
- return (count);
}
+#endif
+ if (file->i_offset+count > file->i_ino.i_size)
+ count = file->i_ino.i_size - file->i_offset;
+ if ((i = count) <= 0)
+ return (0);
+ /*
+ * While reading full blocks, do I/O into user buffer.
+ * Anything else uses getc().
+ */
+ fs = &file->i_fs;
+ while (i) {
+ off = blkoff(fs, file->i_offset);
+ lbn = lblkno(fs, file->i_offset);
+ size = blksize(fs, &file->i_ino, lbn);
+ if (off == 0 && size <= i) {
+ file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
+ file->i_boff;
+ file->i_cc = size;
+ file->i_ma = buf;
+ if (devread(file) < 0) {
+ errno = file->i_error;
+ return (-1);
+ }
+ file->i_offset += size;
+ file->i_cc = 0;
+ buf += size;
+ i -= size;
+ } else {
+ size -= off;
+ if (size > i)
+ size = i;
+ i -= size;
+ do {
+ *buf++ = getc(fdesc+3);
+ } while (--size);
+ }
+ }
+ return (count);
}
+#ifndef SMALL
write(fdesc, buf, count)
int fdesc, count;
char *buf;
errno = file->i_error;
return (i);
}
+#endif
int openfirst = 1;
+u_int opendev; /* last device opened */
+extern u_int bootdev;
open(str, how)
char *str;
int how;
{
- register char *cp;
- int i;
+ register char *t;
+ register int cnt;
register struct iob *file;
- register struct devsw *dp;
- int fdesc;
- long atol();
+ int fdesc, args[8], *argp;
if (openfirst) {
- for (i = 0; i < NFILES; i++)
- iob[i].i_flgs = 0;
+ for (cnt = 0; cnt < NFILES; cnt++)
+ iob[cnt].i_flgs = 0;
openfirst = 0;
}
- for (fdesc = 0; fdesc < NFILES; fdesc++)
- if (iob[fdesc].i_flgs == 0)
- goto gotfile;
- _stop("No more file slots");
-gotfile:
- (file = &iob[fdesc])->i_flgs |= F_ALLOC;
-
- for (cp = str; *cp && *cp != '('; cp++)
- ;
- if (*cp != '(') {
- printf("Bad device\n");
- file->i_flgs = 0;
- errno = EDEV;
- return (-1);
- }
- *cp++ = '\0';
- for (dp = devsw; dp->dv_name; dp++) {
- if (!strcmp(str, dp->dv_name))
- goto gotdev;
- }
- printf("Unknown device\n");
- file->i_flgs = 0;
- errno = ENXIO;
- return (-1);
-gotdev:
- *(cp-1) = '(';
- file->i_ino.i_dev = dp-devsw;
- file->i_unit = *cp++ - '0';
- if (*cp >= '0' && *cp <= '9')
- file->i_unit = file->i_unit * 10 + *cp++ - '0';
- if (file->i_unit < 0 || file->i_unit > 31) {
- printf("Bad unit specifier\n");
- file->i_flgs = 0;
- errno = EUNIT;
- return (-1);
- }
- if (*cp++ != ',') {
-badoff:
- printf("Missing offset specification\n");
- file->i_flgs = 0;
- errno = EOFFSET;
- return (-1);
- }
- file->i_boff = atol(cp);
- for (;;) {
- if (*cp == ')')
+ for (fdesc = 0;; fdesc++) {
+ if (fdesc == NFILES)
+ _stop("No more file slots");
+ if (iob[fdesc].i_flgs == 0) {
+ file = &iob[fdesc];
+ file->i_flgs |= F_ALLOC;
+ file->i_adapt = file->i_ctlr = file->i_unit =
+ file->i_part = 0;
break;
- if (*cp++)
- continue;
- goto badoff;
+ }
}
- devopen(file);
- if (*++cp == '\0') {
- file->i_flgs |= how+1;
+
+ for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0);
+#ifndef SMALL
+ for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t)
+ if (isupper(*t))
+ *t = tolower(*t);
+ switch(*t) {
+ case '(': /* type(adapt, ctlr, drive, partition)file */
+ if ((file->i_ino.i_dev = getdev(str, t - str)) == -1)
+ goto bad;
+ for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) {
+ for (++t; isspace(*t); ++t);
+ if (*t == ')')
+ break;
+ if (!isdigit(*t))
+ goto badspec;
+ *argp++ = atoi(t);
+ for (++t; isdigit(*t); ++t);
+ if (*t != ',' && *t != ')' || cnt == 4)
+ goto badspec;
+ }
+ for (++t; isspace(*t); ++t);
+ argp -= 4;
+ file->i_adapt = *argp++;
+ file->i_ctlr = *argp++;
+ file->i_unit = *argp++;
+ file->i_part = *argp;
+ break;
+ case ':': /* [A-Za-z]*[0-9]*[A-Za-z]:file */
+ for (t = str; *t != ':' && !isdigit(*t); ++t);
+ if ((file->i_ino.i_dev = getdev(str, t - str)) == -1)
+ goto bad;
+ if ((file->i_unit = getunit(t)) == -1)
+ goto bad;
+ for (; isdigit(*t); ++t);
+ if (*t >= 'a' && *t <= 'h')
+ file->i_part = *t++ - 'a';
+ if (*t != ':') {
+ errno = EOFFSET;
+ goto badspec;
+ }
+ for (++t; isspace(*t); ++t);
+ break;
+ case '/':
+ default: /* default bootstrap unit and device */
+#else
+ {
+#endif /* SMALL */
+ file->i_ino.i_dev = B_TYPE(bootdev);
+ file->i_adapt = B_ADAPTOR(bootdev);
+ file->i_ctlr = B_CONTROLLER(bootdev);
+ file->i_unit = B_UNIT(bootdev);
+ file->i_part = B_PARTITION(bootdev);
+ t = str;
+ }
+
+ opendev = MAKEBOOTDEV(file->i_ino.i_dev, file->i_adapt, file->i_ctlr,
+ file->i_unit, file->i_part);
+
+ if (errno = devopen(file))
+ goto bad;
+
+ if (*t == '\0') {
+ file->i_flgs |= how + 1;
file->i_cc = 0;
file->i_offset = 0;
return (fdesc+3);
}
+#ifndef SMALL
+ else if (how != 0) {
+ printf("Can't write files yet.. Sorry\n");
+ errno = EIO;
+ goto bad;
+ }
+#endif
file->i_ma = (char *)(&file->i_fs);
file->i_cc = SBSIZE;
- file->i_bn = SBLOCK + file->i_boff;
+ file->i_bn = SBOFF / DEV_BSIZE + file->i_boff;
file->i_offset = 0;
if (devread(file) < 0) {
errno = file->i_error;
printf("super block read error\n");
- return (-1);
+ goto bad;
}
- if ((i = find(cp, file)) == 0) {
- file->i_flgs = 0;
+ if ((cnt = find(t, file)) == 0) {
errno = ESRCH;
- return (-1);
+ goto bad;
}
- if (how != 0) {
- printf("Can't write files yet.. Sorry\n");
- file->i_flgs = 0;
- errno = EIO;
- return (-1);
- }
- if (openi(i, file) < 0) {
+ if (openi(cnt, file) < 0) {
errno = file->i_error;
- return (-1);
+ goto bad;
}
file->i_offset = 0;
file->i_cc = 0;
file->i_flgs |= F_FILE | (how+1);
return (fdesc+3);
+
+#ifndef SMALL
+badspec:
+ printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file\n");
+#endif
+bad:
+ file->i_flgs = 0;
+ return (-1);
+}
+
+#ifndef SMALL
+static
+getdev(str, len)
+ register char *str;
+ int len;
+{
+ register struct devsw *dp;
+ register int i;
+ char savedch = str[len];
+
+ str[len] = '\0';
+ for (dp = devsw, i = 0; i < ndevs; dp++, i++)
+ if (dp->dv_name && strcmp(str, dp->dv_name) == 0) {
+ str[len] = savedch;
+ return (i);
+ }
+ printf("Unknown device\nKnown devices are:\n");
+ for (dp = devsw, i = 0; i < ndevs; dp++, i++)
+ if (dp->dv_name)
+ printf(" %s", dp->dv_name);
+ printf("\n");
+ errno = ENXIO;
+ return (-1);
+}
+
+static
+getunit(cp)
+ register char *cp;
+{
+ int unit;
+
+ unit = atoi(cp);
+ if ((u_int)unit > 255) {
+ printf("minor device number out of range (0-255)\n");
+ errno = EUNIT;
+ return (-1);
+ }
+ return (unit);
}
+#endif /* SMALL */
close(fdesc)
int fdesc;
return (0);
}
+#ifndef SMALL
ioctl(fdesc, cmd, arg)
int fdesc, cmd;
char *arg;
file->i_flgs &= ~F_NBSF;
break;
- case SAIOECCLIM:
- file->i_flgs |= F_ECCLM;
- break;
-
- case SAIOECCUNL:
- file->i_flgs &= ~F_ECCLM;
- break;
-
- case SAIOSEVRE:
- file->i_flgs |= F_SEVRE;
- break;
-
- case SAIONSEVRE:
- file->i_flgs &= ~F_SEVRE;
- break;
-
default:
error = devioctl(file, cmd, arg);
break;
errno = file->i_error;
return (error);
}
+#endif /* SMALL */
exit()
{
printf("%s\n", s);
_rtt();
}
-
-trap(ps)
- int ps;
-{
- printf("Trap %o\n", ps);
- for (;;)
- ;
-}