home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_02_07 / 2n07032a < prev    next >
Text File  |  1991-06-02  |  14KB  |  367 lines

  1.  
  2. /***************************************************************************/
  3. /* function main                                                           */
  4. /***************************************************************************/
  5. int main (int argc, char *argv[])
  6. {
  7.    union REGS Myregs;
  8.  
  9.    if (argc < 2) {
  10.       fprintf (stderr,
  11.             "This program sends the contents of an HPFS file to standard\n"
  12.             "output.  This may be piped to a file or device.\n"
  13.             "Usage:  getfile <filename>\n"
  14.             "where <filename is a fully qualified path without a drive\n"
  15.             "specification.\n");
  16.       exit (NO_ARG);
  17.    }
  18.    setmode (STDOUT, (int) O_BINARY);
  19.    Myregs.x.ax = 0x4400;               // IOCtl Get Data
  20.    Myregs.x.bx = STDOUT;
  21.    intdos (&Myregs, &Myregs);
  22.    Myregs.h.dh = 0;
  23.    Myregs.h.dl |= 0x20;                // Set raw mode
  24.    Myregs.x.ax = 0x4401;               // IOCtl Set Data
  25.    intdos (&Myregs, &Myregs);
  26.    GetBootRecords ();
  27.    GetRootDir ();
  28.    FindFileFnode (strupr(argv[1]));    // FileFnode will contain file fnode
  29.    DoFewFrags (&FileFnode.FewFragsFnode);
  30.    return (0);
  31. }
  32. //
  33.  
  34. /***************************************************************************/
  35. /* function GetBootRecords                                                 */
  36. /***************************************************************************/
  37. void GetBootRecords ()
  38. {
  39.    PartitionEntry *ThisPartition;
  40.    unsigned MoreCyl;
  41.  
  42.    DiskInfo.drive = FIXED_DRIVE;
  43.    DiskInfo.nsectors = 1;
  44.    DiskInfo.head = 0;
  45.    DiskInfo.track = 0;
  46.    DiskInfo.sector = 1;
  47.    DiskInfo.buffer = &VolumeBootSector;
  48.    _bios_disk_with_retry (&DiskInfo);
  49.    HPFSPartition = NULL;
  50.    for (ThisPartition = VolumeBootSector.Partitions;
  51.          ThisPartition <= &VolumeBootSector.Partitions[3];
  52.          ThisPartition++)
  53.       if (ThisPartition->SysInd == HPFS_PART) {
  54.          HPFSPartition = ThisPartition;
  55.          break;
  56.       }
  57.    if (HPFSPartition == NULL) {
  58.       fprintf (stderr, "No HPFS partition found, aborting...\n");
  59.       exit (BAD_DISK);
  60.    }
  61.    DiskInfo.head = HPFSPartition->BH;
  62.    MoreCyl = HPFSPartition->BS & 0xC0;
  63.    MoreCyl = MoreCyl << 2;
  64.    DiskInfo.track = HPFSPartition->BCyl + MoreCyl;
  65.    DiskInfo.sector = HPFSPartition->BS & 0x3F;
  66.    DiskInfo.buffer = &PartitionBootSector;
  67.    _bios_disk_with_retry (&DiskInfo);
  68.  
  69.    BytesPerSector = PartitionBootSector.BytesPerSector;
  70.    SectorsInSegment = (USHORT) (0x10000UL / (ULONG) BytesPerSector);
  71.    HugeShift = 0x1000;
  72.    SectorsInFullTrack = PartitionBootSector.SectorsInTrack *
  73.                         PartitionBootSector.NumOfHeads;
  74. }
  75. //
  76.  
  77. /***************************************************************************/
  78. /* function GetRootDir                                                     */
  79. /* Correct for OS/2 1.2 on ST-251 disk                                     */
  80. /***************************************************************************/
  81. void GetRootDir (void)
  82. {
  83.    GetRelativeSectors (SUPER_BLOCK, 1, &SuperBlock);
  84.    GetRelativeSectors (SuperBlock.RootDirFnode, 1, &DirFnode);
  85.    RootDirSector = DirFnode.FragTable.FewFrags[0].ulFragSector;
  86. }
  87. //
  88.  
  89. /***************************************************************************/
  90. /* function FindFileFnode                                                  */
  91. /* Puts the file Fnode in FileFnode                                        */
  92. /***************************************************************************/
  93. void FindFileFnode (char *Fname)
  94. {
  95.    USHORT flast;
  96.  
  97.    GetRelativeSectors (RootDirSector, 4, &DirectoryCluster);
  98.    flast = strlen (Fname) - 1;
  99.    if (Fname[flast] == '.')         // OS/2 directories do not contain ending
  100.       Fname[flast] = 0;             //    period of file names
  101.    FindFile (Fname);
  102.    FileSize = FileFnode.FewFragsFnode.ulcFileLength;
  103. }
  104. //
  105.  
  106. /***************************************************************************/
  107. /* function FindFile                                                       */
  108. /***************************************************************************/
  109. void FindFile (const char *path)
  110. {
  111.    char PathCopy [_MAX_PATH];
  112.    char Element [_MAX_FNAME];
  113.    BOOL Result;
  114.    DirEntryType *CurrDirEntry;
  115.    RSN SectorNum;
  116.  
  117.    Level++;
  118.    _fstrcpy (PathCopy, path); /* Make local copy */
  119.    MakeFilename (PathCopy, PathCopy, Element); /* Split and update */
  120.    if (PathCopy[0])                       // At least '\' left in path
  121.       PathCopy[strlen (PathCopy) - 1] = 0;// Erase the '\'
  122.    if (PathCopy[0] != 0)                  // More than '\'
  123.       FindFile (PathCopy);                // continue recursively
  124.    Result = FindDirEntry (Element, &CurrDirEntry);
  125.    if (Result != TRUE) {
  126.       fprintf (stderr, "Could not find %s, aborting...\n", path);
  127.       exit (NO_FILE);
  128.    }
  129.    if (Level > 1) {                       // Directory
  130.       if ((CurrDirEntry->bFlags & FLAG_DIR) == 0) {
  131.          fprintf (stderr, "%s is a file, not a directory. Aborting...\n",
  132.                   path);
  133.          exit (NO_FILE);
  134.       }
  135.    } else { /* File name */
  136.       if ((CurrDirEntry->bFlags & FLAG_DIR) != 0) {
  137.          fprintf (stderr, "%s is a directory, not a file. Aborting...\n",
  138.                   path);
  139.          exit (NO_FILE);
  140.       }
  141.    }
  142.    if (Level > 1) {                       // Directory fnode
  143.       GetRelativeSectors (CurrDirEntry->ulPointedSector, 1, &DirFnode);
  144.       SectorNum = DirFnode.FragTable.FewFrags[0].ulFragSector;
  145.       GetRelativeSectors (SectorNum, 4, &DirectoryCluster); // Directory body
  146.    } else
  147.       GetRelativeSectors (CurrDirEntry->ulPointedSector, 1, &FileFnode);
  148.    Level--;
  149. }
  150. //
  151.  
  152. /***************************************************************************/
  153. /* function FindDirEntry                                                   */
  154. /* Assumes that correct directory cluster is in DirectoryCluster
  155.   */
  156. /***************************************************************************/
  157. BOOL FindDirEntry (char *EntryName, DirEntryType **Location)
  158. {
  159.    BYTE EntryNameLength, CmpLen;
  160.    DirEntryType *TmpLoc;
  161.    int UpDownLen, UpDown;
  162.    RSN SectorNum;
  163.  
  164.    EntryNameLength = (BYTE) strlen (EntryName);
  165.    for (TmpLoc = &DirectoryCluster.FirstDirEntry;;) {
  166.       if (EntryNameLength > TmpLoc->bcNameLength) { // Compare lengths
  167.          CmpLen = TmpLoc->bcNameLength;
  168.          UpDownLen = UP;
  169.       } else {
  170.          CmpLen = EntryNameLength;
  171.          if (EntryNameLength < TmpLoc->bcNameLength)
  172.             UpDownLen = DOWN;
  173.          else
  174.             UpDownLen = SAME;
  175.       }
  176.       UpDown = memcmp (EntryName, TmpLoc->bName, CmpLen); // Compare contents
  177.       if (UpDown == SAME)                                // Contents same
  178.          UpDown = UpDownLen;                             // Judge by length
  179.       if (UpDown == SAME) {                              // Identical
  180.          *Location = TmpLoc;
  181.          return (TRUE);
  182.       }                                                  // Where to look now?
  183.       if (UpDown < 0) {                                  // Try down?
  184.          if ((TmpLoc->bSplitFlag & DIR_SPLITS) == 0)     // No connection
  185.             return (FALSE);                              //    File not there
  186.          SectorNum = *(RSN *)                         // Find connection
  187.                       (((BYTE *) TmpLoc) + TmpLoc->uscDirEntrySize - 4);
  188.          GetRelativeSectors (SectorNum, 4, &DirectoryCluster);
  189.          TmpLoc = &DirectoryCluster.FirstDirEntry;
  190.          continue;
  191.       }                                                  // Try same level
  192.       if ((TmpLoc->bSplitFlag & END_OF_DIR) != 0)        // No more here
  193.          return (FALSE);                                 //    File not there
  194.       TmpLoc = (DirEntryType *)                          // Next Entry
  195.                 (((BYTE *) TmpLoc) + TmpLoc->uscDirEntrySize);
  196.    }
  197. }
  198. //
  199.  
  200. /***************************************************************************/
  201. /* function MakeFileName                                                   */
  202. /***************************************************************************/
  203. void MakeFilename (char *path, char *dir, char *filname)
  204. {
  205.    char drive[_MAX_DRIVE], NDir [_MAX_DIR], ext[_MAX_EXT];
  206.  
  207.    _splitpath (path, drive, NDir, filname, ext);
  208.    if ((ext[0] != 0) && (ext[1] != 0))
  209.       strcat (filname, ext);
  210.    strcpy (dir, NDir); // Caller may use same argument for "path" and "dir"
  211. }
  212. //
  213.  
  214. /***************************************************************************/
  215. /* function DoFewFrags                                                     */
  216. /***************************************************************************/
  217. void DoFewFrags (EntryFnodeType *Fnode)
  218. {
  219.    ULONG FragSize;
  220.    RSN FragSector;
  221.    USHORT i;
  222.  
  223.    if ((Fnode->bFragFileInd & MANY_FRAGMENTS) == 0) { // Few fragments
  224.       for (i = 0; FileSize != 0; i++) {
  225.          FragSize = Fnode->FragTable.FewFrags[i].ulcFragSectors *
  226.                      0x200;
  227.          if (FragSize > FileSize)
  228.             FragSize = FileSize;
  229.          FileSize -= FragSize;
  230.          FragSector = Fnode->FragTable.FewFrags[i].ulFragSector;
  231.          DoSectors (FragSize, FragSector);
  232.       }
  233.    } else {
  234.       for (i = 0; FileSize != 0; i++) {
  235.          GetRelativeSectors (Fnode->FragTable.ManyFrags[i].ulFragSector,
  236.                              4,
  237.                              &FileFnode);
  238.          DoManyFrags (&FileFnode.ManyFragsFnode);
  239.       }
  240.    }
  241. }
  242. //
  243.  
  244. /***************************************************************************/
  245. /* function DoManyFrags                                                    */
  246. /***************************************************************************/
  247. void DoManyFrags (FragmentedFileTableType *FTable)
  248. {
  249.    ULONG FragSize;
  250.    RSN FragSector;
  251.    USHORT i;
  252.  
  253.    if ((FTable->bFragFileInd & MANY_FRAGMENTS) == 0) {// Few fragments in
  254.                                                       // this cluster
  255.       for (i = 0; (FileSize != 0) && (i < FTable->bcFragNum); i++) {
  256.          FragSize = FTable->FragTable[i].ulcFragSectors *   0x200;
  257.          if (FragSize > FileSize)
  258.             FragSize = FileSize;
  259.          FileSize -= FragSize;
  260.          FragSector = FTable->FragTable[i].ulFragSector;
  261.          DoSectors (FragSize, FragSector);
  262.       }
  263.    } else {
  264.       for (i = 0; (FileSize != 0) && (i < FTable->bcFragNum); i++) {
  265.          GetRelativeSectors (FTable->FragTable[i].ulFragSector,
  266.                              4,
  267.                              &FileFnode);
  268.          DoManyFrags (&FileFnode.ManyFragsFnode);
  269.       }
  270.    }
  271.    GetRelativeSectors (FTable->ulParentSector, 4, &FileFnode);
  272. }
  273. //
  274.  
  275. /***************************************************************************/
  276. /* function DoSectors                                                      */
  277. /***************************************************************************/
  278. void DoSectors (ULONG FragSize, RSN FragSector)
  279. {
  280.    USHORT Chunk, ChunkSectors;
  281.  
  282.    while (FragSize > 0) {
  283.       Chunk = (USHORT) min ((ULONG) CHUNK, FragSize);
  284.       ChunkSectors = (Chunk + 0x1FF) / 0x200;
  285.       GetRelativeSectors (FragSector, ChunkSectors, FileBuff);
  286.       if ((unsigned) write (STDOUT, FileBuff, Chunk) != Chunk) {
  287.          perror ("Error writing to STDOUT");
  288.          exit (IO_ERR);
  289.       }
  290.       FragSize -= Chunk;
  291.       FragSector += ChunkSectors;
  292.    }
  293. }
  294. //
  295.  
  296. /***************************************************************************/
  297. /* function GetRelativeSectors                                             */
  298. /***************************************************************************/
  299. void GetRelativeSectors (RSN SectorLoc, USHORT SectorNum, void *Into)
  300. {
  301.    RSN SectorsToLoc;
  302.    ULONG TempLONG;
  303.    USHORT RoomInSegment;
  304.  
  305.    SectorLoc += HPFSPartition->PartitionOffset;
  306.    while (SectorNum) {
  307.       SectorsToLoc = SectorLoc;
  308.       DiskInfo.track = (USHORT) (SectorsToLoc / SectorsInFullTrack);
  309.       SectorsToLoc -= (ULONG) DiskInfo.track * (ULONG) SectorsInFullTrack;
  310.  
  311.       DiskInfo.head = (USHORT) (SectorsToLoc /
  312.                         PartitionBootSector.SectorsInTrack);
  313.       TempLONG = 1L + SectorsToLoc - (ULONG) DiskInfo.head *
  314.                         (ULONG) PartitionBootSector.SectorsInTrack;
  315.       DiskInfo.sector = (USHORT) TempLONG;
  316.       DiskInfo.buffer = Into;
  317.       if (SectorNum + DiskInfo.sector <=
  318.                                  PartitionBootSector.SectorsInTrack + 1)
  319.          DiskInfo.nsectors = SectorNum;
  320.       else
  321.          DiskInfo.nsectors = PartitionBootSector.SectorsInTrack
  322.                          - DiskInfo.sector + 1;
  323.       if ((FP_OFF (Into)) == 0)
  324.          RoomInSegment = SectorsInSegment;
  325.       else
  326.          RoomInSegment = (USHORT) ((0x10000UL - (ULONG) FP_OFF (Into))
  327.                            / BytesPerSector);
  328.       if (DiskInfo.nsectors > RoomInSegment)
  329.          DiskInfo.nsectors = RoomInSegment;
  330.  
  331.       _bios_disk_with_retry (&DiskInfo);
  332.  
  333.       SectorNum -= DiskInfo.nsectors;
  334.       if (SectorNum) {
  335.          FP_OFF (Into) += DiskInfo.nsectors * BytesPerSector;
  336.          if (FP_OFF (Into) == 0)
  337.             FP_SEG (Into) += HugeShift;
  338.          SectorLoc += DiskInfo.nsectors;
  339.       }
  340.    }
  341. }
  342. //
  343.  
  344. /***************************************************************************/
  345. /* function _bios_disk_with_retry                                          */
  346. /***************************************************************************/
  347. void _bios_disk_with_retry (struct diskinfo_t *Info)
  348. {
  349.    union REGS regs;
  350.    unsigned RetCode;
  351.  
  352.    if (_bios_disk (_DISK_READ, Info) >> 8) {
  353.       regs.h.dl = (BYTE) Info->drive;
  354.       regs.h.ah = 0; /* Reset drive */
  355.       int86 (0x13, ®s, ®s);
  356.       RetCode = _bios_disk (_DISK_READ, Info) >> 8;
  357.       if (RetCode != 0) {
  358.          fprintf (stderr, "Error %u in low level disk read, aborting...\n",
  359.                   RetCode);
  360.          exit (IO_ERR);
  361.       }
  362.    }
  363. }
  364. //
  365.  
  366.  
  367.