/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ /************************************************************************ * ToDo * * Fix osl_getCanonicalName * * - Fix: check for corresponding struct sizes in exported functions * - check size/use of oslDirectory * - check size/use of oslDirectoryItem * - check size/use of oslFileStatus * - check size/use of oslVolumeDeviceHandle * - check size/use of oslVolumeInfo * - check size/use of oslFileHandle ***********************************************************************/ #define INCL_DOSDEVIOCTL // OS2 device definitions #include "system.h" #include #include "osl/file.hxx" #include #include #include #include "file_error_transl.h" #include #ifndef _FILE_URL_H_ #include "file_url.h" #endif #include "file_path_helper.hxx" #include "uunxapi.hxx" #ifndef _STRING_H_ #include #endif #ifndef _CTYPE_H_ #include #endif #ifndef _WCHAR_H_ #include #endif #include #include #include #if OSL_DEBUG_LEVEL > 1 extern void debug_ustring(rtl_uString*); #endif #ifdef DEBUG_OSL_FILE # define PERROR( a, b ) perror( a ); fprintf( stderr, b ) #else # define PERROR( a, b ) #endif extern "C" oslFileHandle osl_createFileHandleFromFD( int fd ); struct errentry errtable[] = { { NO_ERROR, osl_File_E_None }, /* 0 */ { ERROR_INVALID_FUNCTION, osl_File_E_INVAL }, /* 1 */ { ERROR_FILE_NOT_FOUND, osl_File_E_NOENT }, /* 2 */ { ERROR_PATH_NOT_FOUND, osl_File_E_NOENT }, /* 3 */ { ERROR_TOO_MANY_OPEN_FILES, osl_File_E_MFILE }, /* 4 */ { ERROR_ACCESS_DENIED, osl_File_E_ACCES }, /* 5 */ { ERROR_INVALID_HANDLE, osl_File_E_BADF }, /* 6 */ { ERROR_ARENA_TRASHED, osl_File_E_NOMEM }, /* 7 */ { ERROR_NOT_ENOUGH_MEMORY, osl_File_E_NOMEM }, /* 8 */ { ERROR_INVALID_BLOCK, osl_File_E_NOMEM }, /* 9 */ { ERROR_BAD_ENVIRONMENT, osl_File_E_2BIG }, /* 10 */ { ERROR_BAD_FORMAT, osl_File_E_NOEXEC }, /* 11 */ { ERROR_INVALID_ACCESS, osl_File_E_INVAL }, /* 12 */ { ERROR_INVALID_DATA, osl_File_E_INVAL }, /* 13 */ { ERROR_INVALID_DRIVE, osl_File_E_NOENT }, /* 15 */ { ERROR_CURRENT_DIRECTORY, osl_File_E_ACCES }, /* 16 */ { ERROR_NOT_SAME_DEVICE, osl_File_E_XDEV }, /* 17 */ { ERROR_NO_MORE_FILES, osl_File_E_NOENT }, /* 18 */ { ERROR_NOT_READY, osl_File_E_NOTREADY }, /* 21 */ { ERROR_LOCK_VIOLATION, osl_File_E_ACCES }, /* 33 */ { ERROR_BAD_NETPATH, osl_File_E_NOENT }, /* 53 */ { ERROR_NETWORK_ACCESS_DENIED, osl_File_E_ACCES }, /* 65 */ { ERROR_BAD_NET_NAME, osl_File_E_NOENT }, /* 67 */ { ERROR_FILE_EXISTS, osl_File_E_EXIST }, /* 80 */ { ERROR_CANNOT_MAKE, osl_File_E_ACCES }, /* 82 */ { ERROR_FAIL_I24, osl_File_E_ACCES }, /* 83 */ { ERROR_INVALID_PARAMETER, osl_File_E_INVAL }, /* 87 */ { ERROR_NO_PROC_SLOTS, osl_File_E_AGAIN }, /* 89 */ { ERROR_DRIVE_LOCKED, osl_File_E_ACCES }, /* 108 */ { ERROR_BROKEN_PIPE, osl_File_E_PIPE }, /* 109 */ { ERROR_DISK_FULL, osl_File_E_NOSPC }, /* 112 */ { ERROR_INVALID_TARGET_HANDLE, osl_File_E_BADF }, /* 114 */ { ERROR_INVALID_HANDLE, osl_File_E_INVAL }, /* 124 */ { ERROR_WAIT_NO_CHILDREN, osl_File_E_CHILD }, /* 128 */ { ERROR_CHILD_NOT_COMPLETE, osl_File_E_CHILD }, /* 129 */ { ERROR_DIRECT_ACCESS_HANDLE, osl_File_E_BADF }, /* 130 */ { ERROR_NEGATIVE_SEEK, osl_File_E_INVAL }, /* 131 */ { ERROR_SEEK_ON_DEVICE, osl_File_E_ACCES }, /* 132 */ { ERROR_DIR_NOT_EMPTY, osl_File_E_NOTEMPTY }, /* 145 */ { ERROR_NOT_LOCKED, osl_File_E_ACCES }, /* 158 */ { ERROR_BAD_PATHNAME, osl_File_E_NOENT }, /* 161 */ { ERROR_MAX_THRDS_REACHED, osl_File_E_AGAIN }, /* 164 */ { ERROR_LOCK_FAILED, osl_File_E_ACCES }, /* 167 */ { ERROR_ALREADY_EXISTS, osl_File_E_EXIST }, /* 183 */ { ERROR_FILENAME_EXCED_RANGE, osl_File_E_NOENT }, /* 206 */ { ERROR_NESTING_NOT_ALLOWED, osl_File_E_AGAIN }, /* 215 */ { ERROR_DIRECTORY, osl_File_E_NOENT }, /* 267 */ //{ ERROR_NOT_ENOUGH_QUOTA, osl_File_E_NOMEM } /* 1816 */ }; #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0]))) //##################################################### oslFileError MapError(APIRET dwError) { for (int i = 0; i < ELEMENTS_OF_ARRAY(errtable); ++i ) { if (dwError == errtable[i].oscode) return static_cast(errtable[i].errnocode); } return osl_File_E_INVAL; } #ifdef DEBUG_OSL_FILE # define OSL_FILE_TRACE 0 ? (void)(0) : osl_trace # define PERROR( a, b ) perror( a ); fprintf( stderr, b ) #else # define OSL_FILE_TRACE 1 ? (void)(0) : osl_trace # define PERROR( a, b ) #endif //################################################################## // File handle implementation //################################################################## struct FileHandle_Impl { rtl_String * m_strFilePath; /* holds native file path */ int m_fd; /** State */ enum StateBits { STATE_SEEKABLE = 1, /* default */ STATE_READABLE = 2, /* default */ STATE_WRITEABLE = 4, /* open() sets, write() requires, else osl_File_E_BADF */ STATE_MODIFIED = 8 /* write() sets, flush() resets */ }; int m_state; sal_uInt64 m_size; /* file size */ off_t m_offset; /* physical offset from begin of file */ //off_t m_filepos; /* logical offset from begin of file */ off_t m_fileptr; /* logical offset from begin of file */ off_t m_bufptr; /* buffer offset from begin of file */ size_t m_buflen; /* buffer filled [0, m_bufsiz - 1] */ size_t m_bufsiz; sal_uInt8 * m_buffer; explicit FileHandle_Impl (int fd, char const * path = ""); ~FileHandle_Impl(); static void* operator new(size_t n); static void operator delete(void * p, size_t); static size_t getpagesize(); sal_uInt64 getPos() const; oslFileError setPos (sal_uInt64 uPos); sal_uInt64 getSize() const; oslFileError setSize (sal_uInt64 uPos); oslFileError readAt ( off_t nOffset, void * pBuffer, size_t nBytesRequested, sal_uInt64 * pBytesRead); oslFileError writeAt ( off_t nOffset, void const * pBuffer, size_t nBytesToWrite, sal_uInt64 * pBytesWritten); oslFileError readFileAt ( off_t nOffset, void * pBuffer, size_t nBytesRequested, sal_uInt64 * pBytesRead); oslFileError writeFileAt ( off_t nOffset, void const * pBuffer, size_t nBytesToWrite, sal_uInt64 * pBytesWritten); oslFileError readLineAt ( LONGLONG nOffset, sal_Sequence ** ppSequence, sal_uInt64 * pBytesRead); oslFileError writeSequence_Impl ( sal_Sequence ** ppSequence, size_t * pnOffset, const void * pBuffer, size_t nBytes); oslFileError syncFile(); /** Buffer cache / allocator. */ class Allocator { rtl_cache_type * m_cache; size_t m_bufsiz; Allocator (Allocator const &); Allocator & operator= (Allocator const &); public: static Allocator & get(); void allocate (sal_uInt8 ** ppBuffer, size_t * pnSize); void deallocate (sal_uInt8 * pBuffer); protected: Allocator(); ~Allocator(); }; }; FileHandle_Impl::Allocator & FileHandle_Impl::Allocator::get() { static Allocator g_aBufferAllocator; return g_aBufferAllocator; } FileHandle_Impl::Allocator::Allocator() : m_cache (0), m_bufsiz (0) { size_t const pagesize = FileHandle_Impl::getpagesize(); m_cache = rtl_cache_create ( "osl_file_buffer_cache", pagesize, 0, 0, 0, 0, 0, 0, 0); if (0 != m_cache) m_bufsiz = pagesize; } FileHandle_Impl::Allocator::~Allocator() { rtl_cache_destroy(m_cache), m_cache = 0; } void FileHandle_Impl::Allocator::allocate (sal_uInt8 ** ppBuffer, size_t * pnSize) { OSL_PRECOND((0 != ppBuffer) && (0 != pnSize), "FileHandle_Impl::Allocator::allocate(): contract violation"); *ppBuffer = static_cast< sal_uInt8* >(rtl_cache_alloc(m_cache)), *pnSize = m_bufsiz; } void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer) { if (0 != pBuffer) rtl_cache_free (m_cache, pBuffer); } FileHandle_Impl::FileHandle_Impl (int fd, char const * path) : m_strFilePath (0), m_fd (fd), m_state (STATE_SEEKABLE | STATE_READABLE), m_size (0), m_offset (0), m_fileptr (0), m_bufptr (-1), m_buflen (0), m_bufsiz (0), m_buffer (0) { rtl_string_newFromStr (&m_strFilePath, path); Allocator::get().allocate (&m_buffer, &m_bufsiz); if (m_buffer != 0) memset (m_buffer, 0, m_bufsiz); } FileHandle_Impl::~FileHandle_Impl() { Allocator::get().deallocate (m_buffer), m_buffer = 0; rtl_string_release (m_strFilePath), m_strFilePath = 0; } void * FileHandle_Impl::operator new(size_t n) { return rtl_allocateMemory(n); } void FileHandle_Impl::operator delete(void * p, size_t) { rtl_freeMemory(p); } size_t FileHandle_Impl::getpagesize() { ULONG ulPageSize; DosQuerySysInfo(QSV_PAGE_SIZE, QSV_PAGE_SIZE, &ulPageSize, sizeof(ULONG)); return sal::static_int_cast< size_t >(ulPageSize); } sal_uInt64 FileHandle_Impl::getPos() const { return sal::static_int_cast< sal_uInt64 >(m_fileptr); } oslFileError FileHandle_Impl::setPos (sal_uInt64 uPos) { m_fileptr = sal::static_int_cast< LONGLONG >(uPos); return osl_File_E_None; } sal_uInt64 FileHandle_Impl::getSize() const { LONGLONG bufend = std::max((LONGLONG)(0), m_bufptr) + m_buflen; return std::max(m_size, sal::static_int_cast< sal_uInt64 >(bufend)); } oslFileError FileHandle_Impl::setSize (sal_uInt64 uSize) { off_t const nSize = sal::static_int_cast< off_t >(uSize); if (-1 == ftruncate (m_fd, nSize)) { /* Failure. Save original result. Try fallback algorithm */ oslFileError result = oslTranslateFileError (OSL_FET_ERROR, errno); /* Check against current size. Fail upon 'shrink' */ if (uSize <= getSize()) { /* Failure upon 'shrink'. Return original result */ return (result); } /* Save current position */ off_t const nCurPos = (off_t)lseek (m_fd, (off_t)0, SEEK_CUR); if (nCurPos == (off_t)(-1)) return (result); /* Try 'expand' via 'lseek()' and 'write()' */ if (-1 == lseek (m_fd, (off_t)(nSize - 1), SEEK_SET)) return (result); if (-1 == write (m_fd, (char*)"", (size_t)1)) { /* Failure. Restore saved position */ (void) lseek (m_fd, (off_t)(nCurPos), SEEK_SET); return (result); } /* Success. Restore saved position */ if (-1 == lseek (m_fd, (off_t)nCurPos, SEEK_SET)) return (result); } OSL_FILE_TRACE("osl_setFileSize(%d, %lld) => %ld", m_fd, getSize(), nSize); m_size = sal::static_int_cast< sal_uInt64 >(nSize); return osl_File_E_None; } oslFileError FileHandle_Impl::readAt ( off_t nOffset, void * pBuffer, size_t nBytesRequested, sal_uInt64 * pBytesRead) { OSL_PRECOND((m_state & STATE_SEEKABLE), "FileHandle_Impl::readAt(): not seekable"); if (!(m_state & STATE_SEEKABLE)) return osl_File_E_SPIPE; OSL_PRECOND((m_state & STATE_READABLE), "FileHandle_Impl::readAt(): not readable"); if (!(m_state & STATE_READABLE)) return osl_File_E_BADF; if (nOffset != m_offset) { if (-1 == ::lseek (m_fd, nOffset, SEEK_SET)) return oslTranslateFileError (OSL_FET_ERROR, errno); m_offset = nOffset; } ssize_t nBytes = ::read (m_fd, pBuffer, nBytesRequested); if (-1 == nBytes) return oslTranslateFileError (OSL_FET_ERROR, errno); m_offset += nBytes; OSL_FILE_TRACE("FileHandle_Impl::readAt(%d, %lld, %ld)", m_fd, nOffset, nBytes); *pBytesRead = nBytes; return osl_File_E_None; } oslFileError FileHandle_Impl::writeAt ( off_t nOffset, void const * pBuffer, size_t nBytesToWrite, sal_uInt64 * pBytesWritten) { OSL_PRECOND((m_state & STATE_SEEKABLE), "FileHandle_Impl::writeAt(): not seekable"); if (!(m_state & STATE_SEEKABLE)) return osl_File_E_SPIPE; OSL_PRECOND((m_state & STATE_WRITEABLE), "FileHandle_Impl::writeAt(): not writeable"); if (!(m_state & STATE_WRITEABLE)) return osl_File_E_BADF; if (nOffset != m_offset) { if (-1 == ::lseek (m_fd, nOffset, SEEK_SET)) return oslTranslateFileError (OSL_FET_ERROR, errno); m_offset = nOffset; } ssize_t nBytes = ::write (m_fd, pBuffer, nBytesToWrite); if (-1 == nBytes) return oslTranslateFileError (OSL_FET_ERROR, errno); m_offset += nBytes; OSL_FILE_TRACE("FileHandle_Impl::writeAt(%d, %lld, %ld)", m_fd, nOffset, nBytes); m_size = std::max (m_size, sal::static_int_cast< sal_uInt64 >(nOffset + nBytes)); *pBytesWritten = nBytes; return osl_File_E_None; } oslFileError FileHandle_Impl::readFileAt ( off_t nOffset, void * pBuffer, size_t nBytesRequested, sal_uInt64 * pBytesRead) { if (0 == (m_state & STATE_SEEKABLE)) { // not seekable (pipe) ssize_t nBytes = ::read (m_fd, pBuffer, nBytesRequested); if (-1 == nBytes) return oslTranslateFileError (OSL_FET_ERROR, errno); *pBytesRead = nBytes; return osl_File_E_None; } else if (0 == m_buffer) { // not buffered return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead); } else { sal_uInt8 * buffer = static_cast(pBuffer); for (*pBytesRead = 0; nBytesRequested > 0; ) { off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz; size_t const bufpos = (nOffset % m_bufsiz); if (bufptr != m_bufptr) { // flush current buffer oslFileError result = syncFile(); if (result != osl_File_E_None) return (result); if (nBytesRequested >= m_bufsiz) { // buffer too small, read through from file sal_uInt64 uDone = 0; result = readAt (nOffset, &(buffer[*pBytesRead]), nBytesRequested, &uDone); if (result != osl_File_E_None) return (result); nBytesRequested -= uDone, *pBytesRead += uDone; return osl_File_E_None; } // update buffer (pointer) sal_uInt64 uDone = 0; result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); if (result != osl_File_E_None) return (result); m_bufptr = bufptr, m_buflen = uDone; } if (bufpos >= m_buflen) { // end of file return osl_File_E_None; } size_t const bytes = std::min (m_buflen - bufpos, nBytesRequested); OSL_FILE_TRACE("FileHandle_Impl::readFileAt(%d, %lld, %ld)", m_fd, nOffset, bytes); memcpy (&(buffer[*pBytesRead]), &(m_buffer[bufpos]), bytes); nBytesRequested -= bytes, *pBytesRead += bytes, nOffset += bytes; } return osl_File_E_None; } } oslFileError FileHandle_Impl::writeFileAt ( off_t nOffset, void const * pBuffer, size_t nBytesToWrite, sal_uInt64 * pBytesWritten) { if (0 == (m_state & STATE_SEEKABLE)) { // not seekable (pipe) ssize_t nBytes = ::write (m_fd, pBuffer, nBytesToWrite); if (-1 == nBytes) return oslTranslateFileError (OSL_FET_ERROR, errno); *pBytesWritten = nBytes; return osl_File_E_None; } else if (0 == m_buffer) { // not buffered return writeAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten); } else { sal_uInt8 const * buffer = static_cast(pBuffer); for (*pBytesWritten = 0; nBytesToWrite > 0; ) { off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz; size_t const bufpos = (nOffset % m_bufsiz); if (bufptr != m_bufptr) { // flush current buffer oslFileError result = syncFile(); if (result != osl_File_E_None) return (result); if (nBytesToWrite >= m_bufsiz) { // buffer to small, write through to file sal_uInt64 uDone = 0; result = writeAt (nOffset, &(buffer[*pBytesWritten]), nBytesToWrite, &uDone); if (result != osl_File_E_None) return (result); if (uDone != nBytesToWrite) return osl_File_E_IO; nBytesToWrite -= uDone, *pBytesWritten += uDone; return osl_File_E_None; } // update buffer (pointer) sal_uInt64 uDone = 0; result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); if (result != osl_File_E_None) return (result); m_bufptr = bufptr, m_buflen = uDone; } size_t const bytes = std::min (m_bufsiz - bufpos, nBytesToWrite); OSL_FILE_TRACE("FileHandle_Impl::writeFileAt(%d, %lld, %ld)", m_fd, nOffset, bytes); memcpy (&(m_buffer[bufpos]), &(buffer[*pBytesWritten]), bytes); nBytesToWrite -= bytes, *pBytesWritten += bytes, nOffset += bytes; m_buflen = std::max(m_buflen, bufpos + bytes); m_state |= STATE_MODIFIED; } return osl_File_E_None; } } oslFileError FileHandle_Impl::readLineAt ( LONGLONG nOffset, sal_Sequence ** ppSequence, sal_uInt64 * pBytesRead) { oslFileError result = osl_File_E_None; LONGLONG bufptr = (nOffset / m_bufsiz) * m_bufsiz; if (bufptr != m_bufptr) { /* flush current buffer */ result = syncFile(); if (result != osl_File_E_None) return (result); /* update buffer (pointer) */ sal_uInt64 uDone = 0; result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); if (result != osl_File_E_None) return (result); m_bufptr = bufptr, m_buflen = sal::static_int_cast< size_t >(uDone); } static int const LINE_STATE_BEGIN = 0; static int const LINE_STATE_CR = 1; static int const LINE_STATE_LF = 2; size_t bufpos = sal::static_int_cast< size_t >(nOffset - m_bufptr), curpos = bufpos, dstpos = 0; int state = (bufpos >= m_buflen) ? LINE_STATE_LF : LINE_STATE_BEGIN; for ( ; state != LINE_STATE_LF; ) { if (curpos >= m_buflen) { /* buffer examined */ if (0 < (curpos - bufpos)) { /* flush buffer to sequence */ result = writeSequence_Impl ( ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos); if (result != osl_File_E_None) return (result); *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos; } bufptr = nOffset / m_bufsiz * m_bufsiz; if (bufptr != m_bufptr) { /* update buffer (pointer) */ sal_uInt64 uDone = 0; result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); if (result != osl_File_E_None) return (result); m_bufptr = bufptr, m_buflen = sal::static_int_cast< size_t >(uDone); } bufpos = sal::static_int_cast< size_t >(nOffset - m_bufptr), curpos = bufpos; if (bufpos >= m_buflen) break; } switch (state) { case LINE_STATE_CR: state = LINE_STATE_LF; switch (m_buffer[curpos]) { case 0x0A: /* CRLF */ /* eat current char */ curpos++; break; default: /* single CR */ /* keep current char */ break; } break; default: /* determine next state */ switch (m_buffer[curpos]) { case 0x0A: /* single LF */ state = LINE_STATE_LF; break; case 0x0D: /* CR */ state = LINE_STATE_CR; break; default: /* advance to next char */ curpos++; break; } if (state != LINE_STATE_BEGIN) { /* store (and eat) the newline char */ m_buffer[curpos] = 0x0A, curpos++; /* flush buffer to sequence */ result = writeSequence_Impl ( ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos - 1); if (result != osl_File_E_None) return (result); *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos; } break; } } result = writeSequence_Impl (ppSequence, &dstpos, 0, 0); if (result != osl_File_E_None) return (result); if (0 < dstpos) return osl_File_E_None; if (bufpos >= m_buflen) return osl_File_E_AGAIN; return osl_File_E_None; } oslFileError FileHandle_Impl::writeSequence_Impl ( sal_Sequence ** ppSequence, size_t * pnOffset, const void * pBuffer, size_t nBytes) { sal_Int32 nElements = *pnOffset + nBytes; if (!*ppSequence) { /* construct sequence */ rtl_byte_sequence_constructNoDefault(ppSequence, nElements); } else if (nElements != (*ppSequence)->nElements) { /* resize sequence */ rtl_byte_sequence_realloc(ppSequence, nElements); } if (*ppSequence != 0) { /* fill sequence */ memcpy(&((*ppSequence)->elements[*pnOffset]), pBuffer, nBytes), *pnOffset += nBytes; } return (*ppSequence != 0) ? osl_File_E_None : osl_File_E_NOMEM; } oslFileError FileHandle_Impl::syncFile() { oslFileError result = osl_File_E_None; if (m_state & STATE_MODIFIED) { sal_uInt64 uDone = 0; result = writeAt (m_bufptr, m_buffer, m_buflen, &uDone); if (result != osl_File_E_None) return (result); if (uDone != m_buflen) return osl_File_E_IO; m_state &= ~STATE_MODIFIED; } return (result); } /****************************************************************************** * * static members * *****************************************************************************/ static const char * pFileLockEnvVar = (char *) -1; /****************************************************************************** * * C-String Function Declarations * *****************************************************************************/ static oslFileError osl_psz_getVolumeInformation(const sal_Char* , oslVolumeInfo* pInfo, sal_uInt32 uFieldMask); static oslFileError osl_psz_removeFile(const sal_Char* pszPath); static oslFileError osl_psz_createDirectory(const sal_Char* pszPath); static oslFileError osl_psz_removeDirectory(const sal_Char* pszPath); static oslFileError osl_psz_copyFile(const sal_Char* pszPath, const sal_Char* pszDestPath); static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath); static oslFileError osl_psz_setFileTime(const sal_Char* strFilePath, const TimeValue* pCreationTime, const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime); /****************************************************************************** * * Static Module Utility Function Declarations * *****************************************************************************/ static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists); static oslFileError oslChangeFileModes(const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID); static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName); static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode); static oslFileError oslDoMoveFile(const sal_Char* pszPath, const sal_Char* pszDestPath); rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr,rtl_uString** uStr); /****************************************************************************** * * Non-Static Utility Function Declarations * *****************************************************************************/ extern "C" int UnicodeToText( char *, size_t, const sal_Unicode *, sal_Int32 ); extern "C" int TextToUnicode( const char* text, size_t text_buffer_size, sal_Unicode* unic_text, sal_Int32 unic_text_buffer_size); /****************************************************************************** * * 'removeable device' aka floppy functions * *****************************************************************************/ static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath); static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy); static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy); #ifdef DEBUG_OSL_FILE static void osl_printFloppyHandle(oslVolumeDeviceHandleImpl* hFloppy); #endif /********************************************** * _osl_openLocalRoot * enumerate available drives *********************************************/ static oslFileError _osl_openLocalRoot( rtl_uString *strDirectoryPath, oslDirectory *pDirectory) { rtl_uString *ustrSystemPath = NULL; oslFileError error; if ( !pDirectory ) return osl_File_E_INVAL; *pDirectory = NULL; error = osl_getSystemPathFromFileURL_Ex( strDirectoryPath, &ustrSystemPath, sal_False ); if ( osl_File_E_None == error ) { /* create and initialize impl structure */ DirectoryImpl* pDirImpl = (DirectoryImpl*) rtl_allocateMemory( sizeof(DirectoryImpl) ); if( pDirImpl ) { ULONG ulDriveNum; APIRET rc; pDirImpl->uType = DIRECTORYTYPE_LOCALROOT; pDirImpl->ustrPath = ustrSystemPath; rc = DosQueryCurrentDisk (&ulDriveNum, &pDirImpl->ulDriveMap); pDirImpl->pDirStruct = 0; pDirImpl->ulNextDrive = 1; pDirImpl->ulNextDriveMask = 1; // determine number of floppy-drives BYTE nFloppies; rc = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY ); if (nFloppies == 0) { // if no floppies, start with 3rd drive (C:) pDirImpl->ulNextDrive = 3; pDirImpl->ulNextDriveMask <<= 2; } else if (nFloppies == 1) { // mask drive B (second bit) in this case pDirImpl->ulDriveMap &= ~0x02; } *pDirectory = (oslDirectory) pDirImpl; return osl_File_E_None; } else { errno = osl_File_E_NOMEM; } } rtl_uString_release( ustrSystemPath ); return error; } /********************************************** * _osl_getNextDrive *********************************************/ static oslFileError SAL_CALL _osl_getNextDrive( oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint ) { DirectoryImpl *pDirImpl = (DirectoryImpl *)Directory; DirectoryItem_Impl *pItemImpl = NULL; rtl_uString * ustrDrive = NULL; BOOL fSuccess; char buffer[3]; uHint = uHint; /* avoid warnings */ if ( !pItem ) return osl_File_E_INVAL; *pItem = NULL; if ( !pDirImpl ) return osl_File_E_INVAL; while( pDirImpl->ulNextDrive <= 26) { // exit if bit==1 -> drive found if (pDirImpl->ulDriveMap & pDirImpl->ulNextDriveMask) { /* convert file name to unicode */ buffer[0] = '@' + pDirImpl->ulNextDrive; buffer[1] = ':'; buffer[2] = 0; pItemImpl = (DirectoryItem_Impl*) rtl_allocateMemory(sizeof(DirectoryItem_Impl)); if ( !pItemImpl ) return osl_File_E_NOMEM; memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); pItemImpl->uType = DIRECTORYITEM_DRIVE; pItemImpl->nRefCount = 1; rtl_string2UString( &pItemImpl->ustrDrive, buffer, 3, osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); OSL_ASSERT(pItemImpl->ustrDrive != 0); /* use drive as directory item */ *pItem = (oslDirectoryItem) pItemImpl; } // scan next bit position pDirImpl->ulNextDrive++; pDirImpl->ulNextDriveMask <<= 1; if (*pItem) // item assigned, return now. return osl_File_E_None; } // no more items return osl_File_E_NOENT; } /********************************************** * _osl_readdir_impl_ * * readdir wrapper, filters out "." and ".." * on request *********************************************/ static struct dirent* _osl_readdir_impl_(DIR* pdir, sal_Bool bFilterLocalAndParentDir) { struct dirent* pdirent; while ((pdirent = readdir(pdir)) != NULL) { if (bFilterLocalAndParentDir && ((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, "..")))) continue; else break; } return pdirent; } /******************************************************************* * osl_openDirectory ******************************************************************/ oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirectory* pDirectory) { rtl_uString* ustrSystemPath = NULL; oslFileError eRet; char path[PATH_MAX]; OSL_ASSERT(ustrDirectoryURL && (ustrDirectoryURL->length > 0)); OSL_ASSERT(pDirectory); if (0 == ustrDirectoryURL->length ) return osl_File_E_INVAL; if ( 0 == rtl_ustr_compareIgnoreAsciiCase( ustrDirectoryURL->buffer, (const sal_Unicode*)L"file:///" ) ) return _osl_openLocalRoot( ustrDirectoryURL, pDirectory ); /* convert file URL to system path */ eRet = osl_getSystemPathFromFileURL_Ex(ustrDirectoryURL, &ustrSystemPath, sal_False); if( osl_File_E_None != eRet ) return eRet; osl_systemPathRemoveSeparator(ustrSystemPath); /* convert unicode path to text */ if ( UnicodeToText( path, PATH_MAX, ustrSystemPath->buffer, ustrSystemPath->length ) ) { // if only the drive is specified (x:), add a \ (x:\) otherwise current // directory is browsed instead of root. if (strlen( path) == 2 && path[1] == ':') strcat( path, "\\"); /* open directory */ DIR *pdir = opendir( path ); if( pdir ) { /* create and initialize impl structure */ DirectoryImpl* pDirImpl = (DirectoryImpl*) rtl_allocateMemory( sizeof(DirectoryImpl) ); if( pDirImpl ) { pDirImpl->uType = DIRECTORYTYPE_FILESYSTEM; pDirImpl->pDirStruct = pdir; pDirImpl->ustrPath = ustrSystemPath; *pDirectory = (oslDirectory) pDirImpl; return osl_File_E_None; } else { errno = ENOMEM; closedir( pdir ); } } else /* should be removed by optimizer in product version */ PERROR( "osl_openDirectory", path ); } rtl_uString_release( ustrSystemPath ); return oslTranslateFileError(OSL_FET_ERROR, errno); } /**************************************************************************** * osl_getNextDirectoryItem ***************************************************************************/ oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, sal_uInt32 uHint) { DirectoryImpl* pDirImpl = (DirectoryImpl*)Directory; DirectoryItem_Impl *pItemImpl = NULL; rtl_uString* ustrFileName = NULL; rtl_uString* ustrFilePath = NULL; struct dirent* pEntry; OSL_ASSERT(Directory); OSL_ASSERT(pItem); if ((NULL == Directory) || (NULL == pItem)) return osl_File_E_INVAL; if ( pDirImpl->uType == DIRECTORYTYPE_LOCALROOT) return _osl_getNextDrive( Directory, pItem, uHint ); pEntry = _osl_readdir_impl_(pDirImpl->pDirStruct, sal_True); if (NULL == pEntry) return osl_File_E_NOENT; pItemImpl = (DirectoryItem_Impl*) rtl_allocateMemory(sizeof(DirectoryItem_Impl)); if ( !pItemImpl ) return osl_File_E_NOMEM; memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); pItemImpl->uType = DIRECTORYITEM_FILE; pItemImpl->nRefCount = 1; pItemImpl->d_attr = pEntry->d_attr; /* convert file name to unicode */ rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); OSL_ASSERT(ustrFileName != 0); osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &pItemImpl->ustrFilePath); rtl_uString_release( ustrFileName ); *pItem = (oslDirectoryItem)pItemImpl; return osl_File_E_None; } /****************************************************************************/ /* osl_closeDirectory */ /****************************************************************************/ oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory ) { DirectoryImpl* pDirImpl = (DirectoryImpl*) Directory; oslFileError err = osl_File_E_None; OSL_ASSERT( Directory ); if( NULL == pDirImpl ) return osl_File_E_INVAL; switch ( pDirImpl->uType ) { case DIRECTORYTYPE_FILESYSTEM: if( closedir( pDirImpl->pDirStruct ) ) err = oslTranslateFileError(OSL_FET_ERROR, errno); break; case DIRECTORYTYPE_LOCALROOT: err = osl_File_E_None; break; #if 0 case DIRECTORYTYPE_NETROOT: { DWORD err = WNetCloseEnum(pDirImpl->hDirectory); eError = (err == NO_ERROR) ? osl_File_E_None : MapError(err); } break; #endif default: OSL_ENSURE( 0, "Invalid directory type" ); break; } /* cleanup members */ rtl_uString_release( pDirImpl->ustrPath ); rtl_freeMemory( pDirImpl ); return err; } /****************************************************************************/ /* osl_getDirectoryItem */ /****************************************************************************/ oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem ) { rtl_uString* strSysFilePath = NULL; oslFileError error = osl_File_E_INVAL; ULONG dwPathType; PATHTYPE type = PATHTYPE_FILE; OSL_ASSERT(ustrFileURL); OSL_ASSERT(pItem); /* Assume failure */ if ( !pItem ) return osl_File_E_INVAL; *pItem = NULL; if (0 == ustrFileURL->length || NULL == pItem) return osl_File_E_INVAL; error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &strSysFilePath, sal_False); if (osl_File_E_None != error) return error; dwPathType = IsValidFilePath( strSysFilePath->buffer, NULL, VALIDATEPATH_NORMAL ); if ( dwPathType & PATHTYPE_IS_VOLUME ) type = PATHTYPE_VOLUME; else if ( dwPathType & PATHTYPE_IS_SERVER ) type = PATHTYPE_NETSERVER; else type = PATHTYPE_FILE; switch ( type ) { case PATHTYPE_NETSERVER: { DirectoryItem_Impl* pItemImpl = reinterpret_cast(rtl_allocateMemory(sizeof(DirectoryItem_Impl))); if ( !pItemImpl ) error = osl_File_E_NOMEM; if ( osl_File_E_None == error ) { memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); pItemImpl->uType = DIRECTORYITEM_SERVER; pItemImpl->nRefCount = 1; rtl_uString_assign( &pItemImpl->ustrFilePath, strSysFilePath ); *pItem = pItemImpl; } } break; case PATHTYPE_VOLUME: { DirectoryItem_Impl* pItemImpl = reinterpret_cast(rtl_allocateMemory(sizeof(DirectoryItem_Impl))); if ( !pItemImpl ) error = osl_File_E_NOMEM; if ( osl_File_E_None == error ) { memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); pItemImpl->uType = DIRECTORYITEM_DRIVE; pItemImpl->nRefCount = 1; rtl_uString_assign( &pItemImpl->ustrDrive, strSysFilePath ); if ( pItemImpl->ustrDrive->buffer[pItemImpl->ustrDrive->length-1] != sal_Unicode('\\') ) rtl_uString_newConcat( &pItemImpl->ustrDrive, pItemImpl->ustrDrive, rtl::OUString::createFromAscii( "\\" ).pData); *pItem = pItemImpl; } } break; default: case PATHTYPE_FILE: { if ( strSysFilePath->length > 0 && strSysFilePath->buffer[strSysFilePath->length - 1] == '\\' ) rtl_uString_newFromStr_WithLength( &strSysFilePath, strSysFilePath->buffer, strSysFilePath->length - 1 ); if (0 == access_u(strSysFilePath, F_OK)) { DirectoryItem_Impl *pItemImpl = reinterpret_cast(rtl_allocateMemory(sizeof(DirectoryItem_Impl))); memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); pItemImpl->uType = DIRECTORYITEM_FILE; pItemImpl->nRefCount = 1; rtl_uString_assign( &pItemImpl->ustrFilePath, strSysFilePath ); *pItem = pItemImpl; } else error = oslTranslateFileError(OSL_FET_ERROR, errno); } break; } if ( strSysFilePath ) rtl_uString_release( strSysFilePath ); return error; } /****************************************************************************/ /* osl_acquireDirectoryItem */ /****************************************************************************/ oslFileError osl_acquireDirectoryItem( oslDirectoryItem Item ) { OSL_ASSERT( Item ); DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; if ( !pItemImpl ) return osl_File_E_INVAL; pItemImpl->nRefCount++; return osl_File_E_None; } /****************************************************************************/ /* osl_releaseDirectoryItem */ /****************************************************************************/ oslFileError osl_releaseDirectoryItem( oslDirectoryItem Item ) { OSL_ASSERT( Item ); DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; if ( !pItemImpl ) return osl_File_E_INVAL; if ( ! --pItemImpl->nRefCount ) { if (pItemImpl->ustrFilePath) rtl_uString_release( pItemImpl->ustrFilePath ); if (pItemImpl->ustrDrive) rtl_uString_release( pItemImpl->ustrDrive ); rtl_freeMemory( pItemImpl ); } return osl_File_E_None; } /**************************************************************************** * osl_createFileHandleFromFD ***************************************************************************/ extern "C" oslFileHandle osl_createFileHandleFromFD( int fd ) { if (-1 == fd) return 0; // EINVAL struct stat aFileStat; if (-1 == fstat (fd, &aFileStat)) return 0; // EBADF FileHandle_Impl * pImpl = new FileHandle_Impl (fd); if (0 == pImpl) return 0; // ENOMEM // assume writeable pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE; if (!S_ISREG(aFileStat.st_mode)) { /* not a regular file, mark not seekable */ pImpl->m_state &= ~FileHandle_Impl::STATE_SEEKABLE; } else { /* regular file, init current size */ pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size); } OSL_FILE_TRACE("osl_createFileHandleFromFD(%d, writeable) => %s", pImpl->m_fd, rtl_string_getStr(pImpl->m_strFilePath)); return (oslFileHandle)(pImpl); } /******************************************************************* * osl_file_adjustLockFlags ******************************************************************/ static int osl_file_adjustLockFlags (const char * path, int flags) { #ifdef MACOSX /* * The AFP implementation of MacOS X 10.4 treats O_EXLOCK in a way * that makes it impossible for OOo to create a backup copy of the * file it keeps opened. OTOH O_SHLOCK for AFP behaves as desired by * the OOo file handling, so we need to check the path of the file * for the filesystem name. */ struct statfs s; if( 0 <= statfs( path, &s ) ) { if( 0 == strncmp("afpfs", s.f_fstypename, 5) ) { flags &= ~O_EXLOCK; flags |= O_SHLOCK; } else { /* Needed flags to allow opening a webdav file */ flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK); } } #endif /* MACOSX */ (void) path; return flags; } /**************************************************************************** * osl_file_queryLocking ***************************************************************************/ struct Locking_Impl { int m_enabled; Locking_Impl() : m_enabled(0) { #ifndef HAVE_O_EXLOCK m_enabled = ((getenv("SAL_ENABLE_FILE_LOCKING") != 0) || (getenv("STAR_ENABLE_FILE_LOCKING") != 0)); #endif /* HAVE_O_EXLOCK */ } }; static int osl_file_queryLocking (sal_uInt32 uFlags) { if (!(uFlags & osl_File_OpenFlag_NoLock)) { if ((uFlags & osl_File_OpenFlag_Write) || (uFlags & osl_File_OpenFlag_Create)) { static Locking_Impl g_locking; return (g_locking.m_enabled != 0); } } return 0; } /**************************************************************************** * osl_openFile ***************************************************************************/ #ifdef HAVE_O_EXLOCK #define OPEN_WRITE_FLAGS ( O_RDWR | O_EXLOCK | O_NONBLOCK ) #define OPEN_CREATE_FLAGS ( O_CREAT | O_EXCL | O_RDWR | O_EXLOCK | O_NONBLOCK ) #else #define OPEN_WRITE_FLAGS ( O_RDWR ) #define OPEN_CREATE_FLAGS ( O_CREAT | O_EXCL | O_RDWR ) #endif oslFileError SAL_CALL osl_openFile( rtl_uString* ustrFileURL, oslFileHandle* pHandle, sal_uInt32 uFlags ) { oslFileError eRet; if ((ustrFileURL == 0) || (ustrFileURL->length == 0) || (pHandle == 0)) return osl_File_E_INVAL; /* convert file URL to system path */ char buffer[PATH_MAX]; eRet = FileURLToPath (buffer, sizeof(buffer), ustrFileURL); if (eRet != osl_File_E_None) return eRet; #ifdef MACOSX if (macxp_resolveAlias (buffer, sizeof(buffer)) != 0) return oslTranslateFileError (OSL_FET_ERROR, errno); #endif /* MACOSX */ /* set mode and flags */ int mode = S_IRUSR | S_IRGRP | S_IROTH; int flags = O_RDONLY; if (uFlags & osl_File_OpenFlag_Write) { mode |= S_IWUSR | S_IWGRP | S_IWOTH; flags = OPEN_WRITE_FLAGS; } if (uFlags & osl_File_OpenFlag_Create) { mode |= S_IWUSR | S_IWGRP | S_IWOTH; flags = OPEN_CREATE_FLAGS; } if (uFlags & osl_File_OpenFlag_NoLock) { #ifdef HAVE_O_EXLOCK flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK); #endif /* HAVE_O_EXLOCK */ } else { flags = osl_file_adjustLockFlags (buffer, flags); } /* open the file */ int fd = open( buffer, flags | O_BINARY, mode ); if (-1 == fd) return oslTranslateFileError (OSL_FET_ERROR, errno); /* reset O_NONBLOCK flag */ if (flags & O_NONBLOCK) { int f = fcntl (fd, F_GETFL, 0); if (-1 == f) { eRet = oslTranslateFileError (OSL_FET_ERROR, errno); (void) close(fd); return eRet; } if (-1 == fcntl (fd, F_SETFL, (f & ~O_NONBLOCK))) { eRet = oslTranslateFileError (OSL_FET_ERROR, errno); (void) close(fd); return eRet; } } /* get file status (mode, size) */ struct stat aFileStat; if (-1 == fstat (fd, &aFileStat)) { eRet = oslTranslateFileError (OSL_FET_ERROR, errno); (void) close(fd); return eRet; } if (!S_ISREG(aFileStat.st_mode)) { /* we only open regular files here */ (void) close(fd); return osl_File_E_INVAL; } if (osl_file_queryLocking (uFlags)) { #ifdef MACOSX if (-1 == flock (fd, LOCK_EX | LOCK_NB)) { /* Mac OSX returns ENOTSUP for webdav drives. We should try read lock */ if ((errno != ENOTSUP) || ((-1 == flock (fd, LOCK_SH | LOCK_NB)) && (errno != ENOTSUP))) { eRet = oslTranslateFileError (OSL_FET_ERROR, errno); (void) close(fd); return eRet; } } #else /* F_SETLK */ { struct flock aflock; aflock.l_type = F_WRLCK; aflock.l_whence = SEEK_SET; aflock.l_start = 0; aflock.l_len = 0; if (-1 == fcntl (fd, F_SETLK, &aflock)) { eRet = oslTranslateFileError (OSL_FET_ERROR, errno); (void) close(fd); return eRet; } } #endif /* F_SETLK */ } /* allocate memory for impl structure */ FileHandle_Impl * pImpl = new FileHandle_Impl (fd, buffer); if (!pImpl) { eRet = oslTranslateFileError (OSL_FET_ERROR, ENOMEM); (void) close(fd); return eRet; } if (flags & O_RDWR) pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE; pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size); OSL_TRACE("osl_openFile(%d, %s) => %s", pImpl->m_fd, flags & O_RDWR ? "writeable":"readonly", rtl_string_getStr(pImpl->m_strFilePath)); *pHandle = (oslFileHandle)(pImpl); return osl_File_E_None; } /****************************************************************************/ /* osl_closeFile */ /****************************************************************************/ oslFileError SAL_CALL osl_closeFile( oslFileHandle Handle ) { FileHandle_Impl* pImpl = static_cast(Handle); if ((pImpl == 0) || (pImpl->m_fd < 0)) return osl_File_E_INVAL; /* close(2) implicitly (and unconditionally) unlocks */ OSL_TRACE("osl_closeFile(%d) => %s", pImpl->m_fd, rtl_string_getStr(pImpl->m_strFilePath)); oslFileError result = pImpl->syncFile(); if (result != osl_File_E_None) { /* close, ignoring double failure */ (void) close (pImpl->m_fd); } else if (-1 == close (pImpl->m_fd)) { /* translate error code */ result = oslTranslateFileError (OSL_FET_ERROR, errno); } delete pImpl; return (result); } /************************************************ * osl_syncFile ***********************************************/ oslFileError SAL_CALL osl_syncFile(oslFileHandle Handle) { FileHandle_Impl* pImpl = static_cast(Handle); if ((0 == pImpl) || (-1 == pImpl->m_fd)) return osl_File_E_INVAL; OSL_FILE_TRACE("osl_syncFile(%d)", pImpl->m_fd); oslFileError result = pImpl->syncFile(); if (result != osl_File_E_None) return (result); if (-1 == fsync (pImpl->m_fd)) return oslTranslateFileError (OSL_FET_ERROR, errno); return osl_File_E_None; } /******************************************* osl_mapFile ********************************************/ oslFileError SAL_CALL osl_mapFile ( oslFileHandle Handle, void** ppAddr, sal_uInt64 uLength, sal_uInt64 uOffset, sal_uInt32 uFlags ) { FileHandle_Impl* pImpl = static_cast(Handle); if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == ppAddr)) return osl_File_E_INVAL; *ppAddr = 0; static sal_uInt64 const g_limit_size_t = std::numeric_limits< size_t >::max(); if (g_limit_size_t < uLength) return osl_File_E_OVERFLOW; size_t const nLength = sal::static_int_cast< size_t >(uLength); static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max(); if (g_limit_off_t < uOffset) return osl_File_E_OVERFLOW; off_t const nOffset = sal::static_int_cast< off_t >(uOffset); #ifdef SAL_OS2 // YD mmap does not support shared void* p = mmap(NULL, nLength, PROT_READ, MAP_PRIVATE, pImpl->m_fd, nOffset); #else void* p = mmap(NULL, nLength, PROT_READ, MAP_SHARED, pImpl->m_fd, nOffset); #endif if (MAP_FAILED == p) return oslTranslateFileError(OSL_FET_ERROR, errno); *ppAddr = p; if (uFlags & osl_File_MapFlag_RandomAccess) { // Determine memory pagesize. size_t const nPageSize = FileHandle_Impl::getpagesize(); if (size_t(-1) != nPageSize) { /* * Pagein, touching first byte of every memory page. * Note: volatile disables optimizing the loop away. */ sal_uInt8 * pData (reinterpret_cast(*ppAddr)); size_t nSize (nLength); volatile sal_uInt8 c = 0; while (nSize > nPageSize) { c ^= pData[0]; pData += nPageSize; nSize -= nPageSize; } if (nSize > 0) { c^= pData[0]; pData += nSize; nSize -= nSize; } } } return osl_File_E_None; } /******************************************* osl_unmapFile ********************************************/ oslFileError SAL_CALL osl_unmapFile (void* pAddr, sal_uInt64 uLength) { if (0 == pAddr) return osl_File_E_INVAL; static sal_uInt64 const g_limit_size_t = std::numeric_limits< size_t >::max(); if (g_limit_size_t < uLength) return osl_File_E_OVERFLOW; size_t const nLength = sal::static_int_cast< size_t >(uLength); if (-1 == munmap(static_cast(pAddr), nLength)) return oslTranslateFileError(OSL_FET_ERROR, errno); return osl_File_E_None; } /******************************************* osl_readLine ********************************************/ oslFileError SAL_CALL osl_readLine ( oslFileHandle Handle, sal_Sequence ** ppSequence) { FileHandle_Impl * pImpl = static_cast(Handle); if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == ppSequence)) return osl_File_E_INVAL; sal_uInt64 uBytesRead = 0; // read at current fileptr; fileptr += uBytesRead; oslFileError result = pImpl->readLineAt ( pImpl->m_fileptr, ppSequence, &uBytesRead); if (result == osl_File_E_None) pImpl->m_fileptr += uBytesRead; return (result); } /******************************************* osl_readFile ********************************************/ oslFileError SAL_CALL osl_readFile ( oslFileHandle Handle, void * pBuffer, sal_uInt64 uBytesRequested, sal_uInt64 * pBytesRead) { FileHandle_Impl* pImpl = static_cast(Handle); if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesRead)) return osl_File_E_INVAL; static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max(); if (g_limit_ssize_t < uBytesRequested) return osl_File_E_OVERFLOW; size_t const nBytesRequested = sal::static_int_cast< size_t >(uBytesRequested); // read at current fileptr; fileptr += *pBytesRead; oslFileError result = pImpl->readFileAt ( pImpl->m_fileptr, pBuffer, nBytesRequested, pBytesRead); if (result == osl_File_E_None) pImpl->m_fileptr += *pBytesRead; return (result); } /******************************************* osl_writeFile ********************************************/ oslFileError SAL_CALL osl_writeFile ( oslFileHandle Handle, const void * pBuffer, sal_uInt64 uBytesToWrite, sal_uInt64 * pBytesWritten) { FileHandle_Impl* pImpl = static_cast(Handle); if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesWritten)) return osl_File_E_INVAL; if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE)) return osl_File_E_BADF; static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max(); if (g_limit_ssize_t < uBytesToWrite) return osl_File_E_OVERFLOW; size_t const nBytesToWrite = sal::static_int_cast< size_t >(uBytesToWrite); // write at current fileptr; fileptr += *pBytesWritten; oslFileError result = pImpl->writeFileAt ( pImpl->m_fileptr, pBuffer, nBytesToWrite, pBytesWritten); if (result == osl_File_E_None) pImpl->m_fileptr += *pBytesWritten; return (result); } /******************************************* osl_readFileAt ********************************************/ oslFileError SAL_CALL osl_readFileAt ( oslFileHandle Handle, sal_uInt64 uOffset, void* pBuffer, sal_uInt64 uBytesRequested, sal_uInt64* pBytesRead) { FileHandle_Impl* pImpl = static_cast(Handle); if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesRead)) return osl_File_E_INVAL; if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE)) return osl_File_E_SPIPE; static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max(); if (g_limit_off_t < uOffset) return osl_File_E_OVERFLOW; off_t const nOffset = sal::static_int_cast< off_t >(uOffset); static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max(); if (g_limit_ssize_t < uBytesRequested) return osl_File_E_OVERFLOW; size_t const nBytesRequested = sal::static_int_cast< size_t >(uBytesRequested); // read at specified fileptr return pImpl->readFileAt (nOffset, pBuffer, nBytesRequested, pBytesRead); } /******************************************* osl_writeFileAt ********************************************/ oslFileError SAL_CALL osl_writeFileAt ( oslFileHandle Handle, sal_uInt64 uOffset, const void* pBuffer, sal_uInt64 uBytesToWrite, sal_uInt64* pBytesWritten) { FileHandle_Impl* pImpl = static_cast(Handle); if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesWritten)) return osl_File_E_INVAL; if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE)) return osl_File_E_SPIPE; if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE)) return osl_File_E_BADF; static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max(); if (g_limit_off_t < uOffset) return osl_File_E_OVERFLOW; off_t const nOffset = sal::static_int_cast< off_t >(uOffset); static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max(); if (g_limit_ssize_t < uBytesToWrite) return osl_File_E_OVERFLOW; size_t const nBytesToWrite = sal::static_int_cast< size_t >(uBytesToWrite); // write at specified fileptr return pImpl->writeFileAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten); } /****************************************************************************/ /* osl_isEndOfFile */ /****************************************************************************/ oslFileError SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF ) { FileHandle_Impl* pImpl = static_cast(Handle); if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pIsEOF)) return osl_File_E_INVAL; *pIsEOF = (pImpl->getPos() == pImpl->getSize()); return osl_File_E_None; } /************************************************ * osl_getFilePos ***********************************************/ oslFileError SAL_CALL osl_getFilePos( oslFileHandle Handle, sal_uInt64* pPos ) { FileHandle_Impl* pImpl = static_cast(Handle); if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pPos)) return osl_File_E_INVAL; *pPos = pImpl->getPos(); return osl_File_E_None; } /******************************************* osl_setFilePos ********************************************/ oslFileError SAL_CALL osl_setFilePos (oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uOffset) { FileHandle_Impl* pImpl = static_cast(Handle); if ((0 == pImpl) || (-1 == pImpl->m_fd)) return osl_File_E_INVAL; static sal_Int64 const g_limit_off_t = std::numeric_limits< off_t >::max(); if (g_limit_off_t < uOffset) return osl_File_E_OVERFLOW; off_t nPos = 0, nOffset = sal::static_int_cast< off_t >(uOffset); switch(uHow) { case osl_Pos_Absolut: if (0 > nOffset) return osl_File_E_INVAL; break; case osl_Pos_Current: nPos = sal::static_int_cast< off_t >(pImpl->getPos()); if ((0 > nOffset) && (-1*nOffset > nPos)) return osl_File_E_INVAL; if (g_limit_off_t < nPos + nOffset) return osl_File_E_OVERFLOW; break; case osl_Pos_End: nPos = sal::static_int_cast< off_t >(pImpl->getSize()); if ((0 > nOffset) && (-1*nOffset > nPos)) return osl_File_E_INVAL; if (g_limit_off_t < nPos + nOffset) return osl_File_E_OVERFLOW; break; default: return osl_File_E_INVAL; } return pImpl->setPos (nPos + nOffset); } /**************************************************************************** * osl_getFileSize ****************************************************************************/ oslFileError SAL_CALL osl_getFileSize( oslFileHandle Handle, sal_uInt64* pSize ) { FileHandle_Impl* pImpl = static_cast(Handle); if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pSize)) return osl_File_E_INVAL; *pSize = pImpl->getSize(); return osl_File_E_None; } /************************************************ * osl_setFileSize ***********************************************/ oslFileError SAL_CALL osl_setFileSize( oslFileHandle Handle, sal_uInt64 uSize ) { FileHandle_Impl* pImpl = static_cast(Handle); if ((0 == pImpl) || (-1 == pImpl->m_fd)) return osl_File_E_INVAL; if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE)) return osl_File_E_BADF; static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max(); if (g_limit_off_t < uSize) return osl_File_E_OVERFLOW; oslFileError result = pImpl->syncFile(); if (result != osl_File_E_None) return (result); pImpl->m_bufptr = -1, pImpl->m_buflen = 0; return pImpl->setSize (uSize); } /****************************************************************************/ /* osl_moveFile */ /****************************************************************************/ oslFileError osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL ) { char srcPath[PATH_MAX]; char destPath[PATH_MAX]; oslFileError eRet; APIRET rc; OSL_ASSERT( ustrFileURL ); OSL_ASSERT( ustrDestURL ); /* convert source url to system path */ eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL ); if( eRet != osl_File_E_None ) return eRet; /* convert destination url to system path */ eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL ); if( eRet != osl_File_E_None ) return eRet; //YD 01/05/06 rename() can overwrite existing files. rc = DosDelete( (PCSZ)destPath); rc = DosMove( (PCSZ)srcPath, (PCSZ)destPath); if (!rc) eRet = osl_File_E_None; else eRet = MapError( rc); return eRet; } /****************************************************************************/ /* osl_copyFile */ /****************************************************************************/ #define TMP_DEST_FILE_EXTENSION ".osl-tmp" static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists) { int nRet=0; sal_Char pszTmpDestFile[PATH_MAX]; size_t size_tmp_dest_buff = sizeof(pszTmpDestFile); /* Quick fix for #106048, the whole copy file function seems to be erroneous anyway and needs to be rewritten. Besides osl_copyFile is currently not used from OO/SO code. */ memset(pszTmpDestFile, 0, size_tmp_dest_buff); if ( DestFileExists ) { strncpy(pszTmpDestFile, pszDestFileName, size_tmp_dest_buff - 1); if ((strlen(pszTmpDestFile) + strlen(TMP_DEST_FILE_EXTENSION)) >= size_tmp_dest_buff) return osl_File_E_NAMETOOLONG; strncat(pszTmpDestFile, TMP_DEST_FILE_EXTENSION, strlen(TMP_DEST_FILE_EXTENSION)); /* FIXME: what if pszTmpDestFile already exists? */ /* with getcanonical??? */ nRet=rename(pszDestFileName,pszTmpDestFile); } /* mfe: should be S_ISREG */ if ( !S_ISLNK(nMode) ) { /* copy SourceFile to DestFile */ nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode); } /* mfe: OK redundant at the moment */ else if ( S_ISLNK(nMode) ) { nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName); } else { /* mfe: what to do here? */ nRet=ENOSYS; } if ( nRet > 0 && DestFileExists == 1 ) { unlink(pszDestFileName); rename(pszTmpDestFile,pszDestFileName); } if ( nRet > 0 ) { return oslTranslateFileError(OSL_FET_ERROR, nRet); } if ( DestFileExists == 1 ) { unlink(pszTmpDestFile); } return osl_File_E_None; } /***************************************** * oslChangeFileModes ****************************************/ static oslFileError oslChangeFileModes( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID) { int nRet=0; struct utimbuf aTimeBuffer; nRet = chmod(pszFileName,nMode); if ( nRet < 0 ) { nRet=errno; return oslTranslateFileError(OSL_FET_ERROR, nRet); } aTimeBuffer.actime=nAcTime; aTimeBuffer.modtime=nModTime; nRet=utime(pszFileName,&aTimeBuffer); if ( nRet < 0 ) { nRet=errno; return oslTranslateFileError(OSL_FET_ERROR, nRet); } if ( nUID != getuid() ) { nUID=getuid(); } nRet=chown(pszFileName,nUID,nGID); if ( nRet < 0 ) { nRet=errno; /* mfe: do not return an error here! */ /* return oslTranslateFileError(nRet);*/ } return osl_File_E_None; } /***************************************** * oslDoCopyLink ****************************************/ static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName) { int nRet=0; /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */ /* mfe: if source is a link copy the link and not the file it points to (hro says so) */ sal_Char pszLinkContent[PATH_MAX]; pszLinkContent[0] = '\0'; nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX); if ( nRet < 0 ) { nRet=errno; return nRet; } else pszLinkContent[ nRet ] = 0; nRet = symlink(pszLinkContent,pszDestFileName); if ( nRet < 0 ) { nRet=errno; return nRet; } return 0; } /***************************************** * oslDoCopyFile ****************************************/ static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode) { int SourceFileFD=0; int DestFileFD=0; int nRet=0; void* pSourceFile=0; char buffer[ 4096]; SourceFileFD=open(pszSourceFileName,O_RDONLY | O_BINARY); if ( SourceFileFD < 0 ) { nRet=errno; return nRet; } DestFileFD=open(pszDestFileName, O_WRONLY | O_CREAT | O_BINARY, mode); if ( DestFileFD < 0 ) { nRet=errno; close(SourceFileFD); return nRet; } /* HACK: because memory mapping fails on various platforms if the size of the source file is 0 byte */ if (0 == nSourceSize) { close(SourceFileFD); close(DestFileFD); return 0; } while( (nRet = read(SourceFileFD, buffer, sizeof(buffer))) !=0 ) { nRet = write( DestFileFD, buffer, nRet); } close(SourceFileFD); close(DestFileFD); return nRet; } static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath ) { time_t nAcTime=0; time_t nModTime=0; uid_t nUID=0; gid_t nGID=0; int nRet=0; mode_t nMode=0; struct stat aFileStat; oslFileError tErr=osl_File_E_invalidError; size_t nSourceSize=0; int DestFileExists=1; /* mfe: does the source file really exists? */ nRet = lstat(pszPath,&aFileStat); if ( nRet < 0 ) { nRet=errno; return oslTranslateFileError(OSL_FET_ERROR, nRet); } /* mfe: we do only copy files here! */ if ( S_ISDIR(aFileStat.st_mode) ) { return osl_File_E_ISDIR; } nSourceSize=(size_t)aFileStat.st_size; nMode=aFileStat.st_mode; nAcTime=aFileStat.st_atime; nModTime=aFileStat.st_mtime; nUID=aFileStat.st_uid; nGID=aFileStat.st_gid; nRet = stat(pszDestPath,&aFileStat); if ( nRet < 0 ) { nRet=errno; if ( nRet == ENOENT ) { DestFileExists=0; } /* return oslTranslateFileError(nRet);*/ } /* mfe: the destination file must not be a directory! */ if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) ) { return osl_File_E_ISDIR; } else { /* mfe: file does not exists or is no dir */ } tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists); if ( tErr != osl_File_E_None ) { return tErr; } /* * mfe: ignore return code * since only the success of the copy is * important */ oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID); return tErr; } oslFileError osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL ) { char srcPath[PATH_MAX]; char destPath[PATH_MAX]; oslFileError eRet; APIRET rc; OSL_ASSERT( ustrFileURL ); OSL_ASSERT( ustrDestURL ); /* convert source url to system path */ eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL ); if( eRet != osl_File_E_None ) return eRet; /* convert destination url to system path */ eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL ); if( eRet != osl_File_E_None ) return eRet; return osl_psz_copyFile( srcPath, destPath ); } /****************************************************************************/ /* osl_removeFile */ /****************************************************************************/ oslFileError osl_removeFile( rtl_uString* ustrFileURL ) { char path[PATH_MAX]; oslFileError eRet; APIRET rc; OSL_ASSERT( ustrFileURL ); /* convert file url to system path */ eRet = FileURLToPath( path, PATH_MAX, ustrFileURL ); if( eRet != osl_File_E_None ) return eRet; rc = DosDelete( (PCSZ)path); if (!rc) eRet = osl_File_E_None; else eRet = MapError( rc); return eRet; } /****************************************************************************/ /* osl_getVolumeInformation */ /****************************************************************************/ #define TXFSDC_BLOCKR 0x00 // block device removable #define TXFSDC_GETBPB 0x00 // get device bpb info #define TXFSBPB_REMOVABLE 0x08 // BPB attribute for removable typedef struct drivecmd { BYTE cmd; // 0=unlock 1=lock 2=eject BYTE drv; // 0=A, 1=B 2=C ... } DRIVECMD; // end of struct "drivecmd" #pragma pack(push, 1) // byte packing typedef struct txfs_ebpb // ext. boot parameter block { // at offset 0x0b in bootsector USHORT SectSize; // 0B bytes per sector BYTE ClustSize; // 0D sectors per cluster USHORT FatOffset; // 0E sectors to 1st FAT BYTE NrOfFats; // 10 nr of FATS (FAT only) USHORT RootEntries; // 11 Max entries \ (FAT only) USHORT Sectors; // 13 nr of sectors if < 64K BYTE MediaType; // 15 mediatype (F8 for HD) USHORT FatSectors; // 16 sectors/FAT (FAT only) USHORT LogGeoSect; // 18 sectors/Track USHORT LogGeoHead; // 1a nr of heads ULONG HiddenSectors; // 1c sector-offset from MBR/EBR ULONG BigSectors; // 20 nr of sectors if >= 64K } TXFS_EBPB; // last byte is at offset 0x23 typedef struct drivebpb { TXFS_EBPB ebpb; // extended BPB BYTE reserved[6]; USHORT cyls; BYTE type; USHORT attributes; // device attributes BYTE fill[6]; // documented for IOCtl } DRIVEBPB; // end of struct "drivebpb" struct CDInfo { USHORT usCount; USHORT usFirst; }; #pragma pack(pop) /*****************************************************************************/ // Get number of cdrom readers /*****************************************************************************/ BOOL GetCDInfo( CDInfo * pCDInfo ) { HFILE hFileCD; ULONG ulAction; if( NO_ERROR == DosOpen( (PCSZ)"\\DEV\\CD-ROM2$", &hFileCD, &ulAction, 0, FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL )) { ULONG ulDataSize = sizeof(CDInfo); APIRET rc = DosDevIOCtl( hFileCD, 0x82, 0x60, NULL, 0, NULL, (PVOID)pCDInfo, ulDataSize, &ulDataSize); DosClose( hFileCD); if(rc == NO_ERROR) return TRUE; } // failed pCDInfo->usFirst = 0; pCDInfo->usCount = 0; return FALSE; } /*****************************************************************************/ // Determine if unit is a cdrom or not /*****************************************************************************/ BOOL DriveIsCDROM(UINT uiDrive, CDInfo *pCDInfo) { return (uiDrive >= pCDInfo->usFirst) && (uiDrive < (pCDInfo->usFirst + pCDInfo->usCount)); } /*****************************************************************************/ // Determine attached fstype, e.g. HPFS for specified drive /*****************************************************************************/ BOOL TxFsType // RET FS type resolved ( char *drive, // IN Drive specification char *fstype, // OUT Attached FS type char *details // OUT details (UNC) or NULL ) { BOOL rc = FALSE; FSQBUFFER2 *fsinfo; // Attached FS info ULONG fsdlen = 2048; // Fs info data length strcpy(fstype, "none"); if (details) { strcpy(details, ""); } if ((fsinfo = (FSQBUFFER2*)calloc(1, fsdlen)) != NULL) { if (DosQFSAttach((PCSZ)drive, 0, 1, fsinfo, &fsdlen) == NO_ERROR) { strcpy(fstype, (char*) fsinfo->szName + fsinfo->cbName +1); if (details && (fsinfo->cbFSAData != 0)) { strcpy( details, (char*) fsinfo->szName + fsinfo->cbName + fsinfo->cbFSDName +2); } rc = TRUE; } free(fsinfo); } return (rc); } // end 'TxFsType' /*---------------------------------------------------------------------------*/ /*****************************************************************************/ // Determine if a driveletter represents a removable medium/device /*****************************************************************************/ BOOL TxFsIsRemovable // RET drive is removable ( char *drive // IN Driveletter to test ) { BOOL rc = FALSE; DRIVECMD IOCtl; DRIVEBPB RemAt; ULONG DataLen; ULONG ParmLen; BYTE NoRem; DosError( FERR_DISABLEHARDERR); // avoid 'not ready' popups ParmLen = sizeof(IOCtl); IOCtl.cmd = TXFSDC_BLOCKR; IOCtl.drv = toupper(drive[0]) - 'A'; DataLen = sizeof(NoRem); if (DosDevIOCtl((HFILE) -1, IOCTL_DISK, DSK_BLOCKREMOVABLE, &IOCtl, ParmLen, &ParmLen, &NoRem, DataLen, &DataLen) == NO_ERROR) { if (NoRem) // non-removable sofar, check { // BPB as well (USB devices) ParmLen = sizeof(IOCtl); IOCtl.cmd = TXFSDC_GETBPB; IOCtl.drv = toupper(drive[0]) - 'A'; DataLen = sizeof(RemAt); if (DosDevIOCtl((HFILE) -1, IOCTL_DISK, DSK_GETDEVICEPARAMS, &IOCtl, ParmLen, &ParmLen, &RemAt, DataLen, &DataLen) == NO_ERROR) { if (RemAt.attributes & TXFSBPB_REMOVABLE) { rc = TRUE; // removable, probably USB } } } else { rc = TRUE; // removable block device } } DosError( FERR_ENABLEHARDERR); // enable criterror handler return (rc); } // end 'TxFsIsRemovable' /*---------------------------------------------------------------------------*/ static oslFileError get_drive_type(const char* path, oslVolumeInfo* pInfo) { char Drive_Letter = toupper( *path); char fstype[ 64]; pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; // check for floppy A/B BYTE nFloppies; APIRET rc; rc = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY ); if ((Drive_Letter - 'A') < nFloppies) { pInfo->uAttributes |= osl_Volume_Attribute_Removeable; pInfo->uAttributes |= osl_Volume_Attribute_FloppyDisk; return osl_File_E_None; } // query system for CD drives CDInfo cdInfo; GetCDInfo(&cdInfo); // query if drive is a CDROM if (DriveIsCDROM( Drive_Letter - 'A', &cdInfo)) pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable; if (TxFsIsRemovable( (char*)path)) pInfo->uAttributes |= osl_Volume_Attribute_Removeable; if (TxFsType( (char*)path, fstype, NULL) == FALSE) { // query failed, assume fixed disk pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk; return osl_File_E_None; } //- Note, connected Win-NT drives use the REAL FS-name like NTFS! if ((strncasecmp( fstype, "LAN", 3) == 0) //- OS/2 LAN drives || (strncasecmp( fstype, "NDFS", 4) == 0) //- NetDrive || (strncasecmp( fstype, "REMOTE", 5) == 0) ) //- NT disconnected pInfo->uAttributes |= osl_Volume_Attribute_Remote; else if (strncasecmp( fstype, "RAMFS", 5) == 0) pInfo->uAttributes |= osl_Volume_Attribute_RAMDisk; else if ((strncasecmp( fstype, "CD", 2) == 0) // OS2:CDFS, DOS/WIN:CDROM || (strncasecmp( fstype, "UDF", 3) == 0) ) // OS2:UDF DVD's pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable; else pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk; return osl_File_E_None; } //############################################# inline bool is_volume_space_info_request(sal_uInt32 field_mask) { return (field_mask & (osl_VolumeInfo_Mask_TotalSpace | osl_VolumeInfo_Mask_UsedSpace | osl_VolumeInfo_Mask_FreeSpace)); } //############################################# static void get_volume_space_information(const char* path, oslVolumeInfo *pInfo) { FSALLOCATE aFSInfoBuf; ULONG nDriveNumber = toupper( *path) - 'A' + 1; // disable error popups DosError(FERR_DISABLEHARDERR); APIRET rc = DosQueryFSInfo( nDriveNumber, FSIL_ALLOC, &aFSInfoBuf, sizeof(aFSInfoBuf) ); // enable error popups DosError(FERR_ENABLEHARDERR); if (!rc) { uint64_t aBytesPerCluster( uint64_t(aFSInfoBuf.cbSector) * uint64_t(aFSInfoBuf.cSectorUnit) ); pInfo->uFreeSpace = aBytesPerCluster * uint64_t(aFSInfoBuf.cUnitAvail); pInfo->uTotalSpace = aBytesPerCluster * uint64_t(aFSInfoBuf.cUnit); pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace; pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace | osl_VolumeInfo_Mask_UsedSpace | osl_VolumeInfo_Mask_FreeSpace; } } //############################################# inline bool is_filesystem_attributes_request(sal_uInt32 field_mask) { return (field_mask & (osl_VolumeInfo_Mask_MaxNameLength | osl_VolumeInfo_Mask_MaxPathLength | osl_VolumeInfo_Mask_FileSystemName | osl_VolumeInfo_Mask_FileSystemCaseHandling)); } //############################################# inline bool is_drivetype_request(sal_uInt32 field_mask) { return (field_mask & osl_VolumeInfo_Mask_Attributes); } typedef struct _FSQBUFFER_ { FSQBUFFER2 aBuf; UCHAR sBuf[64]; } FSQBUFFER_; //############################################# static oslFileError get_filesystem_attributes(const char* path, sal_uInt32 field_mask, oslVolumeInfo* pInfo) { pInfo->uAttributes = 0; oslFileError osl_error = osl_File_E_None; // osl_get_drive_type must be called first because // this function resets osl_VolumeInfo_Mask_Attributes // on failure if (is_drivetype_request(field_mask)) osl_error = get_drive_type(path, pInfo); if ((osl_File_E_None == osl_error) && is_filesystem_attributes_request(field_mask)) { FSQBUFFER_ aBuf; ULONG nBufLen; APIRET nRet; nBufLen = sizeof( aBuf ); // disable error popups DosError(FERR_DISABLEHARDERR); nRet = DosQueryFSAttach( (PCSZ)path, 0, FSAIL_QUERYNAME, (_FSQBUFFER2*) &aBuf, &nBufLen ); if ( !nRet ) { char *pType = (char*)(aBuf.aBuf.szName + aBuf.aBuf.cbName + 1); pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength; pInfo->uMaxNameLength = _MAX_FNAME; pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength; pInfo->uMaxPathLength = _MAX_PATH; pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName; rtl_uString_newFromAscii(&pInfo->ustrFileSystemName, pType); // case is preserved always except for FAT if (strcmp( pType, "FAT" )) pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved; pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; } // enable error popups DosError(FERR_ENABLEHARDERR); } return osl_error; } oslFileError SAL_CALL osl_getVolumeInformation( rtl_uString* ustrDirectoryURL, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask ) { char volume_root[PATH_MAX]; oslFileError error; OSL_ASSERT( ustrDirectoryURL ); OSL_ASSERT( pInfo ); /* convert directory url to system path */ error = FileURLToPath( volume_root, PATH_MAX, ustrDirectoryURL ); if( error != osl_File_E_None ) return error; if (!pInfo) return osl_File_E_INVAL; pInfo->uValidFields = 0; if ((error = get_filesystem_attributes(volume_root, uFieldMask, pInfo)) != osl_File_E_None) return error; if (is_volume_space_info_request(uFieldMask)) get_volume_space_information(volume_root, pInfo); if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle) { pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle; rtl_uString* uVolumeRoot; rtl_uString_newFromAscii( &uVolumeRoot, volume_root); osl_getFileURLFromSystemPath( uVolumeRoot, (rtl_uString**)&pInfo->pDeviceHandle); rtl_uString_release( uVolumeRoot); } return osl_File_E_None; } /****************************************************************************/ /* osl_getFileStatus */ /****************************************************************************/ static oslFileError _osl_getDriveInfo( oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask) { DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; sal_Unicode cDrive[3]; sal_Unicode cRoot[4]; if ( !pItemImpl ) return osl_File_E_INVAL; pStatus->uValidFields = 0; cDrive[0] = pItemImpl->ustrDrive->buffer[0]; cDrive[1] = (sal_Unicode)':'; cDrive[2] = 0; cRoot[0] = pItemImpl->ustrDrive->buffer[0]; cRoot[1] = (sal_Unicode)':'; cRoot[2] = 0; if ( uFieldMask & osl_FileStatus_Mask_FileName ) { if ( pItemImpl->ustrDrive->buffer[0] == '\\' && pItemImpl->ustrDrive->buffer[1] == '\\' ) { LPCWSTR lpFirstBkSlash = wcschr( (const wchar_t*)&pItemImpl->ustrDrive->buffer[2], '\\' ); if ( lpFirstBkSlash && lpFirstBkSlash[1] ) { LPCWSTR lpLastBkSlash = wcschr( (const wchar_t*)&lpFirstBkSlash[1], '\\' ); if ( lpLastBkSlash ) rtl_uString_newFromStr_WithLength( &pStatus->ustrFileName, (sal_Unicode*)&lpFirstBkSlash[1], lpLastBkSlash - lpFirstBkSlash - 1 ); else rtl_uString_newFromStr( &pStatus->ustrFileName, (sal_Unicode*)&lpFirstBkSlash[1] ); pStatus->uValidFields |= osl_FileStatus_Mask_FileName; } } else { FSINFO aFSInfoBuf; ULONG ulFSInfoLevel = FSIL_VOLSER; ULONG nDriveNumber; char szFileName[ _MAX_PATH]; nDriveNumber = toupper(*cDrive) - 'A' + 1; memset( &aFSInfoBuf, 0, sizeof(FSINFO) ); // disable error popups DosError(FERR_DISABLEHARDERR); APIRET rc = DosQueryFSInfo( nDriveNumber, ulFSInfoLevel, &aFSInfoBuf, sizeof(FSINFO) ); // enable error popups DosError(FERR_ENABLEHARDERR); memset( szFileName, 0, sizeof( szFileName)); *szFileName = toupper(*cDrive); strcat( szFileName, ": ["); if ( !rc || aFSInfoBuf.vol.cch) strncat( szFileName, aFSInfoBuf.vol.szVolLabel, aFSInfoBuf.vol.cch); strcat( szFileName, "]"); rtl_uString_newFromAscii( &pStatus->ustrFileName, szFileName ); pStatus->uValidFields |= osl_FileStatus_Mask_FileName; } } pStatus->eType = osl_File_Type_Volume; pStatus->uValidFields |= osl_FileStatus_Mask_Type; if ( uFieldMask & osl_FileStatus_Mask_FileURL ) { rtl_uString *ustrSystemPath = NULL; rtl_uString_newFromStr( &ustrSystemPath, pItemImpl->ustrDrive->buffer ); osl_getFileURLFromSystemPath( ustrSystemPath, &pStatus->ustrFileURL ); rtl_uString_release( ustrSystemPath ); pStatus->uValidFields |= osl_FileStatus_Mask_FileURL; } return osl_File_E_None; } oslFileError SAL_CALL osl_getFileStatus( oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask ) { DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; struct stat file_stat; if ( !pItemImpl ) return osl_File_E_INVAL; if ( pItemImpl->uType == DIRECTORYITEM_DRIVE) return _osl_getDriveInfo( Item, pStatus, uFieldMask ); osl::lstat(pItemImpl->ustrFilePath, file_stat); if ( uFieldMask & osl_FileStatus_Mask_Validate ) { uFieldMask &= ~ osl_FileStatus_Mask_Validate; } /* If no fields to retrieve left ignore pStatus */ if ( !uFieldMask ) return osl_File_E_None; /* Otherwise, this must be a valid pointer */ if ( !pStatus ) return osl_File_E_INVAL; if ( pStatus->uStructSize != sizeof(oslFileStatus) ) return osl_File_E_INVAL; pStatus->uValidFields = 0; /* File time stamps */ if ( (uFieldMask & osl_FileStatus_Mask_ModifyTime)) { pStatus->aModifyTime.Seconds = file_stat.st_mtime; pStatus->aModifyTime.Nanosec = 0; pStatus->uValidFields |= osl_FileStatus_Mask_ModifyTime; } if ( (uFieldMask & osl_FileStatus_Mask_AccessTime)) { pStatus->aAccessTime.Seconds = file_stat.st_atime; pStatus->aAccessTime.Nanosec = 0; pStatus->uValidFields |= osl_FileStatus_Mask_AccessTime; } if ( (uFieldMask & osl_FileStatus_Mask_CreationTime)) { pStatus->aAccessTime.Seconds = file_stat.st_birthtime; pStatus->aAccessTime.Nanosec = 0; pStatus->uValidFields |= osl_FileStatus_Mask_CreationTime; } /* Most of the fields are already set, regardless of requiered fields */ osl_systemPathGetFileNameOrLastDirectoryPart(pItemImpl->ustrFilePath, &pStatus->ustrFileName); pStatus->uValidFields |= osl_FileStatus_Mask_FileName; if (S_ISLNK(file_stat.st_mode)) pStatus->eType = osl_File_Type_Link; else if (S_ISDIR(file_stat.st_mode)) pStatus->eType = osl_File_Type_Directory; else if (S_ISREG(file_stat.st_mode)) pStatus->eType = osl_File_Type_Regular; else if (S_ISFIFO(file_stat.st_mode)) pStatus->eType = osl_File_Type_Fifo; else if (S_ISSOCK(file_stat.st_mode)) pStatus->eType = osl_File_Type_Socket; else if (S_ISCHR(file_stat.st_mode) || S_ISBLK(file_stat.st_mode)) pStatus->eType = osl_File_Type_Special; else pStatus->eType = osl_File_Type_Unknown; pStatus->uValidFields |= osl_FileStatus_Mask_Type; pStatus->uAttributes = pItemImpl->d_attr; pStatus->uValidFields |= osl_FileStatus_Mask_Attributes; pStatus->uFileSize = file_stat.st_size; pStatus->uValidFields |= osl_FileStatus_Mask_FileSize; if ( uFieldMask & osl_FileStatus_Mask_LinkTargetURL ) { rtl_uString *ustrFullPath = NULL; rtl_uString_newFromStr( &ustrFullPath, rtl_uString_getStr(pItemImpl->ustrFilePath) ); osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrLinkTargetURL ); rtl_uString_release( ustrFullPath ); pStatus->uValidFields |= osl_FileStatus_Mask_LinkTargetURL; } if ( uFieldMask & osl_FileStatus_Mask_FileURL ) { rtl_uString *ustrFullPath = NULL; rtl_uString_newFromStr( &ustrFullPath, rtl_uString_getStr(pItemImpl->ustrFilePath) ); osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrFileURL ); rtl_uString_release( ustrFullPath ); pStatus->uValidFields |= osl_FileStatus_Mask_FileURL; } return osl_File_E_None; } /****************************************************************************/ /* osl_createDirectory */ /****************************************************************************/ oslFileError osl_createDirectory( rtl_uString* ustrDirectoryURL ) { char path[PATH_MAX]; oslFileError eRet; APIRET rc; OSL_ASSERT( ustrDirectoryURL ); /* convert directory url to system path */ eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL ); if( eRet != osl_File_E_None ) return eRet; rc = DosCreateDir( (PCSZ)path, NULL); if (rc == ERROR_ACCESS_DENIED) rc=ERROR_FILE_EXISTS; if (!rc) eRet = osl_File_E_None; else eRet = MapError( rc); return eRet; } /****************************************************************************/ /* osl_removeDirectory */ /****************************************************************************/ oslFileError osl_removeDirectory( rtl_uString* ustrDirectoryURL ) { char path[PATH_MAX]; oslFileError eRet; APIRET rc; OSL_ASSERT( ustrDirectoryURL ); /* convert directory url to system path */ eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL ); if( eRet != osl_File_E_None ) return eRet; rc = DosDeleteDir( (PCSZ)path); if (!rc) eRet = osl_File_E_None; else eRet = MapError( rc); return eRet; } //############################################# int path_make_parent(sal_Unicode* path) { int i = rtl_ustr_lastIndexOfChar(path, '/'); if (i == -1) i = rtl_ustr_lastIndexOfChar(path, '\\'); if (i > 0) { *(path + i) = 0; return i; } else return 0; } //############################################# int create_dir_with_callback( sal_Unicode* directory_path, oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, void* pData) { int mode = S_IRWXU | S_IRWXG | S_IRWXO; if (osl::mkdir(directory_path, mode) == 0) { if (aDirectoryCreationCallbackFunc) { rtl::OUString url; osl::FileBase::getFileURLFromSystemPath(directory_path, url); aDirectoryCreationCallbackFunc(pData, url.pData); } return 0; } return errno; } //############################################# oslFileError create_dir_recursively_( sal_Unicode* dir_path, oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, void* pData) { OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \ "Path must not end with a slash"); int native_err = create_dir_with_callback( dir_path, aDirectoryCreationCallbackFunc, pData); if (native_err == 0) return osl_File_E_None; if (native_err != ENOENT) return oslTranslateFileError(OSL_FET_ERROR, native_err); // we step back until '/a_dir' at maximum because // we should get an error unequal ENOENT when // we try to create 'a_dir' at '/' and would so // return before int pos = path_make_parent(dir_path); oslFileError osl_error = create_dir_recursively_( dir_path, aDirectoryCreationCallbackFunc, pData); if (osl_File_E_None != osl_error) return osl_error; dir_path[pos] = '/'; return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData); } //####################################### oslFileError SAL_CALL osl_createDirectoryPath( rtl_uString* aDirectoryUrl, oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, void* pData) { if (aDirectoryUrl == NULL) return osl_File_E_INVAL; rtl::OUString sys_path; oslFileError osl_error = osl_getSystemPathFromFileURL_Ex( aDirectoryUrl, &sys_path.pData, sal_False); if (osl_error != osl_File_E_None) return osl_error; osl::systemPathRemoveSeparator(sys_path); // const_cast because sys_path is a local copy which we want to modify inplace instead of // coyp it into another buffer on the heap again return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData); } /****************************************************************************/ /* osl_getCanonicalName */ /****************************************************************************/ oslFileError osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uString** pustrValidURL ) { OSL_ENSURE(sal_False, "osl_getCanonicalName not implemented"); rtl_uString_newFromString(pustrValidURL, ustrFileURL); return osl_File_E_None; } /****************************************************************************/ /* osl_setFileAttributes */ /****************************************************************************/ oslFileError osl_setFileAttributes( rtl_uString* ustrFileURL, sal_uInt64 uAttributes ) { char path[PATH_MAX]; oslFileError eRet; FILESTATUS3 fsts3ConfigInfo; ULONG ulBufSize = sizeof(FILESTATUS3); APIRET rc = NO_ERROR; OSL_ASSERT( ustrFileURL ); /* convert file url to system path */ eRet = FileURLToPath( path, PATH_MAX, ustrFileURL ); if( eRet != osl_File_E_None ) return eRet; /* query current attributes */ rc = DosQueryPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize); if (rc != NO_ERROR) return MapError( rc); /* set/reset readonly/hidden (see w32\file.cxx) */ fsts3ConfigInfo.attrFile &= ~(FILE_READONLY | FILE_HIDDEN); if ( uAttributes & osl_File_Attribute_ReadOnly ) fsts3ConfigInfo.attrFile |= FILE_READONLY; if ( uAttributes & osl_File_Attribute_Hidden ) fsts3ConfigInfo.attrFile |= FILE_HIDDEN; /* write new attributes */ rc = DosSetPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize, 0); if (rc != NO_ERROR) return MapError( rc); /* everything ok */ return osl_File_E_None; } /****************************************************************************/ /* osl_setFileTime */ /****************************************************************************/ oslFileError osl_setFileTime( rtl_uString* ustrFileURL, const TimeValue* pCreationTime, const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime ) { char path[PATH_MAX]; oslFileError eRet; OSL_ASSERT( ustrFileURL ); /* convert file url to system path */ eRet = FileURLToPath( path, PATH_MAX, ustrFileURL ); if( eRet != osl_File_E_None ) return eRet; return osl_psz_setFileTime( path, pCreationTime, pLastAccessTime, pLastWriteTime ); } /****************************************************************************** * * Exported Module Functions * (independent of C or Unicode Strings) * *****************************************************************************/ /****************************************************************************** * * C-String Versions of Exported Module Functions * *****************************************************************************/ /****************************************** * osl_psz_setFileTime *****************************************/ static oslFileError osl_psz_setFileTime( const sal_Char* pszFilePath, const TimeValue* /*pCreationTime*/, const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime ) { int nRet=0; struct utimbuf aTimeBuffer; struct stat aFileStat; #ifdef DEBUG_OSL_FILE struct tm* pTM=0; #endif nRet = lstat(pszFilePath,&aFileStat); if ( nRet < 0 ) { nRet=errno; return oslTranslateFileError(OSL_FET_ERROR, nRet); } #ifdef DEBUG_OSL_FILE fprintf(stderr,"File Times are (in localtime):\n"); pTM=localtime(&aFileStat.st_ctime); fprintf(stderr,"CreationTime is '%s'\n",asctime(pTM)); pTM=localtime(&aFileStat.st_atime); fprintf(stderr,"AccessTime is '%s'\n",asctime(pTM)); pTM=localtime(&aFileStat.st_mtime); fprintf(stderr,"Modification is '%s'\n",asctime(pTM)); fprintf(stderr,"File Times are (in UTC):\n"); fprintf(stderr,"CreationTime is '%s'\n",ctime(&aFileStat.st_ctime)); fprintf(stderr,"AccessTime is '%s'\n",ctime(&aTimeBuffer.actime)); fprintf(stderr,"Modification is '%s'\n",ctime(&aTimeBuffer.modtime)); #endif if ( pLastAccessTime != 0 ) { aTimeBuffer.actime=pLastAccessTime->Seconds; } else { aTimeBuffer.actime=aFileStat.st_atime; } if ( pLastWriteTime != 0 ) { aTimeBuffer.modtime=pLastWriteTime->Seconds; } else { aTimeBuffer.modtime=aFileStat.st_mtime; } /* mfe: Creation time not used here! */ #ifdef DEBUG_OSL_FILE fprintf(stderr,"File Times are (in localtime):\n"); pTM=localtime(&aFileStat.st_ctime); fprintf(stderr,"CreationTime now '%s'\n",asctime(pTM)); pTM=localtime(&aTimeBuffer.actime); fprintf(stderr,"AccessTime now '%s'\n",asctime(pTM)); pTM=localtime(&aTimeBuffer.modtime); fprintf(stderr,"Modification now '%s'\n",asctime(pTM)); fprintf(stderr,"File Times are (in UTC):\n"); fprintf(stderr,"CreationTime now '%s'\n",ctime(&aFileStat.st_ctime)); fprintf(stderr,"AccessTime now '%s'\n",ctime(&aTimeBuffer.actime)); fprintf(stderr,"Modification now '%s'\n",ctime(&aTimeBuffer.modtime)); #endif nRet=utime(pszFilePath,&aTimeBuffer); if ( nRet < 0 ) { nRet=errno; return oslTranslateFileError(OSL_FET_ERROR, nRet); } return osl_File_E_None; } /****************************************************************************** * * Utility Functions * *****************************************************************************/ /***************************************** * oslMakeUStrFromPsz ****************************************/ rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr, rtl_uString** ustrValid) { rtl_string2UString( ustrValid, pszStr, rtl_str_getLength( pszStr ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS ); OSL_ASSERT(*ustrValid != 0); return *ustrValid; } /***************************************************************************** * UnicodeToText * converting unicode to text manually saves us the penalty of a temporary * rtl_String object. ****************************************************************************/ int UnicodeToText( char * buffer, size_t bufLen, const sal_Unicode * uniText, sal_Int32 uniTextLen ) { rtl_UnicodeToTextConverter hConverter; sal_uInt32 nInfo; sal_Size nSrcChars, nDestBytes; /* stolen from rtl/string.c */ hConverter = rtl_createUnicodeToTextConverter( osl_getThreadTextEncoding() ); nDestBytes = rtl_convertUnicodeToText( hConverter, 0, uniText, uniTextLen, buffer, bufLen, OUSTRING_TO_OSTRING_CVTFLAGS | RTL_UNICODETOTEXT_FLAGS_FLUSH, &nInfo, &nSrcChars ); rtl_destroyUnicodeToTextConverter( hConverter ); if( nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL ) { errno = EOVERFLOW; return 0; } /* ensure trailing '\0' */ buffer[nDestBytes] = '\0'; return nDestBytes; } /***************************************************************************** TextToUnicode @param text The text to convert. @param text_buffer_size The number of characters. @param unic_text The unicode buffer. @param unic_text_buffer_size The size in characters of the unicode buffer. ****************************************************************************/ int TextToUnicode( const char* text, size_t text_buffer_size, sal_Unicode* unic_text, sal_Int32 unic_text_buffer_size) { rtl_TextToUnicodeConverter hConverter; sal_uInt32 nInfo; sal_Size nSrcChars; sal_Size nDestBytes; /* stolen from rtl/string.c */ hConverter = rtl_createTextToUnicodeConverter(osl_getThreadTextEncoding()); nDestBytes = rtl_convertTextToUnicode(hConverter, 0, text, text_buffer_size, unic_text, unic_text_buffer_size, OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_FLUSH, &nInfo, &nSrcChars); rtl_destroyTextToUnicodeConverter(hConverter); if (nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL) { errno = EOVERFLOW; return 0; } /* ensure trailing '\0' */ unic_text[nDestBytes] = '\0'; return nDestBytes; } /****************************************************************************** * * GENERIC FLOPPY FUNCTIONS * *****************************************************************************/ /***************************************** * osl_unmountVolumeDevice ****************************************/ oslFileError osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle ) { if ( Handle ) return osl_File_E_None; else return osl_File_E_INVAL; } /***************************************** * osl_automountVolumeDevice ****************************************/ oslFileError osl_automountVolumeDevice( oslVolumeDeviceHandle Handle ) { if ( Handle ) return osl_File_E_None; else return osl_File_E_INVAL; } /***************************************** * osl_getVolumeDeviceMountPath ****************************************/ oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath ) { if ( Handle && pstrPath ) { rtl_uString_assign( pstrPath, (rtl_uString *)Handle ); return osl_File_E_None; } else return osl_File_E_INVAL; } /***************************************** * osl_acquireVolumeDeviceHandle ****************************************/ oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle ) { if ( Handle ) { rtl_uString_acquire( (rtl_uString *)Handle ); return osl_File_E_None; } else return osl_File_E_INVAL; } /***************************************** * osl_releaseVolumeDeviceHandle ****************************************/ oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle ) { if ( Handle ) { rtl_uString_release( (rtl_uString *)Handle ); return osl_File_E_None; } else return osl_File_E_INVAL; } /****************************************************************************** * * OS/2 FLOPPY FUNCTIONS * *****************************************************************************/ static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath) { return NULL; }