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