home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / DIR / CSAP302.ZIP / SORTDIR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-20  |  10.1 KB  |  393 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, unsigned char *Fat);
  25. void            FreeCluster (int Is12Bit, unsigned Val, unsigned Cluster, unsigned char Fat[]);
  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.         if (TruncateSwt) WriteSub();
  135.         r = &Parent[strlen(Parent) - 1];
  136.         if (r[-1] == ':') r++;
  137.         *r = 0x00;
  138.         return;
  139.         }
  140.  
  141.     /* If VerSwt ON - request operator confirmation BEFORE sorting */
  142.  
  143.     if (VerSwt != 0) {
  144.         if (isdevice(1)) {
  145.             printf("   Sort (Y or N)? ");
  146.             fflush(stdout);
  147.             }
  148.         else {
  149.             fprintf(stderr, "   Sort (Y or N)? ");
  150.             fflush(stderr);
  151.             }
  152.         if (toupper(getche()) != 'Y') {
  153.             if (!isdevice(1)) fprintf(stderr, "n");
  154.             printf("\n");
  155.             return;
  156.             }
  157.         }
  158.  
  159.     if (!isdevice(1)) fprintf(stderr, "\n");
  160.     printf("\n");
  161.  
  162.     /* Sort directory */
  163.  
  164.     qsort(&DirBuff[j], i, sizeof(struct DirEntry), strincmp);
  165.  
  166.     ECount = 0;
  167.  
  168.     /*
  169.      * If Packed OFF, remove "erased" entries from directory (mark them
  170.      * "unused)
  171.      */
  172.  
  173.     if (Packed != 0) {
  174.         for (i = k; i >= 0; i--) {
  175.             if ((DirBuff[i].Name[0] != 0xE5) && (DirBuff[i].Name[0] != 0x00)) break;
  176.             if (DirBuff[i].Name[0] == 0xE5) {
  177.                 DirBuff[i].Name[0] = 0x00;
  178.                 ++ECount;
  179.                 }
  180.             }
  181.         }
  182.  
  183.     if (TruncateSwt) {
  184.         for (i = k; i >= 0; --i) {
  185.             if (DirBuff[i].Name[0] != 0x00) break;
  186.             }
  187.         i += 2;
  188.         }
  189.  
  190.     /*
  191.      * Compute the number of directory sectors to write out - don't write
  192.      * sectors that don't contain active entries.
  193.      */
  194.  
  195.     OutSectors = ((i * 32) + Dpb.SectorSize - 1) / Dpb.SectorSize;
  196.     OutClusters = (OutSectors + Dpb.ClusterSize) >> Dpb.ClusterShift;
  197.  
  198.     /* Build list of subdirectories - skipping "current" and "parent" entries */
  199.  
  200.     for (l = 0, i = 0; DirBuff[i].Name[0]; i++) {
  201.         if ((DirBuff[i].Attribute & 0x10) && (DirBuff[i].Name[0] != '.')) {
  202.             for (k = 0, j = 0; j < 8; ++j) {
  203.                 if (DirBuff[i].Name[j] == ' ') break;
  204.                 else Line[k++] = DirBuff[i].Name[j];
  205.                 }
  206.             if (DirBuff[i].Ext[0] != ' ') {
  207.                 Line[k++] = '.';
  208.                 for (j = 0; j < 3; ++j) {
  209.                     if (DirBuff[i].Ext[j] == ' ') break;
  210.                     else Line[k++] = DirBuff[i].Ext[j];
  211.                     }
  212.                 }
  213.             Line[k++] = '\0';
  214.             if ((DirVector[l] = malloc(k)) == NULL) {
  215.                 fprintf(stderr, "Insufficient memory.\n");
  216.                 return;
  217.                 }
  218.             strcpy(DirVector[l++], Line);
  219.             }
  220.         }
  221.  
  222.     /* Write out sorted directory */
  223.  
  224.     if (Root) {
  225.         WriteRoot();
  226.         if (RSwt) printf("    Location: %04XH-%04XH\n", DirStart, DirStart + NumSec - 1);
  227.         }
  228.     else {
  229.         WriteSub();
  230.         if (RSwt) {
  231.             printf("    Location:");
  232.             for (i = 0; i < CluQ.Count; ++i) {
  233.                 if (i == 0) printf(" %04XH", Alu2Sec(&Dpb, CluArray[i]));
  234.                 if ((i > 0) && (CluArray[i] != CluArray[i - 1] + 1)) {
  235.                     printf("-%04XH %04XH",
  236.                            Alu2Sec(&Dpb, CluArray[i - 1] + 1) - 1,
  237.                            Alu2Sec(&Dpb, CluArray[i])
  238.                         );
  239.                     }
  240.                 }
  241.             printf("-%04XH\n", Alu2Sec(&Dpb, CluArray[i - 1] + 1) - 1);
  242.             }
  243.         }
  244.     if (RSwt) printf("    %d Erased entries removed\n", ECount);
  245.  
  246.     Mem = coreleft();
  247.     if (MinMem < Mem) MinMem = Mem;
  248.  
  249.     /* Release dynamically acquired space for this directory */
  250.  
  251.     free(DirBuff);
  252.     for (p = CluQ.Head; p != NULL; p = t) {
  253.         t = p->Next;
  254.         free(p);
  255.         }
  256.     free(CluArray);
  257.  
  258.     /*
  259.      * If Recursive sort - build Parent and Element for sub directories &
  260.      * sort
  261.      */
  262.  
  263.     if (!Level) {
  264.         strcat(Parent, Element);
  265.         for (i = 0; i < DirCount; i++) {
  266.             strcpy(Element, DirVector[i]);
  267.  
  268.             SortDir();
  269.  
  270.             }
  271.         r = strrspn(Parent, "\\/");
  272.         if (r[-1] == ':') r++;
  273.         *r = 0x00;
  274.         }
  275.     }
  276.  
  277.  void
  278. ReadSub (void) {
  279.     extern unsigned Cluster;
  280.     extern unsigned LastCluster;
  281.     extern unsigned char *Fat;
  282.     extern struct ExtendedEntry Dir;
  283.     extern struct ClusterQueue CluQ;
  284.     extern int      Is12Bit, *CluArray, BytesPerCluster, Lim;
  285.     extern char     Disk;
  286.     extern struct DirEntry *DirBuff;
  287.     extern struct DpbStruct Dpb;
  288.  
  289.     int             i;
  290.     struct ClusterEntry *p;
  291.     void            PutQueue();
  292.     unsigned        NextCl();
  293.  
  294.     Cluster = Dir.Body.FirstCluster;
  295.     CluQ.Head = CluQ.Current = NULL;
  296.     CluQ.Count = 0;
  297.     while (Cluster < LastCluster) {
  298.         PutQueue(&CluQ, Cluster);
  299.         Cluster = NextCl(Is12Bit, Cluster, Fat);
  300.         }
  301.     if ((CluArray = malloc(CluQ.Count * sizeof(int))) == NULL) {
  302.         fprintf(stderr, "Insufficient memory (3).\n");
  303.         return;
  304.         }
  305.     for (i = 0, p = CluQ.Head; p != NULL; i++, p = p->Next) {
  306.         CluArray[i] = p->Cluster;
  307.         }
  308.     Lim = CluQ.Count * BytesPerCluster;
  309.     if ((DirBuff = malloc(Lim)) == NULL) {
  310.         fprintf(stderr, "Insufficient memory for directory buffer.\n");
  311.         return;
  312.         }
  313.     for (i = 0; i < CluQ.Count; i++) {
  314.         if (absread(Disk - 'A', Dpb.ClusterSize + 1,
  315.                     Alu2Sec(&Dpb, CluArray[i]),
  316.                     (char *) &DirBuff[(i * BytesPerCluster) / 32])) {
  317.             fprintf(stderr, "Error reading directory.\n");
  318.             exit(1);
  319.             }
  320.         }
  321.     }
  322.  
  323.  void
  324. WriteSub (void) {
  325.     extern char     TruncateSwt;
  326.     extern char     FatDirty;
  327.     extern struct ClusterQueue CluQ;
  328.     extern char     Disk;
  329.     extern struct DpbStruct Dpb;
  330.     extern int     *CluArray, BytesPerCluster;
  331.     extern int      OutClusters;
  332.     extern struct DirEntry *DirBuff;
  333.  
  334.     int             i;
  335.  
  336.     for (i = 0; i < OutClusters; i++) {
  337.         if (abswrite(Disk - 'A', Dpb.ClusterSize + 1,
  338.                      Alu2Sec(&Dpb, CluArray[i]),
  339.                      (char *) &DirBuff[(i * BytesPerCluster) / 32])) {
  340.             fprintf(stderr, "Error writing directory.\n");
  341.             exit(1);
  342.             }
  343.         }
  344.     if ( (TruncateSwt) && (i < CluQ.Count) ) {
  345.         FatDirty |= 1;
  346.         FreeCluster(Is12Bit, 0xFFFF, CluArray[i - 1], Fat);
  347.         for (; i < CluQ.Count; ++i) FreeCluster(Is12Bit, 0, CluArray[i], Fat);
  348.         }
  349.     }
  350.  
  351.  void
  352. ReadRoot (void) {
  353.     extern struct DpbStruct Dpb;
  354.     extern unsigned NumSec;
  355.     extern unsigned DirStart;
  356.     extern struct DirEntry *DirBuff;
  357.     extern int     *CluArray, Lim;
  358.     extern char     Disk;
  359.  
  360.     int             Error;
  361.  
  362.     Lim = Dpb.MaxEntries * 32;
  363.     NumSec = (Lim + Dpb.SectorSize - 1) / Dpb.SectorSize;
  364.     if ((DirBuff = malloc(Lim)) == NULL) {
  365.         fprintf(stderr, "Insufficient memory for cluster buffer.\n");
  366.         return;
  367.         }
  368.     if ((CluArray = malloc(sizeof(int))) == NULL) {
  369.         fprintf(stderr, "Insufficient memory (4).\n");
  370.         return;
  371.         }
  372.     CluArray[0] = 0;
  373.     if ((Error = absread(Disk - 'A', NumSec, DirStart, (char *) DirBuff)) != 0) {
  374.         fprintf(stderr, "Error reading root:  %04X.\n", Error);
  375.         exit(1);
  376.         }
  377.     }
  378.  
  379.  
  380.  void
  381. WriteRoot (void) {
  382.     extern char     Disk;
  383.     extern unsigned NumSec;
  384.     extern unsigned DirStart;
  385.     extern struct DpbStruct Dpb;
  386.     extern struct DirEntry *DirBuff;
  387.  
  388.     if (abswrite(Disk - 'A', NumSec, DirStart, (char *) DirBuff)) {
  389.         fprintf(stderr, "Error writing Root.\n");
  390.         exit(1);
  391.         }
  392.     }
  393.