int SCXFile::ReadAvailableBytesAsUnsigned()

in source/code/scxcorelib/pal/scxfile.cpp [518:778]


    int SCXFile::ReadAvailableBytesAsUnsigned(const SCXFilePath& , unsigned char* , size_t , size_t /*= 0*/) {
            throw SCXNotSupportedException(L"Reads not supported on windows", SCXSRCLOCATION);
#else
    int SCXFile::ReadAvailableBytesAsUnsigned(const SCXFilePath& path, unsigned char* buf, size_t size, size_t offset /*= 0*/) {
        int fd = open(SCXFileSystem::EncodePath(path).c_str(),O_RDONLY);
        if (-1 == fd) {
            return errno;
        }

        size_t remainder;
        void *pDevice = NULL;
#ifdef _SC_PAGESIZE  //!< Size of a page in bytes
        remainder = offset% sysconf(_SC_PAGESIZE);
#else
        remainder = offset% getpagesize();
#endif
        //
        //For API mmap, the sixth parameter mmapoffset must be a multiple of pagesize.
        //
        size_t mmapoffset = offset - remainder;
        pDevice = mmap(NULL, remainder + size, PROT_READ, MAP_SHARED, fd, mmapoffset);
        if (MAP_FAILED == pDevice) {
            int ret = errno;
            close(fd);
            return ret;
        }

        memcpy(buf, reinterpret_cast<unsigned char*>(pDevice) + remainder, size);

        munmap(reinterpret_cast<char*>(pDevice), remainder + size);
        close(fd);

        return 0;
#endif
    }

    /*--------------------------------------------------------------*/
    /**
       Seek get position to absolute position

       \param[in]  source stream
       \param[in]  pos    Absolute position to seek to.
    */
    void SCXFile::SeekG(std::wfstream& source, std::wstreampos pos) {
#if defined(linux) && defined(PF_DISTRO_SUSE) && (PF_MAJOR==9)
        // seekg does not seem to work on suse9
        // It moves the position pos*4 instead of just pos.
        std::wstreampos current = source.tellg();
        if (current > pos) {
            source.seekg(0);
            source.ignore(pos);
        } else if (current < pos) {
            source.ignore(pos-current);
        }
#else
        source.seekg(pos);
#endif
    }


#if !defined(DISABLE_WIN_UNSUPPORTED)

    pthread_mutex_t SCXFile::scxTempFileCountLock=PTHREAD_MUTEX_INITIALIZER;
    int SCXFile::scxTempFileCount=0;

    /*--------------------------------------------------------------*/
    /**
        Creates a temp file and writes to it

        \param[in]  fileContent    Content to write to file.
        \returns    Complete path of newly created file.

     */

    SCXFilePath SCXFile::CreateTempFile(const std::wstring& fileContent, const std::wstring& tmpDir /* = "/tmp/" */) {
        /**
         * The code below behaves as it does because of limitations in the
         * various temp file functions.
         *
         * \li Use the tempnam function to retrieve an "appropriate" directory
         *     to store files in.
         * \li Only use the directory part of what is returned and append a
         *     pattern to use for creating temporary file.
         * \li Use the pattern as argument to mkstemp which is the recommended
         *     function since it avoids race conditions.
         *
         */
        SCXFilePath pattern;
#if defined(WIN32)
        char* fp = tempnam(0, 0);
        if (fp == 0) {
            throw SCXInternalErrorException(
                UnexpectedErrno(L"Failed to find an appropriate temporary file directory", errno),
                SCXSRCLOCATION);
        }

        try
        {
            pattern = SCXFileSystem::DecodePath(fp);
        }
        catch ( SCXCoreLib::SCXException& e )
        {
            free(fp);
            fp = 0;
            SCXRETHROW(e, L"Unable to decode file path." );
        }
        free(fp);
        fp = 0;
#else
        pattern = SCXFileSystem::DecodePath(StrToUTF8(tmpDir));
        if(!SCXCoreLib::SCXDirectory::Exists(pattern))
        {
        	throw SCXCoreLib::SCXFilePathNotFoundException(pattern.GetDirectory(), SCXSRCLOCATION);
        }
#endif

        std::stringstream ss;

        pthread_mutex_lock(&scxTempFileCountLock);
        ss<<scxTempFileCount;
        scxTempFileCount=(scxTempFileCount+1)%SCXTEMPPREFIXCOUNT;
        pthread_mutex_unlock(&scxTempFileCountLock);

        std::string tempfileNamePrefix;
        ss>>tempfileNamePrefix;
        tempfileNamePrefix="scx"+tempfileNamePrefix+"XXXXXX";

        pattern.SetFilename(StrFromUTF8(tempfileNamePrefix));
        std::string patternString = SCXFileSystem::EncodePath(pattern);
        std::vector<char> buf;

        buf.resize( patternString.length()+1, 0 );
        strcpy(&buf[0], patternString.c_str());

        mode_t oldUmask = umask(077);
        int fileDescriptor = mkstemp(&buf[0]);
        umask(oldUmask);

        if (fileDescriptor == -1) {
            std::wstring problem(L"Failed to create temporary file from pattern " + pattern.Get());
            throw SCXInternalErrorException(UnexpectedErrno(problem, errno), SCXSRCLOCATION);
        }

        SCXFilePath filepath = SCXFileSystem::DecodePath(&buf[0]);

        if ( access(SCRIPTCONTROLLOGFILE, W_OK) != -1 ) {
           FILE *fptr = fopen(SCRIPTCONTROLLOGFILE,"a");
           if( fptr != NULL ) {
               std::string tempFileName = StrToUTF8(filepath.Get());
               fprintf(fptr, "%s temporary file created.\n",tempFileName.c_str());
               fclose(fptr);
           }
        }

        std::ostringstream fileContentStream;
        SCXStream::WriteAsUTF8(fileContentStream, fileContent);
        std::string fileContentUTF8 = fileContentStream.str();
        ssize_t written = write(fileDescriptor, fileContentUTF8.c_str(), fileContentUTF8.length());
        if (written == -1) {
            std::wstring problem(L"Failed to write to temporary file " + filepath.Get());
            close(fileDescriptor);
            throw SCXInternalErrorException(UnexpectedErrno(problem, errno), SCXSRCLOCATION);
        }

        close(fileDescriptor);
        return filepath;
    }
#endif

    /*--------------------------------------------------------------*/
    /**
     * Retrieves preferred kind of new line of a particular path. May
     * take into account the kind of file system the path refers to
     * as well as new lines currently used if the path refers to an
     * already existing file.
     * \returns Preferred kind of new line
     * \note Right now the implementation is simplified, it just returns
     * SCXFileSystem::GetDefaultNewLine()
     */
    SCXStream::NLF SCXFile::GetPreferredNewLine(const SCXFilePath&) {
        return SCXFileSystem::GetDefaultNewLine();
    }

    /*--------------------------------------------------------------*/
    /**
     * Writes all lines to a file using preferred kind of new line
     * \param[in]   target      Stream to be written to
     * \param[in]   lines       Lines to be written
     * \param[in]   mode        How to open the file
     * No new line is appended after all lines.
     * If mode is "append" an extra new line is prepended before the lines.
     */
    void SCXFile::WriteAllLines(const SCXFilePath& target, const std::vector<std::wstring>& lines, std::ios_base::openmode mode) {
        WriteAllLines(target, lines, mode, GetPreferredNewLine(target));
    }

    /*--------------------------------------------------------------*/
    /**
     * Writes all lines to a file using specified kind of new line
     * \param[in]   target      Stream to be written to
     * \param[in]   lines       Lines to be written
     * \param[in]   mode        How to open the file
     * \param[in]   nlf         Kind of new line to write
     * No new line is appended after all lines.
     * If mode is "append" an extra new line is prepended before the lines.
     */
    void SCXFile::WriteAllLines(const SCXFilePath& target, const std::vector<std::wstring>& lines, std::ios_base::openmode mode,
            SCXStream::NLF nlf) {
        SCXHandle<std::wfstream> stream(OpenWFstream(target, mode));
        if (lines.size() > 0) {
            if (mode & std::ios_base::app) {
                SCXStream::WriteNewLine(*stream, nlf);
            }
            SCXStream::Write(*stream, lines.at(0));
            for (std::wstring::size_type lineNr = 1; lineNr < lines.size(); lineNr++) {
                SCXStream::WriteNewLine(*stream, nlf);
                SCXStream::Write(*stream, lines.at(lineNr));
            }
        }
    }

    /*--------------------------------------------------------------*/
    /**
     * Writes all lines to a UTF8 encoded file using preferred kind of new line
     * \param[in]   target      Stream to be written to
     * \param[in]   lines       Lines to be written
     * \param[in]   mode        How to open the file
     * No new line is appended after all lines.
     * If mode is "append" an extra new line is prepended before the lines.
     */
    void SCXFile::WriteAllLinesAsUTF8(const SCXFilePath& target,
                const std::vector<std::wstring>& lines, std::ios_base::openmode mode) {
        WriteAllLinesAsUTF8(target, lines, mode, GetPreferredNewLine(target));
    }

    /*--------------------------------------------------------------*/
    /**
     * Writes all lines to a UTF8 encoded file using specified kind of newline
     * \param[in]   target      Stream to be written to
     * \param[in]   lines       Lines to be written
     * \param[in]   mode        How to open the file
     * \param[in]   nlf         Kind of newline to write
     * No newline is appended after all lines.
     * If mode is "append" an extra newline is prepended before the lines.
     */
    void SCXFile::WriteAllLinesAsUTF8(const SCXFilePath& target, const std::vector<std::wstring>& lines, std::ios_base::openmode mode,
            SCXStream::NLF nlf) {
        SCXHandle<std::fstream> stream(OpenFstream(target, mode));
        if (lines.size() > 0) {
            if (mode & std::ios_base::app) {
                SCXStream::WriteNewLineAsUTF8(*stream, nlf);
            }
            SCXStream::WriteAsUTF8(*stream, lines.at(0));
            for (std::wstring::size_type lineNr = 1; lineNr < lines.size(); lineNr++) {
                SCXStream::WriteNewLineAsUTF8(*stream, nlf);
                SCXStream::WriteAsUTF8(*stream, lines.at(lineNr));
            }
        }
    }

}