OS390PlatformUtils.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:35k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: OS390PlatformUtils.cpp,v 1.10 2003/05/15 18:37:48 knoaman Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #ifdef OS390
  63. #define _OPEN_SYS
  64. #endif
  65. #ifndef APP_NO_THREADS
  66. #include    <pthread.h>
  67. #endif
  68. #include    <xercesc/util/PlatformUtils.hpp>
  69. #include    <xercesc/util/RuntimeException.hpp>
  70. #include    <xercesc/util/Janitor.hpp>
  71. #include    <stdio.h>
  72. #include    <stdlib.h>
  73. #include    <errno.h>
  74. #include    <libgen.h>
  75. #ifdef EXM_OS390
  76. #include    <timeb.h>
  77. #else
  78. #include    <sys/timeb.h>
  79. #endif
  80. #include    <string.h>
  81. #include    <unistd.h>
  82. #include    <limits.h>
  83. #include    <xercesc/util/XMLString.hpp>
  84. #include    <xercesc/util/XMLUniDefs.hpp>
  85. #include    <xercesc/util/XMLUni.hpp>
  86. #include    <xercesc/util/PanicHandler.hpp>
  87. #include    "Path390.hpp"
  88. #include    "FileHandleImpl.hpp"
  89. #if defined (XML_USE_ICU_TRANSCODER)
  90.     #include <xercesc/util/Transcoders/ICU/ICUTransService.hpp>
  91. #elif defined (XML_USE_UNICONV390_TRANSCODER)
  92.     #include <xercesc/util/Transcoders/Uniconv390/Uniconv390TransService.hpp>
  93. #else   // use native transcoder
  94.     #include <xercesc/util/Transcoders/Iconv390/Iconv390TransService.hpp>
  95. #endif
  96. #if defined (XML_USE_ICU_MESSAGELOADER)
  97.     #include <xercesc/util/MsgLoaders/ICU/ICUMsgLoader.hpp>
  98. #elif defined (XML_USE_ICONV_MESSAGELOADER)
  99.     #include <xercesc/util/MsgLoaders/MsgCatalog/MsgCatalogLoader.hpp>
  100. #else   // use In-memory message loader
  101.     #include <xercesc/util/MsgLoaders/InMemory/InMemMsgLoader.hpp>   //hint for the user to include this file.
  102. #endif
  103. #if defined (XML_USE_NETACCESSOR_SOCKET)
  104.     #include <xercesc/util/NetAccessors/Socket/SocketNetAccessor.hpp>
  105. #endif
  106. XERCES_CPP_NAMESPACE_BEGIN
  107. // ---------------------------------------------------------------------------
  108. //  Static data
  109. // ---------------------------------------------------------------------------
  110. static bool isPosixEnabled = false;
  111. // ---------------------------------------------------------------------------
  112. //  XMLPlatformUtils: Platform init method
  113. // ---------------------------------------------------------------------------
  114. void XMLPlatformUtils::platformInit()
  115. {
  116. // The next conditional section is to turn on support for allowing
  117. // the NEL character as a valid whitespace character. Once this is
  118. // enabled the parser is non-compliant with the XML standard.
  119. // Assumption: Once this is enabled, it cannot be reset and
  120. // should remain the same during the same process.
  121. #if defined XML_ALLOW_NELWS
  122.    try
  123.    {
  124.      XMLPlatformUtils::recognizeNEL(true);
  125.    }
  126.    catch (...)
  127.    {
  128.       panic(PanicHandler::Panic_SystemInit);
  129.    }
  130. #endif
  131. // The next section checks if Posix is enabled on the OS/390 system.
  132. // It stores the result in the static isPosixEnabled flag.
  133. // The __isPosixOn() native routine uses too much
  134. // overhead to call repeatedly at runtime so this will be the only
  135. // remaining call of it.
  136. // Assumption: Once this is enabled, it cannot be reset and
  137. // should remain the same during the same process.
  138.    try
  139.    {
  140.       if (__isPosixOn())
  141.       {
  142.         if (!isPosixEnabled)
  143.             isPosixEnabled = true;
  144.       }
  145.    }
  146.    catch (...)
  147.    {
  148.       panic(PanicHandler::Panic_SystemInit);
  149.    }
  150. }
  151. // ---------------------------------------------------------------------------
  152. //  XMLPlatformUtils: Private Static Methods
  153. // ---------------------------------------------------------------------------
  154. XMLNetAccessor* XMLPlatformUtils::makeNetAccessor()
  155. {
  156. #if defined (XML_USE_NETACCESSOR_SOCKET)
  157.     return new SocketNetAccessor();
  158. #else
  159.     return 0;
  160. #endif
  161. }
  162. //
  163. //  This method is called by the platform independent part of this class
  164. //  when client code asks to have one of the supported message sets loaded.
  165. //  In our case, we use the ICU based message loader mechanism.
  166. //
  167. XMLMsgLoader* XMLPlatformUtils::loadAMsgSet(const XMLCh* const msgDomain)
  168. {
  169.     XMLMsgLoader* retVal;
  170.     try
  171.     {
  172. #if defined (XML_USE_ICU_MESSAGELOADER)
  173.         retVal = new ICUMsgLoader(msgDomain);
  174. #elif defined (XML_USE_ICONV_MESSAGELOADER)
  175.         retVal = new MsgCatalogLoader(msgDomain);
  176. #else
  177.         retVal = new InMemMsgLoader(msgDomain);
  178. #endif
  179.     }
  180.     catch(...)
  181.     {
  182.    panic(PanicHandler::Panic_CantLoadMsgDomain);
  183.     }
  184.     return retVal;
  185. }
  186. //
  187. //  This method is called very early in the bootstrapping process. This guy
  188. //  must create a transcoding service and return it. It cannot use any string
  189. //  methods, any transcoding services, throw any exceptions, etc... It just
  190. //  makes a transcoding service and returns it, or returns zero on failure.
  191. //
  192. XMLTransService* XMLPlatformUtils::makeTransService()
  193. #if defined (XML_USE_ICU_TRANSCODER)
  194. {
  195.     return new ICUTransService;
  196. }
  197. #elif defined (XML_USE_UNICONV390_TRANSCODER)
  198. {
  199.     return new Uniconv390TransService;
  200. }
  201. #else
  202. {
  203.     return new Iconv390TransService;
  204. }
  205. #endif
  206. // ---------------------------------------------------------------------------
  207. //  XMLPlatformUtils: The panic method
  208. // ---------------------------------------------------------------------------
  209. void XMLPlatformUtils::panic(const PanicHandler::PanicReasons reason)
  210. {
  211.     fgUserPanicHandler? fgUserPanicHandler->panic(reason) : fgDefaultPanicHandler->panic(reason);
  212. }
  213. // ---------------------------------------------------------------------------
  214. //  Local Functions
  215. // ---------------------------------------------------------------------------
  216. static void emptyBuffer(XMLByte* writeBuffer,
  217.                         size_t   bytesToWrite,
  218.                         FileHandleImpl* fhiPtr)
  219. {
  220.      FILE* fileHandle = (FILE*)fhiPtr->getHandle();
  221.      size_t bytesThisWrite = 0;
  222.      size_t bytesThisPass = 0;
  223.      int typeRecordLrecl = 0;
  224.      bool isTypeRecord = fhiPtr->isRecordType();
  225.      if (isTypeRecord)
  226.         typeRecordLrecl = fhiPtr->getLrecl();
  227.      // Try to write as many bytes as possible at a time to the file.
  228.      // If less than the total bytes were written then loop as many times
  229.      // as necessary until all bytes are written. For the case of
  230.      // an MVS dataset with "type=record" specified, we must not
  231.      // attempt to write more than one logical record at a time
  232.      // or it will fail and not return the number of bytes remaining.
  233.      while (bytesToWrite > 0)
  234.      {
  235.         if ((isTypeRecord) &&
  236.             (bytesToWrite > typeRecordLrecl))
  237.         {
  238.            bytesThisPass = typeRecordLrecl;
  239.         }
  240.         else
  241.            bytesThisPass = bytesToWrite;
  242.         bytesThisWrite = fwrite(writeBuffer, sizeof(XMLByte), bytesThisPass, fileHandle);
  243.         if (ferror(fileHandle))
  244.            ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotWriteToFile);
  245.         bytesToWrite -= bytesThisWrite;
  246.         writeBuffer += bytesThisWrite;
  247.      }  // while (bytesToWrite > 0)
  248.   return;
  249. }
  250. static FileHandleImpl* openRead(char* tmpFileName)
  251. {
  252.      FileHandleImpl* retVal;
  253.      FILE* fileHandle = 0;
  254.      Path390 pathobj;
  255.      pathobj.setPath(tmpFileName);
  256.      int optionBufferSize = strlen("rb,");
  257.      // Check if we have fopen options specified in addition to a
  258.      // filename. If we do then we need to build a buffer that has
  259.      // "rb," followed by the options. Otherwise we just pass "rb"
  260.      // in as the options.
  261.      if (pathobj.getfopenParms())
  262.      {
  263.         optionBufferSize += (strlen(pathobj.getfopenParms()) + 1);
  264.      }
  265.      char* optionBuffer = (char*) fgMemoryManager->allocate(optionBufferSize * sizeof(char));//new char[optionBufferSize];
  266.      ArrayJanitor<char> janText((char*)optionBuffer, fgMemoryManager);
  267.      strcpy(optionBuffer,"rb");
  268.      // Build the options buffer
  269.      if (pathobj.getfopenParms())
  270.      {
  271.         strcpy(optionBuffer + 2, ",");
  272.         strcpy(optionBuffer + 3, pathobj.getfopenParms());
  273.      }
  274.      // If we don't have a valid path specified just exit now
  275.      if (pathobj.getfopenPath() == NULL)
  276.         return 0;
  277.      // Take the file handle returned by fopen and create an instance
  278.      // of the FileHandleImpl class.
  279.      fileHandle = fopen(pathobj.getfopenPath(), optionBuffer);
  280.      retVal = new FileHandleImpl(fileHandle, _FHI_READ, pathobj.isRecordType());
  281.      // temp fix for HFS files with "type=record" specified
  282.      // close the file and re-open it without the fopen options
  283.      // since they don't work too well with HFS files.
  284.      if ((pathobj.isRecordType()) && (fileHandle != NULL))
  285.      {
  286.         int fldata_rc = 0;
  287.         fldata_t fileinfo;
  288.         fldata_rc = fldata(fileHandle, pathobj.getfopenPath(), &fileinfo);
  289.         if (fldata_rc)
  290.            ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile);
  291.         if (fileinfo.__dsorgHFS)
  292.         {
  293.            if (fclose(fileHandle))
  294.               ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile);
  295.            fileHandle=fopen(pathobj.getfopenPath(), "rb");
  296.            retVal->setHandle(fileHandle);
  297.            retVal->setRecordType(_FHI_NOT_TYPE_RECORD);
  298.         }
  299.      }
  300.      // End temp fix ......
  301.     if ((fileHandle == NULL) && (pathobj.getPathType() == PATH390_OTHER)) {
  302.     //
  303.     // We failed to open the file using its native format (OE or MVS)
  304.     // Try to go an extra step to map the path into a MVS dataset under BATCH:
  305.     //
  306.     //     /path/path2/filename.ext => //'path.path2.ext(filename)'
  307.     //     /path/path2/filename     => //'path.path2.filename'
  308.     // and
  309.     //     path/path2/filename.ext  => //path.path2.ext(filename)
  310.     //     path/path2/filename      => //path.path2.filename
  311.     char* datasetName = (char*) fgMemoryManager->allocate
  312.     (
  313.         (strlen(tmpFileName) + 5) * sizeof(char)
  314.     );//new char[ strlen(tmpFileName) + 5 ];
  315.     ArrayJanitor<char> janText1((char*)datasetName, fgMemoryManager);
  316.     char *datasetPos = datasetName, *tmpPos = tmpFileName;
  317.     // We are in EBCDIC mode here
  318.     // Specify "//" to indicate that the filename refers to a non-POSIX file
  319.     // or a MVS data set
  320.     strcpy(datasetName, "//");
  321.     datasetPos += 2;
  322.     // If we have a leading '/' then the path is absolute
  323.     if( *tmpPos == '/' ) {
  324.         *datasetPos++ = ''';
  325.         tmpPos++;
  326.     }
  327.     // Find the last '/' in the path - this seperates the path from the
  328.     // filename.  Then copy the pathname.
  329.     char* pathEnd = strrchr( tmpPos, '/' );
  330.     if( pathEnd == NULL ) pathEnd = tmpPos - 1;
  331.     while( tmpPos <= pathEnd ) {
  332.         switch( *tmpPos ) {
  333.                 case '/':
  334.                         *datasetPos = '.';
  335.                         break;
  336.                 default:
  337.                         *datasetPos = *tmpPos;
  338.         }
  339.         datasetPos++; tmpPos++;
  340.     }
  341.     // Now we try to locate the extension, and copy that.
  342.     char* extStart = strrchr( tmpFileName, '.' );
  343.     if ( extStart != NULL ) {
  344.         tmpPos = extStart + 1;
  345.         while( *tmpPos != '' ) {
  346.                 *datasetPos++ = *tmpPos++;
  347.         }
  348.         *datasetPos++ = '(';
  349.     }
  350.     // Now we copy in the filename.
  351.     tmpPos = pathEnd + 1;
  352.     while( *tmpPos != '' && ((extStart == NULL) || (tmpPos < extStart)) ) {
  353.         *datasetPos++ = *tmpPos++;
  354.     }
  355.     // Finally cap off the filename with optional ")" and "'", plus a null
  356.     if( extStart != NULL ) *datasetPos++ = ')';
  357.     if( *tmpFileName == '/' ) *datasetPos++ = ''';
  358.     *datasetPos = '';
  359.     fileHandle = fopen( datasetName , optionBuffer);
  360.     retVal->setHandle(fileHandle);
  361.     }
  362.     // fix for file:// protocol
  363.     // the tmpFileName has a prefix of //absolute path
  364.     // for example, file:////u/.... instead of file:///u/....
  365.     // the fopen() on OS/390 cannot open a //u/... POSIX file
  366.     if ((fileHandle == NULL) && (pathobj.getPathType() == PATH390_OTHER))
  367.     {
  368.        if ((tmpFileName[0] == '/') && (tmpFileName[1] == '/'))
  369.         {
  370.             char *srcName = tmpFileName + 1; // points past the first '/'
  371.             fileHandle = fopen(srcName , optionBuffer);
  372.             retVal->setHandle(fileHandle);
  373.             // temp fix for HFS files with type=record specified
  374.             // close the file and re-open it without the fopen options
  375.             // since they don't work too well with HFS files.
  376.             if (pathobj.isRecordType())
  377.             {
  378.                int fldata_rc = 0;
  379.                fldata_t fileinfo;
  380.                fldata_rc = fldata(fileHandle, srcName, &fileinfo);
  381.                if (fldata_rc)
  382.                  ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile);
  383.                if (fileinfo.__dsorgHFS)
  384.                {
  385.                   if (fclose(fileHandle))
  386.                      ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile);
  387.                   fileHandle=fopen(srcName, "rb");
  388.                   retVal->setHandle(fileHandle);
  389.                   retVal->setRecordType(_FHI_NOT_TYPE_RECORD);
  390.                }
  391.             }
  392.             // End temp fix ......
  393.    }
  394.     }
  395.     // If the fopen failed we have a pointer to the FileHandleImpl class but
  396.     // inside that class a file handle of NULL. In this case we need to delete
  397.     // the class and return a NULL to the caller since they should be checking
  398.     // for a NULL returned as a file open failed indicator.
  399.     if (fileHandle == NULL)
  400.     {
  401.        delete retVal;
  402.        retVal = 0;
  403.     }
  404.     return retVal;
  405. }
  406. static FileHandleImpl* openWrite(char* tmpFileName)
  407. {
  408.     FileHandleImpl* retVal;
  409.     FILE* fileHandle = 0;
  410.     Path390 pathobj;
  411.     pathobj.setPath(tmpFileName);
  412.     fldata_t fileinfo;
  413.     int fldata_rc = 0;
  414.     int optionBufferSize = strlen("wb,");
  415.     int fileLrecl = 0;
  416.     bool isTypeRecord = _FHI_NOT_TYPE_RECORD;
  417.     // Check if we have fopen options specified in addition to a
  418.     // filename. If we do then we need to build a buffer that has
  419.     // "wb," followed by the options. Otherwise we just pass "wb"
  420.     // in as the options.
  421.     if (pathobj.getfopenParms())
  422.        optionBufferSize += (strlen(pathobj.getfopenParms()) + 1);
  423.     char* optionBuffer = (char*) fgMemoryManager->allocate((optionBufferSize) * sizeof(char));//new char[optionBufferSize];
  424.     ArrayJanitor<char> janText((char*)optionBuffer, fgMemoryManager);
  425.     strcpy(optionBuffer,"wb");
  426.     // Build the options buffer
  427.     if (pathobj.getfopenParms())
  428.     {
  429.        strcpy(optionBuffer + 2, ",");
  430.        strcpy(optionBuffer + 3, pathobj.getfopenParms());
  431.     }
  432.     // FileHandleImpl class. The constructor will allocate our staging
  433.     // buffer if it is a "type=record" open.
  434.     fileHandle = fopen(pathobj.getfopenPath(),optionBuffer);
  435.     // If this is a "type=record" open then we need to determine the
  436.     // LRECL of the file. The fldata info will have this in it.
  437.     // We save this in the FileHandleImpl class for use on subsequent
  438.     // writes to the file.
  439.     if (pathobj.isRecordType())
  440.     {
  441.        isTypeRecord = _FHI_TYPE_RECORD;
  442.        fldata_rc = fldata(fileHandle, pathobj.getfopenPath(), &fileinfo);
  443.        if (fldata_rc)
  444.           ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotWriteToFile);
  445.        fileLrecl = fileinfo.__maxreclen;
  446.        // temp fix for HFS files
  447.        // close the file and re-open it without the fopen options
  448.        // since they don't work too well with HFS files.
  449.        if (fileinfo.__dsorgHFS)
  450.        {
  451.           if (fclose(fileHandle))
  452.             ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile);
  453.           fileHandle=fopen(pathobj.getfopenPath(), "wb");
  454.        }
  455.       // end temp fix
  456.     }
  457.     // If the fopen failed we won't need to create an instance of the
  458.     // FileHandleImpl class .... just return a NULL wich the caller recognizes
  459.     // as a failure. If we have a valid file handle then we'll build create
  460.     // an instance of the class and return that to the caller.
  461.     if (fileHandle == NULL)
  462.        retVal = 0;
  463.     else
  464.        retVal = new FileHandleImpl(fileHandle, _FHI_WRITE, isTypeRecord,fileLrecl);
  465.     return retVal;
  466. }
  467. // ---------------------------------------------------------------------------
  468. //  XMLPlatformUtils: File Methods
  469. // ---------------------------------------------------------------------------
  470. unsigned int XMLPlatformUtils::curFilePos(FileHandle theFile)
  471. {
  472.     // Get the current position
  473.     FileHandleImpl* fhiPtr = (FileHandleImpl*) theFile;
  474.     FILE* fileHandle = (FILE*)fhiPtr->getHandle();
  475.     int curPos = ftell(fileHandle);
  476.     if (curPos == -1)
  477.        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetSize);
  478.     return (unsigned int)curPos;
  479. }
  480. void XMLPlatformUtils::closeFile(FileHandle theFile)
  481. {
  482.     FileHandleImpl* fhiPtr = (FileHandleImpl*) theFile;
  483.     FILE* fileHandle = (FILE*)fhiPtr->getHandle();
  484.     // We need to handle a close differently if this was a
  485.     // "type=record" open. In that case we may have data sitting in
  486.     // the staging buffer that is waiting to be written to the file.
  487.     // In this case write that data to the file before we actually
  488.     // close it.
  489.     if ( (fhiPtr->getOpenType() == _FHI_WRITE) &&
  490.          (fhiPtr->isRecordType())  &&
  491.          (fhiPtr->getNextByte()) )
  492.     {
  493.         XMLByte* tmpFlush = fhiPtr->getStgBufferPtr();
  494.         size_t bytesToWrite = fhiPtr->getNextByte();
  495.         emptyBuffer(tmpFlush, bytesToWrite,fhiPtr);
  496.     }
  497.     // Do the regular close stuff ....
  498.     if (fclose(fileHandle))
  499.        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile);
  500.     // Delete the instance of the FileHandleImpl class (this will free the
  501.     // staging buffer for us)
  502.     delete fhiPtr;
  503. }
  504. unsigned int XMLPlatformUtils::fileSize(FileHandle theFile)
  505. {
  506.     // Get the current position
  507.     FileHandleImpl* fhiPtr = (FileHandleImpl*) theFile;
  508.     FILE* fileHandle = (FILE*)fhiPtr->getHandle();
  509.     long  int curPos = ftell(fileHandle);
  510.     if (curPos == -1)
  511.        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos);
  512.     // Seek to the end and save that value for return
  513.      if (fseek(fileHandle, 0, SEEK_END))
  514.         ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToEnd);
  515.     long int retVal = ftell(fileHandle);
  516.     if (retVal == -1)
  517.        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToEnd);
  518.     // And put the pointer back
  519.     if (fseek(fileHandle, curPos, SEEK_SET) )
  520.        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToPos);
  521.     return (unsigned int)retVal;
  522. }
  523. FileHandle XMLPlatformUtils::openFile(const XMLCh* const fileName)
  524. {
  525.     char* tmpFileName = XMLString::transcode(fileName, fgMemoryManager);
  526.     ArrayJanitor<char> janText((char*)tmpFileName, fgMemoryManager);
  527.     return openRead(tmpFileName);
  528. }
  529. FileHandle XMLPlatformUtils::openFile(const char* const fileName)
  530. {
  531.     char* tmpFileName = (char*) fgMemoryManager->allocate
  532.     (
  533.         (strlen(fileName) + 1) * sizeof(char)
  534.     );//new char[strlen(fileName) + 1];
  535.     ArrayJanitor<char> janText((char*)tmpFileName, fgMemoryManager);
  536.     strcpy(tmpFileName,fileName);
  537.     return openRead(tmpFileName);
  538. }
  539. FileHandle XMLPlatformUtils::openFileToWrite(const XMLCh* const fileName)
  540. {
  541.     char* tmpFileName = XMLString::transcode(fileName, fgMemoryManager);
  542.     ArrayJanitor<char> janText((char*)tmpFileName, fgMemoryManager);
  543.     return openWrite(tmpFileName);
  544. }
  545. FileHandle XMLPlatformUtils::openFileToWrite(const char* const fileName)
  546. {
  547.     char* tmpFileName = (char*) fgMemoryManager->allocate
  548.     (
  549.         (strlen(fileName) + 1) * sizeof(char)
  550.     );//new char[strlen(fileName) + 1];
  551.     ArrayJanitor<char> janText((char*)tmpFileName, fgMemoryManager);
  552.     strcpy(tmpFileName,fileName);
  553.     return openWrite(tmpFileName);
  554. }
  555. void
  556. XMLPlatformUtils::writeBufferToFile( FileHandle     const  theFile
  557.                                    , long                  toWrite
  558.                                    , const XMLByte* const  toFlush)
  559. {
  560.     FileHandleImpl* fhiPtr = (FileHandleImpl*) theFile;
  561.     FILE* fileHandle = (FILE*)fhiPtr->getHandle();
  562.     if (!fileHandle     ||
  563.         (toWrite <= 0 ) ||
  564.         !toFlush )
  565.         return;
  566.     XMLByte* tmpFlush = (XMLByte*) toFlush;
  567.     // For writes where the file has been opened with the "type=record"
  568.     // option we must do a lot of extra work. In this case we have
  569.     // a staging buffer that we copy data to and only write it out
  570.     // when we find a newline or line feed in the buffer.
  571.     if (fhiPtr->isRecordType())
  572.     {
  573.        XMLByte* inputBufferPtr =  tmpFlush;
  574.        XMLByte* stageBufferStartPtr =  fhiPtr->getStgBufferPtr();
  575.        int stageBufferNextByte = fhiPtr->getNextByte();
  576.        XMLByte* stageBufferAddPtr =  stageBufferStartPtr + stageBufferNextByte;
  577.        int stageThisAdd = 0;
  578.        int stageTotalAdded = 0;
  579.        int stageToWrite = 0;
  580.        int fileLrecl = fhiPtr->getLrecl();
  581.        // Check each byte passed into us. If it is a new line or
  582.        // line feed we copy up to and including that byte to the
  583.        // staging buffer starting at the next available byte. We
  584.        // then write the valid contents of the staging buffer to
  585.        // the file and then continue going thru the input data
  586.        // since a newline is not the end of the input.
  587.        // Also we want to copy the data to the staging buffer and
  588.        // write it to disk as soon as the staging buffer contains
  589.        // a logical record's worth of data.
  590.        for(int i = 0; i < toWrite; i++)
  591.        {
  592.           if ( (tmpFlush[i] == 'n') ||
  593.                (tmpFlush[i] == 0x25) ||
  594.                ((stageBufferNextByte + (i + 1)) - stageTotalAdded == fileLrecl) )
  595.           {
  596.              stageThisAdd = (i + 1) - stageTotalAdded;
  597.              memcpy((void*) stageBufferAddPtr, (void*) inputBufferPtr, stageThisAdd);
  598.              stageTotalAdded += stageThisAdd;
  599.              inputBufferPtr += stageThisAdd;
  600.              stageBufferAddPtr += stageThisAdd;
  601.              stageToWrite = stageBufferAddPtr - stageBufferStartPtr;
  602.              emptyBuffer(stageBufferStartPtr, stageToWrite, fhiPtr);
  603.              stageBufferAddPtr = stageBufferStartPtr;
  604.              stageBufferNextByte = 0;
  605.           }
  606.        }  // for loop
  607.       // When we finish looping thru the input buffer we may have data
  608.       // left in it that was not copied to the staging buffer yet. Copy
  609.       // whatever is left in the input buffer to the staging buffer now
  610.       // and update the staging buffer next byte offset.
  611.       if (stageTotalAdded < toWrite)
  612.       {
  613.          stageThisAdd = toWrite - stageTotalAdded;
  614.          memcpy((void*) stageBufferAddPtr, (void*) inputBufferPtr, stageThisAdd);
  615.          stageBufferNextByte += stageThisAdd;
  616.       }
  617.       fhiPtr->setNextByte(stageBufferNextByte);
  618.     }
  619.     // Normal type of write, just write data to disk ...
  620.     else
  621.        emptyBuffer(tmpFlush, toWrite, fhiPtr);
  622.   return;
  623. }
  624. unsigned int
  625. XMLPlatformUtils::readFileBuffer(  FileHandle      theFile
  626.                                 , const unsigned int    toRead
  627.                                 , XMLByte* const  toFill)
  628. {
  629.     FileHandleImpl* fhiPtr = (FileHandleImpl*) theFile;
  630.     FILE* fileHandle = (FILE*)fhiPtr->getHandle();
  631.     size_t noOfItemsRead = 0;
  632.     bool isTypeRecord = fhiPtr->isRecordType();
  633.     // On a read, if this was a "type=record" open then we do not want
  634.     // to return any terminating NULLS that fill out a logical
  635.     // record. We also will discard a record that is all NULLS.
  636.     while (true)
  637.     {
  638.        noOfItemsRead = fread( (void*) toFill, 1, toRead, fileHandle);
  639.        if(ferror(fileHandle))
  640.           ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile);
  641.        if (isTypeRecord)
  642.        {
  643.           if (noOfItemsRead == 0)
  644.               break;
  645.           // Go thru the data we read and strip off trailing NULLS
  646.           // until a non-NULL is encountered. If a record is all
  647.           // NULLS then we discard it.
  648.           bool recordIsValid = false;
  649.           for (int i = noOfItemsRead; i > 0; i--)
  650.           {
  651.              if (toFill[i - 1])
  652.              {
  653.                 recordIsValid = true;
  654.                 break;
  655.              }
  656.              else
  657.                 noOfItemsRead--;
  658.           }
  659.           // If we didn't hit a non-NULL we need will go read another
  660.           // record in hopes of returning some valid data.
  661.           if (recordIsValid)
  662.              break;
  663.           else
  664.           {
  665.              noOfItemsRead = 0;
  666.              break;
  667.           }
  668.        } // isTypeRecord
  669.        // for a "non-type=record" read we do only one read
  670.        else
  671.           break;
  672.     }  // while (true)
  673.     return (unsigned int)noOfItemsRead;
  674. }
  675. void XMLPlatformUtils::resetFile(FileHandle theFile)
  676. {
  677.     // Seek to the start of the file
  678.     FileHandleImpl* fhiPtr = (FileHandleImpl*) theFile;
  679.     FILE* fileHandle = (FILE*)fhiPtr->getHandle();
  680.     if (fseek(fileHandle, 0, SEEK_SET) )
  681.    ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotResetFile);
  682. }
  683. // ---------------------------------------------------------------------------
  684. //  XMLPlatformUtils: File system methods
  685. // ---------------------------------------------------------------------------
  686. XMLCh* XMLPlatformUtils::getFullPath(const XMLCh* const srcPath,
  687.                                      MemoryManager* const manager)
  688. {
  689.     //
  690.     //  NOTE: THe path provided has always already been opened successfully,
  691.     //  so we know that its not some pathological freaky path. It comes in
  692.     //  in native format, and goes out as Unicode always
  693.     //
  694.     char* newSrc = XMLString::transcode(srcPath, fgMemoryManager);
  695.     ArrayJanitor<char> janText(newSrc, fgMemoryManager);
  696.     Path390 pathobj;
  697.     pathobj.setPath(newSrc);
  698.     char* retPath = 0;
  699.     // Use a local buffer that is big enough for the largest legal path
  700.     char *absPath = (char*) fgMemoryManager->allocate((_POSIX_PATH_MAX) * sizeof(char));//new char[_POSIX_PATH_MAX];
  701.     ArrayJanitor<char> janText2(absPath, fgMemoryManager);
  702.     if ( (pathobj.getPathType() == PATH390_HFS) || (pathobj.getPathType() == PATH390_OTHER) ) {
  703.        //get the absolute path
  704.        char* retPath = realpath(pathobj.getfopenPath(), absPath);
  705.        if (!retPath) {
  706.           ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetBasePathName);
  707.           }
  708.        return XMLString::transcode(absPath, manager);
  709.     }
  710.     return XMLString::transcode(newSrc, manager);
  711. }
  712. bool XMLPlatformUtils::isRelative(const XMLCh* const toCheck)
  713. {
  714.     // Check for pathological case of empty path
  715.     if (!toCheck[0])
  716.         return false;
  717.     //
  718.     //  If it starts with a slash, then it cannot be relative. This covers
  719.     //  both something like "TestFile.xml" and an NT Lan type remote path
  720.     //  that starts with a node like "\MyNodeTestFile.xml".
  721.     //
  722.     //  Check for 0x2F instead of '/' because '/' will be compiled into
  723.     //  0x61
  724.     //
  725.     if (toCheck[0] == 0x2F)
  726.         return false;
  727.     //
  728.     //  Determine whether we are using the DD convention
  729.     //  'D': 0x44 'd': 0x64 ':': 0x3A
  730.     //
  731.     if (XMLString::stringLen(toCheck) > 3) {
  732.       if (
  733.           ((toCheck[0] == (0x44)) || (toCheck[0] == (0x64))) &&
  734.           ((toCheck[1] == (0x44)) || (toCheck[1] == (0x64))) &&
  735.           (toCheck[2] == XMLCh(0x3A))
  736.          )
  737.          return false;
  738.     }
  739.     char* tmpFileName = XMLString::transcode(toCheck, fgMemoryManager);
  740.     ArrayJanitor<char> janText((char*)tmpFileName, fgMemoryManager);
  741.     Path390 pathobj;
  742.     pathobj.setPath(tmpFileName);
  743.     // let Path390 do the final determination
  744.     return pathobj.isRelative();
  745. }
  746. XMLCh* XMLPlatformUtils::getCurrentDirectory(MemoryManager* const manager)
  747. {
  748.     /*** 
  749.      *  REVISIT:
  750.      * 
  751.      *   To be implemented later
  752.     ***/
  753.     XMLCh curDir[]={ chPeriod, chForwardSlash, chNull};
  754.     return getFullPath(curDir, manager);
  755. }
  756. inline bool XMLPlatformUtils::isAnySlash(XMLCh c) 
  757. {
  758.     return ( chBackSlash == c || chForwardSlash == c);
  759. }
  760. // ---------------------------------------------------------------------------
  761. //  XMLPlatformUtils: Timing Methods
  762. // ---------------------------------------------------------------------------
  763. unsigned long XMLPlatformUtils::getCurrentMillis()
  764. {
  765.     timeb aTime;
  766.     ftime(&aTime);
  767.     return (unsigned long)(aTime.time*1000 + aTime.millitm);
  768. }
  769. // -----------------------------------------------------------------------
  770. //  Mutex methods
  771. //  OS390BATCH: Unless POSIX(ON) is specified, pthread functions are
  772. //  not available. We will use compareAndSwap for now untill a block
  773. //  locking mechanism is developed
  774. // -----------------------------------------------------------------------
  775. #ifndef APP_NO_THREADS
  776. void XMLPlatformUtils::closeMutex(void* const mtxHandle)
  777. {
  778.     if (mtxHandle == NULL)
  779.         return;
  780.     if (isPosixEnabled) {
  781.     if (pthread_mutex_destroy( (pthread_mutex_t*)mtxHandle))
  782.     {
  783.    ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotDestroy);
  784.     }
  785.     if ( (pthread_mutex_t*)mtxHandle)
  786.         delete (pthread_mutex_t*) mtxHandle;
  787.     } // __isPosixOn
  788.     else {
  789.     if ( (int*)mtxHandle)
  790.         delete (int*) mtxHandle;
  791.     }
  792. }
  793. void XMLPlatformUtils::lockMutex(void* const mtxHandle)
  794. {
  795.     if (mtxHandle == NULL)
  796.         return;
  797.     if (isPosixEnabled) {
  798.     if (pthread_mutex_lock( (pthread_mutex_t*)mtxHandle))
  799.     {
  800.    ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotLock);
  801.     }
  802.     } // __isPosixOn
  803.     else {
  804.    int locked = 1, unlocked;
  805.     do {
  806.         unlocked = 0;
  807.         compareAndSwap( (void**) &mtxHandle, (void*) locked, (void*) unlocked );
  808.     } while( unlocked != 0 );
  809.     }
  810.     return;
  811. }
  812. void* XMLPlatformUtils::makeMutex()
  813. {
  814.     if (isPosixEnabled) {
  815.     pthread_mutex_t* mutex = new pthread_mutex_t;
  816.     if (mutex == NULL)
  817.     {
  818.    ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotCreate);
  819.     }
  820.     pthread_mutexattr_t*  attr = new pthread_mutexattr_t;
  821.     pthread_mutexattr_init(attr);
  822.     pthread_mutexattr_setkind_np(attr, __MUTEX_RECURSIVE);
  823.     if (pthread_mutex_init(mutex, attr))
  824.     {
  825.         ThrowXML(XMLPlatformUtilsException,
  826.                 XMLExcepts::Mutex_CouldNotCreate);
  827.     }
  828.     pthread_mutexattr_destroy(attr);
  829.     delete attr;
  830.     return (void*)(mutex);
  831.     } // __isPosixOn
  832.     else {
  833.    int* mutex = new int;
  834.    *mutex = 0;
  835.    return (void*)(mutex);
  836.     }
  837. }
  838. void XMLPlatformUtils::unlockMutex(void* const mtxHandle)
  839. {
  840.     if (mtxHandle == NULL)
  841.         return;
  842.     if (isPosixEnabled) {
  843.     if (pthread_mutex_unlock( (pthread_mutex_t*)mtxHandle))
  844.     {
  845.    ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotUnlock);
  846.     }
  847.     } // __isPosixOn
  848.     else {
  849.    if (*(int*) mtxHandle == 0 )
  850.    *(int*) mtxHandle = 0;
  851.     }
  852. }
  853. #else // #ifndef APP_NO_THREADS
  854. void XMLPlatformUtils::closeMutex(void* const mtxHandle)
  855. {
  856. }
  857. void XMLPlatformUtils::lockMutex(void* const mtxHandle)
  858. {
  859. }
  860. void* XMLPlatformUtils::makeMutex()
  861. {
  862.         return 0;
  863. }
  864. void XMLPlatformUtils::unlockMutex(void* const mtxHandle)
  865. {
  866. }
  867. #endif // APP_NO_THREADS
  868. // -----------------------------------------------------------------------
  869. //  Miscellaneous synchronization methods
  870. // -----------------------------------------------------------------------
  871. void* XMLPlatformUtils::compareAndSwap ( void**      toFill ,
  872.                     const void* const newValue ,
  873.                     const void* const toCompare)
  874. {
  875.   int boolVar = cs( (cs_t*) &toCompare, (cs_t*) toFill, (cs_t) newValue );
  876.   return (void*) toCompare;
  877. }
  878. int XMLPlatformUtils::atomicIncrement(int &location)
  879. {
  880.   int newVal, oldVal = location;
  881.   do {
  882.     newVal = oldVal + 1;
  883.     oldVal = (int) compareAndSwap( (void**) &location, (void*) newVal, (void*) oldVal );
  884.   } while( newVal != oldVal + 1 );
  885.   return newVal;
  886. }
  887. int XMLPlatformUtils::atomicDecrement(int &location)
  888. {
  889.   int newVal, oldVal = location;
  890.   do {
  891.     newVal = oldVal - 1;
  892.     oldVal = (int) compareAndSwap( (void**) &location, (void*) newVal, (void*) oldVal );
  893.   } while( newVal != oldVal - 1 );
  894.   return newVal;
  895. }
  896. FileHandle XMLPlatformUtils::openStdInHandle()
  897. {
  898.      FileHandleImpl* retVal;
  899.      FILE* fileHandle = 0;
  900.      fileHandle = fdopen(dup(0), "rb");
  901.      if (fileHandle)
  902.         retVal = new FileHandleImpl(fileHandle, _FHI_READ, _FHI_NOT_TYPE_RECORD);
  903.      else
  904.         retVal = 0;
  905.      return retVal;
  906. }
  907. void XMLPlatformUtils::platformTerm()
  908. {
  909.     // We don't have any termination requirements at this time
  910. }
  911. #include <xercesc/util/LogicalPath.c>
  912. XERCES_CPP_NAMESPACE_END