home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 182_01 / ldir.c < prev    next >
Text File  |  1990-07-31  |  12KB  |  487 lines

  1. /*    Paul Homchick 31 Aug 84
  2.  *
  3.  *    directory display routines from lu86
  4.  *
  5.  *    will compile with Computer Innovations C86, or
  6.  *              Digital Research C
  7.  *
  8.  *    v 1.03    added 'close(lbr)'s' in error return code in get_directory()
  9.  *      v 1.04  expanded input list definitions to 128 from 30
  10.  *        checked for wildexp error in CI C86 version
  11.  */
  12.  
  13. #include <stdio.h>
  14.  
  15. /************************************************************************/
  16. /*            PREPROCESSOR DEFINITIONS            */
  17. /************************************************************************/
  18.  
  19. #define VERNO        " 1.04"            /* VERSION number    */
  20. #define VERDATE        "26 Sep 84"        /* VERSION date        */
  21.  
  22. #define ERROR        -1
  23. #define FLAG        int
  24.  
  25. #define ACTIVE        0    /* active, non-deleted file,        */
  26. #define UNUSED        0xff    /* never used slot,            */
  27. #define DELETED        0xfe    /* deleted file slot,            */
  28.  
  29. #define MAXNAMES    128    /* maximum number of names in cmnd line    */
  30. #define MAXFILES    256    /* max files per LBR file        */
  31. #define NOCOLS        4    /* number of colums on 80 col screen    */
  32. #define JBASE        1965    /* for julian date routines        */
  33. #define DATEADJ        4748    /* to conform to DRI julian date    */
  34.  
  35. #define DRC        1    /* using Dig Res Compiler        */
  36.  
  37. #ifdef DRC
  38. #include <ctype.h>
  39. #define BREAD        0
  40. #define UNSIGNED
  41. #define OPEN        openb
  42. #else                /* else use CI C86            */
  43. #define OPEN        open
  44. #define UNSIGNED    unsigned
  45. #endif
  46.  
  47. /************************************************************************/
  48. /*              STRUCTURES                    */
  49. /************************************************************************/
  50.  
  51. /* This is the structure of the LBR file directory. One per slot.    */
  52.  
  53. struct _ludir {
  54.     UNSIGNED char stat;    /* file status,                */
  55.     char name[11];    /* FCB type filename,                */
  56.     unsigned off;    /* offset to data, (sectors)            */
  57.     unsigned len;    /* length (sectors) of data ,            */
  58.     unsigned crc;    /* CRC checksum for member            */
  59.     unsigned cdate;    /* file create date, uses DRI julian dt format    */
  60.             /* (jan 1, 1978 = 1; july 4, 1984 =2273, etc.)    */
  61.     unsigned udate;    /* file update date, uses Dig Res format    */
  62.     unsigned ctime; /* file create time, uses MSDOS format        */
  63.     unsigned utime;    /* file update time, uses MSDOS format        */
  64.     UNSIGNED char padchar;    /* number of pad bytes in last sector    */
  65.     UNSIGNED char filler;    /* fill out to 32 bytes            */
  66.     int fill[2];    /* fill out to 32 bytes                */
  67. } ludir; /* (dummy ludir so we can sizeof() it) */
  68.  
  69. struct dtbl {
  70.     struct _ludir ldir[MAXFILES];
  71. };
  72.  
  73. struct _date {
  74.     int    day;
  75.     int    month;
  76.     int    year;
  77.     int    yearday;
  78. };                    /* date    */
  79.  
  80. struct _tod {
  81.     int    hr;
  82.     int    min;
  83.     int    sec;
  84. };                    /* time    */
  85.  
  86. static int day_tab[2][13] = {
  87.     {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
  88.     {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
  89.     };
  90.  
  91. /************************************************************************/
  92. /*               TYPE DECLARATIONS                */
  93. /************************************************************************/
  94.  
  95. struct dtbl     *dtblPtr;
  96. struct _date     *datePtr;
  97. struct _tod      *todPtr;
  98.  
  99. char names[MAXNAMES][30];    /* list of names from command line, */
  100. char *substr, *index();
  101.  
  102. FLAG crcflag;
  103.  
  104. int lbr;            /* LBR file handle,        */
  105. int num_names;            /* number of names in above list */
  106. int num_slots;            /* number of slots in LBR file, */
  107.  
  108. unsigned updcrc(),checksum;    /* crc support for LU 3.0 compatibility */
  109.  
  110. /************************************************************************/
  111. /*                main()                    */
  112. /************************************************************************/
  113.  
  114. main(argc,argv)
  115. int argc;
  116. char *argv[];
  117. {
  118. int i;
  119.  
  120. #ifndef DRC
  121.     if (wildexp(&argc, &argv) == ERROR)    /* parse ambig. names */
  122.         abort("ldir: wildexp error.");
  123. #endif
  124.     ++argv; --argc;
  125.     if (argc < 1) {
  126.         fprintf(stderr,"ldir Ver%s, %s; Paul Homchick\n",VERNO,VERDATE);
  127.         fprintf(stderr,"Use:  ldir lbrfile ... [ >output ]\n");
  128.         fprintf(stderr,"      displays Novosielski LBR directories.\n");
  129.         fprintf(stderr,"examples:\tldir one.lbr\t\tldir one\n");
  130.         fprintf(stderr,"\t\tldir *.lbr\t\tldir a:*.lbr\n");
  131.         fprintf(stderr,"\t\tldir one two three\tldir a*.lbr >a-lbr.dir\n");
  132.         exit(0);
  133.     }
  134.     num_names= argc;
  135.     for( i= 0; i < argc; i++) {
  136.         cpyarg(names[i],argv[i]);
  137.         stoupper(names[i]);        /* add ".lbr" if not already there */
  138.         if ( ((substr= index(names[i],'.')) != 0) &&
  139.         (cmdeq(substr,".LBR")) )
  140.             ;            /* do nothing in this case */
  141.         else {
  142.             if (substr) {
  143.             fprintf(stderr,"ldir:\tError- illegal filetype for library file.\n");
  144.             fprintf(stderr,"\tIf a filetype is supplied, it must be \".LBR\".\n");
  145.             fprintf(stderr,"\tIf no filetype is supplied, \".LBR\" is assumed.\n");
  146.             exit(1);
  147.             } else
  148.             strcat(names[i],".LBR"); /* add .lbr type */
  149.         }
  150.     }
  151.     if (argc > MAXNAMES) {
  152.         fprintf(stderr,"ldir: Program only allows 128 input names,\n");
  153.         fprintf(stderr,"      and %d names are present.  Please cut\n",argc);
  154.         fprintf(stderr,"      down on size of input list.\n");
  155.         exit(1);
  156.     }
  157.  
  158.     dtblPtr= calloc(sizeof(struct dtbl),1);
  159.     todPtr= calloc(sizeof(struct _tod),1);
  160.     /* note 2000 byte insurance */
  161.     if ( ! (datePtr= calloc((sizeof(struct _date)+2000),1)) )
  162.         abort("ldir: CALLOC returned NULL, not enough memory.");
  163.     list();
  164. }
  165.  
  166. list()
  167. {
  168.   int i,j;
  169.   long size, unused;
  170.   char name[14];
  171.   int active,deleted,empty;
  172.  
  173.     for(j= 0; j < num_names; j++) {
  174.     size= unused= 0L;
  175.     active= deleted= empty= 0;
  176.  
  177.     if (get_directory(names[j]) == -1)
  178.     {
  179.         fprintf(stderr,"ldir: Error  %s, invalid or not found\n",names[j]);
  180.         close(lbr);
  181.         return;
  182.     }
  183.     printf("\nLibrary: %s",names[j]);
  184.     if (!(dtblPtr->ldir[0].udate))
  185.         slist();
  186.     else {
  187.         printf("\nFilename       Bytes  Sectors  Index");
  188.         printf("   --- Created ---    --- Updated ---");
  189.     for (i= 0; i < num_slots; i++)
  190.     {
  191.         if (dtblPtr->ldir[i].stat == ACTIVE)
  192.         {
  193.             cvt_from_fcb(dtblPtr->ldir[i].name,name);
  194.             if(!i)
  195.                 printf("\ndirectory    %7lu   %6u  %5u",
  196.                   (long)dtblPtr->ldir[i].len * 128L,dtblPtr->ldir[i].len,
  197.                   dtblPtr->ldir[i].off);
  198.             else
  199.                 printf("\n%-12s %7lu   %6u  %5u",name,
  200.                   (((long)dtblPtr->ldir[i].len * 128L)-dtblPtr->ldir[i].padchar),
  201.                   dtblPtr->ldir[i].len,dtblPtr->ldir[i].off);
  202.             if(dtblPtr->ldir[i].cdate) {
  203.                 pdate(dtblPtr->ldir[i].cdate);
  204.                 ptime(dtblPtr->ldir[i].ctime);
  205.             }
  206.             if(!(dtblPtr->ldir[i].cdate) && dtblPtr->ldir[i].udate)
  207.                 printf("%19s"," ");
  208.             if(dtblPtr->ldir[i].udate) {
  209.                 pdate(dtblPtr->ldir[i].udate);
  210.                 ptime(dtblPtr->ldir[i].utime);
  211.             }
  212.         size+= (((long)dtblPtr->ldir[i].len * 128L)-dtblPtr->ldir[i].padchar);
  213.             ++active;
  214.         }
  215.         if (dtblPtr->ldir[i].stat == DELETED) {
  216.             unused+= dtblPtr->ldir[i].len * 128;
  217.             ++deleted;
  218.         }
  219.         if (dtblPtr->ldir[i].stat == UNUSED) ++empty;
  220.     }
  221.     if (unused != 0L)
  222.         printf("\n(%6lu bytes unused)",unused);
  223.     else
  224.         printf("\n");
  225.     printf("\n%7lu bytes used;",size);
  226.     printf("%5u active entries; %5u deleted; %5u empty.\n",
  227.         active,deleted,empty);
  228.       }
  229.     close(lbr);
  230.    }
  231. }
  232.  
  233. /*
  234.  * short list for pre version 4.0 lbrs
  235.  */
  236.  
  237. slist()
  238. {
  239. long tot_siz, unused;
  240. int i, room, ndir, deleted, empty, newline;
  241. char name[14];
  242.  
  243.     tot_siz= unused= 0;
  244.     ndir= deleted= empty= newline= 0;
  245.     room = (NOCOLS); 
  246.     printf("\n");
  247.     while(room--)
  248.         printf("Name      Sectors  ");
  249.     printf("\n\n");
  250.  
  251.     room = (NOCOLS);
  252.     for (i = 0; i < num_slots; i++) {
  253.         if (dtblPtr->ldir[i].stat == ACTIVE) {
  254.             newline= 0;
  255.             ndir++;
  256.             tot_siz += dtblPtr->ldir[i].len;
  257.             cvt_from_fcb(dtblPtr->ldir[i].name,name);
  258.             if (!i)
  259.                 printf("%-12s %4d  ","directory",dtblPtr->ldir[i].len);
  260.             else
  261.                 printf("%-12s %4d  ",name,dtblPtr->ldir[i].len);
  262.             if(--room == 0) {
  263.                 room = (NOCOLS);
  264.                 printf("\n");
  265.                 newline= 1;
  266.             }
  267.         }
  268.         if (dtblPtr->ldir[i].stat == DELETED) {
  269.             unused+= dtblPtr->ldir[i].len * 128;
  270.             ++deleted;
  271.         }
  272.         if (dtblPtr->ldir[i].stat == UNUSED) ++empty;
  273.     }
  274.     if (!newline)
  275.         printf("\n");
  276.     if (unused != 0L)
  277.         printf("(%6lu bytes unused)\n",unused);
  278.     else
  279.         printf("\n");
  280.  
  281.     printf("%7lu bytes used;",tot_siz*128);
  282.     printf("%5u active entries; %5u deleted; %5u empty.\n",
  283.         ndir,deleted,empty);
  284. }
  285.  
  286. /* Read the directory. */
  287.  
  288. get_directory(lbrname)
  289. char *lbrname;
  290. {
  291. unsigned size, checksum, dirchk;
  292. int i, j, count;
  293. UNSIGNED char *bp;
  294.  
  295.     lbr= OPEN(lbrname,BREAD);
  296.     if (lbr == -1) return(-1);
  297.  
  298.     if (read(lbr,&dtblPtr->ldir[0],sizeof(ludir)) != sizeof(ludir)) {
  299.         return(-1);
  300.     }
  301.     num_slots= (dtblPtr->ldir[0].len * 128) / sizeof(ludir);
  302.     size= (num_slots - 1) * sizeof(ludir);    /* already read one, */
  303.     if (num_slots > MAXFILES) {
  304.         fprintf(stderr,"Directory error: %s is bad or not an LBR file\n"
  305.             ,lbrname);
  306.         return(-1);
  307.     }
  308.     if ( ! ((dtblPtr->ldir[0].stat == 0) &&
  309.         (!strncmp(dtblPtr->ldir[0].name,"           ",11)) &&
  310.         (dtblPtr->ldir[0].off == 0)) ) {
  311.         fprintf(stderr,"%s is not a Library.\n",lbrname);
  312.         return(-1);
  313.     }
  314.     if (read(lbr,&dtblPtr->ldir[1],size) != size) {
  315.         fprintf(stderr,"Directory error: is %s an LBR file?\n",lbrname);
  316.         return(-1);
  317.     }
  318.     /* disable CRC if master entry is 0 */
  319.     crcflag = !(dtblPtr->ldir[0].crc == 0);
  320.     checksum= 0;
  321.     count= size + sizeof(ludir);
  322.     dirchk= dtblPtr->ldir[0].crc;
  323.     dtblPtr->ldir[0].crc= 0;
  324.     bp = &dtblPtr->ldir[0];            /* start of directory */
  325.     for(j = 0;j < count;j++)    /* do crc */
  326.         checksum = updcrc(*bp++,checksum);
  327.     checksum= updcrc(0,updcrc(0,checksum));
  328.     dtblPtr->ldir[0].crc= dirchk;
  329.     if (crcflag && (checksum != dirchk)) {
  330.         printf("Warning: Directory CRC error in %s.\007\n",lbrname);
  331.         printf("Directory seems to have %d entries.\n",num_slots);
  332.     }
  333.     return(1);
  334. }
  335.  
  336.  
  337. /*
  338.  * Convert a CP/M like filename to a normal ASCIZ name.
  339.  * Filter out characters undersireable on MSDOS.
  340.  */
  341.  
  342. cvt_from_fcb(inname,outname)
  343. char *inname,*outname;
  344. {
  345. int i;
  346. char c;
  347.  
  348.     for (i= 8; i != 0; i--) {        /* do name portion, */
  349.         c= toupper(*inname);
  350.         ++inname;
  351.         if (c != ' ')             /* if not space, */
  352.             *outname++= c;        /* set it, */
  353.     }                    /* do all 8 chars, */
  354.  
  355.     if (*inname != ' ') {            /* if there is an extention, */
  356.         *outname++= '.';        /* add the dot, */
  357.         for (i= 3; i != 0; i--) {    /* do extention, */
  358.             c= toupper(*inname);
  359.             ++inname;
  360.             if (c == ' ')
  361.                 break;
  362.             *outname++= c;
  363.         }
  364.     }
  365.     *outname= '\0';                /* terminate it, */
  366.     return;
  367. }
  368.  
  369. /* Convert a string to all upper case. */
  370.  
  371. stoupper(s)
  372. char *s;
  373. {
  374.     while (*s) {
  375.         *s= toupper(*s);
  376.         ++s;
  377.     }
  378. }
  379.  
  380. cpyarg(to,from)
  381. char *to,*from;
  382. {
  383. char *cp;
  384.     cp = from;
  385.     while(*cp)
  386.         *to++ = *cp++;
  387. }
  388.  
  389. cmdeq(s,p)
  390. char *s, *p;
  391. {
  392.     while(*p)
  393.         if(*s++ != *p++)
  394.             return(0);
  395.     return(1);
  396. }
  397.  
  398. /*
  399.  *  convert MS-DOS time to hh:mm:ss
  400.  */
  401. word2hms(mstime)
  402. register unsigned int mstime;
  403. {
  404.     todPtr->hr=  (mstime&0xf800) >> 11;
  405.     todPtr->min= (mstime&0x07e0) >> 5;
  406.     todPtr->sec= (mstime&0x001f) << 1;
  407. }
  408.  
  409. ptime(time)
  410. unsigned time;
  411. {
  412.     word2hms(time);
  413.     printf("%02d:%02d:%02d",todPtr->hr,
  414.                 todPtr->min,
  415.                 todPtr->sec);
  416. }
  417.  
  418. pdate(date)
  419. unsigned date;
  420. {
  421.     jul2greg(date);
  422.     printf("  %02d/%02d/%02d ",datePtr->month,
  423.                    datePtr->day,
  424.                    datePtr->year-1900);
  425. }
  426.  
  427. /*
  428. ** julian to calendar date conversion
  429. **
  430. ** (with greatful acknowledgement to Steve Passe)
  431. */
  432.  
  433. jul2greg(jdate)
  434. unsigned jdate;
  435. {
  436.     register unsigned days, years;
  437.     int x, leap;
  438.  
  439.     jdate += DATEADJ;
  440.     for (years = days = 0; days < jdate; )
  441.         days += (++years % 4 ? 365 : 366);
  442.     days -= (years-- % 4 ? 365 : 366);
  443.     datePtr->year = years + JBASE;
  444.     datePtr->yearday =  (int)jdate - days;
  445.     leap = datePtr->year % 4 == 0 && datePtr->year % 100 != 0
  446.             || datePtr->year % 400 == 0;
  447.     datePtr->day = datePtr->yearday;
  448.     for (x = 1; datePtr->day > day_tab[leap][x]; ++x)
  449.         datePtr->day -= day_tab[leap][x];
  450.     datePtr->month = x;
  451. }
  452.  
  453. /*
  454.  * update CRC
  455.  * Copyright 1983 Computer Development Inc Beaverton Or USA
  456.  *  All rights reserved
  457.  */
  458. unsigned short updcrc(c, crc)
  459. register c;
  460. register unsigned short crc;
  461. {
  462.     register count;
  463.  
  464.     for(count=8; --count>=0;) {
  465.         if(crc & 0x8000) {
  466.             crc <<= 1;
  467.             crc += (((c<<=1) & 0400)  !=  0);
  468.             crc ^= 0x1021;
  469.         }
  470.         else {
  471.             crc <<= 1;
  472.             crc += (((c<<=1) & 0400)  !=  0);
  473.         }
  474.     }
  475.     return crc;    
  476. }
  477.  
  478. #ifdef DRC
  479.  
  480. abort(s)
  481. char *s;
  482. {
  483.     fprintf(stderr,"ABORT: %s\007\n",s);
  484.     exit(1);
  485. }
  486. #endif
  487.