home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc Source Code / Storage / Bento / FSHdr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-22  |  19.2 KB  |  641 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        FSHdr.cpp
  3.  
  4.     Contains:    Class definition for ODFSBentoHandlers class.
  5.  
  6.     Owned by:    Vincent Lo
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <2>     1/15/96    TJ        Cleaned Up
  13.         <17>     8/12/95    TÇ        1276806 Optimization: use kODFalse instead
  14.                                     of kODTrue in comparisons
  15.         <16>     5/26/95    VL        1251403: Multithreading naming support.
  16.         <15>     5/11/95    EL        Use ODBlockMove instead of memcpy.
  17.         <14>     4/25/95    EL        1242376: Synchronize label between handler
  18.                                     and container after WriteLabel.
  19.         <13>     4/10/95    EL        1236290: No debugger warning of file not
  20.                                     properly closed for DR2.
  21.         <12>      4/7/95    EL        1225905: More ModDate stuff to container.
  22.                                     Use FlipEnd.
  23.         <11>     3/24/95    EL        1225905: Move state information such as mod
  24.                                     date from plfmFile to here
  25.         <10>     3/13/95    EL        1226127 fix bug where endOfWrite is very
  26.                                     close to end of file we need a new block
  27.                                     for the safety label.
  28.          <9>     3/10/95    EL        1223465: allocate buffer on the heap.
  29.                                     1226127 fix bug buffering code destory
  30.                                     safety label at file end. Scan backward for
  31.                                     label if file is corrupted. 1227122
  32.                                     truncate file if space was lost in crash.
  33.          <8>     2/15/95    EL        1213321: Fix buffering bug where part of
  34.                                     the read in data is not the same as data in
  35.                                     a dirty buffer.
  36.          <7>     2/10/95    VL        1205627: Make it work for readonly file.
  37.          <6>     1/31/95    EL        1213321: Buffer the Bento file I/O.
  38.          <5>    11/14/94    VL        1188257: Use Bento errors in BenotDef.h.
  39.          <4>     8/26/94    EL        #1182308 Allows non-byte swapping
  40.                                     format/extract.
  41.          <3>      8/8/94    VL        1170009: Wrong byte calculation in
  42.                                     ReadHandler.
  43.          <2>     6/18/94    MB        Correct memory includes
  44.          <1>     5/27/94    VL        first checked in
  45.  
  46. */
  47.  
  48. #ifndef    _ODTYPES_
  49. #include "ODTypes.h"
  50. #endif
  51.  
  52. #ifndef _FSHDR_
  53. #include "FSHdr.h"
  54. #endif
  55.  
  56. #ifndef _BENTOHDR_
  57. #include "BentoHdr.h"
  58. #endif
  59.  
  60. #ifndef _SESSHDR_
  61. #include "SessHdr.h"
  62. #endif
  63.  
  64. #ifndef _EXCEPT_
  65. #include "Except.h"
  66. #endif
  67.  
  68. #ifndef _FLIPEND_
  69. #include "FlipEnd.h"
  70. #endif
  71.  
  72. #ifndef _PLFMFILE_
  73. #include "PlfmFile.h"
  74. #endif
  75.  
  76. #ifndef __CM_API__
  77. #include "CMAPI.h"
  78. #endif
  79.  
  80. #ifndef _ODMEMORY_
  81. #include "ODMemory.h"
  82. #endif
  83.  
  84. #ifndef _ERRORDEF_
  85. #include "ErrorDef.xh"
  86. #endif
  87.  
  88. #ifndef _BENTODEF_
  89. #include "BentoDef.h"
  90. #endif
  91.  
  92. //==============================================================================
  93. // Constants
  94. //==============================================================================
  95.  
  96. const ODType    kODBentoFileTypeName = "FileCtr";
  97.  
  98. #define kInvalidBuffer 1                /* an invalid value for fBufferBegin */
  99. #define ChunkHighBitsMask    ~(fChunkSize-1)    /* mask for masking off the lower bits */
  100.  
  101. //==============================================================================
  102. // Scalar Types
  103. //==============================================================================
  104.  
  105. //struct ContainerLabelFmt {            /* Layout of a container label:            */
  106. // unsigned char  magicBytes[8];        /* 8 bytes: the magic byte identifier    */
  107. // unsigned short flags;                /* 2    as a short                        */
  108. // unsigned short bufSize;            /* 2    TOC buffer size / 1024            */
  109. // unsigned short majorVersion;        /* 2    major format version number        */
  110. // unsigned short minorVersion;        /* 2    minor format version number        */
  111. // unsigned long    tocOffset;            /* 4    offset to start of TOC            */
  112. // unsigned long    tocSize;            /* 4    total byte size of the TOC        */
  113. //};
  114. //typedef struct ContainerLabelFmt ContainerLabelFmt;
  115.  
  116.  
  117. #pragma segment FSHdr
  118.  
  119. static void ODFlipMove(ODPtr from, ODPtr to, ODULong size)
  120. {
  121.     char    *dest = (char *)to + size - 1;
  122.     char    *src = (char *)from;
  123.     
  124.     while (size--)
  125.         *dest-- = *src++;            
  126. }
  127.  
  128. //==============================================================================
  129. // ODFSBentoHandlers
  130. //==============================================================================
  131.  
  132. ODFSBentoHandlers::ODFSBentoHandlers(CMSession session, PlatformFile* file)
  133. {
  134.     fFile = file;
  135.     fSession = session;
  136.     fBuffer = kODNULL;
  137.     fReverseEndian = kODFalse;        /* assume same Endian-ness                */
  138. }
  139.  
  140. ODFSBentoHandlers::~ODFSBentoHandlers()
  141. {
  142. }
  143.  
  144. void ODFSBentoHandlers::Initialize()
  145. {
  146.     CMSetMetaHandler(fSession, kODBentoFileTypeName, (CMMetaHandler) containerMetahandler);
  147. }
  148.  
  149. CMSession ODFSBentoHandlers::GetCMSession()
  150. {
  151.     return fSession;
  152. }
  153.  
  154. CMRefCon ODFSBentoHandlers::OpenHandler(CMOpenMode mode)
  155. {
  156.     ODULong    chunkSize;
  157.  
  158.     fFile->Open();
  159.     fFileSize = fFile->GetEndOfFile();
  160.     fPhysicalFileSize = fFileSize;    /* must set it here because used in read label */
  161.     fWriteLimit = fFileSize;        /* normally initialize in read label, but we may not have label */
  162.     fLogicalPos = 0;
  163.     fBufferBegin = kInvalidBuffer; /* buffer not loaded yet */
  164.     fBufferDirty = kODFalse;
  165.     fHasLabel = kODFalse;
  166.     chunkSize = fFile->GetAllocationBlockSize();
  167.     /* make sure it is a multiple of 2 */
  168.     for (fChunkSize = MininumChunkSize; fChunkSize < chunkSize; fChunkSize *= 2)
  169.         ;
  170.     TRY
  171.         fBuffer = (ODSByte *)ODNewPtr(fChunkSize);
  172.     CATCH_ALL
  173.         /* there may be platform that returns a large chunksize to try to read     */
  174.         /* the whole file into memory. If that fails, we can try to allocate       */
  175.         /* with a default chunksize so that it can still run. In theory even       */
  176.         /* if the default chunksize memory allocation fails, we can still catch    */
  177.         /* and run without buffering, but if memory is really so short at        */
  178.         /* open time, may as well forget about it                                */
  179.         fChunkSize = DefaultChunkSize;
  180.         fBuffer = (ODSByte *)ODNewPtr(fChunkSize);    
  181.     ENDTRY
  182.     if ((strcmp(mode, "rb") == 0) || fFile->IsLocked())
  183.         fOpenReadOnly = kODTrue;
  184.     else {
  185.         fOpenReadOnly = kODFalse;
  186.         if (fFileSize > sizeof(ContainerLabelFmt)) {
  187.             CM_UCHAR magicBytes[8];
  188.             CMContainerFlags flags;
  189.             CM_USHORT bufSize;
  190.             CM_USHORT majorVersion;
  191.             CM_USHORT minorVersion;
  192.             ODULong tocOffset;
  193.             ODULong tocSize;
  194.             TRY
  195.                 this->ReadLabelHandler(magicBytes, &flags, &bufSize,
  196.                                          &majorVersion, &minorVersion,
  197.                                          &tocOffset, &tocSize);
  198.             ENDTRY
  199.         }
  200.     }
  201.  
  202.     return ((CMRefCon) this);
  203. }
  204.  
  205. void ODFSBentoHandlers::CloseHandler()
  206. {
  207.     if (fBufferDirty)
  208.         this->FlushBuffer();
  209.     if (fBuffer != kODNULL) {
  210.         ODDisposePtr(fBuffer);
  211.         fBuffer = kODNULL;
  212.     }
  213.     if (fOpenReadOnly == kODFalse) {
  214.         fFile->SetEndOfFile(fFileSize);        /* remove the reserved space */
  215.     }
  216.     fFile->Close();
  217.     fHasLabel = kODFalse;
  218. }
  219.  
  220. CMSize ODFSBentoHandlers::FlushHandler()
  221. {
  222.     int result = 0;
  223.     
  224.     ODVolatile(result);
  225.     
  226.     TRY    
  227.         if (fBufferDirty)
  228.             this->FlushBuffer();
  229.         fFile->FlushVolume();
  230.     CATCH_ALL
  231.         result = -1;
  232.     ENDTRY
  233.     
  234.     return result;
  235. }
  236.  
  237. CMSize ODFSBentoHandlers::SeekHandler(CM_LONG posOff, CMSeekMode mode)
  238. {
  239.     if (mode == kCMSeekEnd)
  240.         fLogicalPos = fFileSize + posOff;
  241.     else if (mode == kCMSeekCurrent) {
  242.         fLogicalPos = fLogicalPos + posOff;
  243.     }
  244.     else
  245.         fLogicalPos = posOff;
  246.     
  247.     return 0;
  248. }
  249.  
  250. CMSize ODFSBentoHandlers::TellHandler()
  251. {    
  252.     return fLogicalPos;
  253. }
  254.  
  255. CMSize ODFSBentoHandlers::ReadHandler(CMPtr buffer, CMSize elementSize, CMCount theCount)
  256. {
  257.     ODULong    endOfRead, firstReadBlock, lastReadBlock;
  258.  
  259.     ODSLong amountRead = elementSize * theCount;
  260.     endOfRead = fLogicalPos + amountRead;
  261.     if (endOfRead > fFileSize) {
  262.         amountRead = fFileSize - fLogicalPos;
  263.         endOfRead = fFileSize;
  264.     }
  265.     firstReadBlock = fLogicalPos & ChunkHighBitsMask;
  266.     lastReadBlock = (endOfRead-1) & ChunkHighBitsMask;
  267.         
  268.     if (firstReadBlock == lastReadBlock) {
  269.         /* the content to read can be in a single buffer */
  270.         if (firstReadBlock != fBufferBegin) /* the block is not loaded */
  271.             this->ReloadBuffer();
  272.         /* After we make sure the buffer is loaded, we just copy it from the buffer */
  273.         ODBlockMove(fBuffer+fLogicalPos-fBufferBegin, buffer, amountRead);
  274.     }
  275.     else { /* for bigger block we read it directly bypassing the buffer */
  276.         /* if we read directly and part of data is in dirty buffer then write it first */
  277.         if ((fBufferDirty != kODFalse) && (firstReadBlock <= fBufferBegin) && (fBufferBegin <= lastReadBlock))
  278.             this->FlushBuffer();
  279.         fFile->SetFilePos(fsFromStart, fLogicalPos);
  280.         fFile->Read((ODSByte*) buffer, &amountRead);
  281.     }
  282.     
  283.     fLogicalPos = endOfRead;
  284.     
  285.     return ((CMSize)amountRead);
  286. }
  287.  
  288. CMSize ODFSBentoHandlers::WriteHandler(CMPtr buffer, CMSize elementSize, CMCount theCount)
  289. {
  290.     ODULong            endOfWrite, newEndOfFile, beginWriteBlock, toMove, theGap;
  291.     ODSLong            labelSize, amountWritten;
  292.     ODBoolean        needToWrite;
  293.     
  294.     if (theCount > 0) {    
  295.     
  296.         amountWritten = elementSize * theCount;
  297.         endOfWrite = fLogicalPos + amountWritten;
  298.         beginWriteBlock = fLogicalPos & ChunkHighBitsMask;
  299.         needToWrite = kODTrue;
  300.  
  301.         if ((beginWriteBlock == ((endOfWrite-1) & ChunkHighBitsMask)) && (beginWriteBlock != fBufferBegin)) {
  302.             /* changes are all in a single buffer but data not loaded, load it now */
  303.             this->ReloadBuffer();
  304.         }
  305.  
  306.         if (fBufferBegin != kInvalidBuffer) { /* we have a buffer */
  307.             if (fLogicalPos < fBufferBegin) { /* the tail of the write may touch the buffer */
  308.                 if (endOfWrite > fBufferBegin) { /* yes, the tail touches the buffer */
  309.                     /*
  310.                     
  311.                         fLogicalPos     fBufferBegin      endOfWrite
  312.                              |              |                 |       |
  313.                                             <-       ChunkSize      ->
  314.                                             <-  toMove      ->
  315.                     */
  316.                     toMove = endOfWrite - fBufferBegin;  /* move so many bytes into the buffer */
  317.                     if (toMove > fChunkSize)             /* but no larger than the buffer itself */
  318.                         toMove = fChunkSize;
  319.                     /* update the part of the buffer that has been changed */
  320.                     ODBlockMove((char *)buffer+fBufferBegin-fLogicalPos, fBuffer, toMove);
  321.                     /* note that we do not need to dirty it because we still write it out */
  322.                 }
  323.             }
  324.             else { /* the front part of the write may touch the buffer */
  325.                 theGap = fLogicalPos - fBufferBegin;
  326.                 if (theGap < fChunkSize) { /* yes, it does touch the buffer */
  327.                     /*
  328.                     
  329.                         fBufferBegin    fLogicalPos            endOfWrite
  330.                              |               |        |            |
  331.                              <-       ChunkSize      ->
  332.                              <-   theGap    ->
  333.                                              <-   amountWritten   ->
  334.                                              <-toMove->
  335.  
  336.                     */
  337.                     toMove = amountWritten;
  338.                     if (toMove + theGap > fChunkSize)
  339.                         toMove = fChunkSize - theGap;
  340.                     else {
  341.                         fBufferDirty = kODTrue; /* dirty it so we would write it out later */
  342.                         needToWrite = kODFalse;    /* for now, no writing is necessary */
  343.                     }
  344.                     ODBlockMove(buffer, fBuffer + theGap, toMove); /* update the buffer */
  345.                 }
  346.             }
  347.         }
  348.          
  349.         if (endOfWrite > fFileSize) { /* we are appending */
  350.             if (endOfWrite > fWriteLimit) {
  351.                 ODSLong    newWriteLimit;
  352.                 /* extend it to block boundry */
  353.                 newEndOfFile = ((endOfWrite + fChunkSize)) & ChunkHighBitsMask;
  354.                 if (fHasLabel != kODFalse) {
  355.                     /* must have enough room to end of file to fit in a label */
  356.                     if ((newEndOfFile - endOfWrite) < sizeof(ContainerLabelFmt))
  357.                         newEndOfFile = newEndOfFile + fChunkSize;
  358.                     newWriteLimit = newEndOfFile - sizeof(ContainerLabelFmt);
  359.                 }
  360.                 else
  361.                     newWriteLimit = newEndOfFile;
  362.                 /* We will add at least another block to file, so we need a new label at end */
  363.                 fFile->SetEndOfFile(newEndOfFile);
  364.                 fPhysicalFileSize = newEndOfFile;
  365.                 fWriteLimit = newWriteLimit;
  366.                 if (fHasLabel != kODFalse) {
  367.                     if ((fWriteLimit & ChunkHighBitsMask) == fBufferBegin) {
  368.                         /* the label at the end will overlap with the buffer, put it in the buffer */
  369.                         ODBlockMove(&fLabel, fBuffer + fChunkSize - sizeof(ContainerLabelFmt), sizeof(ContainerLabelFmt));
  370.                     }
  371.                     fFile->SetFilePos(fsFromStart, fWriteLimit);
  372.                     labelSize = sizeof(ContainerLabelFmt);
  373.                     TRY
  374.                         fFile->Write((const ODSByte*)&fLabel, &labelSize);
  375.                         /* if fails, no safety label at end of end, that is not end of the world */
  376.                     ENDTRY
  377.                 }
  378.             }
  379.             fFileSize = endOfWrite;
  380.         }
  381.         if (needToWrite != kODFalse) {
  382.             fFile->SetFilePos(fsFromStart, fLogicalPos);
  383.             fFile->Write((const ODSByte*)buffer, &amountWritten);
  384.         }
  385.         fLogicalPos = endOfWrite;
  386.     } else
  387.         amountWritten = 0;
  388.  
  389.     return ((CMSize)amountWritten);
  390. }
  391.  
  392. void ODFSBentoHandlers::FlushBuffer()
  393. {
  394.     ODSLong        theSize = fChunkSize;    
  395.  
  396.     fFile->SetFilePos(fsFromStart, fBufferBegin);
  397.     if (fPhysicalFileSize - fBufferBegin < fChunkSize)
  398.         theSize = fPhysicalFileSize - fBufferBegin;
  399.     fFile->Write(fBuffer, &theSize);
  400.     fBufferDirty = kODFalse;
  401. }
  402.  
  403. void ODFSBentoHandlers::ReloadBuffer()
  404. {
  405.     ODSLong        theSize;    
  406.  
  407.     if (fBufferDirty != kODFalse)
  408.         this->FlushBuffer();
  409.     fBufferBegin = fLogicalPos & ChunkHighBitsMask;
  410.     fFile->SetFilePos(fsFromStart, fBufferBegin);
  411.     theSize = fChunkSize;
  412.     if (fPhysicalFileSize - fBufferBegin < fChunkSize)
  413.         theSize = fPhysicalFileSize - fBufferBegin;
  414.     fFile->Read(fBuffer, &theSize);
  415. }
  416.  
  417. CMEofStatus ODFSBentoHandlers::EOFHandler()
  418. {
  419.     return ((CMEofStatus) kODFalse);
  420.  
  421. }
  422.  
  423. CMBoolean ODFSBentoHandlers::TruncHandler(CMSize containerSize)
  424. {
  425.     fFileSize = containerSize;        
  426.     return kODTrue;
  427. }
  428.  
  429. CMSize ODFSBentoHandlers::ContainerSizeHandler()
  430. {
  431.     return ((CMSize) fFileSize);
  432. }
  433.  
  434. void ODFSBentoHandlers::ReadLabelHandler(CMMagicBytes magicByteSequence,
  435.                                      CMContainerFlags *flags, CM_USHORT *bufSize,
  436.                                      CM_USHORT *majorVersion, CM_USHORT *minorVersion,
  437.                                      CMSize *tocOffset, CMSize *tocSize)
  438. {
  439.     ODULong        endOfTOC, tempFileEnd;
  440.     char *magicSequence = "\xA4""CM""\xA5""Hdr""\xD7";        /* Must be 8 characters        */
  441.     ODBoolean         labelMatches = fHasLabel;
  442.  
  443.     /* Seek to the end of the label at the end of the container and read it...*/
  444.     
  445.     tempFileEnd = fFileSize;
  446.     while (tempFileEnd > sizeof(ContainerLabelFmt)) {
  447.         fLogicalPos = tempFileEnd - sizeof(ContainerLabelFmt);
  448.         /* if we really want to speed it up, we could compare it directly from the buffer     */
  449.         /* but since we only need to loop through this in corrupted file and that does not    */
  450.         /* occur very often, and even when it happens, the current speed is acceptable          */
  451.         /* so we would leave it as it is now                                                */
  452.         if (this->ReadHandler((CMPtr)&fLabel, (CMSize)sizeof(unsigned char), 8) !=  8)
  453.                 THROW(kODErrBentoErr);
  454.         if (memcmp(&fLabel.magicBytes, magicSequence, 8) == 0)
  455.             labelMatches = kODTrue;
  456.         if (labelMatches) {
  457.             /* Return all the label info... */
  458.             fLogicalPos = tempFileEnd - sizeof(ContainerLabelFmt);
  459.             if (this->ReadHandler((CMPtr)&fLabel, 
  460.                                   (CMSize)sizeof(unsigned char), 
  461.                                   sizeof(ContainerLabelFmt)) !=  sizeof(ContainerLabelFmt))
  462.                     THROW(kODErrBentoErr);
  463.             ODBlockMove(&fLabel.magicBytes, magicByteSequence, 8);
  464. #if kCMDefaultEndian
  465.             /* little endian machine */
  466.             if ((fLabel.flags & kCMLittleEndianTwin) == 0) {
  467. #else
  468.             /* big endian machine */
  469.             if (fLabel.flags & kCMLittleEndianTwin) {
  470. #endif
  471.                 fReverseEndian = kODTrue;
  472.                 *flags = ODFlipShort(fLabel.flags);
  473.                 *bufSize = ODFlipShort(fLabel.bufSize);
  474.                 *majorVersion = ODFlipShort(fLabel.majorVersion);
  475.                 *minorVersion = ODFlipShort(fLabel.minorVersion);
  476.                 *tocOffset = ODFlipLong(fLabel.tocOffset);
  477.                 *tocSize = ODFlipLong(fLabel.tocSize);
  478.             }
  479.             else {
  480.                 fReverseEndian = kODFalse;
  481.                 *flags = (CMContainerFlags)fLabel.flags;
  482.                 *bufSize = (CM_USHORT)fLabel.bufSize;
  483.                 *majorVersion = (CM_USHORT)fLabel.majorVersion;
  484.                 *minorVersion = (CM_USHORT)fLabel.minorVersion;
  485.                 *tocOffset = (CMSize)fLabel.tocOffset;
  486.                 *tocSize = (CMSize)fLabel.tocSize;
  487.             }
  488.             endOfTOC = *tocOffset + *tocSize + sizeof(ContainerLabelFmt);
  489.             if (endOfTOC == tempFileEnd) {
  490.                 /* match exactly, this is most likely to be the label */
  491.                 if (endOfTOC != fFileSize) {
  492. #if ODDebug
  493.                     WARN("The file was corrupted! I will just do my best to read it");
  494. #endif
  495.                     fFileSize = endOfTOC;
  496.                 }
  497.                 fHasLabel = kODTrue;
  498.                 break;
  499.             }
  500.             if (endOfTOC < tempFileEnd) {
  501.                 ContainerLabelFmt tempLabel;
  502.                 fLogicalPos = endOfTOC - sizeof(ContainerLabelFmt);
  503.                 if (this->ReadHandler((CMPtr)&tempLabel, 
  504.                                       (CMSize)sizeof(unsigned char), 
  505.                                       sizeof(ContainerLabelFmt)) !=  sizeof(ContainerLabelFmt))
  506.                     THROW(kODErrBentoErr);
  507.                 if (memcmp(&tempLabel, &fLabel, sizeof(ContainerLabelFmt)) == 0) {
  508. //#if ODDebug
  509. //                    WARN("The file was not closed properly! You get away with it this time");
  510. //#endif
  511.                     /* we passed the sanity check, so we can truncate the file and use the label */
  512.                     fFileSize = endOfTOC;
  513.                     fHasLabel = kODTrue;
  514.                     break;
  515.                 }
  516.                 /* even if we did not pass the test, if the label was at the end, still accept it */
  517.                 if (tempFileEnd == fFileSize) {
  518. #if ODDebug
  519.                     WARN("File looks funny! Send a copy to Bento folks");
  520. #endif
  521.                     fHasLabel = kODTrue;
  522.                     break;
  523.                 }
  524.             }
  525.         } /* it is a label */
  526.         /* otherwise keep scanning backwards */
  527.         labelMatches = kODFalse;
  528.         tempFileEnd -= 1;
  529.     }
  530.     if (fHasLabel) {
  531.         fPhysicalFileSize = fFileSize;
  532.         fWriteLimit = fFileSize;
  533.         if ((fOpenReadOnly == kODFalse) && (fFile->GetEndOfFile() != fFileSize)) {
  534.             fFile->SetEndOfFile(fFileSize);        /* get back the correct size */
  535.         }
  536.     }
  537. #if ODDebug
  538.     else
  539.         WARN("File has no valid Bento label. Cannot be recovered");
  540. #endif
  541. }
  542.  
  543. void ODFSBentoHandlers::WriteLabelHandler(CMMagicBytes magicByteSequence,
  544.                                         CMContainerFlags flags, CM_USHORT bufSize,
  545.                                         CM_USHORT majorVersion, CM_USHORT minorVersion,
  546.                                         CMSize tocOffset, CMSize tocSize)
  547. {
  548.     ODULong                labelSize;
  549.     ContainerLabelFmt    theLabel;
  550.         
  551.     /* Fill in the label buffer with the info...                                                                                    */
  552.     
  553.     flags = (CMContainerFlags) ((CM_USHORT)flags & ~kCMLittleEndianTwin);    /* ignore what is passed in */
  554.     if (fReverseEndian) {
  555.         theLabel.flags = ODFlipShort(flags | (kCMLittleEndianTwin & ~kCMDefaultEndian));
  556.         theLabel.bufSize = ODFlipShort(bufSize);
  557.         theLabel.majorVersion = ODFlipShort(majorVersion); 
  558.         theLabel.minorVersion = ODFlipShort(minorVersion);
  559.         theLabel.tocOffset = ODFlipLong(tocOffset);
  560.         theLabel.tocSize = ODFlipLong(tocSize);
  561.     }
  562.     else {
  563.         theLabel.flags = (ODUShort)(flags | kCMDefaultEndian);
  564.         theLabel.bufSize = (ODUShort)bufSize;
  565.         theLabel.majorVersion = (ODUShort)majorVersion; 
  566.         theLabel.minorVersion = (ODUShort)minorVersion;
  567.         theLabel.tocOffset = (ODULong)tocOffset;
  568.         theLabel.tocSize = (ODULong)tocSize;
  569.     }
  570.     
  571.     ODBlockMove(magicByteSequence, theLabel.magicBytes, 8);
  572.  
  573.     /* Write the label to the end of the container value...                                                                */
  574.     
  575.     this->SeekHandler(0, kCMSeekEnd);
  576.     labelSize = (unsigned long)this->WriteHandler((CMPtr)&theLabel,
  577.                                             (CMSize)sizeof(unsigned char),
  578.                                             (CMCount)sizeof(ContainerLabelFmt));
  579.     
  580.     if (labelSize != sizeof(ContainerLabelFmt))
  581.         THROW(kODErrBentoErr);
  582.  
  583.     ODBlockMove(&theLabel, &fLabel, sizeof(ContainerLabelFmt));
  584.     fHasLabel = kODTrue;
  585.     fPhysicalFileSize = fFileSize;
  586.     fWriteLimit = fFileSize;
  587.     fFile->SetEndOfFile(fFileSize);        /* get back the correct size */
  588. }
  589.  
  590. CMValue ODFSBentoHandlers::ReturnParentValueHandler()
  591. {
  592.     return kODNULL;
  593. }
  594.  
  595. CM_UCHAR* ODFSBentoHandlers::ReturnContainerNameHandler()
  596. {
  597.     static Str63    name;
  598.     
  599.     fFile->GetAsciiName((char*)name,sizeof(name));
  600.     return ((CM_UCHAR *) name);
  601. }
  602.  
  603. CMType ODFSBentoHandlers::ReturnTargetTypeHandler(CMContainer container)
  604. {
  605. ODUnused(container);
  606.  
  607.     return kODNULL;
  608. }
  609.  
  610. void ODFSBentoHandlers::ExtractDataHandler(CMDataBuffer buffer,
  611.                                                  CMSize size, CMPrivateData data)
  612. {
  613.     ODBoolean    reverseEndian = fReverseEndian;
  614.     
  615.     if ((CM_LONG)size < 0) {    /* this means it is endian-ness netural    */
  616.         size = -(CM_LONG)size;
  617.         reverseEndian = kODFalse;
  618.     }
  619.     
  620.     if (reverseEndian)
  621.         ODFlipMove(buffer, data, (size_t)size);
  622.     else
  623.         ODBlockMove(buffer, data, (size_t)size);
  624. }
  625.  
  626. void ODFSBentoHandlers::FormatDataHandler(CMDataBuffer buffer,
  627.                                      CMSize size, CMPrivateData data)
  628. {
  629.     ODBoolean    reverseEndian = fReverseEndian;
  630.     
  631.     if ((CM_LONG)size < 0) {    /* this means it is endian-ness netural    */
  632.         size = -(CM_LONG)size;
  633.         reverseEndian = kODFalse;
  634.     }
  635.     
  636.     if (reverseEndian)
  637.         ODFlipMove(data, buffer, (size_t)size);
  638.     else
  639.         ODBlockMove(data, buffer, (size_t)size);
  640. }
  641.