1 /*-
2 * Copyright (c) 1980 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.proprietary.c%
6 */
7
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
11 All rights reserved.\n";
12 #endif /* not lint */
13
14 #ifndef lint
15 static char sccsid[] = "@(#)arff.c 5.8 (Berkeley) 04/18/91";
16 #endif /* not lint */
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <sys/time.h>
21 #include <sys/signal.h>
22 #include <sys/file.h>
23 #include <stdio.h>
24 #include "pathnames.h"
25
26 #define dbprintf printf
27
28 struct rt_dat {
29 u_short rt_yr:5; /* year-1972 */
30 u_short rt_dy:5; /* day */
31 u_short rt_mo:5; /* month */
32 };
33
34 struct rt_axent {
35 char rt_sent[14];
36 };
37
38 struct rt_ent {
39 char rt_pad; /* unusued */
40 u_char rt_stat; /* type of entry, or end of seg */
41 u_short rt_name[3]; /* name, 3 words in rad50 form */
42 u_short rt_len; /* length of file */
43 u_char rt_chan; /* only used in temporary files */
44 char rt_job; /* only used in temporary files */
45 struct rt_dat rt_date; /* creation date */
46 };
47
48 #define RT_TEMP 1
49 #define RT_NULL 2
50 #define RT_FILE 4
51 #define RT_PFILE (0200|RT_FILE) /* protected file */
52 #define RT_ESEG 8
53
54 #define RT_BLOCK 512 /* block size */
55 #define RT_DIRSIZE 31 /* max # of directory segments */
56
57 struct rt_head {
58 short rt_numseg; /* # of segments available */
59 short rt_nxtseg; /* # of next logical segment */
60 short rt_lstseg; /* highest seg currently open */
61 u_short rt_entpad; /* extra words/directory entry */
62 short rt_stfile; /* block # where files begin */
63 };
64
65 struct rt_dir {
66 struct rt_head rt_axhead;
67 struct rt_ent rt_ents[72];
68 char _dirpad[6];
69 };
70
71 #define rd_numseg rt_axhead.rt_numseg
72 #define rd_nxtseg rt_axhead.rt_nxtseg
73 #define rd_lstseg rt_axhead.rt_lstseg
74 #define rd_entpad rt_axhead.rt_entpad
75 #define rd_stfile rt_axhead.rt_stfile
76
77 typedef struct fldope {
78 int startad;
79 int count;
80 struct rt_ent *rtdope;
81 } FLDOPE;
82
83 FLDOPE *lookup();
84
85 #define rt(p) ((struct rt_ent *) p )
86 #define Ain1 03100
87 #define Ain2 050
88 #define flag(c) (flg[('c') - 'a'])
89
90 char *man = "rxtd";
91 char zeroes[512];
92
93 extern char *val;
94 extern char table[256];
95 struct rt_dir rt_dir[RT_DIRSIZE] = {
96 {
97 { 4, 0, 1, 0, 14 },
98 { { 0, RT_NULL, { 0, 0, 0 }, 486, 0 },
99 { 0, RT_ESEG } }
100 }
101 };
102
103 struct rt_dir rt_nulldir = {
104 { 0, 0, 0, 0, 0 },
105 { { 0, RT_NULL, { 0, 0, 0 }, 0, 0 },
106 { 0, RT_ESEG } }
107 };
108
109 int rt_entsiz;
110 int rt_nleft;
111 struct rt_ent *rt_curend[RT_DIRSIZE];
112 int floppydes;
113 int dirdirty;
114 char *rt_last;
115 char *defdev = _PATH_FLOPPY;
116
117 char *opt = "vfbcm";
118
119 extern long lseek();
120 int rcmd(), dcmd(), xcmd(), tcmd();
121
122 int (*comfun)();
123 char flg[26];
124 char **namv;
125 int namc;
126
main(argc,argv)127 main(argc, argv)
128 char *argv[];
129 {
130 register char *cp;
131
132 if (argc < 2)
133 usage();
134 for (cp = argv[1]; *cp; cp++)
135 switch (*cp) {
136
137 case 'm':
138 case 'v':
139 case 'u':
140 case 'w':
141 case 'b':
142 flg[*cp-'a']++;
143 continue;
144 case 'c':
145 flag(c)++;
146 dirdirty++;
147 continue;
148
149 case 'r':
150 setcom(rcmd);
151 flag(r)++;
152 continue;
153
154 case 'd':
155 setcom(dcmd);
156 flag(d)++;
157 continue;
158
159 case 'x':
160 setcom(xcmd);
161 continue;
162
163 case 't':
164 setcom(tcmd);
165 continue;
166
167 case 'f':
168 defdev = argv[2];
169 argv++;
170 argc--;
171 continue;
172
173 default:
174 fprintf(stderr, "arff: bad option `%c'\n", *cp);
175 exit(1);
176 }
177
178 namv = argv+2;
179 namc = argc-2;
180 if (comfun == 0) {
181 if (flag(u) == 0) {
182 fprintf(stderr, "arff: one of [%s] must be specified\n",
183 man);
184 exit(1);
185 }
186 setcom(rcmd);
187 }
188 (*comfun)();
189 exit(notfound());
190 }
191
192 setcom(fun)
193 int (*fun)();
194 {
195 if (comfun != 0) {
196 fprintf(stderr, "arff: only one of [%s] allowed\n", man);
197 exit(1);
198 }
199 comfun = fun;
200 }
201
usage()202 usage()
203 {
204 fprintf(stderr, "usage: ar [%s][%s] archive files ...\n", opt, man);
205 exit(1);
206 }
207
notfound()208 notfound()
209 {
210 register i, n = 0;
211
212 for (i = 0; i < namc; i++)
213 if (namv[i]) {
214 fprintf(stderr, "arff: %s not found\n", namv[i]);
215 n++;
216 }
217 return (n);
218 }
219
tcmd()220 tcmd()
221 {
222 register char *de, *last;
223 FLDOPE *lookup(), *dope;
224 int segnum, nleft;
225 register i;
226 register struct rt_ent *rde;
227
228 rt_init();
229 if (namc != 0) {
230 for (i = 0; i < namc; i++)
231 if (dope = lookup(namv[i])) {
232 rde = dope->rtdope;
233 (void) rtls(rde);
234 namv[i] = 0;
235 }
236 return;
237 }
238 for (segnum = 0; segnum != -1;
239 segnum = rt_dir[segnum].rd_nxtseg - 1) {
240 last = rt_last + segnum*2*RT_BLOCK;
241 for (de = ((char *)&rt_dir[segnum])+10; de <= last;
242 de += rt_entsiz)
243 if (rtls(rt(de))) {
244 nleft = (last-de)/rt_entsiz;
245 #define ENTRIES "\n%d entries remaining in directory segment %d.\n"
246 printf(ENTRIES, nleft, segnum+1);
247 break;
248 }
249 }
250 }
251
rtls(de)252 rtls(de)
253 register struct rt_ent *de;
254 {
255 int month, day, year;
256 char name[12], ext[4];
257
258 switch (de->rt_stat) {
259
260 case RT_TEMP:
261 if (flag(v))
262 printf("Tempfile:\n");
263 /* fall thru...*/
264
265 case RT_FILE:
266 case RT_PFILE:
267 if (!flag(v)) {
268 sunrad50(name, de->rt_name);
269 printf("%s\n", name);
270 break;
271 }
272 unrad50(2, de->rt_name, name);
273 unrad50(1, &(de->rt_name[2]), ext);
274 day = de->rt_date.rt_dy;
275 year = de->rt_date.rt_yr+72;
276 month = de->rt_date.rt_mo;
277 printf("%6.6s %3.3s %02d/%02d/%02d %d\n",name,
278 ext, month, day, year, de->rt_len);
279 break;
280
281 case RT_NULL:
282 printf("%-25.9s %d\n","<UNUSED>", de->rt_len);
283 break;
284
285 case RT_ESEG:
286 return (1);
287 }
288 return (0);
289 }
290
xcmd()291 xcmd()
292 {
293 register char *de, *last;
294 int segnum;
295 char name[12];
296 register int i;
297
298 rt_init();
299 if (namc != 0) {
300 for (i = 0; i < namc; i++)
301 if (rtx(namv[i]) == 0)
302 namv[i] = 0;
303 return;
304 }
305 for (segnum = 0; segnum != -1;
306 segnum = rt_dir[segnum].rd_nxtseg-1)
307 for (last = rt_last+(segnum*2*RT_BLOCK),
308 de = ((char *)&rt_dir[segnum])+10; de <= last;
309 de += rt_entsiz) {
310 switch (rt(de)->rt_stat) {
311
312 case RT_ESEG:
313 break; /* exit loop and try next segment */
314
315 case RT_TEMP:
316 case RT_FILE:
317 case RT_PFILE:
318 sunrad50(name,rt(de)->rt_name);
319 (void) rtx(name);
320
321 case RT_NULL:
322 default:
323 continue;
324 }
325 break;
326 }
327 }
328
rtx(name)329 rtx(name)
330 char *name;
331 {
332 register FLDOPE *dope;
333 FLDOPE *lookup();
334 register startad, count;
335 int file;
336 char buff[512];
337
338
339 if (dope = lookup(name)) {
340 if (flag(v))
341 (void) rtls(dope->rtdope);
342 else
343 printf("x - %s\n",name);
344
345 if ((file = creat(name, 0666)) < 0)
346 return (1);
347 count = dope->count;
348 startad = dope->startad;
349 for( ; count > 0 ; count -= 512) {
350 (void) lread(startad, 512, buff);
351 (void) write(file, buff, 512);
352 startad += 512;
353 }
354 (void) close(file);
355 return (0);
356 }
357 return (1);
358 }
359
rt_init()360 rt_init()
361 {
362 static initized = 0;
363 register char *de, *last;
364 register i;
365 int dirnum;
366 char *mode;
367 FILE *temp_floppydes;
368
369 if (initized)
370 return;
371 initized = 1;
372 if (flag(c)) {
373 struct stat sb;
374 char response[128];
375 int tty;
376
377 if (stat(defdev, &sb) >= 0 && (sb.st_mode & S_IFMT) == S_IFREG)
378 goto ignore;
379 tty = open(_PATH_TTY, O_RDWR);
380 #define SURE "Are you sure you want to clobber the floppy? "
381 (void) write(tty, SURE, sizeof (SURE));
382 (void) read(tty, response, sizeof (response));
383 if (*response != 'y')
384 exit(50);
385 (void) close(tty);
386 ignore:
387 ;
388 }
389 if (flag(c) || flag(d) || flag(r))
390 mode = "r+";
391 else
392 mode = "r";
393 if ((temp_floppydes = fopen(defdev, mode)) == NULL) {
394 perror(defdev);
395 exit(1);
396 } else
397 floppydes = fileno(temp_floppydes);
398 if (!flag(c)) {
399 if (lread(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]))
400 exit(2);
401 dirnum = rt_dir[0].rd_numseg;
402 /* check for blank/uninitialized diskette */
403 if (dirnum <= 0) {
404 fprintf(stderr,"arff: bad directory format\n");
405 exit(1);
406 }
407 if (dirnum > RT_DIRSIZE) {
408 fprintf(stderr,"arff: too many directory segments\n");
409 exit(1);
410 }
411 for (i = 1; i < dirnum; i++)
412 if (lread((6+2*i)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[i]))
413 exit(1);
414 } else {
415 dirnum = 1;
416 if (flag(b)) {
417 rt_dir[0].rd_numseg = 31;
418 rt_dir[0].rd_stfile = 68;
419 rt_dir[0].rt_ents[0].rt_len = 20480 - 68;
420 }
421 }
422
423 rt_entsiz = 2*rt_dir[0].rd_entpad + 14;
424 /*
425 * We assume that the directory entries have no padding. This
426 * may not be a valid assumption, but there are numerous point
427 * in the code where it assumes it is an rt_ent structure and
428 * not an rt_entsiz sized structure.
429 */
430 rt_entsiz = 14;
431 rt_last = ((char *) &rt_dir[0]) + 10 + 1014/rt_entsiz*rt_entsiz;
432 rt_nleft = 0;
433
434 for (i = 0; i < dirnum; i++) {
435 last = rt_last + i*2*RT_BLOCK;
436 for (de = ((char *)&rt_dir[i])+10; de <= last; de += rt_entsiz)
437 if (rt(de)->rt_stat == RT_ESEG)
438 break;
439 rt_curend[i] = rt(de);
440 rt_nleft += (last-de)/rt_entsiz;
441 }
442 }
443
444 static FLDOPE result;
445
446 FLDOPE *
lookup(name)447 lookup(name)
448 char *name;
449 {
450 unsigned short rname[3];
451 register char *de;
452 int segnum;
453 register index;
454
455 srad50(name,rname);
456
457 /*
458 * Search for name, accumulate blocks in index
459 */
460 rt_init();
461 for (segnum = 0; segnum != -1;
462 segnum = rt_dir[segnum].rd_nxtseg - 1)
463 {
464 index = 0;
465 for (de=((char *)&rt_dir[segnum])+10;
466 rt(de)->rt_stat != RT_ESEG; de += rt_entsiz)
467 switch(rt(de)->rt_stat) {
468
469 case RT_FILE:
470 case RT_PFILE:
471 case RT_TEMP:
472 if(samename(rname,rt(de)->rt_name)) {
473 result.count = rt(de)->rt_len * 512;
474 result.startad = 512*
475 (rt_dir[segnum].rd_stfile + index);
476 result.rtdope = (struct rt_ent *) de;
477 return (&result);
478 }
479
480 case RT_NULL:
481 index += rt(de)->rt_len;
482 }
483 }
484 return ((FLDOPE *) 0);
485
486 }
487
488 static
samename(a,b)489 samename(a, b)
490 u_short a[], b[];
491 {
492 return (*a == *b && a[1] == b[1] && a[2] == b[2] );
493 }
494
rad50(cp,out)495 rad50(cp, out)
496 register u_char *cp;
497 u_short *out;
498 {
499 register index, temp;
500
501 for (index = 0; *cp; index++) {
502 temp = Ain1 * table[*cp++];
503 if (*cp!=0) {
504 temp += Ain2 * table[*cp++];
505 if(*cp!=0)
506 temp += table[*cp++];
507 }
508 out[index] = temp;
509 }
510 }
511
512 #define reduce(x, p, q) (x = v[p/q], p %= q);
513
unrad50(count,in,cp)514 unrad50(count, in, cp)
515 u_short *in;
516 register char *cp;
517 {
518 register i, temp;
519 register u_char *v = (u_char *) val;
520
521 for (i = 0; i < count; i++) {
522 temp = in[i];
523 reduce(*cp++, temp, Ain1);
524 reduce(*cp++, temp, Ain2);
525 reduce(*cp++, temp, 1);
526 }
527 *cp=0;
528 }
529
srad50(name,rname)530 srad50(name, rname)
531 register char *name;
532 register u_short *rname;
533 {
534 register index;
535 register char *cp;
536 char file[7], ext[4];
537
538 /*
539 * Find end of pathname
540 */
541 for (cp = name; *cp++; )
542 ;
543 while (cp >= name && *--cp != '/')
544 ;
545 cp++;
546 /*
547 * Change to rad50
548 */
549 for (index = 0; *cp; ) {
550 file[index++] = *cp++;
551 if (*cp == '.') {
552 cp++;
553 break;
554 }
555 if (index >= 6) {
556 break;
557 }
558 }
559 file[index] = 0;
560 for (index = 0; *cp; ) {
561 ext[index++] = *cp++;
562 if (*cp == '.' || index >= 3)
563 break;
564 }
565 ext[index]=0;
566 rname[0] = rname[1] = rname[2] = 0;
567 rad50((u_char *)file, rname);
568 rad50((u_char *)ext, rname+2);
569 }
570
sunrad50(name,rname)571 sunrad50(name, rname)
572 u_short rname[];
573 register char *name;
574 {
575 register char *cp, *cp2;
576 char ext[4];
577
578 unrad50(2, rname, name);
579 unrad50(1, rname + 2, ext);
580 /*
581 * Jam name and extension together with a dot
582 * deleting white space
583 */
584 for (cp = name; *cp++;)
585 ;
586 --cp;
587 while (*--cp == ' ' && cp >= name)
588 ;
589 *++cp = '.';
590 cp++;
591 for (cp2 = ext; *cp2 != ' ' && cp2 < ext+3;)
592 *cp++ = *cp2++;
593 *cp=0;
594 if (cp[-1] == '.')
595 cp[-1] = 0;
596 }
597
598 static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
599
600 static char table[256] = {
601 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
602 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
603 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
604 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
605 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
606 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
607 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
608 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
609 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
610 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
611 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
612 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
613 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
614 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
615 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
616 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
617
618 /*
619 * Logical to physical adress translation
620 */
621 long
trans(logical)622 trans(logical)
623 register int logical;
624 {
625 register int sector, bytes, track;
626
627 logical += 26*128;
628 bytes = (logical&127);
629 logical >>= 7;
630 sector = logical%26;
631 if(sector >= 13)
632 sector = sector*2+1;
633 else
634 sector *= 2;
635 sector += 26 + ((track = (logical/26))-1)*6;
636 sector %= 26;
637 return ((((track*26)+sector) << 7) + bytes);
638 }
639
lread(startad,count,obuff)640 lread(startad, count, obuff)
641 register startad, count;
642 register char *obuff;
643 {
644 long trans();
645 extern floppydes;
646 register int size = flag(m) ? 512 : 128;
647 int error = 0;
648 extern int errno;
649
650 rt_init();
651 while ((count -= size) >= 0) {
652 (void) lseek(floppydes, flag(m) ?
653 (long)startad : trans(startad), 0);
654 if (read(floppydes, obuff, size) != size) {
655 error = errno;
656 fprintf(stderr, "arff: read error block %d: ",
657 startad/size);
658 errno = error;
659 perror("");
660 }
661 obuff += size;
662 startad += size;
663 }
664 return (error);
665 }
666
lwrite(startad,count,obuff)667 lwrite(startad, count, obuff)
668 register startad, count;
669 register char *obuff;
670 {
671 long trans();
672 extern floppydes;
673 register int size = flag(m) ? 512 : 128;
674
675 rt_init();
676 while ((count -= size) >= 0) {
677 (void) lseek(floppydes, flag(m) ?
678 (long)startad : trans(startad), 0);
679 if (write(floppydes, obuff, size) != size)
680 fprintf(stderr, "arff: write error block %d\n",
681 startad/size);
682 obuff += size;
683 startad += size;
684 }
685 }
686
rcmd()687 rcmd()
688 {
689 register int i;
690
691 rt_init();
692 if (namc > 0)
693 for (i = 0; i < namc; i++)
694 if (rtr(namv[i]) == 0)
695 namv[i] = 0;
696 }
697
rtr(name)698 rtr(name)
699 char *name;
700 {
701 register FLDOPE *dope;
702 register struct rt_ent *de;
703 struct stat buf;
704 register struct stat *bufp = &buf;
705 int segnum;
706 char type;
707
708 if (stat(name, bufp) < 0) {
709 perror(name);
710 return (-1);
711 }
712 type = 'a';
713 if (dope = lookup(name)) {
714 /* can replace, no problem */
715 de = dope->rtdope;
716 if (bufp->st_size <= (de->rt_len * 512)) {
717 printf("r - %s\n",name);
718 toflop(name, bufp->st_size, dope);
719 goto found;
720 } else {
721 de = dope->rtdope;
722 type = 'r';
723 de->rt_stat = RT_NULL;
724 de->rt_name[0] = 0;
725 de->rt_name[1] = 0;
726 de->rt_name[2] = 0;
727 *((u_short *)&(de->rt_date)) = 0;
728 scrunch();
729 }
730 }
731 /*
732 * Search for vacant spot
733 */
734 for (segnum = 0; segnum != -1;
735 segnum = rt_dir[segnum].rd_nxtseg - 1)
736 {
737 for (de = rt_dir[segnum].rt_ents;
738 rt(de)->rt_stat != RT_ESEG; de++)
739 if ((de)->rt_stat == RT_NULL) {
740 if (bufp->st_size <= (de->rt_len*512)) {
741 printf("%c - %s\n", type, name),
742 mkent(de, segnum, bufp,name);
743 goto found;
744 }
745 continue;
746 }
747 }
748 if (type == 'r')
749 printf("%s: no slot for file, file deleted\n",name);
750 else
751 printf("%s: no slot for file\n", name);
752 return (-1);
753
754 found:
755 if (dope = lookup(name)) {
756 toflop(name, bufp->st_size, dope);
757 return (0);
758 }
759 printf("%s: internal error, added then not found\n", name);
760 return (-1);
761 }
762
mkent(de,segnum,bufp,name)763 mkent(de, segnum, bufp, name)
764 register struct rt_ent *de;
765 int segnum;
766 register struct stat *bufp;
767 char *name;
768 {
769 struct tm *localtime();
770 register struct tm *timp;
771 register struct rt_ent *workp;
772 int count;
773
774 count = (((bufp->st_size -1) >>9) + 1);
775 /* make sure there is room */
776 if (de->rt_len == count)
777 goto overwrite;
778 if ((char *)rt_curend[segnum] == (rt_last + (segnum*2*RT_BLOCK))) {
779 /* no entries left on segment, trying adding new segment */
780 if (rt_dir[0].rd_numseg > rt_dir[0].rd_lstseg) {
781 short newseg;
782 register int i;
783 int maxseg;
784 short size;
785
786 newseg = rt_dir[0].rd_lstseg++;
787 rt_dir[newseg] = rt_nulldir;
788 rt_dir[newseg].rd_nxtseg = rt_dir[segnum].rd_nxtseg;
789 rt_dir[segnum].rd_nxtseg = newseg + 1;
790 rt_dir[newseg].rd_entpad = rt_dir[0].rd_entpad;
791 rt_dir[newseg].rd_numseg = rt_dir[0].rd_numseg;
792 size = 0;
793 maxseg = 0;
794 for(i = newseg - 1; i >= 0; i--) {
795 workp = rt_curend[i] - 1;
796 if (workp->rt_stat != RT_NULL)
797 continue;
798 if (workp->rt_len < size)
799 continue;
800 size = workp->rt_len;
801 maxseg = i;
802 }
803 size = 0;
804 for (workp = &rt_dir[maxseg].rt_ents[0];
805 workp->rt_stat != RT_ESEG; workp++) {
806 size += workp->rt_len;
807 }
808 workp--;
809 rt_dir[newseg].rt_ents[0].rt_len = workp->rt_len;
810 rt_dir[newseg].rd_stfile =
811 rt_dir[maxseg].rd_stfile + size - workp->rt_len;
812 workp->rt_len = 0;
813 rt_curend[newseg] = &rt_dir[newseg].rt_ents[1];
814 lwrite(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]);
815 if (segnum != 0)
816 lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
817 (char *)&rt_dir[segnum]);
818 lwrite((6+newseg*2)*RT_BLOCK, 2*RT_BLOCK,
819 (char *)&rt_dir[newseg]);
820 segnum = newseg;
821 de = &rt_dir[newseg].rt_ents[0];
822 } else {
823 fprintf(stderr, "All directory segments full on %s\n",
824 defdev);
825 exit(1);
826 }
827 }
828 /* copy directory entries up */
829 for (workp = rt_curend[segnum]+1; workp > de; workp--)
830 *workp = workp[-1];
831 de[1].rt_len -= count;
832 de->rt_len = count;
833 rt_curend[segnum]++;
834 rt_nleft--;
835
836 overwrite:
837 srad50(name,de->rt_name);
838 timp = localtime(&bufp->st_mtime);
839 de->rt_date.rt_dy = timp->tm_mday;
840 de->rt_date.rt_mo = timp->tm_mon + 1;
841 de->rt_date.rt_yr = timp->tm_year - 72;
842 de->rt_stat = RT_FILE;
843 de->rt_pad = 0;
844 de->rt_chan = 0;
845 de->rt_job = 0;
846 lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[segnum]);
847 }
848
toflop(name,ocount,dope)849 toflop(name, ocount, dope)
850 char *name;
851 register FLDOPE *dope;
852 long ocount;
853 {
854 register file, n, startad = dope->startad, count = ocount;
855 char buff[512];
856
857 file = open(name, 0);
858 if (file < 0) {
859 fprintf(stderr, "arff: couldn't open %s\n",name);
860 exit(1);
861 }
862 for( ; count >= 512; count -= 512) {
863 (void) read(file, buff, 512);
864 lwrite(startad, 512, buff);
865 startad += 512;
866 }
867 (void) read(file, buff, count);
868 (void) close(file);
869 if (count <= 0)
870 return;
871 for (n = count; n < 512; n ++)
872 buff[n] = 0;
873 lwrite(startad, 512, buff);
874 count = (dope->rtdope->rt_len*512-ocount)/512 ;
875 if (count <= 0)
876 return;
877 for ( ; count > 0 ; count--) {
878 startad += 512;
879 lwrite(startad, 512, zeroes);
880 }
881 }
882
dcmd()883 dcmd()
884 {
885 register int i;
886
887 rt_init();
888 if (namc)
889 for (i = 0; i < namc; i++)
890 if (rtk(namv[i])==0)
891 namv[i]=0;
892 if (dirdirty)
893 scrunch();
894 }
895
rtk(name)896 rtk(name)
897 char *name;
898 {
899 register FLDOPE *dope;
900 register struct rt_ent *de;
901 FLDOPE *lookup();
902
903 if (dope = lookup(name)) {
904 printf("d - %s\n",name);
905 de = dope->rtdope;
906 de->rt_stat = RT_NULL;
907 de->rt_name[0] = 0;
908 de->rt_name[1] = 0;
909 de->rt_name[2] = 0;
910 *((u_short *)&(de->rt_date)) = 0;
911 dirdirty = 1;
912 return (0);
913 }
914 return (1);
915 }
916
scrunch()917 scrunch()
918 {
919 register struct rt_ent *de , *workp;
920 register segnum;
921
922 for (segnum = 0; segnum != -1;
923 segnum = rt_dir[segnum].rd_nxtseg - 1) {
924 for (de = rt_dir[segnum].rt_ents; de <= rt_curend[segnum]; de++)
925 if (de->rt_stat == RT_NULL &&
926 (de+1)->rt_stat == RT_NULL) {
927 (de+1)->rt_len += de->rt_len;
928 for (workp=de; workp<rt_curend[segnum]; workp++)
929 *workp = workp[1];
930 de--;
931 rt_curend[segnum]--;
932 rt_nleft++;
933 }
934 lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
935 (char *)&rt_dir[segnum]);
936 }
937 dirdirty = 0;
938 }
939