home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / VRAC / CSAP400.ZIP / SORTDIR.C < prev    next >
C/C++ Source or Header  |  1993-09-09  |  10KB  |  398 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <conio.h>
  5. #include <dos.h>
  6. #include <ctype.h>
  7. #include <mem.h>
  8. #include <alloc.h>
  9.  
  10. #include "dosstruc.h"
  11.  
  12. /*---   Function Prototypes   ---*/
  13.  
  14. int             SearchFirst(struct ExtFcb * Fcb);
  15. int             AbortProgram(void);
  16. int             isdevice(int handle);
  17. void            ReadRoot(void);
  18. void            ReadSub(void);
  19. void            WriteRoot(void);
  20. void            WriteSub(void);
  21. long            Alu2Sec(struct DpbStruct * Dpb, unsigned Alu);
  22. char           *strrspn(char *s1, char *s2);
  23. void            PutQueue(struct ClusterQueue * Q, unsigned Cluster);
  24. unsigned        NextCl(int Is12Bit, unsigned Cluster);
  25. void            FreeCluster(int Is12Bit, unsigned Val, unsigned Cluster);
  26.  
  27. /*---  End of Prototypes  ---*/
  28.  
  29.  
  30. /*
  31.  * SORTDIR is the main routine of CSAP.  It is a recursive routine that will
  32.  * walk the directory hierarchy, sorting all directories that it finds.  It
  33.  * uses the quick sort or quicker sort algorithm provided by most C runtime
  34.  * libraries to perform the actual sort.  It uses DOS Int 25H and 26H,
  35.  * Absolute Disk Read and Absolute Disk Write, to read the directories into
  36.  * memory for sorting and to write out the sorted directories.  It depends
  37.  * upon information about the physical characteristics of the disk provided
  38.  * by GETDPB.
  39.  */
  40.  
  41.  void
  42. SortDir (void) {
  43.     extern char     Disk, Parent[67], Element[13];
  44.     extern char     Line[80], Level, RSwt, VerSwt, Packed, TruncateSwt;
  45.     extern int      Lim, j, l;
  46.     extern int      OutSectors, OutClusters, BytesPerCluster, ECount;
  47.     extern int     *CluArray;
  48.     extern unsigned NumSec;
  49.     extern unsigned DirStart;
  50.     extern long     MinMem;
  51.     extern struct DpbStruct Dpb;
  52.     extern struct DirEntry *DirBuff;
  53.     extern struct ClusterEntry *p, *t;
  54.     extern struct ExtFcb Fcb;
  55.     extern struct ExtendedEntry Dir;
  56.     extern struct ClusterQueue CluQ;
  57.  
  58.     char           *strrspn();
  59.     char          **DirVector, *r;
  60.     int             strincmp();
  61.     int             i, k, DirCount, Root;
  62.     long            Mem;
  63.  
  64.     BytesPerCluster = (Dpb.ClusterSize + 1) * Dpb.SectorSize;
  65.     if (strlen(Element) != 0) {    /* Sorting a sub-directory */
  66.         Root = 0;
  67.         bdosptr(0x3B, Parent, 0);    /* Set Current Directory */
  68.         if ((Parent[strlen(Parent) - 1] != '\\') && (Parent[strlen(Parent) - 1] != '/'))
  69.             strcat(Parent, "\\");
  70.         setdta((char *) &Dir);
  71.         parsfnm(Element, (struct fcb *) & Fcb.DriveId, 0);
  72.         Fcb.FcbHdr.Header = 0xFF;
  73.         Fcb.DriveId = Disk - '@';
  74.         Fcb.FcbHdr.Attrib = 0xFF;
  75.         if (SearchFirst(&Fcb) != 0) {
  76.             fprintf(stderr, "Not found: %s%s\n", Parent, Element);
  77.             AbortProgram();
  78.         }
  79.     }
  80.     else Root = 1;                /* Sorting the Root directory */
  81.  
  82.     printf("Sorting: %s%s", Parent, Element);
  83.     if (!isdevice(1)) fprintf(stderr, "Sorting: %s%s", Parent, Element);
  84.  
  85.     /* Read directory to be sorted into memory */
  86.  
  87.     if (Root) ReadRoot();
  88.     else ReadSub();
  89.  
  90.     /* Count sub-directories, skipping "current" and "parent" entries */
  91.  
  92.     for (DirCount = 0, i = 0; i < Lim / sizeof(struct DirEntry); i++) {
  93.         if (DirBuff[i].Name[0] == 0) break;
  94.         if ((DirBuff[i].Attribute & 0x10)
  95.             && (DirBuff[i].Name[0] != '.')
  96.             && (DirBuff[i].Name[0] != 0xE5)) DirCount++;
  97.     }
  98.     k = i;
  99.     if (DirCount != 0) {
  100.         if ((DirVector = malloc(DirCount * sizeof(DirVector))) == NULL) {
  101.             fprintf(stderr, "Insufficient memory (2).\n");
  102.             return;
  103.         }
  104.     }
  105.  
  106.     j = 0;
  107.     if (Root) {
  108.  
  109.         /* If sorting Root - skip 1st two files if "System" & "Hidden" */
  110.  
  111.         if (i > 1) {
  112.             if (DirBuff[j].Attribute & 0x06) {
  113.                 j++;
  114.                 i--;
  115.                 if (DirBuff[j].Attribute & 0x06) {
  116.                     j++;
  117.                     i--;
  118.                 }
  119.             }
  120.         }
  121.     }
  122.     else {
  123.  
  124.         /*
  125.          * If sorting subdirectory - skip 1st two entries, "current" and
  126.          * "parent"
  127.          */
  128.  
  129.         j += 2;
  130.         i -= 2;
  131.     }
  132.     if (i == 0) {
  133.         printf(" Empty.\n");
  134.         r = &Parent[strlen(Parent) - 1];
  135.         if (r[-1] == ':') r++;
  136.         *r = 0x00;
  137.         if (TruncateSwt) {
  138.             OutClusters = 1;
  139.             WriteSub();
  140.         }
  141.         return;
  142.     }
  143.  
  144.     /* If VerSwt ON - request operator confirmation BEFORE sorting */
  145.  
  146.     if (VerSwt != 0) {
  147.         if (isdevice(1)) {
  148.             printf("   Sort (Y or N)? ");
  149.             fflush(stdout);
  150.         }
  151.         else {
  152.             fprintf(stderr, "   Sort (Y or N)? ");
  153.             fflush(stderr);
  154.         }
  155.         if (toupper(getche()) != 'Y') {
  156.             if (!isdevice(1)) fprintf(stderr, "n");
  157.             printf("\n");
  158.             return;
  159.         }
  160.     }
  161.  
  162.     if (!isdevice(1)) fprintf(stderr, "\n");
  163.     printf("\n");
  164.  
  165.     /* Sort directory */
  166.  
  167.     qsort(&DirBuff[j], i, sizeof(struct DirEntry), strincmp);
  168.  
  169.     ECount = 0;
  170.  
  171.     /*
  172.      * If Packed OFF, remove "erased" entries from directory (mark them
  173.      * "unused")
  174.      */
  175.  
  176.     if (Packed != 0) {
  177.         for (i = k; i >= 0; i--) {
  178.             if ((DirBuff[i].Name[0] != 0xE5) && (DirBuff[i].Name[0] != 0x00))
  179.                 break;
  180.             if (DirBuff[i].Name[0] == 0xE5) {
  181.                 memset(DirBuff[i].Name, '\0', sizeof(DirBuff[i]));
  182.                 ++ECount;
  183.             }
  184.         }
  185.         i = k;
  186.     }
  187.  
  188.     if (TruncateSwt) {
  189.         for (i = k; i >= 0; --i) {
  190.             if (DirBuff[i].Name[0] != 0x00) break;
  191.         }
  192.         i += 2;
  193.     }
  194.  
  195.     /*
  196.      * Compute the number of directory sectors to write out - don't write
  197.      * sectors that don't contain active entries.
  198.      */
  199.  
  200.     OutSectors = ((i * 32) + Dpb.SectorSize - 1) / Dpb.SectorSize;
  201.     OutClusters = (OutSectors + Dpb.ClusterSize) >> Dpb.ClusterShift;
  202.  
  203.     /* Build list of subdirectories - skipping "current" and "parent" entries */
  204.  
  205.     for (l = 0, i = 0; DirBuff[i].Name[0]; i++) {
  206.         if ((DirBuff[i].Attribute & 0x10) && (DirBuff[i].Name[0] != '.')) {
  207.             for (k = 0, j = 0; j < 8; ++j) {
  208.                 if (DirBuff[i].Name[j] == ' ') break;
  209.                 else Line[k++] = DirBuff[i].Name[j];
  210.             }
  211.             if (DirBuff[i].Ext[0] != ' ') {
  212.                 Line[k++] = '.';
  213.                 for (j = 0; j < 3; ++j) {
  214.                     if (DirBuff[i].Ext[j] == ' ') break;
  215.                     else Line[k++] = DirBuff[i].Ext[j];
  216.                 }
  217.             }
  218.             Line[k++] = '\0';
  219.             if ((DirVector[l] = malloc(k)) == NULL) {
  220.                 fprintf(stderr, "Insufficient memory.\n");
  221.                 return;
  222.             }
  223.             strcpy(DirVector[l++], Line);
  224.         }
  225.     }
  226.  
  227.     /* Write out sorted directory */
  228.  
  229.     if (Root) {
  230.         WriteRoot();
  231.         if (RSwt)
  232.             printf("    Location: %04XH-%04XH\n", DirStart, DirStart + NumSec - 1);
  233.     }
  234.     else {
  235.         WriteSub();
  236.         if (RSwt) {
  237.             printf("    Location:");
  238.             for (i = 0; i < CluQ.Count; ++i) {
  239.                 if (i == 0) printf(" %04XH", Alu2Sec(&Dpb, CluArray[i]));
  240.                 if ((i > 0) && (CluArray[i] != CluArray[i - 1] + 1)) {
  241.                     printf("-%04XH %04XH",
  242.                            Alu2Sec(&Dpb, CluArray[i - 1] + 1) - 1,
  243.                            Alu2Sec(&Dpb, CluArray[i])
  244.                         );
  245.                 }
  246.             }
  247.             printf("-%04XH\n", Alu2Sec(&Dpb, CluArray[i - 1] + 1) - 1);
  248.         }
  249.     }
  250.     if (RSwt) printf("    %d Erased entries removed\n", ECount);
  251.  
  252.     Mem = coreleft();
  253.     if (MinMem < Mem) MinMem = Mem;
  254.  
  255.     /* Release dynamically acquired space for this directory */
  256.  
  257.     free(DirBuff);
  258.     for (p = CluQ.Head; p != NULL; p = t) {
  259.         t = p->Next;
  260.         free(p);
  261.     }
  262.     free(CluArray);
  263.  
  264.     /*
  265.      * If Recursive sort - build Parent and Element for sub directories &
  266.      * sort
  267.      */
  268.  
  269.     if (!Level) {
  270.         strcat(Parent, Element);
  271.         for (i = 0; i < DirCount; i++) {
  272.             strcpy(Element, DirVector[i]);
  273.  
  274.             SortDir();
  275.  
  276.         }
  277.         r = strrspn(Parent, "\\/");
  278.         if (r[-1] == ':') r++;
  279.         *r = 0x00;
  280.     }
  281. }
  282.  
  283.  void
  284. ReadSub (void) {
  285.     extern unsigned Cluster;
  286.     extern unsigned LastCluster;
  287.     extern struct ExtendedEntry Dir;
  288.     extern struct ClusterQueue CluQ;
  289.     extern int      Is12Bit, *CluArray, BytesPerCluster, Lim;
  290.     extern char     Disk;
  291.     extern struct DirEntry *DirBuff;
  292.     extern struct DpbStruct Dpb;
  293.  
  294.     int             i;
  295.     struct ClusterEntry *p;
  296.     void            PutQueue();
  297.     unsigned        NextCl();
  298.  
  299.     Cluster = Dir.Body.FirstCluster;
  300.     CluQ.Head = CluQ.Current = NULL;
  301.     CluQ.Count = 0;
  302.     while (Cluster < LastCluster) {
  303.         PutQueue(&CluQ, Cluster);
  304.         Cluster = NextCl(Is12Bit, Cluster);
  305.     }
  306.     if ((CluArray = malloc(CluQ.Count * sizeof(int))) == NULL) {
  307.         fprintf(stderr, "Insufficient memory (3).\n");
  308.         return;
  309.     }
  310.     for (i = 0, p = CluQ.Head; p != NULL; i++, p = p->Next) {
  311.         CluArray[i] = p->Cluster;
  312.     }
  313.     Lim = CluQ.Count * BytesPerCluster;
  314.     if ((DirBuff = malloc(Lim)) == NULL) {
  315.         fprintf(stderr, "Insufficient memory for directory buffer.\n");
  316.         return;
  317.     }
  318.     for (i = 0; i < CluQ.Count; i++) {
  319.         if (absread(Disk - 'A', Dpb.ClusterSize + 1,
  320.                     Alu2Sec(&Dpb, CluArray[i]),
  321.                     (char *) &DirBuff[(i * BytesPerCluster) / 32])) {
  322.             fprintf(stderr, "Error reading directory.\n");
  323.             exit(1);
  324.         }
  325.     }
  326. }
  327.  
  328.  void
  329. WriteSub (void) {
  330.     extern char     TruncateSwt;
  331.     extern char     FatDirty;
  332.     extern struct ClusterQueue CluQ;
  333.     extern char     Disk;
  334.     extern struct DpbStruct Dpb;
  335.     extern int      Is12Bit, *CluArray, BytesPerCluster;
  336.     extern int      OutClusters;
  337.     extern struct DirEntry *DirBuff;
  338.  
  339.     int             i;
  340.  
  341.     for (i = 0; i < OutClusters; i++) {
  342.         if (abswrite(Disk - 'A', Dpb.ClusterSize + 1,
  343.                      Alu2Sec(&Dpb, CluArray[i]),
  344.                      (char *) &DirBuff[(i * BytesPerCluster) / 32])) {
  345.             fprintf(stderr, "Error writing directory.\n");
  346.             exit(1);
  347.         }
  348.     }
  349.     if ((TruncateSwt) && (i < CluQ.Count)) {
  350.         FatDirty |= 1;
  351.         FreeCluster(Is12Bit, 0xFFFF, CluArray[i - 1]);
  352.         for (; i < CluQ.Count; ++i) FreeCluster(Is12Bit, 0, CluArray[i]);
  353.     }
  354. }
  355.  
  356.  void
  357. ReadRoot (void) {
  358.     extern struct DpbStruct Dpb;
  359.     extern unsigned NumSec;
  360.     extern unsigned DirStart;
  361.     extern struct DirEntry *DirBuff;
  362.     extern int     *CluArray, Lim;
  363.     extern char     Disk;
  364.  
  365.     int             Error;
  366.  
  367.     Lim = Dpb.MaxEntries * 32;
  368.     NumSec = (Lim + Dpb.SectorSize - 1) / Dpb.SectorSize;
  369.     if ((DirBuff = malloc(Lim)) == NULL) {
  370.         fprintf(stderr, "Insufficient memory for cluster buffer.\n");
  371.         return;
  372.     }
  373.     if ((CluArray = malloc(sizeof(int))) == NULL) {
  374.         fprintf(stderr, "Insufficient memory (4).\n");
  375.         return;
  376.     }
  377.     CluArray[0] = 0;
  378.     if ((Error = absread(Disk - 'A', NumSec, DirStart, (char *) DirBuff)) != 0) {
  379.         fprintf(stderr, "Error reading root:  %04X.\n", Error);
  380.         exit(1);
  381.     }
  382. }
  383.  
  384.  
  385.  void
  386. WriteRoot (void) {
  387.     extern char     Disk;
  388.     extern unsigned NumSec;
  389.     extern unsigned DirStart;
  390.     extern struct DpbStruct Dpb;
  391.     extern struct DirEntry *DirBuff;
  392.  
  393.     if (abswrite(Disk - 'A', NumSec, DirStart, (char *) DirBuff)) {
  394.         fprintf(stderr, "Error writing Root.\n");
  395.         exit(1);
  396.     }
  397. }
  398.