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