home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 225_01 / dir2.c < prev    next >
Text File  |  1987-06-09  |  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);
  202. /*-----------------------------------------------------------------*/
  203. /*  Now secure enough storage to hold all the active entries.      */
  204. /*-----------------------------------------------------------------*/
  205.     STORAGE = (((ENTRIES/4)*4) + 4)*32;
  206.     BIG_BUF = alloc(STORAGE);
  207.     setmem(BIG_BUF, STORAGE, 0xe5);    /* Clear the buffer        */
  208. /*-----------------------------------------------------------------*/
  209. /*  Then transfer the active entries to the big buffer.            */
  210. /*-----------------------------------------------------------------*/
  211.     set_trk(DIRECTORY);
  212.     j = 0;
  213.     for(i = 0; i < SECTORS; i++)
  214.     {
  215.         PHYS_SEC = biosh(16, i, *skew_table);
  216.         set_sec(PHYS_SEC);
  217.         setmem(&my_dma[0], 128, 0xe5);
  218.         read_sec();    /* Put information into DMA buffer */
  219.  
  220.         for(k = 0; k < 4; k++)
  221.         {
  222.             if(my_dma[k*32] != 0xe5)
  223.             {
  224.                 movmem(&my_dma[k*32], &BIG_BUF[j], 32);
  225.                 j = j + 32;
  226.             }
  227.         }
  228.     }
  229. /*-----------------------------------------------------------------*/
  230. /*  All the active entries are now in the big buffer so we can
  231.     condition the last track (all 0xe5) and then write the contents
  232.     of the big buffer to this track in (almost) alphabetical
  233.     order.                                                         */
  234. /*-----------------------------------------------------------------*/
  235.     printf("Re-formatting last track of Disk - %c.\n", DRIVE);
  236.     setmem(&my_dma[0], 128, 0xe5);
  237.     set_trk(LAST_TRACK);
  238.  
  239.     for(i = 0; i < SECTORS; i++)
  240.     {
  241.         PHYS_SEC = biosh(16, i, *skew_table);
  242.         set_sec(PHYS_SEC);
  243.         write_sec();
  244.     }
  245.     printf("Writing directory to the last track.\n");
  246.     set_trk(LAST_TRACK);
  247.     k = 0;        /* Count of active files in DMA buffer     */
  248.     l = 0;        /* The directory sector to write           */
  249.  
  250.     for(c = 0x41; c < 0x60; c++)
  251.     {
  252.     for(i = 0; i < STORAGE; i = i + 32)
  253.     {
  254.     if(BIG_BUF[i + 1] == c)
  255.     {
  256.         movmem(&BIG_BUF[i], &my_dma[k*32], 32);
  257.         k++;
  258.         if(k == 4)
  259.         {
  260.             PHYS_SEC = biosh(16, l, *skew_table);
  261.             set_sec(PHYS_SEC);
  262.             write_sec();    /* Write to directory      */
  263.             l++;    /* Advance sector count            */
  264.             k = 0;
  265.             setmem(&my_dma[0], 128, 0xe5);
  266.         }
  267.     }
  268.     }
  269.     }
  270.     if(k > 0 && k < 4)
  271.     {
  272.         PHYS_SEC = biosh(16, l, *skew_table);
  273.         set_sec(PHYS_SEC);
  274.         write_sec();
  275.     }
  276.  
  277.     printf("Directory now re-written onto last track.\n");
  278.  
  279. /*-----------------------------------------------------------------*/
  280. /*  As the final job, now write the entry under DIRECT.ORY to the
  281.     disk's directory tracks.   Put the entry into the first
  282.     available slot.                                                */
  283. /*-----------------------------------------------------------------*/
  284.     user_id(15);        /* Check to see whether the file   */
  285.     if((FD = open("DIRECT.ORY", 0)) != -1)
  286.     {
  287.         close(FD);
  288.         unlink("DIRECT.ORY");    /* already exists          */
  289.         printf("Deleting existing DIRECT.ORY file.\n");
  290.     }
  291.     user_id(OLD_USER);
  292.  
  293.     set_trk(DIRECTORY);
  294.     set_dma(&my_dma[0]);
  295.  
  296.     for(i = 0; i < SECTORS; i++)
  297.     {
  298.         PHYS_SEC = biosh(16, l, *skew_table);
  299.         set_sec(PHYS_SEC);
  300.         read_sec();
  301.     for(j = 0; j < 128; j = j + 32)
  302.     {
  303.         if(my_dma[j] == 0xe5)    /* Found a vacant slot     */
  304.         {
  305.         movmem(&my_fcb[0], &my_dma[j], 32);
  306.         write_sec();
  307.         j = 128;    /* Get out of counting loop        */
  308.         i = SECTORS;
  309.         }
  310.     }
  311.     }
  312.     printf("File ==> DIRECT.ORY written to main directory.");
  313. /*-----------------------------------------------------------------*/
  314. /*  Before closing, make sure the User No. and the Drive return
  315.     to original settings.                                          */
  316. /*-----------------------------------------------------------------*/
  317.  
  318.     user_id(OLD_USER);
  319.     if(select_dsk(OLD_DRIVE) != 0)
  320.     {
  321.         printf("\nUnable to return to original drive.");
  322.         exit();
  323.     }
  324. if((FD = open("UTIL.COM", 0)) != -1)
  325. {
  326.     close(FD);
  327.     exec("UTIL");
  328. }
  329. else printf("\nCan't find - UTIL.COM.   Returning to CP/M.");
  330.  
  331. }
  332. /*-----------------------------------------------------------------*/
  333.             PHYS_SEC = biosh(16, l, *skew_table);
  334.             set_sec(PHYS_SEC);
  335.             write_sec();    /* Write to directory      */
  336.             l