changed set/gettimeofday to set/get timezone alone
[unix-history] / usr / src / sys / stand.att / sys.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
80c81fbf 6 * @(#)sys.c 7.2 (Berkeley) %G%
da7c5cc6 7 */
a5a27f5c 8
70b4ffec
KM
9#include "../h/param.h"
10#include "../h/inode.h"
11#include "../h/fs.h"
b5d17f4d 12#include "../h/dir.h"
80c81fbf 13#include "../h/reboot.h"
a5a27f5c
BJ
14#include "saio.h"
15
16ino_t dlook();
17
70b4ffec
KM
18struct dirstuff {
19 int loc;
20 struct iob *io;
21};
22
a5a27f5c 23static
0839bdeb 24openi(n, io)
70b4ffec 25 register struct iob *io;
a5a27f5c
BJ
26{
27 register struct dinode *dp;
9c0778a9 28 int cc;
a5a27f5c
BJ
29
30 io->i_offset = 0;
70b4ffec
KM
31 io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
32 io->i_cc = io->i_fs.fs_bsize;
a5a27f5c 33 io->i_ma = io->i_buf;
9c0778a9 34 cc = devread(io);
a5a27f5c 35 dp = (struct dinode *)io->i_buf;
70b4ffec 36 io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic;
9c0778a9 37 return (cc);
a5a27f5c
BJ
38}
39
40static
41find(path, file)
70b4ffec
KM
42 register char *path;
43 struct iob *file;
a5a27f5c
BJ
44{
45 register char *q;
46 char c;
47 int n;
48
49 if (path==NULL || *path=='\0') {
50 printf("null path\n");
0839bdeb 51 return (0);
a5a27f5c
BJ
52 }
53
9c0778a9
SL
54 if (openi((ino_t) ROOTINO, file) < 0) {
55 printf("can't read root inode\n");
56 return (0);
57 }
a5a27f5c
BJ
58 while (*path) {
59 while (*path == '/')
60 path++;
61 q = path;
62 while(*q != '/' && *q != '\0')
63 q++;
64 c = *q;
65 *q = '\0';
c015e76f 66 if (q == path) path = "." ; /* "/" means "/." */
a5a27f5c 67
9c0778a9
SL
68 if ((n = dlook(path, file)) != 0) {
69 if (c == '\0')
a5a27f5c 70 break;
9c0778a9
SL
71 if (openi(n, file) < 0)
72 return (0);
a5a27f5c
BJ
73 *q = c;
74 path = q;
75 continue;
76 } else {
c015e76f 77 printf("%s: not found\n", path);
0839bdeb 78 return (0);
a5a27f5c
BJ
79 }
80 }
0839bdeb 81 return (n);
a5a27f5c
BJ
82}
83
84static daddr_t
85sbmap(io, bn)
70b4ffec
KM
86 register struct iob *io;
87 daddr_t bn;
a5a27f5c 88{
a5a27f5c 89 register struct inode *ip;
70b4ffec 90 int i, j, sh;
a5a27f5c 91 daddr_t nb, *bap;
a5a27f5c
BJ
92
93 ip = &io->i_ino;
70b4ffec 94 if (bn < 0) {
a5a27f5c 95 printf("bn negative\n");
0839bdeb 96 return ((daddr_t)0);
a5a27f5c
BJ
97 }
98
99 /*
70b4ffec 100 * blocks 0..NDADDR are direct blocks
a5a27f5c 101 */
70b4ffec
KM
102 if(bn < NDADDR) {
103 nb = ip->i_db[bn];
0839bdeb 104 return (nb);
a5a27f5c
BJ
105 }
106
107 /*
70b4ffec
KM
108 * addresses NIADDR have single and double indirect blocks.
109 * the first step is to determine how many levels of indirection.
a5a27f5c 110 */
70b4ffec
KM
111 sh = 1;
112 bn -= NDADDR;
113 for (j = NIADDR; j > 0; j--) {
114 sh *= NINDIR(&io->i_fs);
115 if (bn < sh)
a5a27f5c 116 break;
70b4ffec 117 bn -= sh;
a5a27f5c 118 }
70b4ffec
KM
119 if (j == 0) {
120 printf("bn ovf %D\n", bn);
121 return ((daddr_t)0);
a5a27f5c
BJ
122 }
123
124 /*
70b4ffec 125 * fetch the first indirect block address from the inode
a5a27f5c 126 */
70b4ffec
KM
127 nb = ip->i_ib[NIADDR - j];
128 if (nb == 0) {
a5a27f5c 129 printf("bn void %D\n",bn);
0839bdeb 130 return ((daddr_t)0);
a5a27f5c
BJ
131 }
132
133 /*
134 * fetch through the indirect blocks
135 */
70b4ffec 136 for (; j <= NIADDR; j++) {
a5a27f5c 137 if (blknos[j] != nb) {
70b4ffec 138 io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
a5a27f5c 139 io->i_ma = b[j];
70b4ffec 140 io->i_cc = io->i_fs.fs_bsize;
9c0778a9
SL
141 if (devread(io) != io->i_fs.fs_bsize) {
142 if (io->i_error)
143 errno = io->i_error;
144 printf("bn %D: read error\n", io->i_bn);
145 return ((daddr_t)0);
146 }
a5a27f5c
BJ
147 blknos[j] = nb;
148 }
149 bap = (daddr_t *)b[j];
70b4ffec
KM
150 sh /= NINDIR(&io->i_fs);
151 i = (bn / sh) % NINDIR(&io->i_fs);
a5a27f5c
BJ
152 nb = bap[i];
153 if(nb == 0) {
154 printf("bn void %D\n",bn);
0839bdeb 155 return ((daddr_t)0);
a5a27f5c
BJ
156 }
157 }
0839bdeb 158 return (nb);
a5a27f5c
BJ
159}
160
161static ino_t
162dlook(s, io)
70b4ffec
KM
163 char *s;
164 register struct iob *io;
a5a27f5c
BJ
165{
166 register struct direct *dp;
167 register struct inode *ip;
70b4ffec
KM
168 struct dirstuff dirp;
169 int len;
a5a27f5c 170
70b4ffec 171 if (s == NULL || *s == '\0')
0839bdeb 172 return (0);
a5a27f5c 173 ip = &io->i_ino;
70b4ffec 174 if ((ip->i_mode&IFMT) != IFDIR) {
a5a27f5c 175 printf("not a directory\n");
c015e76f 176 printf("%s: not a directory\n", s);
0839bdeb 177 return (0);
a5a27f5c 178 }
70b4ffec 179 if (ip->i_size == 0) {
c015e76f 180 printf("%s: zero length directory\n", s);
0839bdeb 181 return (0);
a5a27f5c 182 }
70b4ffec
KM
183 len = strlen(s);
184 dirp.loc = 0;
185 dirp.io = io;
186 for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
187 if(dp->d_ino == 0)
188 continue;
189 if (dp->d_namlen == len && !strcmp(s, dp->d_name))
0839bdeb 190 return (dp->d_ino);
a5a27f5c 191 }
0839bdeb 192 return (0);
a5a27f5c
BJ
193}
194
70b4ffec
KM
195/*
196 * get next entry in a directory.
197 */
198struct direct *
199readdir(dirp)
200 register struct dirstuff *dirp;
a5a27f5c 201{
70b4ffec
KM
202 register struct direct *dp;
203 register struct iob *io;
204 daddr_t lbn, d;
205 int off;
a5a27f5c 206
70b4ffec
KM
207 io = dirp->io;
208 for(;;) {
209 if (dirp->loc >= io->i_ino.i_size)
9c0778a9 210 return (NULL);
70b4ffec
KM
211 off = blkoff(&io->i_fs, dirp->loc);
212 if (off == 0) {
213 lbn = lblkno(&io->i_fs, dirp->loc);
214 d = sbmap(io, lbn);
215 if(d == 0)
216 return NULL;
217 io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
218 io->i_ma = io->i_buf;
219 io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn);
9c0778a9
SL
220 if (devread(io) < 0) {
221 errno = io->i_error;
c015e76f
MK
222 printf("bn %D: directory read error\n",
223 io->i_bn);
9c0778a9
SL
224 return (NULL);
225 }
70b4ffec
KM
226 }
227 dp = (struct direct *)(io->i_buf + off);
228 dirp->loc += dp->d_reclen;
229 if (dp->d_ino == 0)
230 continue;
231 return (dp);
a5a27f5c 232 }
a5a27f5c
BJ
233}
234
235lseek(fdesc, addr, ptr)
0839bdeb
SL
236 int fdesc, ptr;
237 off_t addr;
a5a27f5c
BJ
238{
239 register struct iob *io;
240
31fec9db 241#ifndef SMALL
a5a27f5c
BJ
242 if (ptr != 0) {
243 printf("Seek not from beginning of file\n");
0839bdeb
SL
244 errno = EOFFSET;
245 return (-1);
a5a27f5c 246 }
31fec9db 247#endif SMALL
a5a27f5c 248 fdesc -= 3;
70b4ffec 249 if (fdesc < 0 || fdesc >= NFILES ||
0839bdeb
SL
250 ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
251 errno = EBADF;
252 return (-1);
253 }
a5a27f5c 254 io->i_offset = addr;
70b4ffec 255 io->i_bn = addr / DEV_BSIZE;
a5a27f5c 256 io->i_cc = 0;
0839bdeb 257 return (0);
a5a27f5c
BJ
258}
259
260getc(fdesc)
0839bdeb 261 int fdesc;
a5a27f5c
BJ
262{
263 register struct iob *io;
70b4ffec 264 register struct fs *fs;
a5a27f5c 265 register char *p;
70b4ffec 266 int c, lbn, off, size, diff;
a5a27f5c
BJ
267
268
269 if (fdesc >= 0 && fdesc <= 2)
0839bdeb 270 return (getchar());
a5a27f5c 271 fdesc -= 3;
70b4ffec 272 if (fdesc < 0 || fdesc >= NFILES ||
0839bdeb
SL
273 ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
274 errno = EBADF;
275 return (-1);
276 }
a5a27f5c
BJ
277 p = io->i_ma;
278 if (io->i_cc <= 0) {
70b4ffec
KM
279 if ((io->i_flgs & F_FILE) != 0) {
280 diff = io->i_ino.i_size - io->i_offset;
281 if (diff <= 0)
282 return (-1);
283 fs = &io->i_fs;
284 lbn = lblkno(fs, io->i_offset);
285 io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
286 off = blkoff(fs, io->i_offset);
287 size = blksize(fs, &io->i_ino, lbn);
288 } else {
289 io->i_bn = io->i_offset / DEV_BSIZE;
290 off = 0;
291 size = DEV_BSIZE;
292 }
a5a27f5c 293 io->i_ma = io->i_buf;
70b4ffec 294 io->i_cc = size;
9c0778a9
SL
295 if (devread(io) < 0) {
296 errno = io->i_error;
297 return (-1);
298 }
70b4ffec
KM
299 if ((io->i_flgs & F_FILE) != 0) {
300 if (io->i_offset - off + size >= io->i_ino.i_size)
301 io->i_cc = diff + off;
a5a27f5c 302 io->i_cc -= off;
70b4ffec 303 }
a5a27f5c
BJ
304 p = &io->i_buf[off];
305 }
306 io->i_cc--;
307 io->i_offset++;
308 c = (unsigned)*p++;
309 io->i_ma = p;
0839bdeb 310 return (c);
a5a27f5c 311}
70b4ffec 312
0839bdeb 313int errno;
a5a27f5c
BJ
314
315read(fdesc, buf, count)
0839bdeb
SL
316 int fdesc, count;
317 char *buf;
a5a27f5c 318{
c015e76f 319 register i, size;
a5a27f5c 320 register struct iob *file;
c015e76f
MK
321 register struct fs *fs;
322 int lbn, off;
a5a27f5c 323
0839bdeb 324 errno = 0;
a5a27f5c
BJ
325 if (fdesc >= 0 & fdesc <= 2) {
326 i = count;
327 do {
328 *buf = getchar();
329 } while (--i && *buf++ != '\n');
0839bdeb 330 return (count - i);
a5a27f5c
BJ
331 }
332 fdesc -= 3;
70b4ffec 333 if (fdesc < 0 || fdesc >= NFILES ||
0839bdeb
SL
334 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
335 errno = EBADF;
336 return (-1);
337 }
338 if ((file->i_flgs&F_READ) == 0) {
339 errno = EBADF;
340 return (-1);
341 }
31fec9db 342#ifndef SMALL
70b4ffec 343 if ((file->i_flgs & F_FILE) == 0) {
a5a27f5c
BJ
344 file->i_cc = count;
345 file->i_ma = buf;
b5d17f4d 346 file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
a5a27f5c 347 i = devread(file);
0839bdeb
SL
348 if (i < 0)
349 errno = file->i_error;
80c81fbf
MK
350 else
351 file->i_offset += i;
0839bdeb 352 return (i);
a5a27f5c 353 }
31fec9db 354#endif SMALL
c015e76f
MK
355 if (file->i_offset+count > file->i_ino.i_size)
356 count = file->i_ino.i_size - file->i_offset;
357 if ((i = count) <= 0)
358 return (0);
359 /*
360 * While reading full blocks, do I/O into user buffer.
361 * Anything else uses getc().
362 */
363 fs = &file->i_fs;
364 while (i) {
365 off = blkoff(fs, file->i_offset);
366 lbn = lblkno(fs, file->i_offset);
367 size = blksize(fs, &file->i_ino, lbn);
368 if (off == 0 && size <= i) {
369 file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
370 file->i_boff;
371 file->i_cc = size;
372 file->i_ma = buf;
373 if (devread(file) < 0) {
374 errno = file->i_error;
375 return (-1);
376 }
377 file->i_offset += size;
378 file->i_cc = 0;
379 buf += size;
380 i -= size;
381 } else {
382 size -= off;
383 if (size > i)
384 size = i;
385 i -= size;
386 do {
387 *buf++ = getc(fdesc+3);
388 } while (--size);
389 }
390 }
391 return (count);
a5a27f5c
BJ
392}
393
31fec9db 394#ifndef SMALL
a5a27f5c 395write(fdesc, buf, count)
0839bdeb
SL
396 int fdesc, count;
397 char *buf;
a5a27f5c
BJ
398{
399 register i;
400 register struct iob *file;
401
0839bdeb 402 errno = 0;
a5a27f5c
BJ
403 if (fdesc >= 0 && fdesc <= 2) {
404 i = count;
405 while (i--)
406 putchar(*buf++);
0839bdeb 407 return (count);
a5a27f5c
BJ
408 }
409 fdesc -= 3;
70b4ffec 410 if (fdesc < 0 || fdesc >= NFILES ||
0839bdeb
SL
411 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
412 errno = EBADF;
413 return (-1);
414 }
415 if ((file->i_flgs&F_WRITE) == 0) {
416 errno = EBADF;
417 return (-1);
418 }
a5a27f5c
BJ
419 file->i_cc = count;
420 file->i_ma = buf;
b5d17f4d 421 file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
a5a27f5c 422 i = devwrite(file);
b5d17f4d 423 file->i_offset += count;
0839bdeb
SL
424 if (i < 0)
425 errno = file->i_error;
426 return (i);
a5a27f5c 427}
31fec9db 428#endif SMALL
a5a27f5c 429
10899d3a 430int openfirst = 1;
80c81fbf
MK
431unsigned opendev; /* last device opened */
432extern unsigned bootdev;
10899d3a 433
a5a27f5c 434open(str, how)
70b4ffec 435 char *str;
0839bdeb 436 int how;
a5a27f5c
BJ
437{
438 register char *cp;
80c81fbf 439 register int i;
a5a27f5c 440 register struct iob *file;
0839bdeb
SL
441 int fdesc;
442 long atol();
a5a27f5c 443
10899d3a 444 if (openfirst) {
a5a27f5c
BJ
445 for (i = 0; i < NFILES; i++)
446 iob[i].i_flgs = 0;
10899d3a 447 openfirst = 0;
a5a27f5c
BJ
448 }
449
450 for (fdesc = 0; fdesc < NFILES; fdesc++)
451 if (iob[fdesc].i_flgs == 0)
452 goto gotfile;
453 _stop("No more file slots");
454gotfile:
455 (file = &iob[fdesc])->i_flgs |= F_ALLOC;
456
80c81fbf
MK
457 for (cp = str; *cp && *cp != '/' && *cp != ':' && *cp != '('; cp++)
458 ;
459 if (*cp == '(') {
460 if ((file->i_ino.i_dev = getdev(str, cp - str)) == -1)
461 goto bad;
462 cp++;
463 if ((file->i_unit = getunit(cp)) == -1)
464 goto bad;
465 for (; *cp != ','; cp++)
466 if (*cp == NULL) {
467 errno = EOFFSET;
468 goto badspec;
469 }
470 file->i_boff = atol(cp);
471 for (;;) {
472 if (*cp == ')')
473 break;
474 if (*cp++)
475 continue;
476 goto badspec;
477 }
478 } else if (*cp != ':') {
c015e76f 479 /* default bootstrap unit and device */
80c81fbf
MK
480 file->i_ino.i_dev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
481 file->i_unit = ((bootdev >> B_UNITSHIFT) & B_UNITMASK) +
482 (8 * ((bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK));
483 file->i_boff = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
c015e76f
MK
484 cp = str;
485 } else {
486# define isdigit(n) ((n>='0') && (n<='9'))
80c81fbf
MK
487 if (cp == str)
488 goto badspec;
c015e76f
MK
489 /*
490 * syntax for possible device name:
491 * <alpha-string><digit-string><letter>:
492 */
493 for (cp = str; *cp != ':' && !isdigit(*cp); cp++)
494 ;
80c81fbf
MK
495 if ((file->i_ino.i_dev = getdev(str, cp - str)) == -1)
496 goto bad;
497 if ((file->i_unit = getunit(cp)) == -1)
498 goto bad;
499 while (isdigit(*cp))
500 cp++;
501 file->i_boff = 0;
502 if (*cp >= 'a' && *cp <= 'h')
503 file->i_boff = *cp++ - 'a';
c015e76f 504 if (*cp++ != ':') {
c015e76f 505 errno = EOFFSET;
80c81fbf 506 goto badspec;
c015e76f 507 }
c015e76f 508 }
80c81fbf
MK
509 opendev = file->i_ino.i_dev << B_TYPESHIFT;
510 opendev |= ((file->i_unit % 8) << B_UNITSHIFT);
511 opendev |= ((file->i_unit / 8) << B_ADAPTORSHIFT);
512 opendev |= file->i_boff << B_PARTITIONSHIFT;
513 if (errno = devopen(file))
514 goto bad;
c015e76f
MK
515 if (cp != str && *cp == '\0') {
516 file->i_flgs |= how+1;
517 file->i_cc = 0;
518 file->i_offset = 0;
519 return (fdesc+3);
520 }
70b4ffec
KM
521 file->i_ma = (char *)(&file->i_fs);
522 file->i_cc = SBSIZE;
b5d17f4d 523 file->i_bn = SBLOCK + file->i_boff;
70b4ffec 524 file->i_offset = 0;
9c0778a9
SL
525 if (devread(file) < 0) {
526 errno = file->i_error;
527 printf("super block read error\n");
80c81fbf 528 goto bad;
9c0778a9 529 }
a5a27f5c 530 if ((i = find(cp, file)) == 0) {
0839bdeb 531 errno = ESRCH;
80c81fbf 532 goto bad;
a5a27f5c 533 }
31fec9db 534#ifndef SMALL
a5a27f5c
BJ
535 if (how != 0) {
536 printf("Can't write files yet.. Sorry\n");
0839bdeb 537 errno = EIO;
80c81fbf 538 goto bad;
a5a27f5c 539 }
31fec9db 540#endif SMALL
9c0778a9
SL
541 if (openi(i, file) < 0) {
542 errno = file->i_error;
80c81fbf 543 goto bad;
9c0778a9 544 }
a5a27f5c
BJ
545 file->i_offset = 0;
546 file->i_cc = 0;
547 file->i_flgs |= F_FILE | (how+1);
0839bdeb 548 return (fdesc+3);
80c81fbf
MK
549
550badspec:
551 printf("malformed device specification\n");
552bad:
553 file->i_flgs = 0;
554 return (-1);
555}
556
557static
558getdev(str, len)
559 char *str;
560 int len;
561{
562 register struct devsw *dp;
563
564 for (dp = devsw; dp->dv_name; dp++) {
565 if (!strncmp(str, dp->dv_name, len))
566 return (dp - devsw);
567 }
568 printf("Unknown device\n");
569 errno = ENXIO;
570 return (-1);
571}
572
573static
574getunit(cp)
575 register char *cp;
576{
577 register int i = 0;
578
579 while (*cp >= '0' && *cp <= '9')
580 i = i * 10 + *cp++ - '0';
581 if ((unsigned) i > 255) {
582 printf("minor device number out of range (0-255)\n");
583 errno = EUNIT;
584 i = -1;
585 }
586 return (i);
a5a27f5c
BJ
587}
588
589close(fdesc)
0839bdeb 590 int fdesc;
a5a27f5c
BJ
591{
592 struct iob *file;
593
594 fdesc -= 3;
70b4ffec 595 if (fdesc < 0 || fdesc >= NFILES ||
0839bdeb
SL
596 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
597 errno = EBADF;
598 return (-1);
599 }
a5a27f5c
BJ
600 if ((file->i_flgs&F_FILE) == 0)
601 devclose(file);
602 file->i_flgs = 0;
0839bdeb
SL
603 return (0);
604}
605
31fec9db 606#ifndef SMALL
0839bdeb
SL
607ioctl(fdesc, cmd, arg)
608 int fdesc, cmd;
609 char *arg;
610{
611 register struct iob *file;
612 int error = 0;
613
9a46f589 614 fdesc -= 3;
0839bdeb
SL
615 if (fdesc < 0 || fdesc >= NFILES ||
616 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
617 errno = EBADF;
618 return (-1);
619 }
620 switch (cmd) {
621
622 case SAIOHDR:
623 file->i_flgs |= F_HDR;
624 break;
625
626 case SAIOCHECK:
627 file->i_flgs |= F_CHECK;
628 break;
629
630 case SAIOHCHECK:
631 file->i_flgs |= F_HCHECK;
632 break;
633
9a46f589
HS
634 case SAIONOBAD:
635 file->i_flgs |= F_NBSF;
636 break;
637
638 case SAIODOBAD:
639 file->i_flgs &= ~F_NBSF;
640 break;
641
0839bdeb
SL
642 default:
643 error = devioctl(file, cmd, arg);
644 break;
645 }
646 if (error < 0)
647 errno = file->i_error;
648 return (error);
a5a27f5c 649}
31fec9db 650#endif SMALL
a5a27f5c
BJ
651
652exit()
653{
654 _stop("Exit called");
655}
656
657_stop(s)
0839bdeb 658 char *s;
a5a27f5c 659{
0b87420c
MT
660 int i;
661
662 for (i = 0; i < NFILES; i++)
663 if (iob[i].i_flgs != 0)
664 close(i);
a5a27f5c
BJ
665 printf("%s\n", s);
666 _rtt();
667}