home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource4 / 225_01 / dir2.c < prev    next >
Text File  |  1987-06-10  |  12KB  |  336 lines

  1.  
  2. /*-----------------------------------------------------------------*/
  3. /*       STANDARD HEADER FOR BDS C PROGRAMMES
  4.          ------------------------------------
  5.  
  6.          Programme:     DIR2.C
  7.          ---------
  8.          Purpose:       This programme will delete all inactive
  9.          -------        entries from the directory and then re-write
  10.                         the directory in (almost) alphabetical order
  11.                         onto the last available track of the nominated
  12.                         disk.   It also creates the file "DIRECT.ORY"
  13.                         under user area 15.
  14.  
  15.          Written:       02/01/86
  16.          -------
  17.          Amended:       08/11/86
  18.          -------
  19.          Version:       1.2
  20.          -------
  21.  
  22.          Copyright 1986 - Cogar Computer Services Pty. Ltd.        */
  23. /*-----------------------------------------------------------------*/
  24. #include <bdscio.h>
  25. #include <pec.h>
  26. /*-----------------------------------------------------------------*/
  27. #define    VERSION "1.2\0"
  28. #define NAME    "DIR2\0"
  29. /*-----------------------------------------------------------------*/
  30.  
  31. main(argc, argv)    /* For Command Line processing             */
  32. int argc;
  33. char *argv[];
  34. {
  35. /*-----------------------------------------------------------------*/
  36. /*  Space reserved for variables used in programme                 */
  37. /*-----------------------------------------------------------------*/
  38.     int i, j, k, l, BLOCK1, FD;
  39.     char c, DATA_MAP;
  40.     int CPM;    /* To check the CP/M Version number        */
  41.     char DRIVE;    /* The active drive                        */
  42.     char OLD_DRIVE;    /* The starting drive No.                  */
  43.     char OLD_USER;    /* The User No. at start of programme      */
  44.     char USER;    /* The User No. for this programme         */
  45.     char my_dma[128];    /* The dma buffer to use           */
  46.     char my_fcb[36];    /* The file control block          */
  47.     char **skew_table;
  48.     int  PHYS_SEC;    /* The physical sector to read/write       */
  49.     unsigned STORAGE;    /* The size of the big buffer      */
  50.     struct dpb *THIS;    /* Disk parameter information      */
  51.     int  DIRECTORY;    /* The directory track                     */
  52.     int  SECTORS;    /* Sectors per track                       */
  53.     unsigned RECORDS;    /* Total available records         */
  54.     int LAST_TRACK;    /* The highest track No. on the disk       */
  55.     int BLK_SIZE;    /* Allocation block size in records        */
  56.     int DIR_SIZE;    /* No. of allocation blocks in directory   */
  57.     int FIRST_BLOCK;    /* First block No. in directory    */
  58.     int  ENTRIES;    /* The active entries in directory         */
  59.     char *BIG_BUF;
  60. /*-----------------------------------------------------------------*/
  61.     pec_clear();    /* Universal routine                       */
  62.     printf("%s - Version %s\n",NAME, VERSION);
  63.     printf("Copyright 1986 - Cogar Computer Services Pty.Ltd.\n");
  64.     printf("----------------------------------------------------------\n");
  65.     printf("This programme will first 'clean up' the directory\n");
  66.     printf("tracks by removing any inactive (0xe5) entries.\n");
  67.     printf("Then it sorts the active entries into (approximate)\n");
  68.     printf("alphabetical order and writes them....as a copy of the\n");
  69.     printf("directory onto the last track of the disk, as DIR2.\n");
  70.     printf("Finally it creates the file 'DIRECT.ORY' in User Area\n");
  71.     printf("15 to protect the second directory against being over\n");
  72.     printf("written by other files.\n");
  73.     printf("----------------------------------------------------------\n");
  74. /*-----------------------------------------------------------------*/
  75. /*  First check the CP/M Version in use.   If it is less than
  76.     Version 2.0 then inform the user and terminate programme.      */
  77. /*-----------------------------------------------------------------*/
  78.  
  79.     CPM = get_cpm();    /* Obtain the CP/M version and No. */
  80.  
  81.     i = (CPM & 0xff) - 0x20; /* Mask off the MP/M bit          */
  82.  
  83.     if(i < 0)        /* Must be less than V 2.0         */
  84.     {
  85.     printf("This programme requires at least V 2.x of CP/M.\n");
  86.         printf("Sorry but it won't run for you.\n");
  87.         exit();
  88.     }
  89. /*-----------------------------------------------------------------*/
  90. /*  The CP/M Version is OK, so save the starting User No. and the
  91.     starting drive in case these are changed later.                */
  92. /*-----------------------------------------------------------------*/
  93.  
  94.     OLD_USER = user_id(0xff);
  95.     OLD_DRIVE = get_default() + 0x41;
  96.  
  97. /*-----------------------------------------------------------------*/
  98. /*  Now check the Command Line to see if a Drive Code was entered.
  99.     Other checks can also be used, as required but then it will be
  100.     necessary to change this coding.                               */
  101. /*-----------------------------------------------------------------*/
  102.     if(argc != 2)
  103.     {
  104.         printf("Enter the DRIVE you wish to check...A, B, C...\n");
  105.         DRIVE = toupper(getchar());
  106.     }
  107.     else if(argc == 2)
  108.         DRIVE = toupper(argv[1][0]);
  109.     lines(2);
  110. /*-----------------------------------------------------------------*/
  111. /*  Check that the selected drive is available/on-line.   If not
  112.     then terminate the programme.   You may need to add a message
  113.     about what is going on if your version of CP/M doesn't do
  114.     this automatically, as mine does.                              */
  115. /*-----------------------------------------------------------------*/
  116.     if(!(skew_table = seldsk(DRIVE)))
  117.         exit();        /* Must be something wrong         */
  118.     if(select_dsk(DRIVE) != 0)
  119.         exit();
  120. /*-----------------------------------------------------------------*/
  121. /*  Calculate the values we need to scan the directory.            */
  122. /*-----------------------------------------------------------------*/
  123.  
  124.     THIS      = dpb_adr();
  125.     DIRECTORY = THIS->OFF;
  126.     SECTORS   = THIS->SPT;
  127.  
  128.     RECORDS   = THIS->DSM + 1;    /* Starting value          */
  129.  
  130.     for(i = 0; i < THIS->BSH; i++)
  131.         RECORDS = RECORDS + RECORDS;
  132.  
  133.     if(RECORDS%SECTORS != 0)
  134.         LAST_TRACK = RECORDS/SECTORS + DIRECTORY;
  135.     else LAST_TRACK = RECORDS/SECTORS + DIRECTORY - 1;
  136.     printf("The highest track No.  =  %d\n", LAST_TRACK);
  137.  
  138.     BLK_SIZE = (128 << THIS->BSH)/128;  /* In records          */
  139.     DIR_SIZE = SECTORS/BLK_SIZE;        /* In blocks           */
  140.  
  141.     FIRST_BLOCK = (THIS->DSM + 1) - DIR_SIZE;
  142.  
  143.     if((THIS->DSM >> 8) == 0)
  144.         DATA_MAP = 16;
  145.     else DATA_MAP    =  8;
  146.  
  147. /*-----------------------------------------------------------------*/
  148. /*  Now create a file control block for the file "DIRECT.ORY"
  149.     under User Area 15                                             */
  150. /*-----------------------------------------------------------------*/
  151.     setmem(&my_fcb[0], 36, 0);
  152.     my_fcb[0] = 15;        /* The User Number                 */
  153.     strcpy(&my_fcb[1], "DIRECT  ORY\0"); /* The file name      */
  154.     my_fcb[12] = my_fcb[13] = my_fcb[14] = 0;
  155.     my_fcb[15] = BLK_SIZE*DIR_SIZE;    /* No. of records          */
  156.  
  157.     BLOCK1 = FIRST_BLOCK;    /* Starting value                  */
  158.  
  159.     if(DATA_MAP == 16)
  160.     {
  161.         for(i = 0; i < DIR_SIZE; i++)
  162.         {
  163.             my_fcb[16 + i] = BLOCK1;
  164.             BLOCK1++;
  165.         }
  166.     }
  167.     else if(DATA_MAP == 8)
  168.     {
  169.         for(i = 0; i < DIR_SIZE*2; i = i + 2)
  170.         {
  171.             my_fcb[16 + i] = BLOCK1 & 0xff;
  172.             my_fcb[17 + i] = (BLOCK1 >> 8) & 0xff;
  173.             BLOCK1++;
  174.         }
  175.     }
  176. /*-----------------------------------------------------------------*/
  177.  
  178.     set_dma(&my_dma[0]);    /* Create DMA buffer               */
  179.     set_trk(DIRECTORY);
  180.  
  181. /*-----------------------------------------------------------------*/
  182. /*  Read the directory track and count the number of active
  183.     entries.   This information is required for the size of
  184.     the big buffer.                                                */
  185. /*-----------------------------------------------------------------*/
  186.     printf("Counting the active directory entries.\n");
  187.     ENTRIES = 0;        /* Starting conditions             */
  188.     for(i = 0; i < SECTORS; i++)
  189.     {
  190.         PHYS_SEC = biosh(16, i, *skew_table);
  191.         set_sec(PHYS_SEC);
  192.         setmem(&my_dma[0], 128, 0xe5);
  193.         read_sec();    /* Put information into DMA buffer */
  194.  
  195.     for(j = 0; j < 4; j++)
  196.     {
  197.         if(my_dma[j*32] != 0xe5)
  198.             ENTRIES++;
  199.     }
  200.     }
  201.     printf("Active entries (all extents) = %d\n", ENTRIES