from hibler: don't need retry on key 1
[unix-history] / usr / src / sys / hp300 / stand / sys.c
CommitLineData
a8fd2d0d
KM
1/*
2 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
e4fbbd91 7 * @(#)sys.c 7.2 (Berkeley) %G%
a8fd2d0d
KM
8 */
9
10#include "saio.h"
11#include "ufs/dir.h"
12#ifndef SMALL
13#include "sys/stat.h"
14#endif
15
16ino_t dlook();
17
18struct dirstuff {
19 int loc;
20 struct iob *io;
21};
22
23static
24openi(n, io)
25 register struct iob *io;
26{
27 register struct dinode *dp;
28 int cc;
29
30 io->i_offset = 0;
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;
33 io->i_ma = io->i_buf;
34 cc = devread(io);
35 dp = (struct dinode *)io->i_buf;
e4fbbd91 36 io->i_ino = dp[itoo(&io->i_fs, n)];
a8fd2d0d
KM
37 return (cc);
38}
39
40static
41find(path, file)
42 register char *path;
43 struct iob *file;
44{
45 register char *q;
46 char c;
47 int n;
48
49 if (path==NULL || *path=='\0') {
50 printf("null path\n");
51 return (0);
52 }
53
54 if (openi((ino_t) ROOTINO, file) < 0) {
55 printf("can't read root inode\n");
56 return (0);
57 }
58 while (*path) {
59 while (*path == '/')
60 path++;
61 q = path;
62 while(*q != '/' && *q != '\0')
63 q++;
64 c = *q;
65 *q = '\0';
66 if (q == path) path = "." ; /* "/" means "/." */
67
68 if ((n = dlook(path, file)) != 0) {
69 if (c == '\0')
70 break;
71 if (openi(n, file) < 0)
72 return (0);
73 *q = c;
74 path = q;
75 continue;
76 } else {
77 printf("%s: not found\n", path);
78 return (0);
79 }
80 }
81 return (n);
82}
83
84static daddr_t
85sbmap(io, bn)
86 register struct iob *io;
87 daddr_t bn;
88{
e4fbbd91 89 register struct dinode *ip;
a8fd2d0d
KM
90 int i, j, sh;
91 daddr_t nb, *bap;
92
93 ip = &io->i_ino;
94 if (bn < 0) {
95 printf("bn negative\n");
96 return ((daddr_t)0);
97 }
98
99 /*
100 * blocks 0..NDADDR are direct blocks
101 */
102 if(bn < NDADDR) {
e4fbbd91 103 nb = ip->di_db[bn];
a8fd2d0d
KM
104 return (nb);
105 }
106
107 /*
108 * addresses NIADDR have single and double indirect blocks.
109 * the first step is to determine how many levels of indirection.
110 */
111 sh = 1;
112 bn -= NDADDR;
113 for (j = NIADDR; j > 0; j--) {
114 sh *= NINDIR(&io->i_fs);
115 if (bn < sh)
116 break;
117 bn -= sh;
118 }
119 if (j == 0) {
120 printf("bn ovf %D\n", bn);
121 return ((daddr_t)0);
122 }
123
124 /*
125 * fetch the first indirect block address from the inode
126 */
e4fbbd91 127 nb = ip->di_ib[NIADDR - j];
a8fd2d0d
KM
128 if (nb == 0) {
129 printf("bn void %D\n",bn);
130 return ((daddr_t)0);
131 }
132
133 /*
134 * fetch through the indirect blocks
135 */
136 for (; j <= NIADDR; j++) {
137 if (blknos[j] != nb) {
138 io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
139 io->i_ma = b[j];
140 io->i_cc = io->i_fs.fs_bsize;
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 }
147 blknos[j] = nb;
148 }
149 bap = (daddr_t *)b[j];
150 sh /= NINDIR(&io->i_fs);
151 i = (bn / sh) % NINDIR(&io->i_fs);
152 nb = bap[i];
153 if(nb == 0) {
154 printf("bn void %D\n",bn);
155 return ((daddr_t)0);
156 }
157 }
158 return (nb);
159}
160
161static ino_t
162dlook(s, io)
163 char *s;
164 register struct iob *io;
165{
166 register struct direct *dp;
e4fbbd91
MK
167 struct direct *readdir();
168 register struct dinode *ip;
a8fd2d0d
KM
169 struct dirstuff dirp;
170 int len;
171
172 if (s == NULL || *s == '\0')
173 return (0);
174 ip = &io->i_ino;
e4fbbd91 175 if ((ip->di_mode&IFMT) != IFDIR) {
a8fd2d0d
KM
176 printf("not a directory\n");
177 printf("%s: not a directory\n", s);
178 return (0);
179 }
e4fbbd91 180 if (ip->di_size == 0) {
a8fd2d0d
KM
181 printf("%s: zero length directory\n", s);
182 return (0);
183 }
184 len = strlen(s);
185 dirp.loc = 0;
186 dirp.io = io;
187 for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
188 if(dp->d_ino == 0)
189 continue;
190 if (dp->d_namlen == len && !strcmp(s, dp->d_name))
191 return (dp->d_ino);
192 }
193 return (0);
194}
195
196/*
197 * get next entry in a directory.
198 */
199struct direct *
200readdir(dirp)
201 register struct dirstuff *dirp;
202{
203 register struct direct *dp;
204 register struct iob *io;
205 daddr_t lbn, d;
206 int off;
207
208 io = dirp->io;
209 for(;;) {
e4fbbd91 210 if (dirp->loc >= io->i_ino.di_size)
a8fd2d0d
KM
211 return (NULL);
212 off = blkoff(&io->i_fs, dirp->loc);
213 if (off == 0) {
214 lbn = lblkno(&io->i_fs, dirp->loc);
215 d = sbmap(io, lbn);
216 if(d == 0)
217 return NULL;
218 io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
219 io->i_ma = io->i_buf;
e4fbbd91 220 io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn);
a8fd2d0d
KM
221 if (devread(io) < 0) {
222 errno = io->i_error;
223 printf("bn %D: directory read error\n",
224 io->i_bn);
225 return (NULL);
226 }
227 }
228 dp = (struct direct *)(io->i_buf + off);
229 dirp->loc += dp->d_reclen;
230 if (dp->d_ino == 0)
231 continue;
232 return (dp);
233 }
234}
235
236lseek(fdesc, addr, ptr)
237 int fdesc, ptr;
238 off_t addr;
239{
240 register struct iob *io;
241
242#ifndef SMALL
243 if (ptr != 0) {
244 printf("Seek not from beginning of file\n");
245 errno = EOFFSET;
246 return (-1);
247 }
248#endif SMALL
249 fdesc -= 3;
250 if (fdesc < 0 || fdesc >= NFILES ||
251 ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
252 errno = EBADF;
253 return (-1);
254 }
255 io->i_offset = addr;
256 io->i_bn = addr / DEV_BSIZE;
257 io->i_cc = 0;
258 return (0);
259}
260
261getc(fdesc)
262 int fdesc;
263{
264 register struct iob *io;
265 register struct fs *fs;
266 register char *p;
267 int c, lbn, off, size, diff;
268
269
270 if (fdesc >= 0 && fdesc <= 2)
271 return (getchar());
272 fdesc -= 3;
273 if (fdesc < 0 || fdesc >= NFILES ||
274 ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
275 errno = EBADF;
276 return (-1);
277 }
278 p = io->i_ma;
279 if (io->i_cc <= 0) {
280 if ((io->i_flgs & F_FILE) != 0) {
e4fbbd91 281 diff = io->i_ino.di_size - io->i_offset;
a8fd2d0d
KM
282 if (diff <= 0)
283 return (-1);
284 fs = &io->i_fs;
285 lbn = lblkno(fs, io->i_offset);
286 io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
287 off = blkoff(fs, io->i_offset);
e4fbbd91 288 size = dblksize(fs, &io->i_ino, lbn);
a8fd2d0d
KM
289 } else {
290 io->i_bn = io->i_offset / DEV_BSIZE;
291 off = 0;
292 size = DEV_BSIZE;
293 }
294 io->i_ma = io->i_buf;
295 io->i_cc = size;
296 if (devread(io) < 0) {
297 errno = io->i_error;
298 return (-1);
299 }
300 if ((io->i_flgs & F_FILE) != 0) {
e4fbbd91 301 if (io->i_offset - off + size >= io->i_ino.di_size)
a8fd2d0d
KM
302 io->i_cc = diff + off;
303 io->i_cc -= off;
304 }
305 p = &io->i_buf[off];
306 }
307 io->i_cc--;
308 io->i_offset++;
309 c = (unsigned)*p++;
310 io->i_ma = p;
311 return (c);
312}
313
314int errno;
315
316read(fdesc, buf, count)
317 int fdesc, count;
318 char *buf;
319{
320 register i, size;
321 register struct iob *file;
322 register struct fs *fs;
323 int lbn, off;
324
325 errno = 0;
326 if (fdesc >= 0 & fdesc <= 2) {
327 i = count;
328 do {
329 *buf = getchar();
330 } while (--i && *buf++ != '\n');
331 return (count - i);
332 }
333 fdesc -= 3;
334 if (fdesc < 0 || fdesc >= NFILES ||
335 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
336 errno = EBADF;
337 return (-1);
338 }
339 if ((file->i_flgs&F_READ) == 0) {
340 errno = EBADF;
341 return (-1);
342 }
343#ifndef SMALL
344 if ((file->i_flgs & F_FILE) == 0) {
345 file->i_cc = count;
346 file->i_ma = buf;
347 file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
348 i = devread(file);
349 file->i_offset += count;
350 if (i < 0)
351 errno = file->i_error;
352 return (i);
353 }
354#endif SMALL
e4fbbd91
MK
355 if (file->i_offset+count > file->i_ino.di_size)
356 count = file->i_ino.di_size - file->i_offset;
a8fd2d0d
KM
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);
e4fbbd91 367 size = dblksize(fs, &file->i_ino, lbn);
a8fd2d0d
KM
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);
392}
393
394#ifndef SMALL
395write(fdesc, buf, count)
396 int fdesc, count;
397 char *buf;
398{
399 register i;
400 register struct iob *file;
401
402 errno = 0;
403 if (fdesc >= 0 && fdesc <= 2) {
404 i = count;
405 while (i--)
406 putchar(0, *buf++);
407 return (count);
408 }
409 fdesc -= 3;
410 if (fdesc < 0 || fdesc >= NFILES ||
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 }
419 file->i_cc = count;
420 file->i_ma = buf;
421 file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
422 i = devwrite(file);
423 file->i_offset += count;
424 if (i < 0)
425 errno = file->i_error;
426 return (i);
427}
428#endif SMALL
429
430int openfirst = 1;
431#ifdef notyet
432int opendev; /* last device opened; for boot to set bootdev */
433extern int bootdev;
434#endif notyet
435
436open(str, how)
437 char *str;
438 int how;
439{
440 register char *cp;
441 int i;
442 register struct iob *file;
443 register struct devsw *dp;
444 int fdesc;
445 long atol();
446
447 if (openfirst) {
448 for (i = 0; i < NFILES; i++)
449 iob[i].i_flgs = 0;
450 openfirst = 0;
451 }
452
453 for (fdesc = 0; fdesc < NFILES; fdesc++)
454 if (iob[fdesc].i_flgs == 0)
455 goto gotfile;
456 _stop("No more file slots");
457gotfile:
458 (file = &iob[fdesc])->i_flgs |= F_ALLOC;
459
460#ifdef notyet
461 for (cp = str; *cp && *cp != '/' && *cp != ':'; cp++)
462 ;
463 if (*cp != ':') {
464 /* default bootstrap unit and device */
e4fbbd91 465 file->i_dev = bootdev;
a8fd2d0d
KM
466 cp = str;
467 } else {
468# define isdigit(n) ((n>='0') && (n<='9'))
469 /*
470 * syntax for possible device name:
471 * <alpha-string><digit-string><letter>:
472 */
473 for (cp = str; *cp != ':' && !isdigit(*cp); cp++)
474 ;
475 for (dp = devsw; dp->dv_name; dp++) {
476 if (!strncmp(str, dp->dv_name,cp-str))
477 goto gotdev;
478 }
479 printf("unknown device\n");
480 file->i_flgs = 0;
481 errno = EDEV;
482 return (-1);
483 gotdev:
484 i = 0;
485 while (*cp >= '0' && *cp <= '9')
486 i = i * 10 + *cp++ - '0';
487 if (i < 0 || i > 255) {
488 printf("minor device number out of range (0-255)\n");
489 file->i_flgs = 0;
490 errno = EUNIT;
491 return (-1);
492 }
493 if (*cp >= 'a' && *cp <= 'h') {
494 if (i > 31) {
495 printf("unit number out of range (0-31)\n");
496 file->i_flgs = 0;
497 errno = EUNIT;
498 return (-1);
499 }
500 i = make_minor(i, *cp++ - 'a');
501 }
502
503 if (*cp++ != ':') {
504 printf("incorrect device specification\n");
505 file->i_flgs = 0;
506 errno = EOFFSET;
507 return (-1);
508 }
e4fbbd91 509 opendev = file->i_dev = makedev(dp-devsw, i);
a8fd2d0d
KM
510 }
511 file->i_boff = 0;
512 devopen(file);
513 if (cp != str && *cp == '\0') {
514 file->i_flgs |= how+1;
515 file->i_cc = 0;
516 file->i_offset = 0;
517 return (fdesc+3);
518 }
519#else notyet
520 for (cp = str; *cp && *cp != '('; cp++)
521 ;
522 if (*cp != '(') {
523 printf("Bad device\n");
524 file->i_flgs = 0;
525 errno = EDEV;
526 return (-1);
527 }
528 *cp = '\0';
529 for (dp = devsw; dp->dv_name; dp++)
530 if (!strcmp(str, dp->dv_name))
531 break;
532 *cp++ = '(';
533 if (dp->dv_name == NULL) {
534 printf("Unknown device\n");
535 file->i_flgs = 0;
536 errno = ENXIO;
537 return (-1);
538 }
e4fbbd91 539 file->i_dev = dp-devsw;
a8fd2d0d
KM
540 file->i_unit = *cp++ - '0';
541 if (*cp >= '0' && *cp <= '9')
542 file->i_unit = file->i_unit * 10 + *cp++ - '0';
543 if (file->i_unit < 0 || file->i_unit > 63) {
544 printf("Bad unit specifier\n");
545 file->i_flgs = 0;
546 errno = EUNIT;
547 return (-1);
548 }
549 if (*cp++ != ',') {
550badoff:
551 printf("Missing offset specification\n");
552 file->i_flgs = 0;
553 errno = EOFFSET;
554 return (-1);
555 }
556 file->i_boff = atol(cp);
557 for (;;) {
558 if (*cp == ')')
559 break;
560 if (*cp++)
561 continue;
562 goto badoff;
563 }
564 devopen(file);
565 if (*++cp == '\0') {
566 file->i_flgs |= how+1;
567 file->i_cc = 0;
568 file->i_offset = 0;
569 return (fdesc+3);
570 }
571#endif notyet
572 file->i_ma = (char *)(&file->i_fs);
573 file->i_cc = SBSIZE;
574 file->i_bn = SBLOCK + file->i_boff;
575 file->i_offset = 0;
576 if (devread(file) < 0) {
577 errno = file->i_error;
578 printf("super block read error\n");
579 return (-1);
580 }
581 if ((i = find(cp, file)) == 0) {
582 file->i_flgs = 0;
583 errno = ESRCH;
584 return (-1);
585 }
586#ifndef SMALL
587 if (how != 0) {
588 printf("Can't write files yet.. Sorry\n");
589 file->i_flgs = 0;
590 errno = EIO;
591 return (-1);
592 }
593#endif SMALL
594 if (openi(i, file) < 0) {
595 errno = file->i_error;
596 return (-1);
597 }
598 file->i_offset = 0;
599 file->i_cc = 0;
600 file->i_flgs |= F_FILE | (how+1);
601 return (fdesc+3);
602}
603
604close(fdesc)
605 int fdesc;
606{
607 struct iob *file;
608
609 fdesc -= 3;
610 if (fdesc < 0 || fdesc >= NFILES ||
611 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
612 errno = EBADF;
613 return (-1);
614 }
615 if ((file->i_flgs&F_FILE) == 0)
616 devclose(file);
617 file->i_flgs = 0;
618 return (0);
619}
620
621exit()
622{
623 _stop("Exit called");
624}
625
626_stop(s)
627 char *s;
628{
629 static int stopped = 0;
630 int i;
631
632 if (!stopped) {
633 stopped++;
634 for (i = 0; i < NFILES; i++)
635 if (iob[i].i_flgs != 0)
636 close(i);
637 }
638 printf("%s\n", s);
639 _rtt();
640}
641
642#ifndef SMALL
643ioctl(fdesc, cmd, arg)
644 int fdesc, cmd;
645 char *arg;
646{
647 register struct iob *file;
648 int error = 0;
649
650 fdesc -= 3;
651 if (fdesc < 0 || fdesc >= NFILES ||
652 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
653 errno = EBADF;
654 return (-1);
655 }
656 switch (cmd) {
657
658 case SAIOHDR:
659 file->i_flgs |= F_HDR;
660 break;
661
662 case SAIOCHECK:
663 file->i_flgs |= F_CHECK;
664 break;
665
666 case SAIOHCHECK:
667 file->i_flgs |= F_HCHECK;
668 break;
669
670 case SAIONOBAD:
671 file->i_flgs |= F_NBSF;
672 break;
673
674 case SAIODOBAD:
675 file->i_flgs &= ~F_NBSF;
676 break;
677
678 default:
679 error = devioctl(file, cmd, arg);
680 break;
681 }
682 if (error < 0)
683 errno = file->i_error;
684 return (error);
685}
686
687extern char end;
688static caddr_t theend = 0;
689
690caddr_t
691brk(addr)
692 char *addr;
693{
694 char stkloc;
695
696 if (theend == (caddr_t)0)
697 theend = &end;
698 if (addr > &stkloc || addr < &end)
699 return((caddr_t)-1);
700 if (addr > theend)
701 bzero(theend, addr-theend);
702 theend = addr;
703 return(0);
704}
705
706caddr_t
707sbrk(incr)
708 int incr;
709{
710 caddr_t obrk, brk();
711
712 if (theend == (caddr_t)0)
713 theend = &end;
714 obrk = theend;
715 if (brk(theend+incr) == (caddr_t)-1)
716 return((caddr_t)-1);
717 return(obrk);
718}
719
720getpagesize()
721{
722 return(NBPG);
723}
724
725getdtablesize()
726{
727 return(NFILES);
728}
729
730fstat(fdesc, sb)
731 struct stat *sb;
732{
733 register struct iob *io;
734
735 fdesc -= 3;
736 if (fdesc < 0 || fdesc >= NFILES ||
737 ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
738 errno = EBADF;
739 return (-1);
740 }
741 /* only important stuff */
e4fbbd91
MK
742 sb->st_mode = io->i_ino.di_mode;
743 sb->st_uid = io->i_ino.di_uid;
744 sb->st_gid = io->i_ino.di_gid;
745 sb->st_size = io->i_ino.di_size;
a8fd2d0d
KM
746 return (0);
747}
748
749stat(str, sb)
750{
751 /* the easy way */
752 int f, rv = 0;
753
754 f = open(str, 0);
755 if (f < 0 || fstat(f, sb) < 0)
756 rv = -1;
757 (void) close(f);
758 return(rv);
759}
760
761#endif SMALL