home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2001 / MacHack 2001.toast / pc / Sessions / Traut / ZStrings / Source / MacOS / CommandLineTool / MacZStringExtractTool.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-06-23  |  6.6 KB  |  269 lines

  1. /*==================================================================
  2.     File:        MacZStringExtractTool.cpp
  3.     
  4.     Contains:    Tool for extracting ZString information from
  5.                 a binary on the Mac.
  6.  
  7.     Written by:    Eric Traut
  8.     
  9.     Copyright:    2000-2001 Connectix Corporation
  10.     
  11.     This source has been placed into the public domain by
  12.     Connectix Corporation. You have the right to modify, 
  13.     distribute or use this code without any legal limitations
  14.     or finanicial/licensing requirements. Connectix is not 
  15.     liable for any problems that result from the use of this 
  16.     code.
  17.     
  18.     If you have comments, feedback, questions, or would like
  19.     to submit bug fixes or updates to this code, please email
  20.     opensource@connectix.com.
  21. ==================================================================*/
  22.  
  23. #include "ZStringTool.h"
  24.  
  25. #include <cstring>
  26. #include <cstddef>
  27. #include <cstdlib>
  28. #include <new>
  29.  
  30. #include <Files.h>
  31. #include <Devices.h>
  32. #include <StandardFile.h>
  33. #include <Resources.h>
  34.  
  35. #include "MacZString.h"
  36.  
  37. extern "C" {
  38. #include <FSp_fopen.h>
  39. }
  40.  
  41. static Boolean
  42. ReadBinaryImage(
  43.     const FSSpec &            inFileSpec,
  44.     char * &            outMemoryImage,
  45.     UInt32 &            outLength);
  46.  
  47.  
  48. /*------------------------------------------------------------------
  49.     main
  50.     
  51.     Application main entry point.
  52. ------------------------------------------------------------------*/
  53.  
  54. int
  55. main()
  56. {
  57.     StandardFileReply         sfReply;
  58.     FSSpec                    newMacFileSpec;
  59.     FSSpec                    oldMacFileSpec;
  60.     FILE *                    reportFile = NULL;
  61.     char *                    newBinaryImage;
  62.     UInt32                    newBinarySize;
  63.     char *                    oldBinaryImage = NULL;
  64.     UInt32                    oldBinarySize;
  65.     OSType                    typeList[4];
  66.     Boolean                    userSuppliedOldSpec = false;
  67.     
  68.     // Initialize the Mac toolbox by printing to the SIOUX log.
  69.     std::printf("Welcome to the ZString tool\n");
  70.     
  71.     // Ask for the new file name.
  72.     StandardGetFile(NULL, 0, typeList, &sfReply);
  73.     if (!sfReply.sfGood)
  74.     {
  75.         std::printf("Operation cancelled\n");
  76.         return 1;
  77.     }
  78.  
  79.     newMacFileSpec = sfReply.sfFile;
  80.  
  81.     // Ask for the old file name.
  82.     StandardGetFile(NULL, 0, typeList, &sfReply);
  83.     if (sfReply.sfGood)
  84.     {
  85.         oldMacFileSpec = sfReply.sfFile;
  86.         userSuppliedOldSpec = true;
  87.     }
  88.     
  89.     // Ask for the name of the output file.
  90.     StandardPutFile("\pName the output file:", "\pZOverride.html", &sfReply);
  91.     if (!sfReply.sfGood)
  92.     {
  93.         std::printf("Operation cancelled\n");
  94.         return 1;
  95.     }
  96.     
  97.     reportFile = FSp_fopen(&sfReply.sfFile, "w");
  98.     
  99.     // Read in the two binaries.
  100.     if (!ReadBinaryImage(newMacFileSpec, newBinaryImage, newBinarySize))
  101.     {
  102.         std::printf("Operation cancelled\n");
  103.         return 1;
  104.     }
  105.  
  106.     if (userSuppliedOldSpec)
  107.     {
  108.         if (!ReadBinaryImage(oldMacFileSpec, oldBinaryImage, oldBinarySize))
  109.         {
  110.             std::printf("Operation cancelled\n");
  111.             return 1;
  112.         }
  113.     }
  114.     
  115.     // Process the data.
  116.     ZStringTool        stringTool;
  117.     Z_Boolean        reportOK;
  118.     ZToolOptions    toolOptions;
  119.     
  120.     stringTool.ProcessBinaries(newBinaryImage, newBinarySize, oldBinaryImage, oldBinarySize, toolOptions);
  121.     reportOK = stringTool.PrintReport(reportFile, toolOptions);
  122.  
  123.     fclose(reportFile);
  124.     delete [] newBinaryImage;
  125.     delete [] oldBinaryImage;
  126.  
  127.     if (reportOK)
  128.         std::printf("Operation completed successfully\n");
  129. }
  130.  
  131.  
  132. /*------------------------------------------------------------------
  133.     ReadBinaryImage
  134. ------------------------------------------------------------------*/
  135.  
  136. Boolean
  137. ReadBinaryImage(
  138.     const FSSpec &    inFileSpec,
  139.     char * &        outMemoryImage,
  140.     UInt32 &        outLength)
  141. {
  142.     FSSpec    theSpec = inFileSpec;
  143.     OSErr     err = noErr;
  144.     
  145.     // get the catalog info
  146.     CInfoPBRec    catInfo;
  147.     {
  148.         catInfo.hFileInfo.ioCompletion    = NULL;
  149.         catInfo.hFileInfo.ioVRefNum        = inFileSpec.vRefNum;
  150.         catInfo.hFileInfo.ioNamePtr        = const_cast<StringPtr>(inFileSpec.name);
  151.         catInfo.hFileInfo.ioFDirIndex    = 0;
  152.         catInfo.hFileInfo.ioDirID        = inFileSpec.parID;
  153.         err = ::PBGetCatInfoSync(&catInfo);
  154.     }
  155.     if (err != noErr)
  156.     {
  157.         std::fprintf(stderr, "Error reading catalog info (err == %d).\n", err);
  158.         return false;
  159.     }
  160.     
  161.     // Allocate total memory required for binary image
  162.     //    We allocate the combined logical lengths of both forks. Since 
  163.     //    we won't be scanning the resource map or the override resources 
  164.     //    this will actually be alittle more memory than we need.
  165.     outMemoryImage = new (nothrow) char[catInfo.hFileInfo.ioFlLgLen + catInfo.hFileInfo.ioFlRLgLen];
  166.     if (outMemoryImage == NULL)
  167.     {
  168.         std::fprintf(stderr, "Not enough memory to load file.\n");
  169.         return false;
  170.     }
  171.     
  172.     if (catInfo.hFileInfo.ioFlAttrib & ioDirMask)
  173.     {
  174.         std::fprintf(stderr, "Selected item is a directory.\n");
  175.         return false;
  176.     }
  177.     
  178.     // initalize read data
  179.        Byte *    outMemPtr    = reinterpret_cast<Byte *>(outMemoryImage);
  180.     outLength    = 0;
  181.     
  182.     if (catInfo.hFileInfo.ioFlLgLen > 0)    // data fork exists
  183.     {
  184.         SInt16    dfRefNum = -1;
  185.         
  186.         // open the data fork
  187.         err = ::FSpOpenDF(&theSpec, fsRdPerm, &dfRefNum);
  188.         if (err != noErr)
  189.         {
  190.             std::fprintf(stderr, "Error opening data fork (err == %d).\n", err);
  191.             return false;
  192.         }
  193.         
  194.         // seek the start of file (redundant)
  195.         err = ::SetFPos(dfRefNum, fsFromStart, 0);
  196.         if (err != noErr)
  197.         {
  198.             std::fprintf(stderr, "Error seeking start-of-file (err == %d).\n", err);
  199.             return false;
  200.         }
  201.         
  202.         // read the entire logical data fork
  203.         long    readLength    = catInfo.hFileInfo.ioFlLgLen;
  204.         err = ::FSRead(dfRefNum, &readLength, outMemPtr);
  205.         if (err != noErr)
  206.         {
  207.             std::fprintf(stderr, "Error reading data fork (err == %d).\n", err);
  208.             return false;
  209.         }
  210.         outMemPtr += readLength;
  211.         outLength += readLength;
  212.         
  213.         // close the data fork
  214.         ::FSClose(dfRefNum);    // error is ignored
  215.     }
  216.     
  217.     if (catInfo.hFileInfo.ioFlRLgLen > 0)    // resource fork exists
  218.     {
  219.         // preserve original resource file
  220.         SInt16    originalResFile = ::CurResFile();
  221.         SInt16    rfRefNum = -1;
  222.         
  223.         // open resource fork
  224.         rfRefNum = ::FSpOpenResFile(&theSpec, fsRdPerm);
  225.         if ((err = ::ResError()) != noErr)
  226.         {
  227.             std::fprintf(stderr, "Error opening resource fork (err == %d).\n", err);
  228.             return false;
  229.         }
  230.         
  231.         // read resources
  232.         UInt32 typeCount = ::Count1Types();
  233.         for (UInt32 i = 1; i <= typeCount; i++)    // loop through res types
  234.         {
  235.             ResType    resType;
  236.             ::Get1IndType(&resType, i);
  237.             
  238.             // Skip over override dictionary res types.
  239.             if (resType != kZStringOverrideDictionaryResType)
  240.             {
  241.                 UInt32    resCount = ::Count1Resources(resType);
  242.                 for (UInt32 i = 1; i <= resCount; i++)    // loop through res count
  243.                 {
  244.                     // read resource
  245.                     Handle     resHandle = ::Get1IndResource(resType, i);
  246.                     if (resHandle != NULL)
  247.                     {
  248.                         Size    resSize = ::GetHandleSize(resHandle);
  249.                         ::BlockMoveData(*resHandle, outMemPtr, resSize);
  250.                         outMemPtr += resSize;
  251.                         outLength += resSize;
  252.                         ::ReleaseResource(resHandle);
  253.                     }
  254.                 }
  255.             }                
  256.         }
  257.         
  258.         // close the resource fork
  259.         ::CloseResFile(rfRefNum);
  260.         
  261.         // restore original resource file
  262.         ::UseResFile(originalResFile);
  263.     }
  264.     
  265.     return (err == noErr);
  266. }
  267.  
  268.  
  269.