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