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