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