home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / h / hpack78s.zip / tags.c < prev    next >
Text File  |  1992-12-03  |  22KB  |  721 lines

  1. /****************************************************************************
  2. *                                                                            *
  3. *                            HPACK Multi-System Archiver                        *
  4. *                            ===========================                        *
  5. *                                                                            *
  6. *                          HPACK Archive Tag Handling Code                    *
  7. *                            TAGS.C  Updated 08/09/92                        *
  8. *                                                                            *
  9. * This program is protected by copyright and as such any use or copying of    *
  10. *  this code for your own purposes directly or indirectly is highly uncool    *
  11. *                      and if you do so there will be....trubble.                *
  12. *                 And remember: We know where your kids go to school.            *
  13. *                                                                            *
  14. *        Copyright 1990 - 1992  Peter C.Gutmann.  All rights reserved        *
  15. *                                                                            *
  16. ****************************************************************************/
  17.  
  18. #ifdef __MAC__
  19.   #include "defs.h"
  20.   #include "error.h"
  21.   #include "hpacklib.h"
  22.   #include "system.h"
  23.   #include "tags.h"
  24.   #include "fastio.h"
  25. #else
  26.   #include "defs.h"
  27.   #include "error.h"
  28.   #include "hpacklib.h"
  29.   #include "system.h"
  30.   #include "tags.h"
  31.   #include "io/fastio.h"
  32. #endif /* __MAC__ */
  33.  
  34. /****************************************************************************
  35. *                                                                            *
  36. *                            Read Tagged Data Routines                        *
  37. *                                                                            *
  38. ****************************************************************************/
  39.  
  40. /* Grovel through a tag field looking for tags we can handle */
  41.  
  42. int readTag( long *tagFieldSize, TAGINFO *tagInfo )
  43.     {
  44.     WORD theTag;
  45.     int tagClass = TAGCLASS_NONE;
  46.     LONG dataLength;
  47.  
  48.     while( *tagFieldSize > 0 && !tagClass )
  49.         {
  50.         dataLength = 0L;
  51.         theTag = fgetWord();
  52.  
  53.         /* Extract the tag ID and data length depending on the type of the tag */
  54.         if( theTag >= LONG_BASE )
  55.             {
  56.             /* Get 9-bit tag ID and tag length information */
  57.             tagInfo->tagID = ( ( ( theTag & 1 ) << 8 ) | fgetByte() ) + NO_SHORT_TAGS;
  58.             tagInfo->dataFormat = ( theTag & LONGTAG_FORMAT_MASK ) >> LONGTAG_FORMAT_SHIFT;
  59.             switch( theTag & LONGTAG_LENGTH_MASK )
  60.                 {
  61.                 case LONGTAG_BYTE_WORD:
  62.                     tagInfo->dataLength = tagInfo->uncoprLength = ( LONG ) fgetByte();
  63.                     dataLength += LONG_TAGSIZE + sizeof( BYTE );
  64.                     if( tagInfo->dataFormat )
  65.                         {
  66.                         tagInfo->uncoprLength = ( LONG ) fgetWord();
  67.                         dataLength += sizeof( WORD );
  68.                         }
  69.                     break;
  70.  
  71.                 case LONGTAG_WORD_WORD:
  72.                     tagInfo->dataLength = tagInfo->uncoprLength = ( LONG ) fgetWord();
  73.                     dataLength += LONG_TAGSIZE + sizeof( WORD );
  74.                     if( tagInfo->dataFormat )
  75.                         {
  76.                         tagInfo->uncoprLength = ( LONG ) fgetWord();
  77.                         dataLength += sizeof( WORD );
  78.                         }
  79.                     break;
  80.  
  81.                 case LONGTAG_WORD_LONG:
  82.                     tagInfo->dataLength = tagInfo->uncoprLength = ( LONG ) fgetWord();
  83.                     dataLength += LONG_TAGSIZE + sizeof( WORD );
  84.                     if( tagInfo->dataFormat )
  85.                         {
  86.                         tagInfo->uncoprLength = fgetLong();
  87.                         dataLength += sizeof( LONG );
  88.                         }
  89.                     break;
  90.  
  91.                 case LONGTAG_LONG_LONG:
  92.                     tagInfo->dataLength = tagInfo->uncoprLength = fgetLong();
  93.                     dataLength += LONG_TAGSIZE + sizeof( LONG );
  94.                     if( tagInfo->dataFormat )
  95.                         {
  96.                         tagInfo->uncoprLength = fgetLong();
  97.                         dataLength += sizeof( LONG );
  98.                         }
  99.                     break;
  100.                 }
  101.             }
  102.         else
  103.             {
  104.             tagInfo->tagID = ( theTag & TAGID_MASK ) >> TAGID_SHIFT;
  105.             tagInfo->dataFormat = TAGFORMAT_STORED;
  106.             tagInfo->dataLength = tagInfo->uncoprLength = theTag & DATALEN_MASK;
  107.             dataLength += SHORT_TAGSIZE;
  108.  
  109.             /* If it's an alternative short-form of a tag, convert the ID to
  110.                the usual form */
  111.             if( tagInfo->tagID == TAG_S_LONGNAME )
  112.                 tagInfo->tagID = TAG_LONGNAME;
  113.             else
  114.                 if( tagInfo->tagID == TAG_S_COMMENT )
  115.                     tagInfo->tagID = TAG_COMMENT;
  116.                 else
  117.                     if( tagInfo->tagID == TAG_S_ERROR )
  118.                         tagInfo->tagID = TAG_ERROR;
  119.             }
  120.         *tagFieldSize -= dataLength + tagInfo->dataLength;
  121.  
  122.         /* If the length field has been corrupted, set the tagID to a non-
  123.            tag and perform error recovery later on */
  124.         if( *tagFieldSize < 0 )
  125.             tagInfo->tagID = BAD_TAGID;
  126.  
  127.         /* Now handle each tag.  At this point we only check whether we know
  128.            what to do with the tag, but don't do any processing.  Any tags
  129.            which contain useless information (as well as those we don't know
  130.            about) are skipped */
  131.         switch( tagInfo->tagID )
  132.             {
  133.             case TAG_AMIGA_ATTR:
  134.             case TAG_APPLE_ATTR:
  135.             case TAG_ARC_ATTR:
  136.             case TAG_ATARI_ATTR:
  137.             case TAG_MAC_ATTR:
  138.             case TAG_MSDOS_ATTR:
  139.             case TAG_OS2_ATTR:
  140.             case TAG_UNIX_ATTR:
  141.             case TAG_VMS_ATTR:
  142.                 tagClass = TAGCLASS_ATTRIBUTE;
  143.                 break;
  144.  
  145.             case TAG_COMMENT:
  146.                 tagClass = TAGCLASS_COMMENT;
  147.                 break;
  148.  
  149.             case TAG_ACCESS_TIME:
  150.             case TAG_BACKUP_TIME:
  151.             case TAG_CREATION_TIME:
  152.             case TAG_EXPIRATION_TIME:
  153.                 tagClass = TAGCLASS_TIME;
  154.                 break;
  155.  
  156.             case TAG_AMIGA_ICON:
  157.             case TAG_OS2_ICON:
  158.                 tagClass = TAGCLASS_ICON;
  159.                 break;
  160.  
  161.             case TAG_EXECUTE_ADDRESS:
  162.             case TAG_LOAD_ADDRESS:
  163.             case TAG_LONGNAME:
  164.             case TAG_MAC_TYPE:
  165.             case TAG_MAC_CREATOR:
  166.             case TAG_OS2_MISC_EA:
  167.             case TAG_POSITION:
  168.             case TAG_SECURITY_INFO:
  169.             case TAG_RESOURCE_FORK:
  170.             case TAG_VERSION_NUMBER:
  171.             case TAG_WINSIZE:
  172.                 tagClass = TAGCLASS_MISC;
  173.                 break;
  174.  
  175.             default:
  176.                 /* Unrecognised tag, skip it and look for next one */
  177.                 if( *tagFieldSize < 0 )
  178.                     {
  179.                     /* If the tag length field is corrupted, just skip
  180.                        over whatever data is left */
  181.                     skipSeek( *tagFieldSize + tagInfo->dataLength );
  182.                     tagInfo->dataLength = tagInfo->uncoprLength = 0L;
  183.                     *tagFieldSize = 0;
  184.                     }
  185.                 else
  186.                     skipSeek( tagInfo->dataLength );
  187.                 break;
  188.             }
  189.         }
  190.  
  191.     return( tagClass );
  192.     }
  193.  
  194. /* Read in attribute data and translate it for the host OS.  Note that
  195.    execute bits are never translated, for obvious reasons */
  196.  
  197. ATTR readAttributeData( const WORD attributeID )
  198.     {
  199.     WORD wordData;
  200.     BYTE byteData;
  201.     ATTR retVal = 0;
  202.  
  203.     switch( attributeID )
  204.         {
  205.         case TAG_ATARI_ATTR:
  206.         case TAG_MSDOS_ATTR:
  207.         case TAG_OS2_ATTR:
  208.             byteData = fgetByte();
  209. #if defined( __ATARI__ ) || defined( __MSDOS__ ) || defined( __OS2__ )
  210.             retVal = byteData & ~DIRECT;    /* Can't set dir.attr */
  211. #elif defined( __AMIGA__ )
  212.             retVal |= AMIGA_ATTR_READ | AMIGA_ATTR_WRITE | AMIGA_ATTR_DELETE;
  213.             if( byteData & MSDOS_ATTR_ARCHIVE )
  214.                 retVal |= AMIGA_ATTR_ARCHIVE;
  215.             if( byteData & MSDOS_ATTR_RDONLY )
  216.                 retVal ^= AMIGA_ATTR_READ;
  217.             if( byteData & MSDOS_ATTR_HIDDEN )
  218.                 retVal |= AMIGA_ATTR_HIDDEN;
  219. #elif defined( __MAC__ )
  220.             if( byteData & MSDOS_ATTR_ARCHIVE )
  221.                 retVal |= MAC_ATTR_CHANGED;
  222.             if( byteData & MSDOS_ATTR_SYSTEM )
  223.                 retVal |= MAC_ATTR_SYSTEM;
  224.             if( byteData & MSDOS_ATTR_HIDDEN )
  225.                 retVal |= MAC_ATTR_INVISIBLE;
  226.             if( byteData & MSDOS_ATTR_RDONLY )
  227.                 retVal |= MAC_ATTR_LOCKED;
  228. #elif defined( __UNIX__ )
  229.             if( byteData & MSDOS_ATTR_RDONLY )
  230.                 retVal = UNIX_ATTR_RBITS;
  231.             else
  232.                 retVal = UNIX_ATTR_RBITS | UNIX_ATTR_WBITS;
  233. #elif defined( __VMS__ )
  234.             if( byteData & MSDOS_ATTR_RDONLY )
  235.                 retVal = VMS_ATTR_RBITS;
  236.             else
  237.                 retVal = VMS_ATTR_RBITS | VMS_ATTR_DBITS;
  238. #else
  239.             hprintf( "Don't know what to do with MSDOS attributes, TAGS.C line %d\n", __LINE__ );
  240. #endif /* Various OS-specific defines */
  241.             break;
  242.  
  243.         case TAG_AMIGA_ATTR:
  244.             byteData = fgetByte();
  245. #if defined( __ATARI__ ) || defined( __MSDOS__ ) || defined( __OS2__ )
  246.             if( !( byteData & AMIGA_ATTR_WRITE ) )
  247.                 retVal |= MSDOS_ATTR_RDONLY;
  248.             if( !( byteData & AMIGA_ATTR_ARCHIVE ) )
  249.                 retVal |= MSDOS_ATTR_ARCHIVE;
  250. #elif defined( __AMIGA__ )
  251.             retVal = byteData;
  252. #elif defined( __MAC__ )
  253.             if( !( wordData & AMIGA_ATTR_WRITE ) )
  254.                 retVal |= MAC_ATTR_LOCKED;
  255.             if( !( wordData & AMIGA_ATTR_ARCHIVE ) )
  256.                 retVal |= MAC_ATTR_CHANGED;
  257. #elif defined( __UNIX__ )
  258.             if( byteData & AMIGA_ATTR_READ )
  259.                 retVal |= UNIX_ATTR_RBITS;
  260.             if( byteData & AMIGA_ATTR_WRITE )
  261.                 retVal |= UNIX_ATTR_WBITS;
  262. #elif defined( __VMS__ )
  263.             if( byteData & AMIGA_ATTR_READ )
  264.                 retVal |= VMS_ATTR_RBITS;
  265.             if( byteData & AMIGA_ATTR_WRITE )
  266.                 retVal |= VMS_ATTR_WBITS;
  267. #else
  268.             hprintf( "Don't know what to do with Amiga attributes, TAGS.C line %d\n", __LINE__ );
  269. #endif /* Various OS-specific defines */
  270.             break;
  271.  
  272.         case TAG_APPLE_ATTR:
  273.             wordData = fgetWord();
  274. #if defined( __ATARI__ ) || defined( __MSDOS__ ) || defined( __OS2__ )
  275.             if( !( wordData & APPLE_ATTR_WRITE ) )
  276.                 retVal |= MSDOS_ATTR_RDONLY;
  277.             if( wordData & APPLE_ATTR_BACKUP )
  278.                 retVal |= MSDOS_ATTR_ARCHIVE;
  279. #elif defined( __AMIGA__ )
  280.             if( wordData & APPLE_ATTR_READ )
  281.                 retVal |= AMIGA_ATTR_READ;
  282.             if( wordData & APPLE_ATTR_WRITE )
  283.                 retVal |= AMIGA_ATTR_WRITE | AMIGA_ATTR_DELETE;
  284.             if( wordData & APPLE_ATTR_BACKUP )
  285.                 retVal |= AMIGA_ATTR_ARCHIVE;
  286. #elif defined( __UNIX__ )
  287.             if( wordData & APPLE_ATTR_READ )
  288.                 retVal |= UNIX_ATTR_RBITS;
  289.             if( wordData & APPLE_ATTR_WRITE )
  290.                 retVal |= UNIX_ATTR_WBITS;
  291. #elif defined( __MAC__ )
  292.             if( !( wordData & APPLE_ATTR_WRITE ) )
  293.                 retVal |= MAC_ATTR_LOCKED;
  294.             if( wordData & APPLE_ATTR_BACKUP )
  295.                 retVal |= MAC_ATTR_CHANGED;
  296. #elif defined( __UNIX__ )
  297.             if( wordData & APPLE_ATTR_READ )
  298.                 retVal |= VMS_ATTR_RBITS;
  299.             if( wordData & APPLE_ATTR_WRITE )
  300.                 retVal |= VMS_ATTR_WBITS;
  301. #else
  302.             hprintf( "Don't know what to do with IIgs attributes, TAGS.C line %d\n", __LINE__ );
  303. #endif /* Various OS-specific defines */
  304.             break;
  305.  
  306.         case TAG_ARC_ATTR:
  307.             byteData = fgetByte();
  308. #if defined( __ATARI__ ) || defined( __MSDOS__ ) || defined( __OS2__ )
  309.             if( byteData & ARC_ATTR_LOCKED )
  310.                 retVal |= MSDOS_ATTR_RDONLY;
  311. #elif defined( __AMIGA__ )
  312.             if( byteData & ARC_ATTR_READ_OWNER )
  313.                 retVal |= AMIGA_ATTR_READ;
  314.             if( byteData & ARC_ATTR_WRITE_OWNER )
  315.                 retVal |= AMIGA_ATTR_WRITE | AMIGA_ATTR_DELETE;
  316. #elif defined( __MAC__ )
  317.             if( byteData & ARC_ATTR_LOCKED )
  318.                 retVal |= MAC_ATTR_LOCKED;
  319. #elif defined( __UNIX__ )
  320.             if( byteData & ARC_ATTR_READ_OWNER )
  321.                 retVal |= UNIX_ATTR_OWNER_R;
  322.             if( byteData & ARC_ATTR_WRITE_OWNER )
  323.                 retVal |= UNIX_ATTR_OWNER_W;
  324.             if( byteData & ARC_ATTR_READ_OTHER )
  325.                 retVal |= UNIX_ATTR_GROUP_R | UNIX_ATTR_OTHER_W;
  326.             if( byteData & ARC_ATTR_WRITE_OTHER )
  327.                 retVal |= UNIX_ATTR_GROUP_W | UNIX_ATTR_OTHER_W;
  328. #elif defined( __VMS__ )
  329.             if( byteData & ARC_ATTR_READ_OWNER )
  330.                 retVal |= VMS_ATTR_SYSTEM_R | VMS_ATTR_OWNER_R;
  331.             if( byteData & ARC_ATTR_WRITE_OWNER )
  332.                 retVal |= VMS_ATTR_SYSTEM_W | VMS_ATTR_OWNER_W;
  333.             if( byteData & ARC_ATTR_READ_OTHER )
  334.                 retVal |= VMS_ATTR_GROUP_R | VMS_ATTR_WORLD_R;
  335.             if( byteData & ARC_ATTR_WRITE_OTHER )
  336.                 retVal |= VMS_ATTR_GROUP_W | VMS_ATTR_WORLD_W;
  337. #else
  338.             hprintf( "Don't know what to do with Archimedes attributes, TAGS.C line %d\n", __LINE__ );
  339. #endif /* Various OS-specific defines */
  340.             break;
  341.  
  342.         case TAG_MAC_ATTR:
  343.             wordData = fgetWord();
  344. #if defined( __ATARI__ ) || defined( __MSDOS__ ) || defined( __OS2__ )
  345.             if( wordData & MAC_ATTR_CHANGED )
  346.                 retVal |= MSDOS_ATTR_ARCHIVE;
  347.             if( wordData & MAC_ATTR_SYSTEM )
  348.                 retVal |= MSDOS_ATTR_SYSTEM;
  349.             if( wordData & MAC_ATTR_INVISIBLE )
  350.                 retVal |= MSDOS_ATTR_HIDDEN;
  351.             if( wordData & MAC_ATTR_LOCKED )
  352.                 retVal |= MSDOS_ATTR_RDONLY;
  353. #elif defined( __AMIGA__ )
  354.             retVal |= AMIGA_ATTR_READ | AMIGA_ATTR_WRITE | AMIGA_ATTR_DELETE;
  355.             if( wordData & MAC_ATTR_CHANGED )
  356.                 retVal |= AMIGA_ATTR_ARCHIVE;
  357.             if( wordData & MAC_ATTR_INVISIBLE )
  358.                 retVal |= AMIGA_ATTR_HIDDEN;
  359.             if( wordData & MAC_ATTR_LOCKED )
  360.                 retVal ^= AMIGA_ATTR_WRITE;
  361. #elif defined( __MAC__ )
  362.             retVal = wordData;
  363. #elif defined( __UNIX__ )
  364.             if( wordData & MAC_ATTR_LOCKED )
  365.                 retVal = UNIX_ATTR_RBITS;
  366.             else
  367.                 retVal = UNIX_ATTR_RBITS | UNIX_ATTR_WBITS;
  368. #elif defined( __VMS__ )
  369.             if( wordData & MAC_ATTR_LOCKED )
  370.                 retVal = VMS_ATTR_RBITS;
  371.             else
  372.                 retVal = VMS_ATTR_RBITS | VMS_ATTR_DBITS;
  373. #else
  374.             hprintf( "Don't know what to do with Mac attributes, TAGS.C line %d\n", __LINE__ );
  375. #endif /* Various OS-specific defines */
  376.             break;
  377.  
  378.         case TAG_UNIX_ATTR:
  379.             wordData = fgetWord();
  380. #if defined( __ATARI__ ) || defined( __MSDOS__ ) || defined( __OS2__ )
  381.             if( !( wordData & UNIX_ATTR_OWNER_W ) )
  382.                 retVal |= MSDOS_ATTR_RDONLY;
  383. #elif defined( __AMIGA__ )
  384.             retVal |= AMIGA_ATTR_READ | AMIGA_ATTR_WRITE | AMIGA_ATTR_DELETE;
  385.             if( !( wordData & UNIX_ATTR_OWNER_R ) )
  386.                 retVal ^= AMIGA_ATTR_READ;
  387.             if( !( wordData & UNIX_ATTR_OWNER_W ) )
  388.                 retVal ^= ( AMIGA_ATTR_WRITE | AMIGA_ATTR_DELETE );
  389. #elif defined( __MAC__ )
  390.             if( !( wordData & UNIX_ATTR_OWNER_W ) )
  391.                 retVal |= MAC_ATTR_LOCKED;
  392. #elif defined( __UNIX__ )
  393.             retVal = wordData;
  394. #elif defined( __VMS__ )
  395.             if( wordData & UNIX_ATTR_OTHER_R )
  396.                 retVal |= VMS_ATTR_WORLD_R;
  397.             if( wordData & UNIX_ATTR_OTHER_W )
  398.                 retVal |= VMS_ATTR_WORLD_W | VMS_ATTR_WORLD_D;
  399.             if( wordData & UNIX_ATTR_GROUP_R )
  400.                 retVal |= VMS_ATTR_GROUP_R;
  401.             if( wordData & UNIX_ATTR_GROUP_W )
  402.                 retVal |= VMS_ATTR_GROUP_W | VMS_ATTR_GROUP_D;
  403.             if( wordData & UNIX_ATTR_OWNER_R )
  404.                 retVal |= VMS_ATTR_OWNER_R;
  405.             if( wordData & UNIX_ATTR_OWNER_W )
  406.                 retVal |= VMS_ATTR_OWNER_W | VMS_ATTR_OWNER_D;
  407. #else
  408.             hprintf( "Don't know what to do with Unix attributes, TAGS.C line %d\n", __LINE__ );
  409. #endif /* Various OS-specific defines */
  410.             break;
  411.  
  412.         case TAG_VMS_ATTR:
  413.             wordData = fgetWord();
  414. #if defined( __ATARI__ ) || defined( __MSDOS__ ) || defined( __OS2__ )
  415.             if( !( wordData & VMS_ATTR_OWNER_W ) )
  416.                 retVal |= MSDOS_ATTR_RDONLY;
  417. #elif defined( __AMIGA__ )
  418.             if( wordData & VMS_ATTR_OWNER_R )
  419.                 retVal |= AMIGA_ATTR_READ;
  420.             if( wordData & VMS_ATTR_OWNER_W )
  421.                 retVal |= AMIGA_ATTR_WRITE;
  422.             if( wordData & VMS_ATTR_OWNER_D )
  423.                 retVal |= AMIGA_ATTR_DELETE;
  424. #elif defined( __MAC__ )
  425.             if( !( wordData & VMS_ATTR_OWNER_W ) )
  426.                 retVal |= MAC_ATTR_LOCKED;
  427. #elif defined( __UNIX__ )
  428.             if( wordData & VMS_ATTR_WORLD_R )
  429.                 retVal |= UNIX_ATTR_OTHER_R;
  430.             if( wordData & ( VMS_ATTR_WORLD_W | VMS_ATTR_WORLD_D ) )
  431.                 retVal |= UNIX_ATTR_OTHER_W;
  432.             if( wordData & VMS_ATTR_GROUP_R )
  433.                 retVal |= UNIX_ATTR_GROUP_R;
  434.             if( wordData & ( VMS_ATTR_GROUP_W | VMS_ATTR_GROUP_D ) )
  435.                 retVal |= UNIX_ATTR_GROUP_W;
  436.             if( wordData & VMS_ATTR_OWNER_R )
  437.                 retVal |= UNIX_ATTR_OWNER_R;
  438.             if( wordData & ( VMS_ATTR_OWNER_W | VMS_ATTR_OWNER_D ) )
  439.                 retVal |= UNIX_ATTR_OWNER_W;
  440. #elif defined( __VMS__ )
  441.             retVal = wordData;
  442. #else
  443.             hprintf( "Don't know what to do with VMS attributes, TAGS.C line %d\n", __LINE__ );
  444. #endif /* Various OS-specific defines */
  445.         }
  446.  
  447.     return( retVal );
  448.     }
  449.  
  450. /****************************************************************************
  451. *                                                                            *
  452. *                            Write Tagged Data Routines                        *
  453. *                                                                            *
  454. ****************************************************************************/
  455.  
  456. /* Write a long tag */
  457.  
  458. int writeTag( WORD tagID, const WORD store, const LONG dataLength, const LONG uncoprLength )
  459.     {
  460.     WORD tagLength = ( dataLength <= 0xFF ) ? LONGTAG_BYTE_WORD : \
  461.                      ( dataLength > 0xFFFF ) ? LONGTAG_LONG_LONG : \
  462.                      ( uncoprLength <= 0xFFFF ) ? LONGTAG_WORD_WORD : \
  463.                      LONGTAG_WORD_LONG;
  464.     int headerLen = sizeof( WORD ) + sizeof( BYTE );
  465.     BOOLEAN isShortForm = ( store == TAGFORMAT_STORED ) && \
  466.                           ( dataLength < SHORT_TAGLEN ) && \
  467.                           ( tagID == TAG_LONGNAME || tagID == TAG_COMMENT || \
  468.                             tagID == TAG_ERROR );
  469.  
  470.     /* Determine whether we can write a short tag or not.  We can do this
  471.        either if the tagID is a short tagID, or if there is a short form of
  472.        the tag and it fulfils the requirements for a short tag */
  473.     if( isShortTag( tagID ) || isShortForm )
  474.         {
  475.         /* If it's a short form tag, convert the ID to the short-form equivalent */
  476.         if( isShortForm )
  477.             {
  478.             if( tagID == TAG_LONGNAME )
  479.                 tagID = TAG_S_LONGNAME;
  480.             else
  481.                 if( tagID == TAG_COMMENT )
  482.                     tagID = TAG_S_COMMENT;
  483.                 else
  484.                     tagID = TAG_S_ERROR;
  485.             }
  486.  
  487.         fputWord( ( tagID << TAGID_SHIFT ) | ( WORD ) dataLength );
  488.         return( sizeof( WORD ) );
  489.         }
  490.  
  491.     /* Write long tag ID, storage class, and 9-bit actual tag ID */
  492.     tagID -= NO_SHORT_TAGS;            /* Convert to base value of zero */
  493.     fputWord( LONG_BASE | tagLength | ( store << LONGTAG_FORMAT_SHIFT ) | ( tagID >> 8 ) );
  494.     fputByte( tagID & 0xFF );
  495.     switch( tagLength )
  496.         {
  497.         case LONGTAG_BYTE_WORD:
  498.             fputByte( ( BYTE ) dataLength );
  499.             headerLen += sizeof( BYTE );
  500.             if( store )
  501.                 {
  502.                 fputWord( ( WORD ) uncoprLength );
  503.                 headerLen += sizeof( WORD );
  504.                 }
  505.             break;
  506.  
  507.         case LONGTAG_WORD_WORD:
  508.             fputWord( ( WORD ) dataLength );
  509.             headerLen += sizeof( WORD );
  510.             if( store )
  511.                 {
  512.                 fputWord( ( WORD ) uncoprLength );
  513.                 headerLen += sizeof( WORD );
  514.                 }
  515.             break;
  516.  
  517.         case LONGTAG_WORD_LONG:
  518.             fputWord( ( WORD ) dataLength );
  519.             headerLen += sizeof( WORD );
  520.             if( store )
  521.                 {
  522.                 fputLong( uncoprLength );
  523.                 headerLen += sizeof( LONG );
  524.                 }
  525.             break;
  526.  
  527.         case LONGTAG_LONG_LONG:
  528.             fputLong( dataLength );
  529.             headerLen += sizeof( LONG );
  530.             if( store )
  531.                 {
  532.                 fputLong( uncoprLength );
  533.                 headerLen += sizeof( LONG );
  534.                 }
  535.             break;
  536.         }
  537.  
  538.     return( headerLen );
  539.     }
  540.  
  541. #ifndef __MSDOS__        /* Save a bit of code size */
  542.  
  543. int writeDirTag( WORD tagID, const WORD store, const LONG dataLength, const LONG uncoprLength )
  544.     {
  545.     WORD tagLength = ( dataLength <= 0xFF ) ? LONGTAG_BYTE_WORD : \
  546.                      ( dataLength > 0xFFFF ) ? LONGTAG_LONG_LONG : \
  547.                      ( uncoprLength <= 0xFFFF ) ? LONGTAG_WORD_WORD : \
  548.                      LONGTAG_WORD_LONG;
  549.     int headerLen = sizeof( WORD ) + sizeof( BYTE );
  550.     BOOLEAN isShortForm = ( store == TAGFORMAT_STORED ) && \
  551.                           ( dataLength < SHORT_TAGLEN ) && \
  552.                           ( tagID == TAG_LONGNAME || tagID == TAG_COMMENT || \
  553.                             tagID == TAG_ERROR );
  554.  
  555.     /* Determine whether we can write a short tag or not.  We can do this
  556.        either if the tagID is a short tagID, or if there is a short form of
  557.        the tag and it fulfils the requirements for a short tag */
  558.     if( isShortTag( tagID ) || isShortForm )
  559.         {
  560.         /* If it's a short form tag, convert the ID to the short-form equivalent */
  561.         if( isShortForm )
  562.             {
  563.             if( tagID == TAG_LONGNAME )
  564.                 tagID = TAG_S_LONGNAME;
  565.             else
  566.                 if( tagID == TAG_COMMENT )
  567.                     tagID = TAG_S_COMMENT;
  568.                 else
  569.                     tagID = TAG_S_ERROR;
  570.             }
  571.  
  572.         fputDirWord( ( tagID << TAGID_SHIFT ) | ( WORD ) dataLength );
  573.         return( sizeof( WORD ) );
  574.         }
  575.  
  576.     /* Write long tag ID, storage class, and 9-bit actual tag ID */
  577.     tagID -= NO_SHORT_TAGS;            /* Convert to base value of zero */
  578.     fputDirWord( LONG_BASE | tagLength | ( store << LONGTAG_FORMAT_SHIFT ) | ( tagID >> 8 ) );
  579.     fputDirByte( tagID & 0xFF );
  580.     switch( tagLength )
  581.         {
  582.         case LONGTAG_BYTE_WORD:
  583.             fputDirByte( ( BYTE ) dataLength );
  584.             headerLen += sizeof( BYTE );
  585.             if( store )
  586.                 {
  587.                 fputDirWord( ( WORD ) uncoprLength );
  588.                 headerLen += sizeof( WORD );
  589.                 }
  590.             break;
  591.  
  592.         case LONGTAG_WORD_WORD:
  593.             fputDirWord( ( WORD ) dataLength );
  594.             headerLen += sizeof( WORD );
  595.             if( store )
  596.                 {
  597.                 fputDirWord( ( WORD ) uncoprLength );
  598.                 headerLen += sizeof( WORD );
  599.                 }
  600.             break;
  601.  
  602.         case LONGTAG_WORD_LONG:
  603.             fputDirWord( ( WORD ) dataLength );
  604.             headerLen += sizeof( WORD );
  605.             if( store )
  606.                 {
  607.                 fputDirLong( uncoprLength );
  608.                 headerLen += sizeof( LONG );
  609.                 }
  610.             break;
  611.  
  612.         case LONGTAG_LONG_LONG:
  613.             fputDirLong( dataLength );
  614.             headerLen += sizeof( LONG );
  615.             if( store )
  616.                 {
  617.                 fputDirLong( uncoprLength );
  618.                 headerLen += sizeof( LONG );
  619.                 }
  620.             break;
  621.         }
  622.  
  623.     return( headerLen );
  624.     }
  625.  
  626. #else
  627.  
  628. int writeDirTag( WORD tagID, const WORD store, const LONG dataLength, const LONG uncoprLength )
  629.     {
  630.     /* Minimal writeTag() routine - MSDOS doesn't need all this code */
  631.     fputDirWord( ( tagID << TAGID_SHIFT ) | ( WORD ) dataLength );
  632.     return( sizeof( WORD ) );
  633.     }
  634. #endif /* __MSDOS__ */
  635.  
  636. /* The following routines are used to write variable-length tagged fields to
  637.    the archive or directory information files.  Only some versions of HPACK
  638.    will need them */
  639.  
  640. #if 0
  641.  
  642. static BYTE *tempBuffer;    /* Kludge for now */
  643. extern BYTE *tempBuffer;
  644.  
  645. /* Try and compress tagged data using the auxiliary compressor */
  646.  
  647. static WORD compressTag( const BYTE *inBuffer, const BYTE *outBuffer, WORD count )
  648.     {
  649.     /* Get rid of "Unused parameter" warning */
  650.     if( inBuffer == outBuffer );
  651.  
  652.     /* Do nothing at the moment */
  653.     return( count );
  654.     }
  655.  
  656. /* Write a tag to the archive */
  657.  
  658. WORD writeTag( WORD tagID, WORD tagLength, BYTE *dataBuffer )
  659.     {
  660.     WORD compressedTagLength, i = 0;
  661.  
  662.     /* Write the tag itself as either a short or a long tag */
  663.     if( tagLength < SHORT_TAGLEN )
  664.         fputWord( tagID | tagLength );
  665.     else
  666.         {
  667.         /* Try and compress the tag data */
  668.         if( ( compressedTagLength = compressTag( dataBuffer, tempBuffer, tagLength ) ) > \
  669.             tagLength - sizeof( WORD ) )
  670.             {
  671.             /* Data couldn't be compressed, stored in uncompressed form */
  672.             fputWord( LONG_TAG( TAGFORMAT_STORED ) );
  673.             fputByte( ( BYTE ) tagID );
  674.             fputWord( tagLength );
  675.             }
  676.         else
  677.             {
  678.             /* Data was compressed, save uncompressed length at start of data */
  679.             fputWord( LONG_TAG( TAGFORMAT_PACKED ) );
  680.             fputByte( ( BYTE ) tagID );
  681.             fputWord( compressedTagLength );
  682.             fputWord( tagLength );
  683.  
  684.             /* Process the compressed data not the original data */
  685.             tagLength = compressedTagLength;
  686.             dataBuffer = tempBuffer;
  687.             }
  688.         }
  689.  
  690.     /* Get the tag length if it has an implicit length */
  691.     if( !tagLength )
  692.         tagLength = extractTagLen( tagID );
  693.  
  694.     /* Write the data associated with the tag */
  695.     while( i < tagLength )
  696.         fputByte( dataBuffer[ i++ ] );
  697.  
  698.     return( TAGSIZE + tagLength );
  699.     }
  700.  
  701. WORD writeDirTag( WORD tagID, WORD tagLength, BYTE *dataBuffer )
  702.     {
  703.     int i = 0;
  704.  
  705.     /* Write the tag itself */
  706.     tagID |= tagLength;
  707.     fputDirWord( tagID );
  708.  
  709.     /* Get the tag length if it has an implicit length */
  710.     if( !tagLength )
  711.         tagLength = extractTagLen( tagID );
  712.  
  713.     /* Write the data associated with the tag */
  714.     while( i < tagLength )
  715.         fputDirByte( dataBuffer[ i++ ] );
  716.  
  717.     return( TAGSIZE + tagLength );
  718.     }
  719.  
  720. #endif /* 0 */
  721.