xref: /csrg-svn/sys/stand.att/sys.c (revision 10022)
1 /*	sys.c	4.8	82/12/30	*/
2 
3 #include "../h/param.h"
4 #include "../h/inode.h"
5 #include "../h/fs.h"
6 #include "../h/dir.h"
7 #include "saio.h"
8 
9 ino_t	dlook();
10 
11 struct dirstuff {
12 	int loc;
13 	struct iob *io;
14 };
15 
16 static
17 openi(n, io)
18 	register struct iob *io;
19 {
20 	register struct dinode *dp;
21 
22 	io->i_offset = 0;
23 	io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
24 	io->i_cc = io->i_fs.fs_bsize;
25 	io->i_ma = io->i_buf;
26 	devread(io);
27 	dp = (struct dinode *)io->i_buf;
28 	io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic;
29 }
30 
31 static
32 find(path, file)
33 	register char *path;
34 	struct iob *file;
35 {
36 	register char *q;
37 	char c;
38 	int n;
39 
40 	if (path==NULL || *path=='\0') {
41 		printf("null path\n");
42 		return (0);
43 	}
44 
45 	openi((ino_t) ROOTINO, file);
46 	while (*path) {
47 		while (*path == '/')
48 			path++;
49 		q = path;
50 		while(*q != '/' && *q != '\0')
51 			q++;
52 		c = *q;
53 		*q = '\0';
54 
55 		if ((n=dlook(path, file))!=0) {
56 			if (c=='\0')
57 				break;
58 			openi(n, file);
59 			*q = c;
60 			path = q;
61 			continue;
62 		} else {
63 			printf("%s not found\n",path);
64 			return (0);
65 		}
66 	}
67 	return (n);
68 }
69 
70 static daddr_t
71 sbmap(io, bn)
72 	register struct iob *io;
73 	daddr_t bn;
74 {
75 	register struct inode *ip;
76 	int i, j, sh;
77 	daddr_t nb, *bap;
78 
79 	ip = &io->i_ino;
80 	if (bn < 0) {
81 		printf("bn negative\n");
82 		return ((daddr_t)0);
83 	}
84 
85 	/*
86 	 * blocks 0..NDADDR are direct blocks
87 	 */
88 	if(bn < NDADDR) {
89 		nb = ip->i_db[bn];
90 		return (nb);
91 	}
92 
93 	/*
94 	 * addresses NIADDR have single and double indirect blocks.
95 	 * the first step is to determine how many levels of indirection.
96 	 */
97 	sh = 1;
98 	bn -= NDADDR;
99 	for (j = NIADDR; j > 0; j--) {
100 		sh *= NINDIR(&io->i_fs);
101 		if (bn < sh)
102 			break;
103 		bn -= sh;
104 	}
105 	if (j == 0) {
106 		printf("bn ovf %D\n", bn);
107 		return ((daddr_t)0);
108 	}
109 
110 	/*
111 	 * fetch the first indirect block address from the inode
112 	 */
113 	nb = ip->i_ib[NIADDR - j];
114 	if (nb == 0) {
115 		printf("bn void %D\n",bn);
116 		return ((daddr_t)0);
117 	}
118 
119 	/*
120 	 * fetch through the indirect blocks
121 	 */
122 	for (; j <= NIADDR; j++) {
123 		if (blknos[j] != nb) {
124 			io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
125 			io->i_ma = b[j];
126 			io->i_cc = io->i_fs.fs_bsize;
127 			devread(io);
128 			blknos[j] = nb;
129 		}
130 		bap = (daddr_t *)b[j];
131 		sh /= NINDIR(&io->i_fs);
132 		i = (bn / sh) % NINDIR(&io->i_fs);
133 		nb = bap[i];
134 		if(nb == 0) {
135 			printf("bn void %D\n",bn);
136 			return ((daddr_t)0);
137 		}
138 	}
139 	return (nb);
140 }
141 
142 static ino_t
143 dlook(s, io)
144 	char *s;
145 	register struct iob *io;
146 {
147 	register struct direct *dp;
148 	register struct inode *ip;
149 	struct dirstuff dirp;
150 	int len;
151 
152 	if (s == NULL || *s == '\0')
153 		return (0);
154 	ip = &io->i_ino;
155 	if ((ip->i_mode&IFMT) != IFDIR) {
156 		printf("not a directory\n");
157 		return (0);
158 	}
159 	if (ip->i_size == 0) {
160 		printf("zero length directory\n");
161 		return (0);
162 	}
163 	len = strlen(s);
164 	dirp.loc = 0;
165 	dirp.io = io;
166 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
167 		if(dp->d_ino == 0)
168 			continue;
169 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
170 			return (dp->d_ino);
171 	}
172 	return (0);
173 }
174 
175 /*
176  * get next entry in a directory.
177  */
178 struct direct *
179 readdir(dirp)
180 	register struct dirstuff *dirp;
181 {
182 	register struct direct *dp;
183 	register struct iob *io;
184 	daddr_t lbn, d;
185 	int off;
186 
187 	io = dirp->io;
188 	for(;;) {
189 		if (dirp->loc >= io->i_ino.i_size)
190 			return NULL;
191 		off = blkoff(&io->i_fs, dirp->loc);
192 		if (off == 0) {
193 			lbn = lblkno(&io->i_fs, dirp->loc);
194 			d = sbmap(io, lbn);
195 			if(d == 0)
196 				return NULL;
197 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
198 			io->i_ma = io->i_buf;
199 			io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn);
200 			devread(io);
201 		}
202 		dp = (struct direct *)(io->i_buf + off);
203 		dirp->loc += dp->d_reclen;
204 		if (dp->d_ino == 0)
205 			continue;
206 		return (dp);
207 	}
208 }
209 
210 lseek(fdesc, addr, ptr)
211 	int fdesc, ptr;
212 	off_t addr;
213 {
214 	register struct iob *io;
215 
216 	if (ptr != 0) {
217 		printf("Seek not from beginning of file\n");
218 		errno = EOFFSET;
219 		return (-1);
220 	}
221 	fdesc -= 3;
222 	if (fdesc < 0 || fdesc >= NFILES ||
223 	    ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
224 		errno = EBADF;
225 		return (-1);
226 	}
227 	io->i_offset = addr;
228 	io->i_bn = addr / DEV_BSIZE;
229 	io->i_cc = 0;
230 	return (0);
231 }
232 
233 getc(fdesc)
234 	int fdesc;
235 {
236 	register struct iob *io;
237 	register struct fs *fs;
238 	register char *p;
239 	int c, lbn, off, size, diff;
240 
241 
242 	if (fdesc >= 0 && fdesc <= 2)
243 		return (getchar());
244 	fdesc -= 3;
245 	if (fdesc < 0 || fdesc >= NFILES ||
246 	    ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
247 		errno = EBADF;
248 		return (-1);
249 	}
250 	p = io->i_ma;
251 	if (io->i_cc <= 0) {
252 		if ((io->i_flgs & F_FILE) != 0) {
253 			diff = io->i_ino.i_size - io->i_offset;
254 			if (diff <= 0)
255 				return (-1);
256 			fs = &io->i_fs;
257 			lbn = lblkno(fs, io->i_offset);
258 			io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
259 			off = blkoff(fs, io->i_offset);
260 			size = blksize(fs, &io->i_ino, lbn);
261 		} else {
262 			io->i_bn = io->i_offset / DEV_BSIZE;
263 			off = 0;
264 			size = DEV_BSIZE;
265 		}
266 		io->i_ma = io->i_buf;
267 		io->i_cc = size;
268 		devread(io);
269 		if ((io->i_flgs & F_FILE) != 0) {
270 			if (io->i_offset - off + size >= io->i_ino.i_size)
271 				io->i_cc = diff + off;
272 			io->i_cc -= off;
273 		}
274 		p = &io->i_buf[off];
275 	}
276 	io->i_cc--;
277 	io->i_offset++;
278 	c = (unsigned)*p++;
279 	io->i_ma = p;
280 	return (c);
281 }
282 
283 /* does this port?
284 getw(fdesc)
285 	int fdesc;
286 {
287 	register w,i;
288 	register char *cp;
289 	int val;
290 
291 	for (i = 0, val = 0, cp = &val; i < sizeof(val); i++) {
292 		w = getc(fdesc);
293 		if (w < 0) {
294 			if (i == 0)
295 				return (-1);
296 			else
297 				return (val);
298 		}
299 		*cp++ = w;
300 	}
301 	return (val);
302 }
303 */
304 int	errno;
305 
306 read(fdesc, buf, count)
307 	int fdesc, count;
308 	char *buf;
309 {
310 	register i;
311 	register struct iob *file;
312 
313 	errno = 0;
314 	if (fdesc >= 0 & fdesc <= 2) {
315 		i = count;
316 		do {
317 			*buf = getchar();
318 		} while (--i && *buf++ != '\n');
319 		return (count - i);
320 	}
321 	fdesc -= 3;
322 	if (fdesc < 0 || fdesc >= NFILES ||
323 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
324 		errno = EBADF;
325 		return (-1);
326 	}
327 	if ((file->i_flgs&F_READ) == 0) {
328 		errno = EBADF;
329 		return (-1);
330 	}
331 	if ((file->i_flgs & F_FILE) == 0) {
332 		file->i_cc = count;
333 		file->i_ma = buf;
334 		file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
335 		i = devread(file);
336 		file->i_offset += count;
337 		if (i < 0)
338 			errno = file->i_error;
339 		return (i);
340 	} else {
341 		if (file->i_offset+count > file->i_ino.i_size)
342 			count = file->i_ino.i_size - file->i_offset;
343 		if ((i = count) <= 0)
344 			return (0);
345 		do {
346 			*buf++ = getc(fdesc+3);
347 		} while (--i);
348 		return (count);
349 	}
350 }
351 
352 write(fdesc, buf, count)
353 	int fdesc, count;
354 	char *buf;
355 {
356 	register i;
357 	register struct iob *file;
358 
359 	errno = 0;
360 	if (fdesc >= 0 && fdesc <= 2) {
361 		i = count;
362 		while (i--)
363 			putchar(*buf++);
364 		return (count);
365 	}
366 	fdesc -= 3;
367 	if (fdesc < 0 || fdesc >= NFILES ||
368 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
369 		errno = EBADF;
370 		return (-1);
371 	}
372 	if ((file->i_flgs&F_WRITE) == 0) {
373 		errno = EBADF;
374 		return (-1);
375 	}
376 	file->i_cc = count;
377 	file->i_ma = buf;
378 	file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
379 	i = devwrite(file);
380 	file->i_offset += count;
381 	if (i < 0)
382 		errno = file->i_error;
383 	return (i);
384 }
385 
386 int	openfirst = 1;
387 
388 open(str, how)
389 	char *str;
390 	int how;
391 {
392 	register char *cp;
393 	int i;
394 	register struct iob *file;
395 	register struct devsw *dp;
396 	int fdesc;
397 	long atol();
398 
399 	if (openfirst) {
400 		for (i = 0; i < NFILES; i++)
401 			iob[i].i_flgs = 0;
402 		openfirst = 0;
403 	}
404 
405 	for (fdesc = 0; fdesc < NFILES; fdesc++)
406 		if (iob[fdesc].i_flgs == 0)
407 			goto gotfile;
408 	_stop("No more file slots");
409 gotfile:
410 	(file = &iob[fdesc])->i_flgs |= F_ALLOC;
411 
412 	for (cp = str; *cp && *cp != '('; cp++)
413 			;
414 	if (*cp != '(') {
415 		printf("Bad device\n");
416 		file->i_flgs = 0;
417 		errno = EDEV;
418 		return (-1);
419 	}
420 	*cp++ = '\0';
421 	for (dp = devsw; dp->dv_name; dp++) {
422 		if (!strcmp(str, dp->dv_name))
423 			goto gotdev;
424 	}
425 	printf("Unknown device\n");
426 	file->i_flgs = 0;
427 	errno = ENXIO;
428 	return (-1);
429 gotdev:
430 	*(cp-1) = '(';
431 	file->i_ino.i_dev = dp-devsw;
432 	file->i_unit = *cp++ - '0';
433 	if (*cp >= '0' && *cp <= '9')
434 		file->i_unit = file->i_unit * 10 + *cp++ - '0';
435 	if (file->i_unit < 0 || file->i_unit > 31) {
436 		printf("Bad unit specifier\n");
437 		file->i_flgs = 0;
438 		errno = EUNIT;
439 		return (-1);
440 	}
441 	if (*cp++ != ',') {
442 badoff:
443 		printf("Missing offset specification\n");
444 		file->i_flgs = 0;
445 		errno = EOFFSET;
446 		return (-1);
447 	}
448 	file->i_boff = atol(cp);
449 	for (;;) {
450 		if (*cp == ')')
451 			break;
452 		if (*cp++)
453 			continue;
454 		goto badoff;
455 	}
456 	devopen(file);
457 	if (*++cp == '\0') {
458 		file->i_flgs |= how+1;
459 		file->i_cc = 0;
460 		file->i_offset = 0;
461 		return (fdesc+3);
462 	}
463 	file->i_ma = (char *)(&file->i_fs);
464 	file->i_cc = SBSIZE;
465 	file->i_bn = SBLOCK + file->i_boff;
466 	file->i_offset = 0;
467 	devread(file);
468 	if ((i = find(cp, file)) == 0) {
469 		file->i_flgs = 0;
470 		errno = ESRCH;
471 		return (-1);
472 	}
473 	if (how != 0) {
474 		printf("Can't write files yet.. Sorry\n");
475 		file->i_flgs = 0;
476 		errno = EIO;
477 		return (-1);
478 	}
479 	openi(i, file);
480 	file->i_offset = 0;
481 	file->i_cc = 0;
482 	file->i_flgs |= F_FILE | (how+1);
483 	return (fdesc+3);
484 }
485 
486 close(fdesc)
487 	int fdesc;
488 {
489 	struct iob *file;
490 
491 	fdesc -= 3;
492 	if (fdesc < 0 || fdesc >= NFILES ||
493 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
494 		errno = EBADF;
495 		return (-1);
496 	}
497 	if ((file->i_flgs&F_FILE) == 0)
498 		devclose(file);
499 	file->i_flgs = 0;
500 	return (0);
501 }
502 
503 ioctl(fdesc, cmd, arg)
504 	int fdesc, cmd;
505 	char *arg;
506 {
507 	register struct iob *file;
508 	int error = 0;
509 
510 	if (fdesc < 0 || fdesc >= NFILES ||
511 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
512 		errno = EBADF;
513 		return (-1);
514 	}
515 	switch (cmd) {
516 
517 	case SAIOHDR:
518 		file->i_flgs |= F_HDR;
519 		break;
520 
521 	case SAIOCHECK:
522 		file->i_flgs |= F_CHECK;
523 		break;
524 
525 	case SAIOHCHECK:
526 		file->i_flgs |= F_HCHECK;
527 		break;
528 
529 	default:
530 		error = devioctl(file, cmd, arg);
531 		break;
532 	}
533 	if (error < 0)
534 		errno = file->i_error;
535 	return (error);
536 }
537 
538 exit()
539 {
540 	_stop("Exit called");
541 }
542 
543 _stop(s)
544 	char *s;
545 {
546 	int i;
547 
548 	for (i = 0; i < NFILES; i++)
549 		if (iob[i].i_flgs != 0)
550 			close(i);
551 	printf("%s\n", s);
552 	_rtt();
553 }
554 
555 trap(ps)
556 	int ps;
557 {
558 	printf("Trap %o\n", ps);
559 	for (;;)
560 		;
561 }
562