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 8 char copyright[] = 9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10 All rights reserved.\n"; 11 #endif not lint 12 13 #ifndef lint 14 static char sccsid[] = "@(#)arff.c 5.7 (Berkeley) 05/11/89"; 15 #endif not lint 16 17 #include <sys/types.h> 18 #include <sys/stat.h> 19 #include <sys/time.h> 20 #include <sys/signal.h> 21 #include <sys/file.h> 22 #include <stdio.h> 23 #include "pathnames.h" 24 25 #define dbprintf printf 26 27 struct rt_dat { 28 u_short rt_yr:5; /* year-1972 */ 29 u_short rt_dy:5; /* day */ 30 u_short rt_mo:5; /* month */ 31 }; 32 33 struct rt_axent { 34 char rt_sent[14]; 35 }; 36 37 struct rt_ent { 38 char rt_pad; /* unusued */ 39 u_char rt_stat; /* type of entry, or end of seg */ 40 u_short rt_name[3]; /* name, 3 words in rad50 form */ 41 u_short rt_len; /* length of file */ 42 u_char rt_chan; /* only used in temporary files */ 43 char rt_job; /* only used in temporary files */ 44 struct rt_dat rt_date; /* creation date */ 45 }; 46 47 #define RT_TEMP 1 48 #define RT_NULL 2 49 #define RT_FILE 4 50 #define RT_PFILE (0200|RT_FILE) /* protected file */ 51 #define RT_ESEG 8 52 53 #define RT_BLOCK 512 /* block size */ 54 #define RT_DIRSIZE 31 /* max # of directory segments */ 55 56 struct rt_head { 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 */ 62 }; 63 64 struct rt_dir { 65 struct rt_head rt_axhead; 66 struct rt_ent rt_ents[72]; 67 char _dirpad[6]; 68 }; 69 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 76 typedef struct fldope { 77 int startad; 78 int count; 79 struct rt_ent *rtdope; 80 } FLDOPE; 81 82 FLDOPE *lookup(); 83 84 #define rt(p) ((struct rt_ent *) p ) 85 #define Ain1 03100 86 #define Ain2 050 87 #define flag(c) (flg[('c') - 'a']) 88 89 char *man = "rxtd"; 90 char zeroes[512]; 91 92 extern char *val; 93 extern char table[256]; 94 struct rt_dir rt_dir[RT_DIRSIZE] = { 95 { 96 { 4, 0, 1, 0, 14 }, 97 { { 0, RT_NULL, { 0, 0, 0 }, 486, 0 }, 98 { 0, RT_ESEG } } 99 } 100 }; 101 102 struct rt_dir rt_nulldir = { 103 { 0, 0, 0, 0, 0 }, 104 { { 0, RT_NULL, { 0, 0, 0 }, 0, 0 }, 105 { 0, RT_ESEG } } 106 }; 107 108 int rt_entsiz; 109 int rt_nleft; 110 struct rt_ent *rt_curend[RT_DIRSIZE]; 111 int floppydes; 112 int dirdirty; 113 char *rt_last; 114 char *defdev = _PATH_FLOPPY; 115 116 char *opt = "vfbcm"; 117 118 extern long lseek(); 119 int rcmd(), dcmd(), xcmd(), tcmd(); 120 121 int (*comfun)(); 122 char flg[26]; 123 char **namv; 124 int namc; 125 126 main(argc, argv) 127 char *argv[]; 128 { 129 register char *cp; 130 131 if (argc < 2) 132 usage(); 133 for (cp = argv[1]; *cp; cp++) 134 switch (*cp) { 135 136 case 'm': 137 case 'v': 138 case 'u': 139 case 'w': 140 case 'b': 141 flg[*cp-'a']++; 142 continue; 143 case 'c': 144 flag(c)++; 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); 175 } 176 177 namv = argv+2; 178 namc = argc-2; 179 if (comfun == 0) { 180 if (flag(u) == 0) { 181 fprintf(stderr, "arff: one of [%s] must be specified\n", 182 man); 183 exit(1); 184 } 185 setcom(rcmd); 186 } 187 (*comfun)(); 188 exit(notfound()); 189 } 190 191 setcom(fun) 192 int (*fun)(); 193 { 194 if (comfun != 0) { 195 fprintf(stderr, "arff: only one of [%s] allowed\n", man); 196 exit(1); 197 } 198 comfun = fun; 199 } 200 201 usage() 202 { 203 fprintf(stderr, "usage: ar [%s][%s] archive files ...\n", opt, man); 204 exit(1); 205 } 206 207 notfound() 208 { 209 register i, n = 0; 210 211 for (i = 0; i < namc; i++) 212 if (namv[i]) { 213 fprintf(stderr, "arff: %s not found\n", namv[i]); 214 n++; 215 } 216 return (n); 217 } 218 219 tcmd() 220 { 221 register char *de, *last; 222 FLDOPE *lookup(), *dope; 223 int segnum, nleft; 224 register i; 225 register struct rt_ent *rde; 226 227 rt_init(); 228 if (namc != 0) { 229 for (i = 0; i < namc; i++) 230 if (dope = lookup(namv[i])) { 231 rde = dope->rtdope; 232 (void) rtls(rde); 233 namv[i] = 0; 234 } 235 return; 236 } 237 for (segnum = 0; segnum != -1; 238 segnum = rt_dir[segnum].rd_nxtseg - 1) { 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 } 249 } 250 251 rtls(de) 252 register struct rt_ent *de; 253 { 254 int month, day, year; 255 char name[12], ext[4]; 256 257 switch (de->rt_stat) { 258 259 case RT_TEMP: 260 if (flag(v)) 261 printf("Tempfile:\n"); 262 /* fall thru...*/ 263 264 case RT_FILE: 265 case RT_PFILE: 266 if (!flag(v)) { 267 sunrad50(name, de->rt_name); 268 printf("%s\n", name); 269 break; 270 } 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: 285 return (1); 286 } 287 return (0); 288 } 289 290 xcmd() 291 { 292 register char *de, *last; 293 int segnum; 294 char name[12]; 295 register int i; 296 297 rt_init(); 298 if (namc != 0) { 299 for (i = 0; i < namc; i++) 300 if (rtx(namv[i]) == 0) 301 namv[i] = 0; 302 return; 303 } 304 for (segnum = 0; segnum != -1; 305 segnum = rt_dir[segnum].rd_nxtseg-1) 306 for (last = rt_last+(segnum*2*RT_BLOCK), 307 de = ((char *)&rt_dir[segnum])+10; de <= last; 308 de += rt_entsiz) { 309 switch (rt(de)->rt_stat) { 310 311 case RT_ESEG: 312 break; /* exit loop and try next segment */ 313 314 case RT_TEMP: 315 case RT_FILE: 316 case RT_PFILE: 317 sunrad50(name,rt(de)->rt_name); 318 (void) rtx(name); 319 320 case RT_NULL: 321 default: 322 continue; 323 } 324 break; 325 } 326 } 327 328 rtx(name) 329 char *name; 330 { 331 register FLDOPE *dope; 332 FLDOPE *lookup(); 333 register startad, count; 334 int file; 335 char buff[512]; 336 337 338 if (dope = lookup(name)) { 339 if (flag(v)) 340 (void) rtls(dope->rtdope); 341 else 342 printf("x - %s\n",name); 343 344 if ((file = creat(name, 0666)) < 0) 345 return (1); 346 count = dope->count; 347 startad = dope->startad; 348 for( ; count > 0 ; count -= 512) { 349 (void) lread(startad, 512, buff); 350 (void) write(file, buff, 512); 351 startad += 512; 352 } 353 (void) close(file); 354 return (0); 355 } 356 return (1); 357 } 358 359 rt_init() 360 { 361 static initized = 0; 362 register char *de, *last; 363 register i; 364 int dirnum; 365 char *mode; 366 FILE *temp_floppydes; 367 368 if (initized) 369 return; 370 initized = 1; 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; 378 tty = open(_PATH_TTY, O_RDWR); 379 #define SURE "Are you sure you want to clobber the floppy? " 380 (void) write(tty, SURE, sizeof (SURE)); 381 (void) read(tty, response, sizeof (response)); 382 if (*response != 'y') 383 exit(50); 384 (void) close(tty); 385 ignore: 386 ; 387 } 388 if (flag(c) || flag(d) || flag(r)) 389 mode = "r+"; 390 else 391 mode = "r"; 392 if ((temp_floppydes = fopen(defdev, mode)) == NULL) { 393 perror(defdev); 394 exit(1); 395 } else 396 floppydes = fileno(temp_floppydes); 397 if (!flag(c)) { 398 if (lread(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0])) 399 exit(2); 400 dirnum = rt_dir[0].rd_numseg; 401 /* check for blank/uninitialized diskette */ 402 if (dirnum <= 0) { 403 fprintf(stderr,"arff: bad directory format\n"); 404 exit(1); 405 } 406 if (dirnum > RT_DIRSIZE) { 407 fprintf(stderr,"arff: too many directory segments\n"); 408 exit(1); 409 } 410 for (i = 1; i < dirnum; i++) 411 if (lread((6+2*i)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[i])) 412 exit(1); 413 } else { 414 dirnum = 1; 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 } 421 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; 430 rt_last = ((char *) &rt_dir[0]) + 10 + 1014/rt_entsiz*rt_entsiz; 431 rt_nleft = 0; 432 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; 440 } 441 } 442 443 static FLDOPE result; 444 445 FLDOPE * 446 lookup(name) 447 char *name; 448 { 449 unsigned short rname[3]; 450 register char *de; 451 int segnum; 452 register index; 453 454 srad50(name,rname); 455 456 /* 457 * Search for name, accumulate blocks in index 458 */ 459 rt_init(); 460 for (segnum = 0; segnum != -1; 461 segnum = rt_dir[segnum].rd_nxtseg - 1) 462 { 463 index = 0; 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: 469 case RT_PFILE: 470 case RT_TEMP: 471 if(samename(rname,rt(de)->rt_name)) { 472 result.count = rt(de)->rt_len * 512; 473 result.startad = 512* 474 (rt_dir[segnum].rd_stfile + index); 475 result.rtdope = (struct rt_ent *) de; 476 return (&result); 477 } 478 479 case RT_NULL: 480 index += rt(de)->rt_len; 481 } 482 } 483 return ((FLDOPE *) 0); 484 485 } 486 487 static 488 samename(a, b) 489 u_short a[], b[]; 490 { 491 return (*a == *b && a[1] == b[1] && a[2] == b[2] ); 492 } 493 494 rad50(cp, out) 495 register u_char *cp; 496 u_short *out; 497 { 498 register index, temp; 499 500 for (index = 0; *cp; index++) { 501 temp = Ain1 * table[*cp++]; 502 if (*cp!=0) { 503 temp += Ain2 * table[*cp++]; 504 if(*cp!=0) 505 temp += table[*cp++]; 506 } 507 out[index] = temp; 508 } 509 } 510 511 #define reduce(x, p, q) (x = v[p/q], p %= q); 512 513 unrad50(count, in, cp) 514 u_short *in; 515 register char *cp; 516 { 517 register i, temp; 518 register u_char *v = (u_char *) val; 519 520 for (i = 0; i < count; i++) { 521 temp = in[i]; 522 reduce(*cp++, temp, Ain1); 523 reduce(*cp++, temp, Ain2); 524 reduce(*cp++, temp, 1); 525 } 526 *cp=0; 527 } 528 529 srad50(name, rname) 530 register char *name; 531 register u_short *rname; 532 { 533 register index; 534 register char *cp; 535 char file[7], ext[4]; 536 537 /* 538 * Find end of pathname 539 */ 540 for (cp = name; *cp++; ) 541 ; 542 while (cp >= name && *--cp != '/') 543 ; 544 cp++; 545 /* 546 * Change to rad50 547 */ 548 for (index = 0; *cp; ) { 549 file[index++] = *cp++; 550 if (*cp == '.') { 551 cp++; 552 break; 553 } 554 if (index >= 6) { 555 break; 556 } 557 } 558 file[index] = 0; 559 for (index = 0; *cp; ) { 560 ext[index++] = *cp++; 561 if (*cp == '.' || index >= 3) 562 break; 563 } 564 ext[index]=0; 565 rname[0] = rname[1] = rname[2] = 0; 566 rad50((u_char *)file, rname); 567 rad50((u_char *)ext, rname+2); 568 } 569 570 sunrad50(name, rname) 571 u_short rname[]; 572 register char *name; 573 { 574 register char *cp, *cp2; 575 char ext[4]; 576 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;) 591 *cp++ = *cp2++; 592 *cp=0; 593 if (cp[-1] == '.') 594 cp[-1] = 0; 595 } 596 597 static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789"; 598 599 static char table[256] = { 600 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 601 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 602 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29, 603 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29, 604 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 605 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29, 606 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 607 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29, 608 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 609 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 610 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29, 611 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29, 612 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 613 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29, 614 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 615 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 }; 616 617 /* 618 * Logical to physical adress translation 619 */ 620 long 621 trans(logical) 622 register int logical; 623 { 624 register int sector, bytes, track; 625 626 logical += 26*128; 627 bytes = (logical&127); 628 logical >>= 7; 629 sector = logical%26; 630 if(sector >= 13) 631 sector = sector*2+1; 632 else 633 sector *= 2; 634 sector += 26 + ((track = (logical/26))-1)*6; 635 sector %= 26; 636 return ((((track*26)+sector) << 7) + bytes); 637 } 638 639 lread(startad, count, obuff) 640 register startad, count; 641 register char *obuff; 642 { 643 long trans(); 644 extern floppydes; 645 register int size = flag(m) ? 512 : 128; 646 int error = 0; 647 extern int errno; 648 649 rt_init(); 650 while ((count -= size) >= 0) { 651 (void) lseek(floppydes, flag(m) ? 652 (long)startad : trans(startad), 0); 653 if (read(floppydes, obuff, size) != size) { 654 error = errno; 655 fprintf(stderr, "arff: read error block %d: ", 656 startad/size); 657 errno = error; 658 perror(""); 659 } 660 obuff += size; 661 startad += size; 662 } 663 return (error); 664 } 665 666 lwrite(startad, count, obuff) 667 register startad, count; 668 register char *obuff; 669 { 670 long trans(); 671 extern floppydes; 672 register int size = flag(m) ? 512 : 128; 673 674 rt_init(); 675 while ((count -= size) >= 0) { 676 (void) lseek(floppydes, flag(m) ? 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 } 684 } 685 686 rcmd() 687 { 688 register int i; 689 690 rt_init(); 691 if (namc > 0) 692 for (i = 0; i < namc; i++) 693 if (rtr(namv[i]) == 0) 694 namv[i] = 0; 695 } 696 697 rtr(name) 698 char *name; 699 { 700 register FLDOPE *dope; 701 register struct rt_ent *de; 702 struct stat buf; 703 register struct stat *bufp = &buf; 704 int segnum; 705 char type; 706 707 if (stat(name, bufp) < 0) { 708 perror(name); 709 return (-1); 710 } 711 type = 'a'; 712 if (dope = lookup(name)) { 713 /* can replace, no problem */ 714 de = dope->rtdope; 715 if (bufp->st_size <= (de->rt_len * 512)) { 716 printf("r - %s\n",name); 717 toflop(name, bufp->st_size, dope); 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(); 728 } 729 } 730 /* 731 * Search for vacant spot 732 */ 733 for (segnum = 0; segnum != -1; 734 segnum = rt_dir[segnum].rd_nxtseg - 1) 735 { 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)) { 740 printf("%c - %s\n", type, name), 741 mkent(de, segnum, bufp,name); 742 goto found; 743 } 744 continue; 745 } 746 } 747 if (type == 'r') 748 printf("%s: no slot for file, file deleted\n",name); 749 else 750 printf("%s: no slot for file\n", name); 751 return (-1); 752 753 found: 754 if (dope = lookup(name)) { 755 toflop(name, bufp->st_size, dope); 756 return (0); 757 } 758 printf("%s: internal error, added then not found\n", name); 759 return (-1); 760 } 761 762 mkent(de, segnum, bufp, name) 763 register struct rt_ent *de; 764 int segnum; 765 register struct stat *bufp; 766 char *name; 767 { 768 struct tm *localtime(); 769 register struct tm *timp; 770 register struct rt_ent *workp; 771 int count; 772 773 count = (((bufp->st_size -1) >>9) + 1); 774 /* make sure there is room */ 775 if (de->rt_len == count) 776 goto overwrite; 777 if ((char *)rt_curend[segnum] == (rt_last + (segnum*2*RT_BLOCK))) { 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 } 826 } 827 /* copy directory entries up */ 828 for (workp = rt_curend[segnum]+1; workp > de; workp--) 829 *workp = workp[-1]; 830 de[1].rt_len -= count; 831 de->rt_len = count; 832 rt_curend[segnum]++; 833 rt_nleft--; 834 835 overwrite: 836 srad50(name,de->rt_name); 837 timp = localtime(&bufp->st_mtime); 838 de->rt_date.rt_dy = timp->tm_mday; 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; 845 lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[segnum]); 846 } 847 848 toflop(name, ocount, dope) 849 char *name; 850 register FLDOPE *dope; 851 long ocount; 852 { 853 register file, n, startad = dope->startad, count = ocount; 854 char buff[512]; 855 856 file = open(name, 0); 857 if (file < 0) { 858 fprintf(stderr, "arff: couldn't open %s\n",name); 859 exit(1); 860 } 861 for( ; count >= 512; count -= 512) { 862 (void) read(file, buff, 512); 863 lwrite(startad, 512, buff); 864 startad += 512; 865 } 866 (void) read(file, buff, count); 867 (void) close(file); 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--) { 877 startad += 512; 878 lwrite(startad, 512, zeroes); 879 } 880 } 881 882 dcmd() 883 { 884 register int i; 885 886 rt_init(); 887 if (namc) 888 for (i = 0; i < namc; i++) 889 if (rtk(namv[i])==0) 890 namv[i]=0; 891 if (dirdirty) 892 scrunch(); 893 } 894 895 rtk(name) 896 char *name; 897 { 898 register FLDOPE *dope; 899 register struct rt_ent *de; 900 FLDOPE *lookup(); 901 902 if (dope = lookup(name)) { 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; 909 *((u_short *)&(de->rt_date)) = 0; 910 dirdirty = 1; 911 return (0); 912 } 913 return (1); 914 } 915 916 scrunch() 917 { 918 register struct rt_ent *de , *workp; 919 register segnum; 920 921 for (segnum = 0; segnum != -1; 922 segnum = rt_dir[segnum].rd_nxtseg - 1) { 923 for (de = rt_dir[segnum].rt_ents; de <= rt_curend[segnum]; de++) 924 if (de->rt_stat == RT_NULL && 925 (de+1)->rt_stat == RT_NULL) { 926 (de+1)->rt_len += de->rt_len; 927 for (workp=de; workp<rt_curend[segnum]; workp++) 928 *workp = workp[1]; 929 de--; 930 rt_curend[segnum]--; 931 rt_nleft++; 932 } 933 lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK, 934 (char *)&rt_dir[segnum]); 935 } 936 dirdirty = 0; 937 } 938