1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 25 /************************************************************************ 26 * ToDo 27 * 28 * Fix osl_getCanonicalName 29 * 30 * - Fix: check for corresponding struct sizes in exported functions 31 * - check size/use of oslDirectory 32 * - check size/use of oslDirectoryItem 33 * - check size/use of oslFileStatus 34 * - check size/use of oslVolumeDeviceHandle 35 * - check size/use of oslVolumeInfo 36 * - check size/use of oslFileHandle 37 ***********************************************************************/ 38 39 #define INCL_DOSDEVIOCTL // OS2 device definitions 40 41 #include "system.h" 42 #include <rtl/alloc.h> 43 44 #include "osl/file.hxx" 45 46 47 #include <sal/types.h> 48 #include <osl/thread.h> 49 #include <osl/diagnose.h> 50 #include "file_error_transl.h" 51 #include <osl/time.h> 52 53 #ifndef _FILE_URL_H_ 54 #include "file_url.h" 55 #endif 56 57 #include "file_path_helper.hxx" 58 #include "uunxapi.hxx" 59 60 #ifndef _STRING_H_ 61 #include <string.h> 62 #endif 63 64 #ifndef _CTYPE_H_ 65 #include <ctype.h> 66 #endif 67 68 #ifndef _WCHAR_H_ 69 #include <wchar.h> 70 #endif 71 72 #include <algorithm> 73 74 #include <limits> 75 #include <sys/mman.h> 76 77 #if OSL_DEBUG_LEVEL > 1 78 extern void debug_ustring(rtl_uString*); 79 #endif 80 81 82 #ifdef DEBUG_OSL_FILE 83 # define PERROR( a, b ) perror( a ); fprintf( stderr, b ) 84 #else 85 # define PERROR( a, b ) 86 #endif 87 88 extern "C" oslFileHandle osl_createFileHandleFromFD( int fd ); 89 90 struct errentry errtable[] = { 91 { NO_ERROR, osl_File_E_None }, /* 0 */ 92 { ERROR_INVALID_FUNCTION, osl_File_E_INVAL }, /* 1 */ 93 { ERROR_FILE_NOT_FOUND, osl_File_E_NOENT }, /* 2 */ 94 { ERROR_PATH_NOT_FOUND, osl_File_E_NOENT }, /* 3 */ 95 { ERROR_TOO_MANY_OPEN_FILES, osl_File_E_MFILE }, /* 4 */ 96 { ERROR_ACCESS_DENIED, osl_File_E_ACCES }, /* 5 */ 97 { ERROR_INVALID_HANDLE, osl_File_E_BADF }, /* 6 */ 98 { ERROR_ARENA_TRASHED, osl_File_E_NOMEM }, /* 7 */ 99 { ERROR_NOT_ENOUGH_MEMORY, osl_File_E_NOMEM }, /* 8 */ 100 { ERROR_INVALID_BLOCK, osl_File_E_NOMEM }, /* 9 */ 101 { ERROR_BAD_ENVIRONMENT, osl_File_E_2BIG }, /* 10 */ 102 { ERROR_BAD_FORMAT, osl_File_E_NOEXEC }, /* 11 */ 103 { ERROR_INVALID_ACCESS, osl_File_E_INVAL }, /* 12 */ 104 { ERROR_INVALID_DATA, osl_File_E_INVAL }, /* 13 */ 105 { ERROR_INVALID_DRIVE, osl_File_E_NOENT }, /* 15 */ 106 { ERROR_CURRENT_DIRECTORY, osl_File_E_ACCES }, /* 16 */ 107 { ERROR_NOT_SAME_DEVICE, osl_File_E_XDEV }, /* 17 */ 108 { ERROR_NO_MORE_FILES, osl_File_E_NOENT }, /* 18 */ 109 { ERROR_NOT_READY, osl_File_E_NOTREADY }, /* 21 */ 110 { ERROR_LOCK_VIOLATION, osl_File_E_ACCES }, /* 33 */ 111 { ERROR_BAD_NETPATH, osl_File_E_NOENT }, /* 53 */ 112 { ERROR_NETWORK_ACCESS_DENIED, osl_File_E_ACCES }, /* 65 */ 113 { ERROR_BAD_NET_NAME, osl_File_E_NOENT }, /* 67 */ 114 { ERROR_FILE_EXISTS, osl_File_E_EXIST }, /* 80 */ 115 { ERROR_CANNOT_MAKE, osl_File_E_ACCES }, /* 82 */ 116 { ERROR_FAIL_I24, osl_File_E_ACCES }, /* 83 */ 117 { ERROR_INVALID_PARAMETER, osl_File_E_INVAL }, /* 87 */ 118 { ERROR_NO_PROC_SLOTS, osl_File_E_AGAIN }, /* 89 */ 119 { ERROR_DRIVE_LOCKED, osl_File_E_ACCES }, /* 108 */ 120 { ERROR_BROKEN_PIPE, osl_File_E_PIPE }, /* 109 */ 121 { ERROR_DISK_FULL, osl_File_E_NOSPC }, /* 112 */ 122 { ERROR_INVALID_TARGET_HANDLE, osl_File_E_BADF }, /* 114 */ 123 { ERROR_INVALID_HANDLE, osl_File_E_INVAL }, /* 124 */ 124 { ERROR_WAIT_NO_CHILDREN, osl_File_E_CHILD }, /* 128 */ 125 { ERROR_CHILD_NOT_COMPLETE, osl_File_E_CHILD }, /* 129 */ 126 { ERROR_DIRECT_ACCESS_HANDLE, osl_File_E_BADF }, /* 130 */ 127 { ERROR_NEGATIVE_SEEK, osl_File_E_INVAL }, /* 131 */ 128 { ERROR_SEEK_ON_DEVICE, osl_File_E_ACCES }, /* 132 */ 129 { ERROR_DIR_NOT_EMPTY, osl_File_E_NOTEMPTY }, /* 145 */ 130 { ERROR_NOT_LOCKED, osl_File_E_ACCES }, /* 158 */ 131 { ERROR_BAD_PATHNAME, osl_File_E_NOENT }, /* 161 */ 132 { ERROR_MAX_THRDS_REACHED, osl_File_E_AGAIN }, /* 164 */ 133 { ERROR_LOCK_FAILED, osl_File_E_ACCES }, /* 167 */ 134 { ERROR_ALREADY_EXISTS, osl_File_E_EXIST }, /* 183 */ 135 { ERROR_FILENAME_EXCED_RANGE, osl_File_E_NOENT }, /* 206 */ 136 { ERROR_NESTING_NOT_ALLOWED, osl_File_E_AGAIN }, /* 215 */ 137 { ERROR_DIRECTORY, osl_File_E_NOENT }, /* 267 */ 138 //{ ERROR_NOT_ENOUGH_QUOTA, osl_File_E_NOMEM } /* 1816 */ 139 }; 140 141 #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0]))) 142 143 //##################################################### 144 oslFileError MapError(APIRET dwError) 145 { 146 for (int i = 0; i < ELEMENTS_OF_ARRAY(errtable); ++i ) 147 { 148 if (dwError == errtable[i].oscode) 149 return static_cast<oslFileError>(errtable[i].errnocode); 150 } 151 return osl_File_E_INVAL; 152 } 153 154 #ifdef DEBUG_OSL_FILE 155 # define OSL_FILE_TRACE 0 ? (void)(0) : osl_trace 156 # define PERROR( a, b ) perror( a ); fprintf( stderr, b ) 157 #else 158 # define OSL_FILE_TRACE 1 ? (void)(0) : osl_trace 159 # define PERROR( a, b ) 160 #endif 161 162 //################################################################## 163 // File handle implementation 164 //################################################################## 165 struct FileHandle_Impl 166 { 167 rtl_String * m_strFilePath; /* holds native file path */ 168 int m_fd; 169 170 /** State 171 */ 172 enum StateBits 173 { 174 STATE_SEEKABLE = 1, /* default */ 175 STATE_READABLE = 2, /* default */ 176 STATE_WRITEABLE = 4, /* open() sets, write() requires, else osl_File_E_BADF */ 177 STATE_MODIFIED = 8 /* write() sets, flush() resets */ 178 }; 179 int m_state; 180 181 sal_uInt64 m_size; /* file size */ 182 off_t m_offset; /* physical offset from begin of file */ 183 //off_t m_filepos; /* logical offset from begin of file */ 184 off_t m_fileptr; /* logical offset from begin of file */ 185 186 off_t m_bufptr; /* buffer offset from begin of file */ 187 size_t m_buflen; /* buffer filled [0, m_bufsiz - 1] */ 188 189 size_t m_bufsiz; 190 sal_uInt8 * m_buffer; 191 192 explicit FileHandle_Impl (int fd, char const * path = "<anon>"); 193 ~FileHandle_Impl(); 194 195 static void* operator new(size_t n); 196 static void operator delete(void * p, size_t); 197 static size_t getpagesize(); 198 199 sal_uInt64 getPos() const; 200 oslFileError setPos (sal_uInt64 uPos); 201 202 sal_uInt64 getSize() const; 203 oslFileError setSize (sal_uInt64 uPos); 204 205 oslFileError readAt ( 206 off_t nOffset, 207 void * pBuffer, 208 size_t nBytesRequested, 209 sal_uInt64 * pBytesRead); 210 211 oslFileError writeAt ( 212 off_t nOffset, 213 void const * pBuffer, 214 size_t nBytesToWrite, 215 sal_uInt64 * pBytesWritten); 216 217 oslFileError readFileAt ( 218 off_t nOffset, 219 void * pBuffer, 220 size_t nBytesRequested, 221 sal_uInt64 * pBytesRead); 222 223 oslFileError writeFileAt ( 224 off_t nOffset, 225 void const * pBuffer, 226 size_t nBytesToWrite, 227 sal_uInt64 * pBytesWritten); 228 229 oslFileError readLineAt ( 230 LONGLONG nOffset, 231 sal_Sequence ** ppSequence, 232 sal_uInt64 * pBytesRead); 233 234 oslFileError writeSequence_Impl ( 235 sal_Sequence ** ppSequence, 236 size_t * pnOffset, 237 const void * pBuffer, 238 size_t nBytes); 239 240 oslFileError syncFile(); 241 242 /** Buffer cache / allocator. 243 */ 244 class Allocator 245 { 246 rtl_cache_type * m_cache; 247 size_t m_bufsiz; 248 249 Allocator (Allocator const &); 250 Allocator & operator= (Allocator const &); 251 252 public: 253 static Allocator & get(); 254 255 void allocate (sal_uInt8 ** ppBuffer, size_t * pnSize); 256 void deallocate (sal_uInt8 * pBuffer); 257 258 protected: 259 Allocator(); 260 ~Allocator(); 261 }; 262 }; 263 264 FileHandle_Impl::Allocator & 265 FileHandle_Impl::Allocator::get() 266 { 267 static Allocator g_aBufferAllocator; 268 return g_aBufferAllocator; 269 } 270 271 FileHandle_Impl::Allocator::Allocator() 272 : m_cache (0), 273 m_bufsiz (0) 274 { 275 size_t const pagesize = FileHandle_Impl::getpagesize(); 276 m_cache = rtl_cache_create ( 277 "osl_file_buffer_cache", pagesize, 0, 0, 0, 0, 0, 0, 0); 278 if (0 != m_cache) 279 m_bufsiz = pagesize; 280 } 281 282 FileHandle_Impl::Allocator::~Allocator() 283 { 284 rtl_cache_destroy(m_cache), m_cache = 0; 285 } 286 287 void FileHandle_Impl::Allocator::allocate (sal_uInt8 ** ppBuffer, size_t * pnSize) 288 { 289 OSL_PRECOND((0 != ppBuffer) && (0 != pnSize), "FileHandle_Impl::Allocator::allocate(): contract violation"); 290 *ppBuffer = static_cast< sal_uInt8* >(rtl_cache_alloc(m_cache)), *pnSize = m_bufsiz; 291 } 292 293 void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer) 294 { 295 if (0 != pBuffer) 296 rtl_cache_free (m_cache, pBuffer); 297 } 298 299 FileHandle_Impl::FileHandle_Impl (int fd, char const * path) 300 : m_strFilePath (0), 301 m_fd (fd), 302 m_state (STATE_SEEKABLE | STATE_READABLE), 303 m_size (0), 304 m_offset (0), 305 m_fileptr (0), 306 m_bufptr (-1), 307 m_buflen (0), 308 m_bufsiz (0), 309 m_buffer (0) 310 { 311 rtl_string_newFromStr (&m_strFilePath, path); 312 Allocator::get().allocate (&m_buffer, &m_bufsiz); 313 if (m_buffer != 0) 314 memset (m_buffer, 0, m_bufsiz); 315 } 316 317 FileHandle_Impl::~FileHandle_Impl() 318 { 319 Allocator::get().deallocate (m_buffer), m_buffer = 0; 320 rtl_string_release (m_strFilePath), m_strFilePath = 0; 321 } 322 323 void * FileHandle_Impl::operator new(size_t n) 324 { 325 return rtl_allocateMemory(n); 326 } 327 328 void FileHandle_Impl::operator delete(void * p, size_t) 329 { 330 rtl_freeMemory(p); 331 } 332 333 size_t FileHandle_Impl::getpagesize() 334 { 335 ULONG ulPageSize; 336 DosQuerySysInfo(QSV_PAGE_SIZE, QSV_PAGE_SIZE, &ulPageSize, sizeof(ULONG)); 337 return sal::static_int_cast< size_t >(ulPageSize); 338 } 339 340 sal_uInt64 FileHandle_Impl::getPos() const 341 { 342 return sal::static_int_cast< sal_uInt64 >(m_fileptr); 343 } 344 345 oslFileError FileHandle_Impl::setPos (sal_uInt64 uPos) 346 { 347 m_fileptr = sal::static_int_cast< LONGLONG >(uPos); 348 return osl_File_E_None; 349 } 350 351 sal_uInt64 FileHandle_Impl::getSize() const 352 { 353 LONGLONG bufend = std::max((LONGLONG)(0), m_bufptr) + m_buflen; 354 return std::max(m_size, sal::static_int_cast< sal_uInt64 >(bufend)); 355 } 356 357 oslFileError FileHandle_Impl::setSize (sal_uInt64 uSize) 358 { 359 off_t const nSize = sal::static_int_cast< off_t >(uSize); 360 if (-1 == ftruncate (m_fd, nSize)) 361 { 362 /* Failure. Save original result. Try fallback algorithm */ 363 oslFileError result = oslTranslateFileError (OSL_FET_ERROR, errno); 364 365 /* Check against current size. Fail upon 'shrink' */ 366 if (uSize <= getSize()) 367 { 368 /* Failure upon 'shrink'. Return original result */ 369 return (result); 370 } 371 372 /* Save current position */ 373 off_t const nCurPos = (off_t)lseek (m_fd, (off_t)0, SEEK_CUR); 374 if (nCurPos == (off_t)(-1)) 375 return (result); 376 377 /* Try 'expand' via 'lseek()' and 'write()' */ 378 if (-1 == lseek (m_fd, (off_t)(nSize - 1), SEEK_SET)) 379 return (result); 380 381 if (-1 == write (m_fd, (char*)"", (size_t)1)) 382 { 383 /* Failure. Restore saved position */ 384 (void) lseek (m_fd, (off_t)(nCurPos), SEEK_SET); 385 return (result); 386 } 387 388 /* Success. Restore saved position */ 389 if (-1 == lseek (m_fd, (off_t)nCurPos, SEEK_SET)) 390 return (result); 391 } 392 393 OSL_FILE_TRACE("osl_setFileSize(%d, %lld) => %ld", m_fd, getSize(), nSize); 394 m_size = sal::static_int_cast< sal_uInt64 >(nSize); 395 return osl_File_E_None; 396 } 397 398 oslFileError FileHandle_Impl::readAt ( 399 off_t nOffset, 400 void * pBuffer, 401 size_t nBytesRequested, 402 sal_uInt64 * pBytesRead) 403 { 404 OSL_PRECOND((m_state & STATE_SEEKABLE), "FileHandle_Impl::readAt(): not seekable"); 405 if (!(m_state & STATE_SEEKABLE)) 406 return osl_File_E_SPIPE; 407 408 OSL_PRECOND((m_state & STATE_READABLE), "FileHandle_Impl::readAt(): not readable"); 409 if (!(m_state & STATE_READABLE)) 410 return osl_File_E_BADF; 411 412 if (nOffset != m_offset) 413 { 414 if (-1 == ::lseek (m_fd, nOffset, SEEK_SET)) 415 return oslTranslateFileError (OSL_FET_ERROR, errno); 416 m_offset = nOffset; 417 } 418 419 ssize_t nBytes = ::read (m_fd, pBuffer, nBytesRequested); 420 if (-1 == nBytes) 421 return oslTranslateFileError (OSL_FET_ERROR, errno); 422 m_offset += nBytes; 423 424 OSL_FILE_TRACE("FileHandle_Impl::readAt(%d, %lld, %ld)", m_fd, nOffset, nBytes); 425 *pBytesRead = nBytes; 426 return osl_File_E_None; 427 } 428 429 oslFileError FileHandle_Impl::writeAt ( 430 off_t nOffset, 431 void const * pBuffer, 432 size_t nBytesToWrite, 433 sal_uInt64 * pBytesWritten) 434 { 435 OSL_PRECOND((m_state & STATE_SEEKABLE), "FileHandle_Impl::writeAt(): not seekable"); 436 if (!(m_state & STATE_SEEKABLE)) 437 return osl_File_E_SPIPE; 438 439 OSL_PRECOND((m_state & STATE_WRITEABLE), "FileHandle_Impl::writeAt(): not writeable"); 440 if (!(m_state & STATE_WRITEABLE)) 441 return osl_File_E_BADF; 442 443 if (nOffset != m_offset) 444 { 445 if (-1 == ::lseek (m_fd, nOffset, SEEK_SET)) 446 return oslTranslateFileError (OSL_FET_ERROR, errno); 447 m_offset = nOffset; 448 } 449 450 ssize_t nBytes = ::write (m_fd, pBuffer, nBytesToWrite); 451 if (-1 == nBytes) 452 return oslTranslateFileError (OSL_FET_ERROR, errno); 453 m_offset += nBytes; 454 455 OSL_FILE_TRACE("FileHandle_Impl::writeAt(%d, %lld, %ld)", m_fd, nOffset, nBytes); 456 m_size = std::max (m_size, sal::static_int_cast< sal_uInt64 >(nOffset + nBytes)); 457 458 *pBytesWritten = nBytes; 459 return osl_File_E_None; 460 } 461 462 oslFileError FileHandle_Impl::readFileAt ( 463 off_t nOffset, 464 void * pBuffer, 465 size_t nBytesRequested, 466 sal_uInt64 * pBytesRead) 467 { 468 if (0 == (m_state & STATE_SEEKABLE)) 469 { 470 // not seekable (pipe) 471 ssize_t nBytes = ::read (m_fd, pBuffer, nBytesRequested); 472 if (-1 == nBytes) 473 return oslTranslateFileError (OSL_FET_ERROR, errno); 474 *pBytesRead = nBytes; 475 return osl_File_E_None; 476 } 477 else if (0 == m_buffer) 478 { 479 // not buffered 480 return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead); 481 } 482 else 483 { 484 sal_uInt8 * buffer = static_cast<sal_uInt8*>(pBuffer); 485 for (*pBytesRead = 0; nBytesRequested > 0; ) 486 { 487 off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz; 488 size_t const bufpos = (nOffset % m_bufsiz); 489 490 if (bufptr != m_bufptr) 491 { 492 // flush current buffer 493 oslFileError result = syncFile(); 494 if (result != osl_File_E_None) 495 return (result); 496 497 if (nBytesRequested >= m_bufsiz) 498 { 499 // buffer too small, read through from file 500 sal_uInt64 uDone = 0; 501 result = readAt (nOffset, &(buffer[*pBytesRead]), nBytesRequested, &uDone); 502 if (result != osl_File_E_None) 503 return (result); 504 505 nBytesRequested -= uDone, *pBytesRead += uDone; 506 return osl_File_E_None; 507 } 508 509 // update buffer (pointer) 510 sal_uInt64 uDone = 0; 511 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); 512 if (result != osl_File_E_None) 513 return (result); 514 m_bufptr = bufptr, m_buflen = uDone; 515 } 516 if (bufpos >= m_buflen) 517 { 518 // end of file 519 return osl_File_E_None; 520 } 521 522 size_t const bytes = std::min (m_buflen - bufpos, nBytesRequested); 523 OSL_FILE_TRACE("FileHandle_Impl::readFileAt(%d, %lld, %ld)", m_fd, nOffset, bytes); 524 525 memcpy (&(buffer[*pBytesRead]), &(m_buffer[bufpos]), bytes); 526 nBytesRequested -= bytes, *pBytesRead += bytes, nOffset += bytes; 527 } 528 return osl_File_E_None; 529 } 530 } 531 532 oslFileError FileHandle_Impl::writeFileAt ( 533 off_t nOffset, 534 void const * pBuffer, 535 size_t nBytesToWrite, 536 sal_uInt64 * pBytesWritten) 537 { 538 if (0 == (m_state & STATE_SEEKABLE)) 539 { 540 // not seekable (pipe) 541 ssize_t nBytes = ::write (m_fd, pBuffer, nBytesToWrite); 542 if (-1 == nBytes) 543 return oslTranslateFileError (OSL_FET_ERROR, errno); 544 *pBytesWritten = nBytes; 545 return osl_File_E_None; 546 } 547 else if (0 == m_buffer) 548 { 549 // not buffered 550 return writeAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten); 551 } 552 else 553 { 554 sal_uInt8 const * buffer = static_cast<sal_uInt8 const *>(pBuffer); 555 for (*pBytesWritten = 0; nBytesToWrite > 0; ) 556 { 557 off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz; 558 size_t const bufpos = (nOffset % m_bufsiz); 559 if (bufptr != m_bufptr) 560 { 561 // flush current buffer 562 oslFileError result = syncFile(); 563 if (result != osl_File_E_None) 564 return (result); 565 566 if (nBytesToWrite >= m_bufsiz) 567 { 568 // buffer to small, write through to file 569 sal_uInt64 uDone = 0; 570 result = writeAt (nOffset, &(buffer[*pBytesWritten]), nBytesToWrite, &uDone); 571 if (result != osl_File_E_None) 572 return (result); 573 if (uDone != nBytesToWrite) 574 return osl_File_E_IO; 575 576 nBytesToWrite -= uDone, *pBytesWritten += uDone; 577 return osl_File_E_None; 578 } 579 580 // update buffer (pointer) 581 sal_uInt64 uDone = 0; 582 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); 583 if (result != osl_File_E_None) 584 return (result); 585 m_bufptr = bufptr, m_buflen = uDone; 586 } 587 588 size_t const bytes = std::min (m_bufsiz - bufpos, nBytesToWrite); 589 OSL_FILE_TRACE("FileHandle_Impl::writeFileAt(%d, %lld, %ld)", m_fd, nOffset, bytes); 590 591 memcpy (&(m_buffer[bufpos]), &(buffer[*pBytesWritten]), bytes); 592 nBytesToWrite -= bytes, *pBytesWritten += bytes, nOffset += bytes; 593 594 m_buflen = std::max(m_buflen, bufpos + bytes); 595 m_state |= STATE_MODIFIED; 596 } 597 return osl_File_E_None; 598 } 599 } 600 601 oslFileError FileHandle_Impl::readLineAt ( 602 LONGLONG nOffset, 603 sal_Sequence ** ppSequence, 604 sal_uInt64 * pBytesRead) 605 { 606 oslFileError result = osl_File_E_None; 607 608 LONGLONG bufptr = (nOffset / m_bufsiz) * m_bufsiz; 609 if (bufptr != m_bufptr) 610 { 611 /* flush current buffer */ 612 result = syncFile(); 613 if (result != osl_File_E_None) 614 return (result); 615 616 /* update buffer (pointer) */ 617 sal_uInt64 uDone = 0; 618 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); 619 if (result != osl_File_E_None) 620 return (result); 621 622 m_bufptr = bufptr, m_buflen = sal::static_int_cast< size_t >(uDone); 623 } 624 625 static int const LINE_STATE_BEGIN = 0; 626 static int const LINE_STATE_CR = 1; 627 static int const LINE_STATE_LF = 2; 628 629 size_t bufpos = sal::static_int_cast< size_t >(nOffset - m_bufptr), curpos = bufpos, dstpos = 0; 630 int state = (bufpos >= m_buflen) ? LINE_STATE_LF : LINE_STATE_BEGIN; 631 632 for ( ; state != LINE_STATE_LF; ) 633 { 634 if (curpos >= m_buflen) 635 { 636 /* buffer examined */ 637 if (0 < (curpos - bufpos)) 638 { 639 /* flush buffer to sequence */ 640 result = writeSequence_Impl ( 641 ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos); 642 if (result != osl_File_E_None) 643 return (result); 644 *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos; 645 } 646 647 bufptr = nOffset / m_bufsiz * m_bufsiz; 648 if (bufptr != m_bufptr) 649 { 650 /* update buffer (pointer) */ 651 sal_uInt64 uDone = 0; 652 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone); 653 if (result != osl_File_E_None) 654 return (result); 655 m_bufptr = bufptr, m_buflen = sal::static_int_cast< size_t >(uDone); 656 } 657 658 bufpos = sal::static_int_cast< size_t >(nOffset - m_bufptr), curpos = bufpos; 659 if (bufpos >= m_buflen) 660 break; 661 } 662 switch (state) 663 { 664 case LINE_STATE_CR: 665 state = LINE_STATE_LF; 666 switch (m_buffer[curpos]) 667 { 668 case 0x0A: /* CRLF */ 669 /* eat current char */ 670 curpos++; 671 break; 672 default: /* single CR */ 673 /* keep current char */ 674 break; 675 } 676 break; 677 default: 678 /* determine next state */ 679 switch (m_buffer[curpos]) 680 { 681 case 0x0A: /* single LF */ 682 state = LINE_STATE_LF; 683 break; 684 case 0x0D: /* CR */ 685 state = LINE_STATE_CR; 686 break; 687 default: /* advance to next char */ 688 curpos++; 689 break; 690 } 691 if (state != LINE_STATE_BEGIN) 692 { 693 /* store (and eat) the newline char */ 694 m_buffer[curpos] = 0x0A, curpos++; 695 696 /* flush buffer to sequence */ 697 result = writeSequence_Impl ( 698 ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos - 1); 699 if (result != osl_File_E_None) 700 return (result); 701 *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos; 702 } 703 break; 704 } 705 } 706 707 result = writeSequence_Impl (ppSequence, &dstpos, 0, 0); 708 if (result != osl_File_E_None) 709 return (result); 710 if (0 < dstpos) 711 return osl_File_E_None; 712 if (bufpos >= m_buflen) 713 return osl_File_E_AGAIN; 714 return osl_File_E_None; 715 } 716 717 oslFileError FileHandle_Impl::writeSequence_Impl ( 718 sal_Sequence ** ppSequence, 719 size_t * pnOffset, 720 const void * pBuffer, 721 size_t nBytes) 722 { 723 sal_Int32 nElements = *pnOffset + nBytes; 724 if (!*ppSequence) 725 { 726 /* construct sequence */ 727 rtl_byte_sequence_constructNoDefault(ppSequence, nElements); 728 } 729 else if (nElements != (*ppSequence)->nElements) 730 { 731 /* resize sequence */ 732 rtl_byte_sequence_realloc(ppSequence, nElements); 733 } 734 if (*ppSequence != 0) 735 { 736 /* fill sequence */ 737 memcpy(&((*ppSequence)->elements[*pnOffset]), pBuffer, nBytes), *pnOffset += nBytes; 738 } 739 return (*ppSequence != 0) ? osl_File_E_None : osl_File_E_NOMEM; 740 } 741 742 oslFileError FileHandle_Impl::syncFile() 743 { 744 oslFileError result = osl_File_E_None; 745 if (m_state & STATE_MODIFIED) 746 { 747 sal_uInt64 uDone = 0; 748 result = writeAt (m_bufptr, m_buffer, m_buflen, &uDone); 749 if (result != osl_File_E_None) 750 return (result); 751 if (uDone != m_buflen) 752 return osl_File_E_IO; 753 m_state &= ~STATE_MODIFIED; 754 } 755 return (result); 756 } 757 758 759 /****************************************************************************** 760 * 761 * static members 762 * 763 *****************************************************************************/ 764 765 static const char * pFileLockEnvVar = (char *) -1; 766 767 768 /****************************************************************************** 769 * 770 * C-String Function Declarations 771 * 772 *****************************************************************************/ 773 774 static oslFileError osl_psz_getVolumeInformation(const sal_Char* , oslVolumeInfo* pInfo, sal_uInt32 uFieldMask); 775 static oslFileError osl_psz_removeFile(const sal_Char* pszPath); 776 static oslFileError osl_psz_createDirectory(const sal_Char* pszPath); 777 static oslFileError osl_psz_removeDirectory(const sal_Char* pszPath); 778 static oslFileError osl_psz_copyFile(const sal_Char* pszPath, const sal_Char* pszDestPath); 779 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath); 780 static oslFileError osl_psz_setFileTime(const sal_Char* strFilePath, const TimeValue* pCreationTime, const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime); 781 782 783 /****************************************************************************** 784 * 785 * Static Module Utility Function Declarations 786 * 787 *****************************************************************************/ 788 789 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists); 790 static oslFileError oslChangeFileModes(const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID); 791 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName); 792 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode); 793 static oslFileError oslDoMoveFile(const sal_Char* pszPath, const sal_Char* pszDestPath); 794 rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr,rtl_uString** uStr); 795 796 /****************************************************************************** 797 * 798 * Non-Static Utility Function Declarations 799 * 800 *****************************************************************************/ 801 802 extern "C" int UnicodeToText( char *, size_t, const sal_Unicode *, sal_Int32 ); 803 extern "C" int TextToUnicode( 804 const char* text, size_t text_buffer_size, sal_Unicode* unic_text, sal_Int32 unic_text_buffer_size); 805 806 /****************************************************************************** 807 * 808 * 'removeable device' aka floppy functions 809 * 810 *****************************************************************************/ 811 812 static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath); 813 static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy); 814 static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy); 815 816 #ifdef DEBUG_OSL_FILE 817 static void osl_printFloppyHandle(oslVolumeDeviceHandleImpl* hFloppy); 818 #endif 819 820 /********************************************** 821 * _osl_openLocalRoot 822 * enumerate available drives 823 *********************************************/ 824 static oslFileError _osl_openLocalRoot( rtl_uString *strDirectoryPath, oslDirectory *pDirectory) 825 { 826 rtl_uString *ustrSystemPath = NULL; 827 oslFileError error; 828 829 if ( !pDirectory ) 830 return osl_File_E_INVAL; 831 832 *pDirectory = NULL; 833 834 error = osl_getSystemPathFromFileURL_Ex( strDirectoryPath, &ustrSystemPath, sal_False ); 835 836 if ( osl_File_E_None == error ) 837 { 838 /* create and initialize impl structure */ 839 DirectoryImpl* pDirImpl = (DirectoryImpl*) rtl_allocateMemory( sizeof(DirectoryImpl) ); 840 if( pDirImpl ) 841 { 842 ULONG ulDriveNum; 843 APIRET rc; 844 pDirImpl->uType = DIRECTORYTYPE_LOCALROOT; 845 pDirImpl->ustrPath = ustrSystemPath; 846 rc = DosQueryCurrentDisk (&ulDriveNum, &pDirImpl->ulDriveMap); 847 pDirImpl->pDirStruct = 0; 848 pDirImpl->ulNextDrive = 1; 849 pDirImpl->ulNextDriveMask = 1; 850 851 // determine number of floppy-drives 852 BYTE nFloppies; 853 rc = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY ); 854 if (nFloppies == 0) { 855 // if no floppies, start with 3rd drive (C:) 856 pDirImpl->ulNextDrive = 3; 857 pDirImpl->ulNextDriveMask <<= 2; 858 } else if (nFloppies == 1) { 859 // mask drive B (second bit) in this case 860 pDirImpl->ulDriveMap &= ~0x02; 861 } 862 *pDirectory = (oslDirectory) pDirImpl; 863 return osl_File_E_None; 864 } 865 else 866 { 867 errno = osl_File_E_NOMEM; 868 } 869 870 } 871 872 rtl_uString_release( ustrSystemPath ); 873 return error; 874 } 875 876 /********************************************** 877 * _osl_getNextDrive 878 *********************************************/ 879 static oslFileError SAL_CALL _osl_getNextDrive( 880 oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint ) 881 { 882 DirectoryImpl *pDirImpl = (DirectoryImpl *)Directory; 883 DirectoryItem_Impl *pItemImpl = NULL; 884 rtl_uString * ustrDrive = NULL; 885 BOOL fSuccess; 886 char buffer[3]; 887 888 uHint = uHint; /* avoid warnings */ 889 890 if ( !pItem ) 891 return osl_File_E_INVAL; 892 893 *pItem = NULL; 894 895 if ( !pDirImpl ) 896 return osl_File_E_INVAL; 897 898 while( pDirImpl->ulNextDrive <= 26) 899 { 900 // exit if bit==1 -> drive found 901 if (pDirImpl->ulDriveMap & pDirImpl->ulNextDriveMask) { 902 903 /* convert file name to unicode */ 904 buffer[0] = '@' + pDirImpl->ulNextDrive; 905 buffer[1] = ':'; 906 buffer[2] = 0; 907 908 pItemImpl = (DirectoryItem_Impl*) rtl_allocateMemory(sizeof(DirectoryItem_Impl)); 909 if ( !pItemImpl ) 910 return osl_File_E_NOMEM; 911 912 memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); 913 pItemImpl->uType = DIRECTORYITEM_DRIVE; 914 pItemImpl->nRefCount = 1; 915 916 rtl_string2UString( &pItemImpl->ustrDrive, buffer, 3, 917 osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); 918 OSL_ASSERT(pItemImpl->ustrDrive != 0); 919 920 /* use drive as directory item */ 921 *pItem = (oslDirectoryItem) pItemImpl; 922 } 923 // scan next bit position 924 pDirImpl->ulNextDrive++; 925 pDirImpl->ulNextDriveMask <<= 1; 926 927 if (*pItem) // item assigned, return now. 928 return osl_File_E_None; 929 } 930 931 // no more items 932 return osl_File_E_NOENT; 933 } 934 935 /********************************************** 936 * _osl_readdir_impl_ 937 * 938 * readdir wrapper, filters out "." and ".." 939 * on request 940 *********************************************/ 941 942 static struct dirent* _osl_readdir_impl_(DIR* pdir, sal_Bool bFilterLocalAndParentDir) 943 { 944 struct dirent* pdirent; 945 946 while ((pdirent = readdir(pdir)) != NULL) 947 { 948 if (bFilterLocalAndParentDir && 949 ((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, "..")))) 950 continue; 951 else 952 break; 953 } 954 955 return pdirent; 956 } 957 958 /******************************************************************* 959 * osl_openDirectory 960 ******************************************************************/ 961 962 oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirectory* pDirectory) 963 { 964 rtl_uString* ustrSystemPath = NULL; 965 oslFileError eRet; 966 967 char path[PATH_MAX]; 968 969 OSL_ASSERT(ustrDirectoryURL && (ustrDirectoryURL->length > 0)); 970 OSL_ASSERT(pDirectory); 971 972 if (0 == ustrDirectoryURL->length ) 973 return osl_File_E_INVAL; 974 975 if ( 0 == rtl_ustr_compareIgnoreAsciiCase( ustrDirectoryURL->buffer, (const sal_Unicode*)L"file:///" ) ) 976 return _osl_openLocalRoot( ustrDirectoryURL, pDirectory ); 977 978 /* convert file URL to system path */ 979 eRet = osl_getSystemPathFromFileURL_Ex(ustrDirectoryURL, &ustrSystemPath, sal_False); 980 981 if( osl_File_E_None != eRet ) 982 return eRet; 983 984 osl_systemPathRemoveSeparator(ustrSystemPath); 985 986 /* convert unicode path to text */ 987 if ( UnicodeToText( path, PATH_MAX, ustrSystemPath->buffer, ustrSystemPath->length ) ) 988 { 989 // if only the drive is specified (x:), add a \ (x:\) otherwise current 990 // directory is browsed instead of root. 991 if (strlen( path) == 2 && path[1] == ':') 992 strcat( path, "\\"); 993 /* open directory */ 994 DIR *pdir = opendir( path ); 995 996 if( pdir ) 997 { 998 /* create and initialize impl structure */ 999 DirectoryImpl* pDirImpl = (DirectoryImpl*) rtl_allocateMemory( sizeof(DirectoryImpl) ); 1000 1001 if( pDirImpl ) 1002 { 1003 pDirImpl->uType = DIRECTORYTYPE_FILESYSTEM; 1004 pDirImpl->pDirStruct = pdir; 1005 pDirImpl->ustrPath = ustrSystemPath; 1006 1007 *pDirectory = (oslDirectory) pDirImpl; 1008 return osl_File_E_None; 1009 } 1010 else 1011 { 1012 errno = ENOMEM; 1013 closedir( pdir ); 1014 } 1015 } 1016 else 1017 /* should be removed by optimizer in product version */ 1018 PERROR( "osl_openDirectory", path ); 1019 } 1020 1021 rtl_uString_release( ustrSystemPath ); 1022 1023 return oslTranslateFileError(OSL_FET_ERROR, errno); 1024 } 1025 1026 1027 /**************************************************************************** 1028 * osl_getNextDirectoryItem 1029 ***************************************************************************/ 1030 1031 oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, sal_uInt32 uHint) 1032 { 1033 DirectoryImpl* pDirImpl = (DirectoryImpl*)Directory; 1034 DirectoryItem_Impl *pItemImpl = NULL; 1035 rtl_uString* ustrFileName = NULL; 1036 rtl_uString* ustrFilePath = NULL; 1037 struct dirent* pEntry; 1038 1039 OSL_ASSERT(Directory); 1040 OSL_ASSERT(pItem); 1041 1042 if ((NULL == Directory) || (NULL == pItem)) 1043 return osl_File_E_INVAL; 1044 1045 if ( pDirImpl->uType == DIRECTORYTYPE_LOCALROOT) 1046 return _osl_getNextDrive( Directory, pItem, uHint ); 1047 1048 pEntry = _osl_readdir_impl_(pDirImpl->pDirStruct, sal_True); 1049 1050 if (NULL == pEntry) 1051 return osl_File_E_NOENT; 1052 1053 pItemImpl = (DirectoryItem_Impl*) rtl_allocateMemory(sizeof(DirectoryItem_Impl)); 1054 if ( !pItemImpl ) 1055 return osl_File_E_NOMEM; 1056 1057 memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); 1058 pItemImpl->uType = DIRECTORYITEM_FILE; 1059 pItemImpl->nRefCount = 1; 1060 pItemImpl->d_attr = pEntry->d_attr; 1061 1062 /* convert file name to unicode */ 1063 rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ), 1064 osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); 1065 OSL_ASSERT(ustrFileName != 0); 1066 1067 osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &pItemImpl->ustrFilePath); 1068 rtl_uString_release( ustrFileName ); 1069 1070 *pItem = (oslDirectoryItem)pItemImpl; 1071 return osl_File_E_None; 1072 } 1073 1074 /****************************************************************************/ 1075 /* osl_closeDirectory */ 1076 /****************************************************************************/ 1077 1078 oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory ) 1079 { 1080 DirectoryImpl* pDirImpl = (DirectoryImpl*) Directory; 1081 oslFileError err = osl_File_E_None; 1082 1083 OSL_ASSERT( Directory ); 1084 1085 if( NULL == pDirImpl ) 1086 return osl_File_E_INVAL; 1087 1088 switch ( pDirImpl->uType ) 1089 { 1090 case DIRECTORYTYPE_FILESYSTEM: 1091 if( closedir( pDirImpl->pDirStruct ) ) 1092 err = oslTranslateFileError(OSL_FET_ERROR, errno); 1093 break; 1094 case DIRECTORYTYPE_LOCALROOT: 1095 err = osl_File_E_None; 1096 break; 1097 #if 0 1098 case DIRECTORYTYPE_NETROOT: 1099 { 1100 DWORD err = WNetCloseEnum(pDirImpl->hDirectory); 1101 eError = (err == NO_ERROR) ? osl_File_E_None : MapError(err); 1102 } 1103 break; 1104 #endif 1105 default: 1106 OSL_ENSURE( 0, "Invalid directory type" ); 1107 break; 1108 } 1109 1110 /* cleanup members */ 1111 rtl_uString_release( pDirImpl->ustrPath ); 1112 1113 rtl_freeMemory( pDirImpl ); 1114 1115 return err; 1116 } 1117 1118 /****************************************************************************/ 1119 /* osl_getDirectoryItem */ 1120 /****************************************************************************/ 1121 1122 oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem ) 1123 { 1124 rtl_uString* strSysFilePath = NULL; 1125 oslFileError error = osl_File_E_INVAL; 1126 ULONG dwPathType; 1127 PATHTYPE type = PATHTYPE_FILE; 1128 1129 OSL_ASSERT(ustrFileURL); 1130 OSL_ASSERT(pItem); 1131 1132 /* Assume failure */ 1133 if ( !pItem ) 1134 return osl_File_E_INVAL; 1135 *pItem = NULL; 1136 1137 if (0 == ustrFileURL->length || NULL == pItem) 1138 return osl_File_E_INVAL; 1139 1140 error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &strSysFilePath, sal_False); 1141 1142 if (osl_File_E_None != error) 1143 return error; 1144 1145 dwPathType = IsValidFilePath( strSysFilePath->buffer, NULL, VALIDATEPATH_NORMAL ); 1146 1147 if ( dwPathType & PATHTYPE_IS_VOLUME ) 1148 type = PATHTYPE_VOLUME; 1149 else if ( dwPathType & PATHTYPE_IS_SERVER ) 1150 type = PATHTYPE_NETSERVER; 1151 else 1152 type = PATHTYPE_FILE; 1153 1154 switch ( type ) 1155 { 1156 case PATHTYPE_NETSERVER: 1157 { 1158 DirectoryItem_Impl* pItemImpl = 1159 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl))); 1160 1161 if ( !pItemImpl ) 1162 error = osl_File_E_NOMEM; 1163 1164 if ( osl_File_E_None == error ) 1165 { 1166 memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); 1167 pItemImpl->uType = DIRECTORYITEM_SERVER; 1168 pItemImpl->nRefCount = 1; 1169 rtl_uString_assign( &pItemImpl->ustrFilePath, strSysFilePath ); 1170 1171 *pItem = pItemImpl; 1172 } 1173 } 1174 break; 1175 case PATHTYPE_VOLUME: 1176 { 1177 DirectoryItem_Impl* pItemImpl = 1178 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl))); 1179 1180 if ( !pItemImpl ) 1181 error = osl_File_E_NOMEM; 1182 1183 if ( osl_File_E_None == error ) 1184 { 1185 memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); 1186 pItemImpl->uType = DIRECTORYITEM_DRIVE; 1187 pItemImpl->nRefCount = 1; 1188 rtl_uString_assign( &pItemImpl->ustrDrive, strSysFilePath ); 1189 1190 if ( pItemImpl->ustrDrive->buffer[pItemImpl->ustrDrive->length-1] != sal_Unicode('\\') ) 1191 rtl_uString_newConcat( &pItemImpl->ustrDrive, 1192 pItemImpl->ustrDrive, rtl::OUString::createFromAscii( "\\" ).pData); 1193 1194 *pItem = pItemImpl; 1195 } 1196 } 1197 break; 1198 default: 1199 case PATHTYPE_FILE: 1200 { 1201 if ( strSysFilePath->length > 0 && strSysFilePath->buffer[strSysFilePath->length - 1] == '\\' ) 1202 rtl_uString_newFromStr_WithLength( &strSysFilePath, strSysFilePath->buffer, strSysFilePath->length - 1 ); 1203 1204 if (0 == access_u(strSysFilePath, F_OK)) 1205 { 1206 DirectoryItem_Impl *pItemImpl = 1207 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl))); 1208 1209 memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); 1210 pItemImpl->uType = DIRECTORYITEM_FILE; 1211 pItemImpl->nRefCount = 1; 1212 rtl_uString_assign( &pItemImpl->ustrFilePath, strSysFilePath ); 1213 1214 *pItem = pItemImpl; 1215 } 1216 else 1217 error = oslTranslateFileError(OSL_FET_ERROR, errno); 1218 } 1219 break; 1220 } 1221 1222 if ( strSysFilePath ) 1223 rtl_uString_release( strSysFilePath ); 1224 1225 return error; 1226 } 1227 1228 /****************************************************************************/ 1229 /* osl_acquireDirectoryItem */ 1230 /****************************************************************************/ 1231 1232 oslFileError osl_acquireDirectoryItem( oslDirectoryItem Item ) 1233 { 1234 OSL_ASSERT( Item ); 1235 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; 1236 1237 if ( !pItemImpl ) 1238 return osl_File_E_INVAL; 1239 1240 pItemImpl->nRefCount++; 1241 return osl_File_E_None; 1242 } 1243 1244 /****************************************************************************/ 1245 /* osl_releaseDirectoryItem */ 1246 /****************************************************************************/ 1247 1248 oslFileError osl_releaseDirectoryItem( oslDirectoryItem Item ) 1249 { 1250 OSL_ASSERT( Item ); 1251 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; 1252 1253 if ( !pItemImpl ) 1254 return osl_File_E_INVAL; 1255 1256 if ( ! --pItemImpl->nRefCount ) 1257 { 1258 if (pItemImpl->ustrFilePath) 1259 rtl_uString_release( pItemImpl->ustrFilePath ); 1260 if (pItemImpl->ustrDrive) 1261 rtl_uString_release( pItemImpl->ustrDrive ); 1262 rtl_freeMemory( pItemImpl ); 1263 } 1264 return osl_File_E_None; 1265 } 1266 1267 /**************************************************************************** 1268 * osl_createFileHandleFromFD 1269 ***************************************************************************/ 1270 extern "C" oslFileHandle osl_createFileHandleFromFD( int fd ) 1271 { 1272 if (-1 == fd) 1273 return 0; // EINVAL 1274 1275 struct stat aFileStat; 1276 if (-1 == fstat (fd, &aFileStat)) 1277 return 0; // EBADF 1278 1279 FileHandle_Impl * pImpl = new FileHandle_Impl (fd); 1280 if (0 == pImpl) 1281 return 0; // ENOMEM 1282 1283 // assume writeable 1284 pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE; 1285 if (!S_ISREG(aFileStat.st_mode)) 1286 { 1287 /* not a regular file, mark not seekable */ 1288 pImpl->m_state &= ~FileHandle_Impl::STATE_SEEKABLE; 1289 } 1290 else 1291 { 1292 /* regular file, init current size */ 1293 pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size); 1294 } 1295 1296 OSL_FILE_TRACE("osl_createFileHandleFromFD(%d, writeable) => %s", 1297 pImpl->m_fd, rtl_string_getStr(pImpl->m_strFilePath)); 1298 return (oslFileHandle)(pImpl); 1299 } 1300 1301 /******************************************************************* 1302 * osl_file_adjustLockFlags 1303 ******************************************************************/ 1304 static int osl_file_adjustLockFlags (const char * path, int flags) 1305 { 1306 #ifdef MACOSX 1307 /* 1308 * The AFP implementation of MacOS X 10.4 treats O_EXLOCK in a way 1309 * that makes it impossible for OOo to create a backup copy of the 1310 * file it keeps opened. OTOH O_SHLOCK for AFP behaves as desired by 1311 * the OOo file handling, so we need to check the path of the file 1312 * for the filesystem name. 1313 */ 1314 struct statfs s; 1315 if( 0 <= statfs( path, &s ) ) 1316 { 1317 if( 0 == strncmp("afpfs", s.f_fstypename, 5) ) 1318 { 1319 flags &= ~O_EXLOCK; 1320 flags |= O_SHLOCK; 1321 } 1322 else 1323 { 1324 /* Needed flags to allow opening a webdav file */ 1325 flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK); 1326 } 1327 } 1328 #endif /* MACOSX */ 1329 1330 (void) path; 1331 return flags; 1332 } 1333 1334 /**************************************************************************** 1335 * osl_file_queryLocking 1336 ***************************************************************************/ 1337 struct Locking_Impl 1338 { 1339 int m_enabled; 1340 Locking_Impl() : m_enabled(0) 1341 { 1342 #ifndef HAVE_O_EXLOCK 1343 m_enabled = ((getenv("SAL_ENABLE_FILE_LOCKING") != 0) || (getenv("STAR_ENABLE_FILE_LOCKING") != 0)); 1344 #endif /* HAVE_O_EXLOCK */ 1345 } 1346 }; 1347 static int osl_file_queryLocking (sal_uInt32 uFlags) 1348 { 1349 if (!(uFlags & osl_File_OpenFlag_NoLock)) 1350 { 1351 if ((uFlags & osl_File_OpenFlag_Write) || (uFlags & osl_File_OpenFlag_Create)) 1352 { 1353 static Locking_Impl g_locking; 1354 return (g_locking.m_enabled != 0); 1355 } 1356 } 1357 return 0; 1358 } 1359 1360 /**************************************************************************** 1361 * osl_openFile 1362 ***************************************************************************/ 1363 #ifdef HAVE_O_EXLOCK 1364 #define OPEN_WRITE_FLAGS ( O_RDWR | O_EXLOCK | O_NONBLOCK ) 1365 #define OPEN_CREATE_FLAGS ( O_CREAT | O_EXCL | O_RDWR | O_EXLOCK | O_NONBLOCK ) 1366 #else 1367 #define OPEN_WRITE_FLAGS ( O_RDWR ) 1368 #define OPEN_CREATE_FLAGS ( O_CREAT | O_EXCL | O_RDWR ) 1369 #endif 1370 1371 oslFileError 1372 SAL_CALL osl_openFile( rtl_uString* ustrFileURL, oslFileHandle* pHandle, sal_uInt32 uFlags ) 1373 { 1374 oslFileError eRet; 1375 1376 if ((ustrFileURL == 0) || (ustrFileURL->length == 0) || (pHandle == 0)) 1377 return osl_File_E_INVAL; 1378 1379 /* convert file URL to system path */ 1380 char buffer[PATH_MAX]; 1381 eRet = FileURLToPath (buffer, sizeof(buffer), ustrFileURL); 1382 if (eRet != osl_File_E_None) 1383 return eRet; 1384 #ifdef MACOSX 1385 if (macxp_resolveAlias (buffer, sizeof(buffer)) != 0) 1386 return oslTranslateFileError (OSL_FET_ERROR, errno); 1387 #endif /* MACOSX */ 1388 1389 /* set mode and flags */ 1390 int mode = S_IRUSR | S_IRGRP | S_IROTH; 1391 int flags = O_RDONLY; 1392 if (uFlags & osl_File_OpenFlag_Write) 1393 { 1394 mode |= S_IWUSR | S_IWGRP | S_IWOTH; 1395 flags = OPEN_WRITE_FLAGS; 1396 } 1397 if (uFlags & osl_File_OpenFlag_Create) 1398 { 1399 mode |= S_IWUSR | S_IWGRP | S_IWOTH; 1400 flags = OPEN_CREATE_FLAGS; 1401 } 1402 if (uFlags & osl_File_OpenFlag_NoLock) 1403 { 1404 #ifdef HAVE_O_EXLOCK 1405 flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK); 1406 #endif /* HAVE_O_EXLOCK */ 1407 } 1408 else 1409 { 1410 flags = osl_file_adjustLockFlags (buffer, flags); 1411 } 1412 1413 /* open the file */ 1414 int fd = open( buffer, flags | O_BINARY, mode ); 1415 if (-1 == fd) 1416 return oslTranslateFileError (OSL_FET_ERROR, errno); 1417 1418 /* reset O_NONBLOCK flag */ 1419 if (flags & O_NONBLOCK) 1420 { 1421 int f = fcntl (fd, F_GETFL, 0); 1422 if (-1 == f) 1423 { 1424 eRet = oslTranslateFileError (OSL_FET_ERROR, errno); 1425 (void) close(fd); 1426 return eRet; 1427 } 1428 if (-1 == fcntl (fd, F_SETFL, (f & ~O_NONBLOCK))) 1429 { 1430 eRet = oslTranslateFileError (OSL_FET_ERROR, errno); 1431 (void) close(fd); 1432 return eRet; 1433 } 1434 } 1435 1436 /* get file status (mode, size) */ 1437 struct stat aFileStat; 1438 if (-1 == fstat (fd, &aFileStat)) 1439 { 1440 eRet = oslTranslateFileError (OSL_FET_ERROR, errno); 1441 (void) close(fd); 1442 return eRet; 1443 } 1444 if (!S_ISREG(aFileStat.st_mode)) 1445 { 1446 /* we only open regular files here */ 1447 (void) close(fd); 1448 return osl_File_E_INVAL; 1449 } 1450 1451 if (osl_file_queryLocking (uFlags)) 1452 { 1453 #ifdef MACOSX 1454 if (-1 == flock (fd, LOCK_EX | LOCK_NB)) 1455 { 1456 /* Mac OSX returns ENOTSUP for webdav drives. We should try read lock */ 1457 if ((errno != ENOTSUP) || ((-1 == flock (fd, LOCK_SH | LOCK_NB)) && (errno != ENOTSUP))) 1458 { 1459 eRet = oslTranslateFileError (OSL_FET_ERROR, errno); 1460 (void) close(fd); 1461 return eRet; 1462 } 1463 } 1464 #else /* F_SETLK */ 1465 { 1466 struct flock aflock; 1467 1468 aflock.l_type = F_WRLCK; 1469 aflock.l_whence = SEEK_SET; 1470 aflock.l_start = 0; 1471 aflock.l_len = 0; 1472 1473 if (-1 == fcntl (fd, F_SETLK, &aflock)) 1474 { 1475 eRet = oslTranslateFileError (OSL_FET_ERROR, errno); 1476 (void) close(fd); 1477 return eRet; 1478 } 1479 } 1480 #endif /* F_SETLK */ 1481 } 1482 1483 /* allocate memory for impl structure */ 1484 FileHandle_Impl * pImpl = new FileHandle_Impl (fd, buffer); 1485 if (!pImpl) 1486 { 1487 eRet = oslTranslateFileError (OSL_FET_ERROR, ENOMEM); 1488 (void) close(fd); 1489 return eRet; 1490 } 1491 if (flags & O_RDWR) 1492 pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE; 1493 pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size); 1494 1495 OSL_TRACE("osl_openFile(%d, %s) => %s", pImpl->m_fd, 1496 flags & O_RDWR ? "writeable":"readonly", 1497 rtl_string_getStr(pImpl->m_strFilePath)); 1498 1499 *pHandle = (oslFileHandle)(pImpl); 1500 return osl_File_E_None; 1501 } 1502 1503 /****************************************************************************/ 1504 /* osl_closeFile */ 1505 /****************************************************************************/ 1506 oslFileError 1507 SAL_CALL osl_closeFile( oslFileHandle Handle ) 1508 { 1509 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1510 1511 if ((pImpl == 0) || (pImpl->m_fd < 0)) 1512 return osl_File_E_INVAL; 1513 1514 /* close(2) implicitly (and unconditionally) unlocks */ 1515 OSL_TRACE("osl_closeFile(%d) => %s", pImpl->m_fd, rtl_string_getStr(pImpl->m_strFilePath)); 1516 oslFileError result = pImpl->syncFile(); 1517 if (result != osl_File_E_None) 1518 { 1519 /* close, ignoring double failure */ 1520 (void) close (pImpl->m_fd); 1521 } 1522 else if (-1 == close (pImpl->m_fd)) 1523 { 1524 /* translate error code */ 1525 result = oslTranslateFileError (OSL_FET_ERROR, errno); 1526 } 1527 1528 delete pImpl; 1529 return (result); 1530 } 1531 1532 /************************************************ 1533 * osl_syncFile 1534 ***********************************************/ 1535 oslFileError 1536 SAL_CALL osl_syncFile(oslFileHandle Handle) 1537 { 1538 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1539 1540 if ((0 == pImpl) || (-1 == pImpl->m_fd)) 1541 return osl_File_E_INVAL; 1542 1543 OSL_FILE_TRACE("osl_syncFile(%d)", pImpl->m_fd); 1544 oslFileError result = pImpl->syncFile(); 1545 if (result != osl_File_E_None) 1546 return (result); 1547 if (-1 == fsync (pImpl->m_fd)) 1548 return oslTranslateFileError (OSL_FET_ERROR, errno); 1549 1550 return osl_File_E_None; 1551 } 1552 1553 /******************************************* 1554 osl_mapFile 1555 ********************************************/ 1556 oslFileError 1557 SAL_CALL osl_mapFile ( 1558 oslFileHandle Handle, 1559 void** ppAddr, 1560 sal_uInt64 uLength, 1561 sal_uInt64 uOffset, 1562 sal_uInt32 uFlags 1563 ) 1564 { 1565 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1566 1567 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == ppAddr)) 1568 return osl_File_E_INVAL; 1569 *ppAddr = 0; 1570 1571 static sal_uInt64 const g_limit_size_t = std::numeric_limits< size_t >::max(); 1572 if (g_limit_size_t < uLength) 1573 return osl_File_E_OVERFLOW; 1574 size_t const nLength = sal::static_int_cast< size_t >(uLength); 1575 1576 static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max(); 1577 if (g_limit_off_t < uOffset) 1578 return osl_File_E_OVERFLOW; 1579 off_t const nOffset = sal::static_int_cast< off_t >(uOffset); 1580 1581 #ifdef SAL_OS2 // YD mmap does not support shared 1582 void* p = mmap(NULL, nLength, PROT_READ, MAP_PRIVATE, pImpl->m_fd, nOffset); 1583 #else 1584 void* p = mmap(NULL, nLength, PROT_READ, MAP_SHARED, pImpl->m_fd, nOffset); 1585 #endif 1586 if (MAP_FAILED == p) 1587 return oslTranslateFileError(OSL_FET_ERROR, errno); 1588 *ppAddr = p; 1589 1590 if (uFlags & osl_File_MapFlag_RandomAccess) 1591 { 1592 // Determine memory pagesize. 1593 size_t const nPageSize = FileHandle_Impl::getpagesize(); 1594 if (size_t(-1) != nPageSize) 1595 { 1596 /* 1597 * Pagein, touching first byte of every memory page. 1598 * Note: volatile disables optimizing the loop away. 1599 */ 1600 sal_uInt8 * pData (reinterpret_cast<sal_uInt8*>(*ppAddr)); 1601 size_t nSize (nLength); 1602 1603 volatile sal_uInt8 c = 0; 1604 while (nSize > nPageSize) 1605 { 1606 c ^= pData[0]; 1607 pData += nPageSize; 1608 nSize -= nPageSize; 1609 } 1610 if (nSize > 0) 1611 { 1612 c^= pData[0]; 1613 pData += nSize; 1614 nSize -= nSize; 1615 } 1616 } 1617 } 1618 return osl_File_E_None; 1619 } 1620 1621 /******************************************* 1622 osl_unmapFile 1623 ********************************************/ 1624 oslFileError 1625 SAL_CALL osl_unmapFile (void* pAddr, sal_uInt64 uLength) 1626 { 1627 if (0 == pAddr) 1628 return osl_File_E_INVAL; 1629 1630 static sal_uInt64 const g_limit_size_t = std::numeric_limits< size_t >::max(); 1631 if (g_limit_size_t < uLength) 1632 return osl_File_E_OVERFLOW; 1633 size_t const nLength = sal::static_int_cast< size_t >(uLength); 1634 1635 if (-1 == munmap(static_cast<char*>(pAddr), nLength)) 1636 return oslTranslateFileError(OSL_FET_ERROR, errno); 1637 1638 return osl_File_E_None; 1639 } 1640 1641 /******************************************* 1642 osl_readLine 1643 ********************************************/ 1644 oslFileError 1645 SAL_CALL osl_readLine ( 1646 oslFileHandle Handle, 1647 sal_Sequence ** ppSequence) 1648 { 1649 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle); 1650 1651 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == ppSequence)) 1652 return osl_File_E_INVAL; 1653 sal_uInt64 uBytesRead = 0; 1654 1655 // read at current fileptr; fileptr += uBytesRead; 1656 oslFileError result = pImpl->readLineAt ( 1657 pImpl->m_fileptr, ppSequence, &uBytesRead); 1658 if (result == osl_File_E_None) 1659 pImpl->m_fileptr += uBytesRead; 1660 return (result); 1661 } 1662 1663 /******************************************* 1664 osl_readFile 1665 ********************************************/ 1666 oslFileError 1667 SAL_CALL osl_readFile ( 1668 oslFileHandle Handle, 1669 void * pBuffer, 1670 sal_uInt64 uBytesRequested, 1671 sal_uInt64 * pBytesRead) 1672 { 1673 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1674 1675 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesRead)) 1676 return osl_File_E_INVAL; 1677 1678 static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max(); 1679 if (g_limit_ssize_t < uBytesRequested) 1680 return osl_File_E_OVERFLOW; 1681 size_t const nBytesRequested = sal::static_int_cast< size_t >(uBytesRequested); 1682 1683 // read at current fileptr; fileptr += *pBytesRead; 1684 oslFileError result = pImpl->readFileAt ( 1685 pImpl->m_fileptr, pBuffer, nBytesRequested, pBytesRead); 1686 if (result == osl_File_E_None) 1687 pImpl->m_fileptr += *pBytesRead; 1688 return (result); 1689 } 1690 1691 /******************************************* 1692 osl_writeFile 1693 ********************************************/ 1694 oslFileError 1695 SAL_CALL osl_writeFile ( 1696 oslFileHandle Handle, 1697 const void * pBuffer, 1698 sal_uInt64 uBytesToWrite, 1699 sal_uInt64 * pBytesWritten) 1700 { 1701 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1702 1703 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesWritten)) 1704 return osl_File_E_INVAL; 1705 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE)) 1706 return osl_File_E_BADF; 1707 1708 static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max(); 1709 if (g_limit_ssize_t < uBytesToWrite) 1710 return osl_File_E_OVERFLOW; 1711 size_t const nBytesToWrite = sal::static_int_cast< size_t >(uBytesToWrite); 1712 1713 // write at current fileptr; fileptr += *pBytesWritten; 1714 oslFileError result = pImpl->writeFileAt ( 1715 pImpl->m_fileptr, pBuffer, nBytesToWrite, pBytesWritten); 1716 if (result == osl_File_E_None) 1717 pImpl->m_fileptr += *pBytesWritten; 1718 return (result); 1719 } 1720 1721 /******************************************* 1722 osl_readFileAt 1723 ********************************************/ 1724 oslFileError 1725 SAL_CALL osl_readFileAt ( 1726 oslFileHandle Handle, 1727 sal_uInt64 uOffset, 1728 void* pBuffer, 1729 sal_uInt64 uBytesRequested, 1730 sal_uInt64* pBytesRead) 1731 { 1732 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1733 1734 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesRead)) 1735 return osl_File_E_INVAL; 1736 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE)) 1737 return osl_File_E_SPIPE; 1738 1739 static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max(); 1740 if (g_limit_off_t < uOffset) 1741 return osl_File_E_OVERFLOW; 1742 off_t const nOffset = sal::static_int_cast< off_t >(uOffset); 1743 1744 static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max(); 1745 if (g_limit_ssize_t < uBytesRequested) 1746 return osl_File_E_OVERFLOW; 1747 size_t const nBytesRequested = sal::static_int_cast< size_t >(uBytesRequested); 1748 1749 // read at specified fileptr 1750 return pImpl->readFileAt (nOffset, pBuffer, nBytesRequested, pBytesRead); 1751 } 1752 1753 /******************************************* 1754 osl_writeFileAt 1755 ********************************************/ 1756 oslFileError 1757 SAL_CALL osl_writeFileAt ( 1758 oslFileHandle Handle, 1759 sal_uInt64 uOffset, 1760 const void* pBuffer, 1761 sal_uInt64 uBytesToWrite, 1762 sal_uInt64* pBytesWritten) 1763 { 1764 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1765 1766 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesWritten)) 1767 return osl_File_E_INVAL; 1768 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE)) 1769 return osl_File_E_SPIPE; 1770 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE)) 1771 return osl_File_E_BADF; 1772 1773 static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max(); 1774 if (g_limit_off_t < uOffset) 1775 return osl_File_E_OVERFLOW; 1776 off_t const nOffset = sal::static_int_cast< off_t >(uOffset); 1777 1778 static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max(); 1779 if (g_limit_ssize_t < uBytesToWrite) 1780 return osl_File_E_OVERFLOW; 1781 size_t const nBytesToWrite = sal::static_int_cast< size_t >(uBytesToWrite); 1782 1783 // write at specified fileptr 1784 return pImpl->writeFileAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten); 1785 } 1786 1787 /****************************************************************************/ 1788 /* osl_isEndOfFile */ 1789 /****************************************************************************/ 1790 oslFileError 1791 SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF ) 1792 { 1793 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1794 1795 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pIsEOF)) 1796 return osl_File_E_INVAL; 1797 1798 *pIsEOF = (pImpl->getPos() == pImpl->getSize()); 1799 return osl_File_E_None; 1800 } 1801 1802 /************************************************ 1803 * osl_getFilePos 1804 ***********************************************/ 1805 oslFileError 1806 SAL_CALL osl_getFilePos( oslFileHandle Handle, sal_uInt64* pPos ) 1807 { 1808 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1809 1810 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pPos)) 1811 return osl_File_E_INVAL; 1812 1813 *pPos = pImpl->getPos(); 1814 return osl_File_E_None; 1815 } 1816 1817 /******************************************* 1818 osl_setFilePos 1819 ********************************************/ 1820 oslFileError 1821 SAL_CALL osl_setFilePos (oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uOffset) 1822 { 1823 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1824 1825 if ((0 == pImpl) || (-1 == pImpl->m_fd)) 1826 return osl_File_E_INVAL; 1827 1828 static sal_Int64 const g_limit_off_t = std::numeric_limits< off_t >::max(); 1829 if (g_limit_off_t < uOffset) 1830 return osl_File_E_OVERFLOW; 1831 off_t nPos = 0, nOffset = sal::static_int_cast< off_t >(uOffset); 1832 1833 switch(uHow) 1834 { 1835 case osl_Pos_Absolut: 1836 if (0 > nOffset) 1837 return osl_File_E_INVAL; 1838 break; 1839 1840 case osl_Pos_Current: 1841 nPos = sal::static_int_cast< off_t >(pImpl->getPos()); 1842 if ((0 > nOffset) && (-1*nOffset > nPos)) 1843 return osl_File_E_INVAL; 1844 if (g_limit_off_t < nPos + nOffset) 1845 return osl_File_E_OVERFLOW; 1846 break; 1847 1848 case osl_Pos_End: 1849 nPos = sal::static_int_cast< off_t >(pImpl->getSize()); 1850 if ((0 > nOffset) && (-1*nOffset > nPos)) 1851 return osl_File_E_INVAL; 1852 if (g_limit_off_t < nPos + nOffset) 1853 return osl_File_E_OVERFLOW; 1854 break; 1855 1856 default: 1857 return osl_File_E_INVAL; 1858 } 1859 1860 return pImpl->setPos (nPos + nOffset); 1861 } 1862 1863 /**************************************************************************** 1864 * osl_getFileSize 1865 ****************************************************************************/ 1866 oslFileError 1867 SAL_CALL osl_getFileSize( oslFileHandle Handle, sal_uInt64* pSize ) 1868 { 1869 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1870 1871 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pSize)) 1872 return osl_File_E_INVAL; 1873 1874 *pSize = pImpl->getSize(); 1875 return osl_File_E_None; 1876 } 1877 1878 /************************************************ 1879 * osl_setFileSize 1880 ***********************************************/ 1881 oslFileError 1882 SAL_CALL osl_setFileSize( oslFileHandle Handle, sal_uInt64 uSize ) 1883 { 1884 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle); 1885 1886 if ((0 == pImpl) || (-1 == pImpl->m_fd)) 1887 return osl_File_E_INVAL; 1888 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE)) 1889 return osl_File_E_BADF; 1890 1891 static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max(); 1892 if (g_limit_off_t < uSize) 1893 return osl_File_E_OVERFLOW; 1894 1895 oslFileError result = pImpl->syncFile(); 1896 if (result != osl_File_E_None) 1897 return (result); 1898 pImpl->m_bufptr = -1, pImpl->m_buflen = 0; 1899 1900 return pImpl->setSize (uSize); 1901 } 1902 1903 /****************************************************************************/ 1904 /* osl_moveFile */ 1905 /****************************************************************************/ 1906 1907 oslFileError osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL ) 1908 { 1909 char srcPath[PATH_MAX]; 1910 char destPath[PATH_MAX]; 1911 oslFileError eRet; 1912 APIRET rc; 1913 1914 OSL_ASSERT( ustrFileURL ); 1915 OSL_ASSERT( ustrDestURL ); 1916 1917 /* convert source url to system path */ 1918 eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL ); 1919 if( eRet != osl_File_E_None ) 1920 return eRet; 1921 1922 /* convert destination url to system path */ 1923 eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL ); 1924 if( eRet != osl_File_E_None ) 1925 return eRet; 1926 1927 //YD 01/05/06 rename() can overwrite existing files. 1928 rc = DosDelete( (PCSZ)destPath); 1929 rc = DosMove( (PCSZ)srcPath, (PCSZ)destPath); 1930 if (!rc) 1931 eRet = osl_File_E_None; 1932 else 1933 eRet = MapError( rc); 1934 1935 return eRet; 1936 } 1937 1938 /****************************************************************************/ 1939 /* osl_copyFile */ 1940 /****************************************************************************/ 1941 1942 #define TMP_DEST_FILE_EXTENSION ".osl-tmp" 1943 1944 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists) 1945 { 1946 int nRet=0; 1947 sal_Char pszTmpDestFile[PATH_MAX]; 1948 size_t size_tmp_dest_buff = sizeof(pszTmpDestFile); 1949 1950 /* Quick fix for #106048, the whole copy file function seems 1951 to be erroneous anyway and needs to be rewritten. 1952 Besides osl_copyFile is currently not used from OO/SO code. 1953 */ 1954 memset(pszTmpDestFile, 0, size_tmp_dest_buff); 1955 1956 if ( DestFileExists ) 1957 { 1958 strncpy(pszTmpDestFile, pszDestFileName, size_tmp_dest_buff - 1); 1959 1960 if ((strlen(pszTmpDestFile) + strlen(TMP_DEST_FILE_EXTENSION)) >= size_tmp_dest_buff) 1961 return osl_File_E_NAMETOOLONG; 1962 1963 strncat(pszTmpDestFile, TMP_DEST_FILE_EXTENSION, strlen(TMP_DEST_FILE_EXTENSION)); 1964 1965 /* FIXME: what if pszTmpDestFile already exists? */ 1966 /* with getcanonical??? */ 1967 nRet=rename(pszDestFileName,pszTmpDestFile); 1968 } 1969 1970 /* mfe: should be S_ISREG */ 1971 if ( !S_ISLNK(nMode) ) 1972 { 1973 /* copy SourceFile to DestFile */ 1974 nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode); 1975 } 1976 /* mfe: OK redundant at the moment */ 1977 else if ( S_ISLNK(nMode) ) 1978 { 1979 nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName); 1980 } 1981 else 1982 { 1983 /* mfe: what to do here? */ 1984 nRet=ENOSYS; 1985 } 1986 1987 if ( nRet > 0 && DestFileExists == 1 ) 1988 { 1989 unlink(pszDestFileName); 1990 rename(pszTmpDestFile,pszDestFileName); 1991 } 1992 1993 if ( nRet > 0 ) 1994 { 1995 return oslTranslateFileError(OSL_FET_ERROR, nRet); 1996 } 1997 1998 if ( DestFileExists == 1 ) 1999 { 2000 unlink(pszTmpDestFile); 2001 } 2002 2003 return osl_File_E_None; 2004 } 2005 2006 /***************************************** 2007 * oslChangeFileModes 2008 ****************************************/ 2009 2010 static oslFileError oslChangeFileModes( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID) 2011 { 2012 int nRet=0; 2013 struct utimbuf aTimeBuffer; 2014 2015 nRet = chmod(pszFileName,nMode); 2016 if ( nRet < 0 ) 2017 { 2018 nRet=errno; 2019 return oslTranslateFileError(OSL_FET_ERROR, nRet); 2020 } 2021 2022 aTimeBuffer.actime=nAcTime; 2023 aTimeBuffer.modtime=nModTime; 2024 nRet=utime(pszFileName,&aTimeBuffer); 2025 if ( nRet < 0 ) 2026 { 2027 nRet=errno; 2028 return oslTranslateFileError(OSL_FET_ERROR, nRet); 2029 } 2030 2031 if ( nUID != getuid() ) 2032 { 2033 nUID=getuid(); 2034 } 2035 2036 nRet=chown(pszFileName,nUID,nGID); 2037 if ( nRet < 0 ) 2038 { 2039 nRet=errno; 2040 2041 /* mfe: do not return an error here! */ 2042 /* return oslTranslateFileError(nRet);*/ 2043 } 2044 2045 return osl_File_E_None; 2046 } 2047 2048 /***************************************** 2049 * oslDoCopyLink 2050 ****************************************/ 2051 2052 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName) 2053 { 2054 int nRet=0; 2055 2056 /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */ 2057 /* mfe: if source is a link copy the link and not the file it points to (hro says so) */ 2058 sal_Char pszLinkContent[PATH_MAX]; 2059 2060 pszLinkContent[0] = '\0'; 2061 2062 nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX); 2063 2064 if ( nRet < 0 ) 2065 { 2066 nRet=errno; 2067 return nRet; 2068 } 2069 else 2070 pszLinkContent[ nRet ] = 0; 2071 2072 nRet = symlink(pszLinkContent,pszDestFileName); 2073 2074 if ( nRet < 0 ) 2075 { 2076 nRet=errno; 2077 return nRet; 2078 } 2079 2080 return 0; 2081 } 2082 2083 /***************************************** 2084 * oslDoCopyFile 2085 ****************************************/ 2086 2087 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode) 2088 { 2089 int SourceFileFD=0; 2090 int DestFileFD=0; 2091 int nRet=0; 2092 void* pSourceFile=0; 2093 char buffer[ 4096]; 2094 2095 SourceFileFD=open(pszSourceFileName,O_RDONLY | O_BINARY); 2096 if ( SourceFileFD < 0 ) 2097 { 2098 nRet=errno; 2099 return nRet; 2100 } 2101 2102 DestFileFD=open(pszDestFileName, O_WRONLY | O_CREAT | O_BINARY, mode); 2103 if ( DestFileFD < 0 ) 2104 { 2105 nRet=errno; 2106 close(SourceFileFD); 2107 return nRet; 2108 } 2109 2110 /* HACK: because memory mapping fails on various 2111 platforms if the size of the source file is 0 byte */ 2112 if (0 == nSourceSize) 2113 { 2114 close(SourceFileFD); 2115 close(DestFileFD); 2116 return 0; 2117 } 2118 2119 while( (nRet = read(SourceFileFD, buffer, sizeof(buffer))) !=0 ) 2120 { 2121 nRet = write( DestFileFD, buffer, nRet); 2122 } 2123 2124 close(SourceFileFD); 2125 close(DestFileFD); 2126 2127 return nRet; 2128 } 2129 2130 static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath ) 2131 { 2132 time_t nAcTime=0; 2133 time_t nModTime=0; 2134 uid_t nUID=0; 2135 gid_t nGID=0; 2136 int nRet=0; 2137 mode_t nMode=0; 2138 struct stat aFileStat; 2139 oslFileError tErr=osl_File_E_invalidError; 2140 size_t nSourceSize=0; 2141 int DestFileExists=1; 2142 2143 /* mfe: does the source file really exists? */ 2144 nRet = lstat(pszPath,&aFileStat); 2145 2146 if ( nRet < 0 ) 2147 { 2148 nRet=errno; 2149 return oslTranslateFileError(OSL_FET_ERROR, nRet); 2150 } 2151 2152 /* mfe: we do only copy files here! */ 2153 if ( S_ISDIR(aFileStat.st_mode) ) 2154 { 2155 return osl_File_E_ISDIR; 2156 } 2157 2158 nSourceSize=(size_t)aFileStat.st_size; 2159 nMode=aFileStat.st_mode; 2160 nAcTime=aFileStat.st_atime; 2161 nModTime=aFileStat.st_mtime; 2162 nUID=aFileStat.st_uid; 2163 nGID=aFileStat.st_gid; 2164 2165 nRet = stat(pszDestPath,&aFileStat); 2166 if ( nRet < 0 ) 2167 { 2168 nRet=errno; 2169 2170 if ( nRet == ENOENT ) 2171 { 2172 DestFileExists=0; 2173 } 2174 /* return oslTranslateFileError(nRet);*/ 2175 } 2176 2177 /* mfe: the destination file must not be a directory! */ 2178 if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) ) 2179 { 2180 return osl_File_E_ISDIR; 2181 } 2182 else 2183 { 2184 /* mfe: file does not exists or is no dir */ 2185 } 2186 2187 tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists); 2188 2189 if ( tErr != osl_File_E_None ) 2190 { 2191 return tErr; 2192 } 2193 2194 /* 2195 * mfe: ignore return code 2196 * since only the success of the copy is 2197 * important 2198 */ 2199 oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID); 2200 2201 return tErr; 2202 } 2203 2204 oslFileError osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL ) 2205 { 2206 char srcPath[PATH_MAX]; 2207 char destPath[PATH_MAX]; 2208 oslFileError eRet; 2209 APIRET rc; 2210 2211 OSL_ASSERT( ustrFileURL ); 2212 OSL_ASSERT( ustrDestURL ); 2213 2214 /* convert source url to system path */ 2215 eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL ); 2216 if( eRet != osl_File_E_None ) 2217 return eRet; 2218 2219 /* convert destination url to system path */ 2220 eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL ); 2221 if( eRet != osl_File_E_None ) 2222 return eRet; 2223 2224 return osl_psz_copyFile( srcPath, destPath ); 2225 } 2226 2227 /****************************************************************************/ 2228 /* osl_removeFile */ 2229 /****************************************************************************/ 2230 2231 oslFileError osl_removeFile( rtl_uString* ustrFileURL ) 2232 { 2233 char path[PATH_MAX]; 2234 oslFileError eRet; 2235 APIRET rc; 2236 2237 OSL_ASSERT( ustrFileURL ); 2238 2239 /* convert file url to system path */ 2240 eRet = FileURLToPath( path, PATH_MAX, ustrFileURL ); 2241 if( eRet != osl_File_E_None ) 2242 return eRet; 2243 2244 rc = DosDelete( (PCSZ)path); 2245 if (!rc) 2246 eRet = osl_File_E_None; 2247 else 2248 eRet = MapError( rc); 2249 2250 return eRet; 2251 } 2252 2253 /****************************************************************************/ 2254 /* osl_getVolumeInformation */ 2255 /****************************************************************************/ 2256 2257 #define TXFSDC_BLOCKR 0x00 // block device removable 2258 #define TXFSDC_GETBPB 0x00 // get device bpb info 2259 #define TXFSBPB_REMOVABLE 0x08 // BPB attribute for removable 2260 2261 typedef struct drivecmd 2262 { 2263 BYTE cmd; // 0=unlock 1=lock 2=eject 2264 BYTE drv; // 0=A, 1=B 2=C ... 2265 } DRIVECMD; // end of struct "drivecmd" 2266 2267 #pragma pack(push, 1) // byte packing 2268 typedef struct txfs_ebpb // ext. boot parameter block 2269 { // at offset 0x0b in bootsector 2270 USHORT SectSize; // 0B bytes per sector 2271 BYTE ClustSize; // 0D sectors per cluster 2272 USHORT FatOffset; // 0E sectors to 1st FAT 2273 BYTE NrOfFats; // 10 nr of FATS (FAT only) 2274 USHORT RootEntries; // 11 Max entries \ (FAT only) 2275 USHORT Sectors; // 13 nr of sectors if < 64K 2276 BYTE MediaType; // 15 mediatype (F8 for HD) 2277 USHORT FatSectors; // 16 sectors/FAT (FAT only) 2278 USHORT LogGeoSect; // 18 sectors/Track 2279 USHORT LogGeoHead; // 1a nr of heads 2280 ULONG HiddenSectors; // 1c sector-offset from MBR/EBR 2281 ULONG BigSectors; // 20 nr of sectors if >= 64K 2282 } TXFS_EBPB; // last byte is at offset 0x23 2283 2284 typedef struct drivebpb 2285 { 2286 TXFS_EBPB ebpb; // extended BPB 2287 BYTE reserved[6]; 2288 USHORT cyls; 2289 BYTE type; 2290 USHORT attributes; // device attributes 2291 BYTE fill[6]; // documented for IOCtl 2292 } DRIVEBPB; // end of struct "drivebpb" 2293 2294 struct CDInfo { 2295 USHORT usCount; 2296 USHORT usFirst; 2297 }; 2298 2299 #pragma pack(pop) 2300 2301 /*****************************************************************************/ 2302 // Get number of cdrom readers 2303 /*****************************************************************************/ 2304 BOOL GetCDInfo( CDInfo * pCDInfo ) 2305 { 2306 HFILE hFileCD; 2307 ULONG ulAction; 2308 2309 if( NO_ERROR == DosOpen( (PCSZ)"\\DEV\\CD-ROM2$", 2310 &hFileCD, &ulAction, 0, FILE_NORMAL, 2311 OPEN_ACTION_OPEN_IF_EXISTS, 2312 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL )) { 2313 ULONG ulDataSize = sizeof(CDInfo); 2314 APIRET rc = DosDevIOCtl( hFileCD, 0x82, 0x60, NULL, 0, 2315 NULL, (PVOID)pCDInfo, ulDataSize, &ulDataSize); 2316 DosClose( hFileCD); 2317 if(rc == NO_ERROR) 2318 return TRUE; 2319 } 2320 // failed 2321 pCDInfo->usFirst = 0; 2322 pCDInfo->usCount = 0; 2323 return FALSE; 2324 } 2325 2326 /*****************************************************************************/ 2327 // Determine if unit is a cdrom or not 2328 /*****************************************************************************/ 2329 BOOL DriveIsCDROM(UINT uiDrive, CDInfo *pCDInfo) 2330 { 2331 return (uiDrive >= pCDInfo->usFirst) 2332 && (uiDrive < (pCDInfo->usFirst + pCDInfo->usCount)); 2333 } 2334 2335 /*****************************************************************************/ 2336 // Determine attached fstype, e.g. HPFS for specified drive 2337 /*****************************************************************************/ 2338 BOOL TxFsType // RET FS type resolved 2339 ( 2340 char *drive, // IN Drive specification 2341 char *fstype, // OUT Attached FS type 2342 char *details // OUT details (UNC) or NULL 2343 ) 2344 { 2345 BOOL rc = FALSE; 2346 FSQBUFFER2 *fsinfo; // Attached FS info 2347 ULONG fsdlen = 2048; // Fs info data length 2348 2349 strcpy(fstype, "none"); 2350 if (details) 2351 { 2352 strcpy(details, ""); 2353 } 2354 if ((fsinfo = (FSQBUFFER2*)calloc(1, fsdlen)) != NULL) 2355 { 2356 if (DosQFSAttach((PCSZ)drive, 0, 1, fsinfo, &fsdlen) == NO_ERROR) 2357 { 2358 strcpy(fstype, (char*) fsinfo->szName + fsinfo->cbName +1); 2359 if (details && (fsinfo->cbFSAData != 0)) 2360 { 2361 strcpy( details, (char*) fsinfo->szName + fsinfo->cbName + 2362 fsinfo->cbFSDName +2); 2363 } 2364 rc = TRUE; 2365 } 2366 free(fsinfo); 2367 } 2368 return (rc); 2369 } // end 'TxFsType' 2370 /*---------------------------------------------------------------------------*/ 2371 2372 2373 /*****************************************************************************/ 2374 // Determine if a driveletter represents a removable medium/device 2375 /*****************************************************************************/ 2376 BOOL TxFsIsRemovable // RET drive is removable 2377 ( 2378 char *drive // IN Driveletter to test 2379 ) 2380 { 2381 BOOL rc = FALSE; 2382 DRIVECMD IOCtl; 2383 DRIVEBPB RemAt; 2384 ULONG DataLen; 2385 ULONG ParmLen; 2386 BYTE NoRem; 2387 2388 DosError( FERR_DISABLEHARDERR); // avoid 'not ready' popups 2389 2390 ParmLen = sizeof(IOCtl); 2391 IOCtl.cmd = TXFSDC_BLOCKR; 2392 IOCtl.drv = toupper(drive[0]) - 'A'; 2393 DataLen = sizeof(NoRem); 2394 2395 if (DosDevIOCtl((HFILE) -1, IOCTL_DISK, 2396 DSK_BLOCKREMOVABLE, 2397 &IOCtl, ParmLen, &ParmLen, 2398 &NoRem, DataLen, &DataLen) == NO_ERROR) 2399 { 2400 if (NoRem) // non-removable sofar, check 2401 { // BPB as well (USB devices) 2402 ParmLen = sizeof(IOCtl); 2403 IOCtl.cmd = TXFSDC_GETBPB; 2404 IOCtl.drv = toupper(drive[0]) - 'A'; 2405 DataLen = sizeof(RemAt); 2406 2407 if (DosDevIOCtl((HFILE) -1, IOCTL_DISK, 2408 DSK_GETDEVICEPARAMS, 2409 &IOCtl, ParmLen, &ParmLen, 2410 &RemAt, DataLen, &DataLen) == NO_ERROR) 2411 2412 { 2413 if (RemAt.attributes & TXFSBPB_REMOVABLE) 2414 { 2415 rc = TRUE; // removable, probably USB 2416 } 2417 } 2418 } 2419 else 2420 { 2421 rc = TRUE; // removable block device 2422 } 2423 } 2424 DosError( FERR_ENABLEHARDERR); // enable criterror handler 2425 return (rc); 2426 } // end 'TxFsIsRemovable' 2427 /*---------------------------------------------------------------------------*/ 2428 2429 static oslFileError get_drive_type(const char* path, oslVolumeInfo* pInfo) 2430 { 2431 char Drive_Letter = toupper( *path); 2432 char fstype[ 64]; 2433 2434 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; 2435 2436 // check for floppy A/B 2437 BYTE nFloppies; 2438 APIRET rc; 2439 rc = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY ); 2440 if ((Drive_Letter - 'A') < nFloppies) { 2441 pInfo->uAttributes |= osl_Volume_Attribute_Removeable; 2442 pInfo->uAttributes |= osl_Volume_Attribute_FloppyDisk; 2443 return osl_File_E_None; 2444 } 2445 2446 // query system for CD drives 2447 CDInfo cdInfo; 2448 GetCDInfo(&cdInfo); 2449 2450 // query if drive is a CDROM 2451 if (DriveIsCDROM( Drive_Letter - 'A', &cdInfo)) 2452 pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable; 2453 2454 if (TxFsIsRemovable( (char*)path)) 2455 pInfo->uAttributes |= osl_Volume_Attribute_Removeable; 2456 2457 if (TxFsType( (char*)path, fstype, NULL) == FALSE) { 2458 // query failed, assume fixed disk 2459 pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk; 2460 return osl_File_E_None; 2461 } 2462 2463 //- Note, connected Win-NT drives use the REAL FS-name like NTFS! 2464 if ((strncasecmp( fstype, "LAN", 3) == 0) //- OS/2 LAN drives 2465 || (strncasecmp( fstype, "NDFS", 4) == 0) //- NetDrive 2466 || (strncasecmp( fstype, "REMOTE", 5) == 0) ) //- NT disconnected 2467 pInfo->uAttributes |= osl_Volume_Attribute_Remote; 2468 else if (strncasecmp( fstype, "RAMFS", 5) == 0) 2469 pInfo->uAttributes |= osl_Volume_Attribute_RAMDisk; 2470 else if ((strncasecmp( fstype, "CD", 2) == 0) // OS2:CDFS, DOS/WIN:CDROM 2471 || (strncasecmp( fstype, "UDF", 3) == 0) ) // OS2:UDF DVD's 2472 pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable; 2473 else 2474 pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk; 2475 2476 return osl_File_E_None; 2477 } 2478 2479 //############################################# 2480 inline bool is_volume_space_info_request(sal_uInt32 field_mask) 2481 { 2482 return (field_mask & 2483 (osl_VolumeInfo_Mask_TotalSpace | 2484 osl_VolumeInfo_Mask_UsedSpace | 2485 osl_VolumeInfo_Mask_FreeSpace)); 2486 } 2487 2488 //############################################# 2489 static void get_volume_space_information(const char* path, oslVolumeInfo *pInfo) 2490 { 2491 FSALLOCATE aFSInfoBuf; 2492 ULONG nDriveNumber = toupper( *path) - 'A' + 1; 2493 2494 // disable error popups 2495 DosError(FERR_DISABLEHARDERR); 2496 APIRET rc = DosQueryFSInfo( nDriveNumber, FSIL_ALLOC, 2497 &aFSInfoBuf, sizeof(aFSInfoBuf) ); 2498 // enable error popups 2499 DosError(FERR_ENABLEHARDERR); 2500 if (!rc) 2501 { 2502 uint64_t aBytesPerCluster( uint64_t(aFSInfoBuf.cbSector) * 2503 uint64_t(aFSInfoBuf.cSectorUnit) ); 2504 pInfo->uFreeSpace = aBytesPerCluster * uint64_t(aFSInfoBuf.cUnitAvail); 2505 pInfo->uTotalSpace = aBytesPerCluster * uint64_t(aFSInfoBuf.cUnit); 2506 pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace; 2507 pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace | 2508 osl_VolumeInfo_Mask_UsedSpace | 2509 osl_VolumeInfo_Mask_FreeSpace; 2510 } 2511 } 2512 2513 //############################################# 2514 inline bool is_filesystem_attributes_request(sal_uInt32 field_mask) 2515 { 2516 return (field_mask & 2517 (osl_VolumeInfo_Mask_MaxNameLength | 2518 osl_VolumeInfo_Mask_MaxPathLength | 2519 osl_VolumeInfo_Mask_FileSystemName | 2520 osl_VolumeInfo_Mask_FileSystemCaseHandling)); 2521 } 2522 2523 //############################################# 2524 inline bool is_drivetype_request(sal_uInt32 field_mask) 2525 { 2526 return (field_mask & osl_VolumeInfo_Mask_Attributes); 2527 } 2528 2529 typedef struct _FSQBUFFER_ 2530 { 2531 FSQBUFFER2 aBuf; 2532 UCHAR sBuf[64]; 2533 } FSQBUFFER_; 2534 2535 //############################################# 2536 static oslFileError get_filesystem_attributes(const char* path, sal_uInt32 field_mask, oslVolumeInfo* pInfo) 2537 { 2538 pInfo->uAttributes = 0; 2539 2540 oslFileError osl_error = osl_File_E_None; 2541 2542 // osl_get_drive_type must be called first because 2543 // this function resets osl_VolumeInfo_Mask_Attributes 2544 // on failure 2545 if (is_drivetype_request(field_mask)) 2546 osl_error = get_drive_type(path, pInfo); 2547 2548 if ((osl_File_E_None == osl_error) && is_filesystem_attributes_request(field_mask)) 2549 { 2550 FSQBUFFER_ aBuf; 2551 ULONG nBufLen; 2552 APIRET nRet; 2553 2554 nBufLen = sizeof( aBuf ); 2555 // disable error popups 2556 DosError(FERR_DISABLEHARDERR); 2557 nRet = DosQueryFSAttach( (PCSZ)path, 0, FSAIL_QUERYNAME, (_FSQBUFFER2*) &aBuf, &nBufLen ); 2558 if ( !nRet ) 2559 { 2560 char *pType = (char*)(aBuf.aBuf.szName + aBuf.aBuf.cbName + 1); 2561 pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength; 2562 pInfo->uMaxNameLength = _MAX_FNAME; 2563 2564 pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength; 2565 pInfo->uMaxPathLength = _MAX_PATH; 2566 2567 pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName; 2568 rtl_uString_newFromAscii(&pInfo->ustrFileSystemName, pType); 2569 2570 // case is preserved always except for FAT 2571 if (strcmp( pType, "FAT" )) 2572 pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved; 2573 2574 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; 2575 } 2576 // enable error popups 2577 DosError(FERR_ENABLEHARDERR); 2578 } 2579 return osl_error; 2580 } 2581 2582 oslFileError SAL_CALL osl_getVolumeInformation( rtl_uString* ustrDirectoryURL, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask ) 2583 { 2584 char volume_root[PATH_MAX]; 2585 oslFileError error; 2586 2587 OSL_ASSERT( ustrDirectoryURL ); 2588 OSL_ASSERT( pInfo ); 2589 2590 /* convert directory url to system path */ 2591 error = FileURLToPath( volume_root, PATH_MAX, ustrDirectoryURL ); 2592 if( error != osl_File_E_None ) 2593 return error; 2594 2595 if (!pInfo) 2596 return osl_File_E_INVAL; 2597 2598 pInfo->uValidFields = 0; 2599 2600 if ((error = get_filesystem_attributes(volume_root, uFieldMask, pInfo)) != osl_File_E_None) 2601 return error; 2602 2603 if (is_volume_space_info_request(uFieldMask)) 2604 get_volume_space_information(volume_root, pInfo); 2605 2606 if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle) 2607 { 2608 pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle; 2609 rtl_uString* uVolumeRoot; 2610 rtl_uString_newFromAscii( &uVolumeRoot, volume_root); 2611 osl_getFileURLFromSystemPath( uVolumeRoot, (rtl_uString**)&pInfo->pDeviceHandle); 2612 rtl_uString_release( uVolumeRoot); 2613 } 2614 2615 return osl_File_E_None; 2616 } 2617 2618 /****************************************************************************/ 2619 /* osl_getFileStatus */ 2620 /****************************************************************************/ 2621 static oslFileError _osl_getDriveInfo( 2622 oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask) 2623 { 2624 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; 2625 sal_Unicode cDrive[3]; 2626 sal_Unicode cRoot[4]; 2627 2628 if ( !pItemImpl ) 2629 return osl_File_E_INVAL; 2630 2631 pStatus->uValidFields = 0; 2632 2633 cDrive[0] = pItemImpl->ustrDrive->buffer[0]; 2634 cDrive[1] = (sal_Unicode)':'; 2635 cDrive[2] = 0; 2636 cRoot[0] = pItemImpl->ustrDrive->buffer[0]; 2637 cRoot[1] = (sal_Unicode)':'; 2638 cRoot[2] = 0; 2639 2640 if ( uFieldMask & osl_FileStatus_Mask_FileName ) 2641 { 2642 if ( pItemImpl->ustrDrive->buffer[0] == '\\' && 2643 pItemImpl->ustrDrive->buffer[1] == '\\' ) 2644 { 2645 LPCWSTR lpFirstBkSlash = wcschr( (const wchar_t*)&pItemImpl->ustrDrive->buffer[2], '\\' ); 2646 2647 if ( lpFirstBkSlash && lpFirstBkSlash[1] ) 2648 { 2649 LPCWSTR lpLastBkSlash = wcschr( (const wchar_t*)&lpFirstBkSlash[1], '\\' ); 2650 2651 if ( lpLastBkSlash ) 2652 rtl_uString_newFromStr_WithLength( &pStatus->ustrFileName, (sal_Unicode*)&lpFirstBkSlash[1], lpLastBkSlash - lpFirstBkSlash - 1 ); 2653 else 2654 rtl_uString_newFromStr( &pStatus->ustrFileName, (sal_Unicode*)&lpFirstBkSlash[1] ); 2655 pStatus->uValidFields |= osl_FileStatus_Mask_FileName; 2656 } 2657 } 2658 else 2659 { 2660 FSINFO aFSInfoBuf; 2661 ULONG ulFSInfoLevel = FSIL_VOLSER; 2662 ULONG nDriveNumber; 2663 char szFileName[ _MAX_PATH]; 2664 2665 nDriveNumber = toupper(*cDrive) - 'A' + 1; 2666 memset( &aFSInfoBuf, 0, sizeof(FSINFO) ); 2667 // disable error popups 2668 DosError(FERR_DISABLEHARDERR); 2669 APIRET rc = DosQueryFSInfo( nDriveNumber, ulFSInfoLevel, &aFSInfoBuf, sizeof(FSINFO) ); 2670 // enable error popups 2671 DosError(FERR_ENABLEHARDERR); 2672 memset( szFileName, 0, sizeof( szFileName)); 2673 *szFileName = toupper(*cDrive); 2674 strcat( szFileName, ": ["); 2675 if ( !rc || aFSInfoBuf.vol.cch) 2676 strncat( szFileName, aFSInfoBuf.vol.szVolLabel, aFSInfoBuf.vol.cch); 2677 strcat( szFileName, "]"); 2678 rtl_uString_newFromAscii( &pStatus->ustrFileName, szFileName ); 2679 2680 pStatus->uValidFields |= osl_FileStatus_Mask_FileName; 2681 } 2682 } 2683 2684 pStatus->eType = osl_File_Type_Volume; 2685 pStatus->uValidFields |= osl_FileStatus_Mask_Type; 2686 2687 if ( uFieldMask & osl_FileStatus_Mask_FileURL ) 2688 { 2689 rtl_uString *ustrSystemPath = NULL; 2690 2691 rtl_uString_newFromStr( &ustrSystemPath, pItemImpl->ustrDrive->buffer ); 2692 osl_getFileURLFromSystemPath( ustrSystemPath, &pStatus->ustrFileURL ); 2693 rtl_uString_release( ustrSystemPath ); 2694 pStatus->uValidFields |= osl_FileStatus_Mask_FileURL; 2695 } 2696 2697 return osl_File_E_None; 2698 } 2699 2700 oslFileError SAL_CALL osl_getFileStatus( 2701 oslDirectoryItem Item, 2702 oslFileStatus *pStatus, 2703 sal_uInt32 uFieldMask ) 2704 { 2705 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; 2706 struct stat file_stat; 2707 2708 if ( !pItemImpl ) 2709 return osl_File_E_INVAL; 2710 2711 if ( pItemImpl->uType == DIRECTORYITEM_DRIVE) 2712 return _osl_getDriveInfo( Item, pStatus, uFieldMask ); 2713 2714 osl::lstat(pItemImpl->ustrFilePath, file_stat); 2715 if ( uFieldMask & osl_FileStatus_Mask_Validate ) 2716 { 2717 uFieldMask &= ~ osl_FileStatus_Mask_Validate; 2718 } 2719 2720 /* If no fields to retrieve left ignore pStatus */ 2721 if ( !uFieldMask ) 2722 return osl_File_E_None; 2723 2724 /* Otherwise, this must be a valid pointer */ 2725 if ( !pStatus ) 2726 return osl_File_E_INVAL; 2727 2728 if ( pStatus->uStructSize != sizeof(oslFileStatus) ) 2729 return osl_File_E_INVAL; 2730 2731 pStatus->uValidFields = 0; 2732 2733 /* File time stamps */ 2734 2735 if ( (uFieldMask & osl_FileStatus_Mask_ModifyTime)) 2736 { 2737 pStatus->aModifyTime.Seconds = file_stat.st_mtime; 2738 pStatus->aModifyTime.Nanosec = 0; 2739 pStatus->uValidFields |= osl_FileStatus_Mask_ModifyTime; 2740 } 2741 2742 if ( (uFieldMask & osl_FileStatus_Mask_AccessTime)) 2743 { 2744 pStatus->aAccessTime.Seconds = file_stat.st_atime; 2745 pStatus->aAccessTime.Nanosec = 0; 2746 pStatus->uValidFields |= osl_FileStatus_Mask_AccessTime; 2747 } 2748 2749 if ( (uFieldMask & osl_FileStatus_Mask_CreationTime)) 2750 { 2751 pStatus->aAccessTime.Seconds = file_stat.st_birthtime; 2752 pStatus->aAccessTime.Nanosec = 0; 2753 pStatus->uValidFields |= osl_FileStatus_Mask_CreationTime; 2754 } 2755 2756 /* Most of the fields are already set, regardless of requiered fields */ 2757 2758 osl_systemPathGetFileNameOrLastDirectoryPart(pItemImpl->ustrFilePath, &pStatus->ustrFileName); 2759 pStatus->uValidFields |= osl_FileStatus_Mask_FileName; 2760 2761 if (S_ISLNK(file_stat.st_mode)) 2762 pStatus->eType = osl_File_Type_Link; 2763 else if (S_ISDIR(file_stat.st_mode)) 2764 pStatus->eType = osl_File_Type_Directory; 2765 else if (S_ISREG(file_stat.st_mode)) 2766 pStatus->eType = osl_File_Type_Regular; 2767 else if (S_ISFIFO(file_stat.st_mode)) 2768 pStatus->eType = osl_File_Type_Fifo; 2769 else if (S_ISSOCK(file_stat.st_mode)) 2770 pStatus->eType = osl_File_Type_Socket; 2771 else if (S_ISCHR(file_stat.st_mode) || S_ISBLK(file_stat.st_mode)) 2772 pStatus->eType = osl_File_Type_Special; 2773 else 2774 pStatus->eType = osl_File_Type_Unknown; 2775 2776 pStatus->uValidFields |= osl_FileStatus_Mask_Type; 2777 2778 pStatus->uAttributes = pItemImpl->d_attr; 2779 pStatus->uValidFields |= osl_FileStatus_Mask_Attributes; 2780 2781 pStatus->uFileSize = file_stat.st_size; 2782 pStatus->uValidFields |= osl_FileStatus_Mask_FileSize; 2783 2784 if ( uFieldMask & osl_FileStatus_Mask_LinkTargetURL ) 2785 { 2786 rtl_uString *ustrFullPath = NULL; 2787 2788 rtl_uString_newFromStr( &ustrFullPath, rtl_uString_getStr(pItemImpl->ustrFilePath) ); 2789 osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrLinkTargetURL ); 2790 rtl_uString_release( ustrFullPath ); 2791 2792 pStatus->uValidFields |= osl_FileStatus_Mask_LinkTargetURL; 2793 } 2794 2795 if ( uFieldMask & osl_FileStatus_Mask_FileURL ) 2796 { 2797 rtl_uString *ustrFullPath = NULL; 2798 2799 rtl_uString_newFromStr( &ustrFullPath, rtl_uString_getStr(pItemImpl->ustrFilePath) ); 2800 osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrFileURL ); 2801 rtl_uString_release( ustrFullPath ); 2802 pStatus->uValidFields |= osl_FileStatus_Mask_FileURL; 2803 } 2804 2805 return osl_File_E_None; 2806 } 2807 2808 /****************************************************************************/ 2809 /* osl_createDirectory */ 2810 /****************************************************************************/ 2811 2812 oslFileError osl_createDirectory( rtl_uString* ustrDirectoryURL ) 2813 { 2814 char path[PATH_MAX]; 2815 oslFileError eRet; 2816 APIRET rc; 2817 2818 OSL_ASSERT( ustrDirectoryURL ); 2819 2820 /* convert directory url to system path */ 2821 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL ); 2822 if( eRet != osl_File_E_None ) 2823 return eRet; 2824 2825 rc = DosCreateDir( (PCSZ)path, NULL); 2826 if (rc == ERROR_ACCESS_DENIED) 2827 rc=ERROR_FILE_EXISTS; 2828 2829 if (!rc) 2830 eRet = osl_File_E_None; 2831 else 2832 eRet = MapError( rc); 2833 2834 return eRet; 2835 } 2836 2837 /****************************************************************************/ 2838 /* osl_removeDirectory */ 2839 /****************************************************************************/ 2840 2841 oslFileError osl_removeDirectory( rtl_uString* ustrDirectoryURL ) 2842 { 2843 char path[PATH_MAX]; 2844 oslFileError eRet; 2845 APIRET rc; 2846 2847 OSL_ASSERT( ustrDirectoryURL ); 2848 2849 /* convert directory url to system path */ 2850 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL ); 2851 if( eRet != osl_File_E_None ) 2852 return eRet; 2853 2854 rc = DosDeleteDir( (PCSZ)path); 2855 if (!rc) 2856 eRet = osl_File_E_None; 2857 else 2858 eRet = MapError( rc); 2859 2860 return eRet; 2861 } 2862 2863 //############################################# 2864 int path_make_parent(sal_Unicode* path) 2865 { 2866 int i = rtl_ustr_lastIndexOfChar(path, '/'); 2867 2868 if (i > 0) 2869 { 2870 *(path + i) = 0; 2871 return i; 2872 } 2873 else 2874 return 0; 2875 } 2876 2877 //############################################# 2878 int create_dir_with_callback( 2879 sal_Unicode* directory_path, 2880 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, 2881 void* pData) 2882 { 2883 int mode = S_IRWXU | S_IRWXG | S_IRWXO; 2884 2885 if (osl::mkdir(directory_path, mode) == 0) 2886 { 2887 if (aDirectoryCreationCallbackFunc) 2888 { 2889 rtl::OUString url; 2890 osl::FileBase::getFileURLFromSystemPath(directory_path, url); 2891 aDirectoryCreationCallbackFunc(pData, url.pData); 2892 } 2893 return 0; 2894 } 2895 return errno; 2896 } 2897 2898 //############################################# 2899 oslFileError create_dir_recursively_( 2900 sal_Unicode* dir_path, 2901 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, 2902 void* pData) 2903 { 2904 OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \ 2905 "Path must not end with a slash"); 2906 2907 int native_err = create_dir_with_callback( 2908 dir_path, aDirectoryCreationCallbackFunc, pData); 2909 2910 if (native_err == 0) 2911 return osl_File_E_None; 2912 2913 if (native_err != ENOENT) 2914 return oslTranslateFileError(OSL_FET_ERROR, native_err); 2915 2916 // we step back until '/a_dir' at maximum because 2917 // we should get an error unequal ENOENT when 2918 // we try to create 'a_dir' at '/' and would so 2919 // return before 2920 int pos = path_make_parent(dir_path); 2921 2922 oslFileError osl_error = create_dir_recursively_( 2923 dir_path, aDirectoryCreationCallbackFunc, pData); 2924 2925 if (osl_File_E_None != osl_error) 2926 return osl_error; 2927 2928 dir_path[pos] = '/'; 2929 2930 return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData); 2931 } 2932 2933 //####################################### 2934 oslFileError SAL_CALL osl_createDirectoryPath( 2935 rtl_uString* aDirectoryUrl, 2936 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, 2937 void* pData) 2938 { 2939 if (aDirectoryUrl == NULL) 2940 return osl_File_E_INVAL; 2941 2942 rtl::OUString sys_path; 2943 oslFileError osl_error = osl_getSystemPathFromFileURL_Ex( 2944 aDirectoryUrl, &sys_path.pData, sal_False); 2945 2946 if (osl_error != osl_File_E_None) 2947 return osl_error; 2948 2949 osl::systemPathRemoveSeparator(sys_path); 2950 2951 // const_cast because sys_path is a local copy which we want to modify inplace instead of 2952 // coyp it into another buffer on the heap again 2953 return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData); 2954 } 2955 2956 /****************************************************************************/ 2957 /* osl_getCanonicalName */ 2958 /****************************************************************************/ 2959 2960 oslFileError osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uString** pustrValidURL ) 2961 { 2962 OSL_ENSURE(sal_False, "osl_getCanonicalName not implemented"); 2963 2964 rtl_uString_newFromString(pustrValidURL, ustrFileURL); 2965 return osl_File_E_None; 2966 } 2967 2968 2969 /****************************************************************************/ 2970 /* osl_setFileAttributes */ 2971 /****************************************************************************/ 2972 2973 oslFileError osl_setFileAttributes( rtl_uString* ustrFileURL, sal_uInt64 uAttributes ) 2974 { 2975 char path[PATH_MAX]; 2976 oslFileError eRet; 2977 FILESTATUS3 fsts3ConfigInfo; 2978 ULONG ulBufSize = sizeof(FILESTATUS3); 2979 APIRET rc = NO_ERROR; 2980 2981 OSL_ASSERT( ustrFileURL ); 2982 2983 /* convert file url to system path */ 2984 eRet = FileURLToPath( path, PATH_MAX, ustrFileURL ); 2985 if( eRet != osl_File_E_None ) 2986 return eRet; 2987 2988 /* query current attributes */ 2989 rc = DosQueryPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize); 2990 if (rc != NO_ERROR) 2991 return MapError( rc); 2992 2993 /* set/reset readonly/hidden (see w32\file.cxx) */ 2994 fsts3ConfigInfo.attrFile &= ~(FILE_READONLY | FILE_HIDDEN); 2995 if ( uAttributes & osl_File_Attribute_ReadOnly ) 2996 fsts3ConfigInfo.attrFile |= FILE_READONLY; 2997 if ( uAttributes & osl_File_Attribute_Hidden ) 2998 fsts3ConfigInfo.attrFile |= FILE_HIDDEN; 2999 3000 /* write new attributes */ 3001 rc = DosSetPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize, 0); 3002 if (rc != NO_ERROR) 3003 return MapError( rc); 3004 3005 /* everything ok */ 3006 return osl_File_E_None; 3007 } 3008 3009 /****************************************************************************/ 3010 /* osl_setFileTime */ 3011 /****************************************************************************/ 3012 3013 oslFileError osl_setFileTime( rtl_uString* ustrFileURL, const TimeValue* pCreationTime, 3014 const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime ) 3015 { 3016 char path[PATH_MAX]; 3017 oslFileError eRet; 3018 3019 OSL_ASSERT( ustrFileURL ); 3020 3021 /* convert file url to system path */ 3022 eRet = FileURLToPath( path, PATH_MAX, ustrFileURL ); 3023 if( eRet != osl_File_E_None ) 3024 return eRet; 3025 3026 return osl_psz_setFileTime( path, pCreationTime, pLastAccessTime, pLastWriteTime ); 3027 } 3028 3029 /****************************************************************************** 3030 * 3031 * Exported Module Functions 3032 * (independent of C or Unicode Strings) 3033 * 3034 *****************************************************************************/ 3035 3036 3037 3038 /****************************************************************************** 3039 * 3040 * C-String Versions of Exported Module Functions 3041 * 3042 *****************************************************************************/ 3043 3044 3045 /****************************************** 3046 * osl_psz_setFileTime 3047 *****************************************/ 3048 3049 static oslFileError osl_psz_setFileTime( const sal_Char* pszFilePath, 3050 const TimeValue* /*pCreationTime*/, 3051 const TimeValue* pLastAccessTime, 3052 const TimeValue* pLastWriteTime ) 3053 { 3054 int nRet=0; 3055 struct utimbuf aTimeBuffer; 3056 struct stat aFileStat; 3057 #ifdef DEBUG_OSL_FILE 3058 struct tm* pTM=0; 3059 #endif 3060 3061 nRet = lstat(pszFilePath,&aFileStat); 3062 3063 if ( nRet < 0 ) 3064 { 3065 nRet=errno; 3066 return oslTranslateFileError(OSL_FET_ERROR, nRet); 3067 } 3068 3069 #ifdef DEBUG_OSL_FILE 3070 fprintf(stderr,"File Times are (in localtime):\n"); 3071 pTM=localtime(&aFileStat.st_ctime); 3072 fprintf(stderr,"CreationTime is '%s'\n",asctime(pTM)); 3073 pTM=localtime(&aFileStat.st_atime); 3074 fprintf(stderr,"AccessTime is '%s'\n",asctime(pTM)); 3075 pTM=localtime(&aFileStat.st_mtime); 3076 fprintf(stderr,"Modification is '%s'\n",asctime(pTM)); 3077 3078 fprintf(stderr,"File Times are (in UTC):\n"); 3079 fprintf(stderr,"CreationTime is '%s'\n",ctime(&aFileStat.st_ctime)); 3080 fprintf(stderr,"AccessTime is '%s'\n",ctime(&aTimeBuffer.actime)); 3081 fprintf(stderr,"Modification is '%s'\n",ctime(&aTimeBuffer.modtime)); 3082 #endif 3083 3084 if ( pLastAccessTime != 0 ) 3085 { 3086 aTimeBuffer.actime=pLastAccessTime->Seconds; 3087 } 3088 else 3089 { 3090 aTimeBuffer.actime=aFileStat.st_atime; 3091 } 3092 3093 if ( pLastWriteTime != 0 ) 3094 { 3095 aTimeBuffer.modtime=pLastWriteTime->Seconds; 3096 } 3097 else 3098 { 3099 aTimeBuffer.modtime=aFileStat.st_mtime; 3100 } 3101 3102 /* mfe: Creation time not used here! */ 3103 3104 #ifdef DEBUG_OSL_FILE 3105 fprintf(stderr,"File Times are (in localtime):\n"); 3106 pTM=localtime(&aFileStat.st_ctime); 3107 fprintf(stderr,"CreationTime now '%s'\n",asctime(pTM)); 3108 pTM=localtime(&aTimeBuffer.actime); 3109 fprintf(stderr,"AccessTime now '%s'\n",asctime(pTM)); 3110 pTM=localtime(&aTimeBuffer.modtime); 3111 fprintf(stderr,"Modification now '%s'\n",asctime(pTM)); 3112 3113 fprintf(stderr,"File Times are (in UTC):\n"); 3114 fprintf(stderr,"CreationTime now '%s'\n",ctime(&aFileStat.st_ctime)); 3115 fprintf(stderr,"AccessTime now '%s'\n",ctime(&aTimeBuffer.actime)); 3116 fprintf(stderr,"Modification now '%s'\n",ctime(&aTimeBuffer.modtime)); 3117 #endif 3118 3119 nRet=utime(pszFilePath,&aTimeBuffer); 3120 if ( nRet < 0 ) 3121 { 3122 nRet=errno; 3123 return oslTranslateFileError(OSL_FET_ERROR, nRet); 3124 } 3125 3126 return osl_File_E_None; 3127 } 3128 3129 3130 /****************************************************************************** 3131 * 3132 * Utility Functions 3133 * 3134 *****************************************************************************/ 3135 3136 3137 /***************************************** 3138 * oslMakeUStrFromPsz 3139 ****************************************/ 3140 3141 rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr, rtl_uString** ustrValid) 3142 { 3143 rtl_string2UString( 3144 ustrValid, 3145 pszStr, 3146 rtl_str_getLength( pszStr ), 3147 osl_getThreadTextEncoding(), 3148 OUSTRING_TO_OSTRING_CVTFLAGS ); 3149 OSL_ASSERT(*ustrValid != 0); 3150 3151 return *ustrValid; 3152 } 3153 3154 /***************************************************************************** 3155 * UnicodeToText 3156 * converting unicode to text manually saves us the penalty of a temporary 3157 * rtl_String object. 3158 ****************************************************************************/ 3159 3160 int UnicodeToText( char * buffer, size_t bufLen, const sal_Unicode * uniText, sal_Int32 uniTextLen ) 3161 { 3162 rtl_UnicodeToTextConverter hConverter; 3163 sal_uInt32 nInfo; 3164 sal_Size nSrcChars, nDestBytes; 3165 3166 /* stolen from rtl/string.c */ 3167 hConverter = rtl_createUnicodeToTextConverter( osl_getThreadTextEncoding() ); 3168 3169 nDestBytes = rtl_convertUnicodeToText( hConverter, 0, uniText, uniTextLen, 3170 buffer, bufLen, 3171 OUSTRING_TO_OSTRING_CVTFLAGS | RTL_UNICODETOTEXT_FLAGS_FLUSH, 3172 &nInfo, &nSrcChars ); 3173 3174 rtl_destroyUnicodeToTextConverter( hConverter ); 3175 3176 if( nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL ) 3177 { 3178 errno = EOVERFLOW; 3179 return 0; 3180 } 3181 3182 /* ensure trailing '\0' */ 3183 buffer[nDestBytes] = '\0'; 3184 3185 return nDestBytes; 3186 } 3187 3188 /***************************************************************************** 3189 TextToUnicode 3190 3191 @param text 3192 The text to convert. 3193 3194 @param text_buffer_size 3195 The number of characters. 3196 3197 @param unic_text 3198 The unicode buffer. 3199 3200 @param unic_text_buffer_size 3201 The size in characters of the unicode buffer. 3202 3203 ****************************************************************************/ 3204 3205 int TextToUnicode( 3206 const char* text, 3207 size_t text_buffer_size, 3208 sal_Unicode* unic_text, 3209 sal_Int32 unic_text_buffer_size) 3210 { 3211 rtl_TextToUnicodeConverter hConverter; 3212 sal_uInt32 nInfo; 3213 sal_Size nSrcChars; 3214 sal_Size nDestBytes; 3215 3216 /* stolen from rtl/string.c */ 3217 hConverter = rtl_createTextToUnicodeConverter(osl_getThreadTextEncoding()); 3218 3219 nDestBytes = rtl_convertTextToUnicode(hConverter, 3220 0, 3221 text, text_buffer_size, 3222 unic_text, unic_text_buffer_size, 3223 OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_FLUSH, 3224 &nInfo, &nSrcChars); 3225 3226 rtl_destroyTextToUnicodeConverter(hConverter); 3227 3228 if (nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL) 3229 { 3230 errno = EOVERFLOW; 3231 return 0; 3232 } 3233 3234 /* ensure trailing '\0' */ 3235 unic_text[nDestBytes] = '\0'; 3236 3237 return nDestBytes; 3238 } 3239 3240 /****************************************************************************** 3241 * 3242 * GENERIC FLOPPY FUNCTIONS 3243 * 3244 *****************************************************************************/ 3245 3246 /***************************************** 3247 * osl_unmountVolumeDevice 3248 ****************************************/ 3249 oslFileError osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle ) 3250 { 3251 if ( Handle ) 3252 return osl_File_E_None; 3253 else 3254 return osl_File_E_INVAL; 3255 } 3256 3257 /***************************************** 3258 * osl_automountVolumeDevice 3259 ****************************************/ 3260 oslFileError osl_automountVolumeDevice( oslVolumeDeviceHandle Handle ) 3261 { 3262 if ( Handle ) 3263 return osl_File_E_None; 3264 else 3265 return osl_File_E_INVAL; 3266 } 3267 3268 /***************************************** 3269 * osl_getVolumeDeviceMountPath 3270 ****************************************/ 3271 oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath ) 3272 { 3273 if ( Handle && pstrPath ) 3274 { 3275 rtl_uString_assign( pstrPath, (rtl_uString *)Handle ); 3276 return osl_File_E_None; 3277 } 3278 else 3279 return osl_File_E_INVAL; 3280 } 3281 3282 /***************************************** 3283 * osl_acquireVolumeDeviceHandle 3284 ****************************************/ 3285 3286 oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle ) 3287 { 3288 if ( Handle ) 3289 { 3290 rtl_uString_acquire( (rtl_uString *)Handle ); 3291 return osl_File_E_None; 3292 } 3293 else 3294 return osl_File_E_INVAL; 3295 } 3296 3297 /***************************************** 3298 * osl_releaseVolumeDeviceHandle 3299 ****************************************/ 3300 3301 oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle ) 3302 { 3303 if ( Handle ) 3304 { 3305 rtl_uString_release( (rtl_uString *)Handle ); 3306 return osl_File_E_None; 3307 } 3308 else 3309 return osl_File_E_INVAL; 3310 } 3311 3312 /****************************************************************************** 3313 * 3314 * OS/2 FLOPPY FUNCTIONS 3315 * 3316 *****************************************************************************/ 3317 static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath) 3318 { 3319 return NULL; 3320 } 3321 3322