home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 December / simtel1292_SIMTEL_1292_Walnut_Creek.iso / msdos / c / cc03.arc / LU.C < prev    next >
Text File  |  1985-06-05  |  22KB  |  625 lines

  1. #include <stdio.h>
  2. /*  #include <ctype.h> */
  3.  
  4. char *sbrk();
  5. unsigned int coreleft();
  6.  
  7. /*
  8.         T. Jennings 13 Jan 84
  9.  
  10.  
  11.         LU Library Utility for all MSDOS and PC DOS machines. Can be used
  12. to pack multiple files into a single LBR file for modem transfers, extract,
  13. delete or update files within an LBR file, and reorganize one.
  14.  
  15.         NOTE: Reorganizing is desireable after deleting, adding, or updating
  16. a file in the library. This due to the way LBR files are organized; deleted
  17. files dont remove the data, and new files are added to the end. The LBR will
  18. become much more compact after a Reorganization.
  19.  
  20. */
  21.  
  22. #define ACTIVE 0        /* active, non-deleted file, */
  23. #define UNUSED 0xff     /* never used slot, */
  24. #define DELETED 0xfe    /* deleted file slot, */
  25.  
  26. #define MAXNAMES 20     /* maximum number of names in command line, */
  27. #define MAXFILES 256    /* max files per LBR file, */
  28.  
  29. char names[30][MAXNAMES];/* list of names from command line, */
  30. int num_names;          /* number of names in above list, */
  31.  
  32. /* Fix some annoyances in the Lattice Library. */
  33.  
  34. long lseek();                   /* not an annoyance, */
  35. #define tell(f) lseek(f,0L,1)   /* wierd */
  36. #define seek lseek              /* wrong name, */
  37.  
  38. /* This is the structure of the LBR file directory. One per slot.
  39. THIS MUST BE COMPILED ON LATTICE WITH THE -B OPTION!!!! */
  40.  
  41. struct _ludir {
  42.         char stat;      /* file status, */
  43.         char name[11];  /* FCB type filename, */
  44.         unsigned off;   /* offset to data, (sectors) */
  45.         unsigned len;   /* length (sectors) of data, */
  46.         int fill[8];    /* fill out to 32 bytes */
  47. } ludir; /* (dummy ludir so we can sizeof() it) */
  48.  
  49. struct _ludir ldir[MAXFILES];
  50. int num_slots;          /* number of slots in LBR file, */
  51.  
  52. char lbrname[14];       /* LBR file name, */
  53. int lbr;                /* LBR file handle, */
  54. char *buf;              /* buffer from DOS, */
  55. unsigned int bufsize;   /* size of buffer, */
  56.  
  57. main(argc,argv)
  58. int argc;
  59. char *argv[];
  60. {
  61. int i;
  62. char command;
  63.  
  64.         ++argv; --argc;
  65.         if (argc < 2) {
  66.  
  67.                 printf("LU -- T. Jennings 15 Jan 84\n");
  68.                 printf("  LU <cmd> lbrfile file file file ...   Where <cmd> is:\n");
  69.                 printf("\tT List of files in LBR file,\n");
  70.                 printf("\tL Same as T,\n");
  71.                 printf("\tA Extract all files from the LBR file,\n");
  72.                 printf("\tE Extract file(s) from LBR file,\n");
  73.                 printf("\tU Add to or create LBR file,\n");
  74.                 printf("\tD Delete a file from LBR file,\n");
  75.                 printf("\tR Reorganize the LBR file.\n");
  76.                 exit();
  77.         }
  78.         command= *argv[0];              /* get command char, */
  79.         strcpy(lbrname,argv[1]);        /* blindly get LBR name, */
  80.         for (i= 0; i < argc - 2; i++) {
  81.                 strcpy(names[i],argv[i + 2]);
  82.                 stoupper(names[i]);
  83.         }
  84.         num_names= i;
  85.  
  86.         /* find largest area to allocate */
  87.         bufsize= coreleft() - (MAXFILES * sizeof(ludir)) - 2000;
  88.         if (bufsize < 512) {
  89.                 printf("Not enough memory\n");
  90.                 exit();
  91.         }
  92.         buf = alloc(bufsize);
  93.  
  94.         switch (tolower(command)) {
  95.                 case 'a':
  96.                         unpack();
  97.                         break;
  98.                 case 't':
  99.                 case 'l':
  100.                         list();
  101.                         break;
  102.                 case 'e':
  103.                         extract();
  104.                         break;
  105.                 case 'u':
  106.                         update();
  107.                         break;
  108.                 case 'd':
  109.                         delete();
  110.                         break;
  111.                 case 'r':
  112.                         reorg();
  113.                         break;
  114.                 default:
  115.                         printf("Not a command.\n");
  116.                         break;
  117.         }
  118. }
  119. /* Update: add or change a file. If the library file does not exist, then
  120. create it and ask for the number of slots. Delete any file of the same
  121. name first, then add it in. */
  122.  
  123. update() {
  124.  
  125. int i;
  126.  
  127.         if (get_directory() == -1) {            /* open or create, */
  128.                 if (new_directory() == -1) {
  129.                         printf("Error: cant create new directory\n");
  130.                         return;                 /* error! */
  131.                 }
  132.         }
  133.         for (i= 0; i < num_names; i++) {        /* add each file, */
  134.                 if (find(names[i]) != -1) printf("Updating existing file %s\n",names[i]);
  135.                 else printf("Adding new file %s\n",names[i]);
  136.                 kill(names[i]);                 /* delete first, */
  137.                 if (add_file(names[i]) == 0)    /* add in, if error, */
  138.                         break;
  139.         }
  140.         put_directory();                        /* close LBR file, */
  141. }
  142. /* Delete all the specified names from the directory. */
  143.  
  144. delete() {
  145.  
  146. int i;
  147.         if (get_directory() == -1) {
  148.                 printf("Error: LBR file not found\n");
  149.                 return;
  150.         }
  151.         for (i= 0; i < num_names; i++) {
  152.                 if (find(names[i]) != -1)
  153.                         printf("Deleting %s\n",names[i]);
  154.                 else printf("%s not in library\n",names[i]);
  155.                 kill(names[i]);
  156.         }
  157.         put_directory();
  158. }
  159.  
  160. /* List all the files in the LBR file. */
  161.  
  162. list() {
  163.  
  164. int i;
  165. long size;
  166. char name[14];
  167. int active,deleted,empty;
  168.  
  169.         size= 0L; active= deleted= empty= 0;
  170.  
  171.         if (get_directory() == -1) {
  172.                 printf("Error: LBR file not found\n");
  173.                 return;
  174.         }
  175.         for (i= 0; i < num_slots; i++) {
  176.                 if (ldir[i].stat == ACTIVE) {
  177.                         cvt_from_fcb(ldir[i].name,name);
  178.                         printf("%-16s %8lu %8u\n",name,
  179.                           (long)ldir[i].len * 128L,ldir[i].off);
  180.                         size+= (long)ldir[i].len * 128L;
  181.                         ++active;
  182.                 }
  183.                 if (ldir[i].stat == DELETED) ++deleted;
  184.                 if (ldir[i].stat == UNUSED) ++empty;
  185.         }
  186.         printf("%-16s %8lu total bytes\n","",size);
  187.         printf("%u active files, %u deleted files, %u empty slots.\n",
  188.                 active,deleted,empty);
  189. }
  190.  
  191. /* Unpack all files from the library. */
  192.  
  193. unpack() {
  194.  
  195. int i;
  196. int slot;
  197. long pos,size;
  198. unsigned count;
  199. int file;
  200. char name[14];
  201.  
  202.         if (get_directory() == -1) {
  203.                 printf("Error: LBR file not found\n");
  204.                 return;
  205.         }
  206.         for (slot= 1; slot < num_slots; slot++) {
  207.                 if (ldir[slot].stat == ACTIVE) {
  208.                         cvt_from_fcb(ldir[slot].name,name);
  209.                         printf("Extracting %s\n",name);
  210.                         file= creat(name,0x8001);       /* make new file, */
  211.                         if (file == -1) {               /* check error, */
  212.                                 printf("Error: cant create %s\n",name);
  213.                                 break;
  214.                         }
  215.                         pos= (long)ldir[slot].off * 128L;       /* find offset, */
  216.                         size= (long)ldir[slot].len * 128L;      /* and file size, */
  217.                         seek(lbr,pos,0);                /* go there, */
  218.                         while (size > 0L) {             /* copy out data, */
  219.                                 count= (size > bufsize ? bufsize : size);
  220.                                 read(lbr,buf,count);    /* read data, */
  221.                                 write(file,buf,count);  /* write it, */
  222.                                 size-= count;           /* update count, */
  223.                         }
  224.                         close(file);
  225.                 }
  226.         }
  227.         close(lbr);
  228. }
  229. /* Extract all specified files. */
  230.  
  231. extract() {
  232.  
  233. int i;
  234. int slot;
  235. long pos,size;
  236. unsigned count;
  237. int file;
  238.  
  239.         if (get_directory() == -1) {
  240.                 printf("Error: LBR file not found\n");
  241.                 return;
  242.         }
  243.         for (i= 0; i < num_names; i++) {
  244.                 slot= find(names[i]);
  245.                 if (slot != -1) {
  246.                         printf("Extracting %s\n",names[i]);
  247.                         file= fopen(names[i],"w");  /* make new file, */
  248.                         if (file == -1) {           /* check error, */
  249.                                 printf("Error: cant create %s\n",names[i]);
  250.                                 break;
  251.                         }
  252.                         pos= (long)ldir[slot].off * 128L;       /* find offset, */
  253.                         size= (long)ldir[slot].len * 128L;      /* and file size, */
  254.                         seek(lbr,pos,0);                /* go there, */
  255.                         while (size > 0L) {             /* copy out data, */
  256.                                 count= (size > bufsize ? bufsize : size);
  257.                                 read(lbr,buf,count);    /* read data, */
  258.                                 write(file,buf,count);  /* write it, */
  259.                                 size-= count;           /* update count, */
  260.                         }
  261.                         close(file);
  262.                 } else printf("%s not in library\n",names[i]);
  263.         }
  264.         close(lbr);
  265. }
  266.  
  267. /* Find the specified file in the directory, return its slot number
  268. or -1 if not found. */
  269.  
  270. find(name)
  271. char *name;
  272. {
  273. int i;
  274. char fname[14];
  275.  
  276.         for (i= 0; i < num_slots; i++) {                /* search all slots, */
  277.                 cvt_from_fcb(ldir[i].name,fname);       /* convert for compare */
  278.                 if (strcmp(name,fname) == 0)            /* if found, */
  279.                         return(i);                      /* return slot number, */
  280.         }
  281.         return(-1);                                     /* not found, */
  282. }
  283. /* Delete the specified file. No error return. */
  284.  
  285. kill(name)
  286. char *name;
  287. {
  288. int slot;
  289.  
  290.         slot= find(name);                               /* find it, */
  291.         if (slot != -1) ldir[slot].stat= DELETED;       /* delete it, */
  292. }
  293.  
  294. /* Find a free slot in the directory. Return -1 if none. */
  295.  
  296. free_slot() {
  297.  
  298. int i;
  299.  
  300.         for (i= 0; i < num_slots; i++) {
  301.                 if (ldir[i].stat == UNUSED) return(i);
  302.                 if (ldir[i].stat == DELETED) return(i);
  303.         }
  304.         return(-1);
  305. }
  306. /* Add a file to the library. All files get added to the end. Returns 0
  307. if couldnt add; either file not found or no room. No check is made that the
  308. file might exist already, etc. */
  309.  
  310. add_file(name)
  311. char *name;
  312. {
  313.  
  314. int i,file,slot;
  315. unsigned count;
  316. long size,pos;
  317.  
  318.         slot= free_slot();                      /* find a free slot, */
  319.         if (slot == -1) {                       /* if none, return 0 */
  320.                 printf("No room in directory\n");
  321.                 return(0);
  322.         }
  323.         file= open(name,0x8000);                /* get file, */
  324.         if (file == -1) {
  325.                 printf("Cant find %s\n",name);
  326.                 return(0);
  327.         }
  328.  
  329.         seek(lbr,0L,2);                         /* seek to end of file, */
  330.         pos= tell(lbr);                         /* save position, */
  331.         size= 0L;                               /* init file size, */
  332.         while (count= read(file,buf,bufsize)) { /* copy data, */
  333.                 size+= count;                   /* get file size, */
  334.                 write(lbr,buf,count);           /* write to library, */
  335.         }
  336.  
  337.         for (i= 0; i < 128; i++)
  338.                 buf[i]= 0x1a;                   /* clear dummy data, */
  339.         count= 128 - (size % 128L);             /* make LBR file a */
  340.         if (count > 0) write(lbr,buf,count);    /* multiple of 128, */
  341.         cvt_to_fcb(name,ldir[slot].name);       /* install name, */
  342.         ldir[slot].off= pos / 128L;             /* position, (sectors) */
  343.         ldir[slot].len= (size + 127L) / 128L;   /* size, (sectors) */
  344.         ldir[slot].stat= ACTIVE;
  345.  
  346.         close(file);
  347.         return(1);
  348. }
  349. /* Reorganize an LBR file. This consists of creating a new LBR, and copying
  350. all entries to it. This removes any space comsumed by deleted files, etc. */
  351.  
  352. reorg() {
  353.  
  354. struct _ludir odir[MAXFILES];
  355. int old,i,n,count;
  356. long size,pos;
  357. char oldname[14],tempname[14],buff[512];
  358. int old_slots,slot;
  359. char *p,*s;
  360.  
  361.         if (get_directory() == -1) {
  362.                 printf("Error: cant find library\n");
  363.                 return;
  364.         }
  365.         p=         &ldir[0];            /* copy old directory, */
  366.         s=         &odir[0];
  367.         for (i= (num_slots * sizeof(ludir)); i; i--)
  368.                 *s++= *p++;
  369.         old= lbr;                       /* old LBR handle, */
  370.         old_slots= num_slots;
  371.         strcpy(oldname,lbrname);        /* old LBR name, */
  372.         printf("Old library has %u slots\n",old_slots);
  373.         strcpy(lbrname,"lu$$$$$$.tmp"); /* make temp file, */
  374.         new_directory();                /* create new one, */
  375.  
  376.         slot= 0;
  377.         for (i= 1; i < old_slots; i++) {
  378.                 if (odir[i].stat == ACTIVE) {
  379.                         if (++slot >= num_slots) {
  380.                                 printf("Not enough room in new directory\n");
  381.                                 break;
  382.                         }
  383.                         cvt_from_fcb(odir[i].name,tempname);
  384.                         printf("Copying %s\n",tempname);
  385.                         seek(old,(long)odir[i].off * 128L,0);   /* seek to old data, */
  386.                         seek(lbr,0L,2);                         /* EOF on new file, */
  387.                         pos= tell(lbr);                         /* current position, */
  388.                         size= odir[i].len * 128L;
  389.                         while (size > 0L) {
  390.                                 count= (size > sizeof(buff) ? sizeof(buff) : size);
  391.                                 read(old,buff,count);
  392.                                 write(lbr,buff,count);
  393.                                 size-= count;
  394.                         }
  395.                         ldir[slot].stat= ACTIVE;                /* update new */
  396.                         ldir[slot].len= odir[i].len;            /* directory, */
  397.                         cvt_to_fcb(tempname,ldir[slot].name);
  398.                         ldir[slot].off= (pos + 127L) / 128L;
  399.                 }
  400.         }
  401.         put_directory();                /* close new directory, */
  402.         close(old);                     /* close old, */
  403.         unlink(oldname);                /* delete old one, */
  404.         rename("lu$$$$$$$.tmp",oldname);  /* back to original name */
  405. }
  406. /* Read the directory. */
  407.  
  408. get_directory()
  409. {
  410. unsigned size;
  411. int i;
  412.  
  413.         lbr= fopen(lbrname,"r");
  414.         if (lbr == -1) return(-1);
  415.  
  416.         if (read(lbr,&ldir[0],sizeof(ludir)) != sizeof(ludir))
  417.                 return(-1);
  418.  
  419.         num_slots= (ldir[0].len * 128) / sizeof(ludir);
  420.         size= (num_slots - 1) * sizeof(ludir);  /* already read one, */
  421.         if (num_slots > MAXFILES) {
  422.                 printf("Directory error: %s is bad or not an LBR file\n",lbrname);
  423.                 return(-1);
  424.         }
  425.         if (read(lbr,&ldir[1],size) != size) {
  426.                 printf("Directory error: is %s an LBR file?\n",lbrname);
  427.                 return(-1);
  428.         }
  429.         return(1);
  430. }
  431.  
  432. /* Create a new directory. When we request the number of slots, always round it
  433. up to the nearest 128 bytes, i.e. 4 slots. Since everything is a multiple
  434. of 128 anyways, all were doing is making otherwose wasted space available. */
  435.  
  436. new_directory() {
  437.  
  438. int i;
  439.  
  440.         num_slots= 0;
  441.         do {    printf("Number of slots (4 - 256, 0 to abort): ");
  442.                 getstring(buf);
  443.                 printf("\n");
  444.                 num_slots= atoi(buf);
  445.         } while (num_slots > 256);
  446.         if (num_slots == 0) return(-1);
  447.         num_slots+= num_slots % (128 / sizeof(ludir));
  448.  
  449.         lbr= creat(lbrname,0x8002);
  450.         if (lbr == -1) return(-1);
  451.         cvt_to_fcb(".",ldir[0].name);
  452.         ldir[0].len= (num_slots * sizeof(ludir)) / 128;
  453.         ldir[0].stat= ACTIVE;
  454.         for (i= 1; i < MAXFILES; i++) { /* clear ALL slots, */
  455.                 cvt_to_fcb(".",ldir[i].name);
  456.                 ldir[i].len= 0;
  457.                 ldir[i].off= 0;
  458.                 ldir[i].stat= UNUSED;
  459.         }
  460.         put_directory();                /* write to disk, */
  461.         return(get_directory());        /* read in new directory, */
  462. }
  463.  
  464. /* Write the directory out.  */
  465.  
  466. put_directory() {
  467.  
  468. int count;
  469.  
  470.         count= ldir[0].len * 128;
  471.         seek(lbr,0L,0);                 /* to start of file, */
  472.         if (write(lbr,&ldir[0],count) != count)
  473.                 printf("LBR close error: library may be trashed\n");
  474.         close(lbr);
  475. }
  476.  
  477.  
  478. /* Convert a normal asciz string to MSDOS/CPM FCB format. Make the filename
  479. portion 8 characters, extention 3 maximum. */
  480.  
  481. cvt_to_fcb(inname,outname)
  482. char *inname;
  483. char outname[];
  484. {
  485. char c;
  486. int i;
  487.  
  488.         if (inname[1] == ':')                   /* if a drive spec, */
  489.                 inname= &inname[2];             /* lop it off, */
  490.  
  491.         for (i= 0; i < 11; i++)
  492.                 outname[i]= ' ';                /* clear out name, */
  493.         outname[i]= '\0';                       /* null terminate, */
  494.         for (i= 0; i < 11; i++) {
  495.                 if (*inname == '\0')            /* if null, */
  496.                         outname[i]= ' ';        /* pad with blanks, */
  497.                 else if (*inname == '.') {      /* if a dot, */
  498.                         ++inname;               /* skip it, */
  499.                         i= 7;                   /* skip to extention, */
  500.                 } else {
  501.                         outname[i]= toupper(*inname);
  502.                         ++inname;
  503.                 }
  504.         }
  505.         return;
  506. }
  507. /* Convert a CP/M like filename to a normal ASCIZ name. Filter out characters
  508. undersireable on MSDOS. */
  509.  
  510. cvt_from_fcb(inname,outname)
  511. char *inname,*outname;
  512. {
  513. int i;
  514. char c;
  515.  
  516.         for (i= 8; i != 0; i--) {               /* do name portion, */
  517.                 c= toupper(*inname);
  518.                 ++inname;
  519.                 if (c != ' ')                   /* if not space, */
  520.                         *outname++= c;          /* set it, */
  521.         }                                       /* do all 8 chars, */
  522.  
  523.         if (*inname != ' ') {                   /* if there is an extention, */
  524.                 *outname++= '.';                /* add the dot, */
  525.                 for (i= 3; i != 0; i--) {       /* do extention, */
  526.                         c= toupper(*inname);
  527.                         ++inname;
  528.                         if (c == ' ')
  529.                                 break;
  530.                         *outname++= c;
  531.                 }
  532.         }
  533.         *outname= '\0';                         /* terminate it, */
  534.         return;
  535. }
  536. /* Get an input string; return NULL if error or empty line. Provide the
  537. usual minimum editing capabilities.  */
  538.  
  539. getstring(string)
  540. char string[];
  541. {
  542. int count;
  543. char c;
  544. char *p;
  545. int pi;
  546.         count= 0;
  547.  
  548.         while (1) {
  549.  
  550.                 c= getchar();                     /* get a character, */
  551.                 switch (c) {
  552.                 case 0x0d:                      /* process it, */
  553.                 case 0x0a:
  554.                 case 0x1b:
  555.                         string[count]= 0x00;    /* terminate string, */
  556.                         return(count);          /* return string length */
  557.                         break;
  558.  
  559.                 case 0x08:
  560.                 case 0x7f:                      /* delete character */
  561.                 case 0x13:
  562.                         if (count) {
  563.                                 --count;        /* one less char, */
  564.                                 putchar('\010');
  565.                                 putchar(' ');
  566.                                 putchar('\010');
  567.                         }
  568.                         break;
  569.                         case 0x18:
  570.                 case 0x15:                      /* delete line */
  571.                 case 0x19:
  572.                 case 0x03:
  573.                         while (count) {
  574.                                 --count;
  575.                                 putchar('\010');
  576.                                 putchar(' ');
  577.                                 putchar('\010');
  578.                         }
  579.                         break;
  580.                 case 0x04:                      /* retype character, */
  581.                         if (string[count])
  582.                                 putchar(string[count++]);
  583.                         break;
  584.                 case 0x12:                      /* retype line, */
  585.                         while (string[count]) {
  586.                                 putchar(string[count++]);
  587.                         }
  588.                         break;
  589.  
  590.                 default:                        /* insert character */
  591.                         if ( (c > 0x1f) && (c < 0x7f) && (count < 80) ) {
  592.                                 string[count++] =toupper(c);
  593.                                 string[count]= 0x00;
  594.                                 putchar(c);
  595.                         } else
  596.                                 putchar(0x07);
  597.                         break;
  598.                 }
  599.         }
  600. }
  601. /* ATOI() function missing from Lattice C. From Kernighan and Richie. */
  602.  
  603. atoi(s)
  604. char s[];
  605. {
  606. int i,n;
  607.  
  608.         n= 0;
  609.         for (i= 0; s[i] >= '0' && s[i] <= '9'; ++i)
  610.                 n= 10*n + s[i]-'0';
  611.         return(n);
  612. }
  613. /* Convert a string to all upper case. */
  614.  
  615. stoupper(s)
  616. char *s;
  617. {
  618.         while (*s) {
  619.                 *s= toupper(*s);
  620.                 ++s;
  621.         }
  622. }
  623. m. */
  624.  
  625. cvt_to_fcb(inname,outname)