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 //#####################################################
MapError(APIRET dwError)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 &
get()265 FileHandle_Impl::Allocator::get()
266 {
267 static Allocator g_aBufferAllocator;
268 return g_aBufferAllocator;
269 }
270
Allocator()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
~Allocator()282 FileHandle_Impl::Allocator::~Allocator()
283 {
284 rtl_cache_destroy(m_cache), m_cache = 0;
285 }
286
allocate(sal_uInt8 ** ppBuffer,size_t * pnSize)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
deallocate(sal_uInt8 * pBuffer)293 void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer)
294 {
295 if (0 != pBuffer)
296 rtl_cache_free (m_cache, pBuffer);
297 }
298
FileHandle_Impl(int fd,char const * path)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
~FileHandle_Impl()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
operator new(size_t n)323 void * FileHandle_Impl::operator new(size_t n)
324 {
325 return rtl_allocateMemory(n);
326 }
327
operator delete(void * p,size_t)328 void FileHandle_Impl::operator delete(void * p, size_t)
329 {
330 rtl_freeMemory(p);
331 }
332
getpagesize()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
getPos() const340 sal_uInt64 FileHandle_Impl::getPos() const
341 {
342 return sal::static_int_cast< sal_uInt64 >(m_fileptr);
343 }
344
setPos(sal_uInt64 uPos)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
getSize() const351 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
setSize(sal_uInt64 uSize)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
readAt(off_t nOffset,void * pBuffer,size_t nBytesRequested,sal_uInt64 * pBytesRead)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
writeAt(off_t nOffset,void const * pBuffer,size_t nBytesToWrite,sal_uInt64 * pBytesWritten)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
readFileAt(off_t nOffset,void * pBuffer,size_t nBytesRequested,sal_uInt64 * pBytesRead)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
writeFileAt(off_t nOffset,void const * pBuffer,size_t nBytesToWrite,sal_uInt64 * pBytesWritten)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
readLineAt(LONGLONG nOffset,sal_Sequence ** ppSequence,sal_uInt64 * pBytesRead)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
writeSequence_Impl(sal_Sequence ** ppSequence,size_t * pnOffset,const void * pBuffer,size_t nBytes)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
syncFile()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 *********************************************/
_osl_openLocalRoot(rtl_uString * strDirectoryPath,oslDirectory * pDirectory)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 *********************************************/
_osl_getNextDrive(oslDirectory Directory,oslDirectoryItem * pItem,sal_uInt32 uHint)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
_osl_readdir_impl_(DIR * pdir,sal_Bool bFilterLocalAndParentDir)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
osl_openDirectory(rtl_uString * ustrDirectoryURL,oslDirectory * pDirectory)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
osl_getNextDirectoryItem(oslDirectory Directory,oslDirectoryItem * pItem,sal_uInt32 uHint)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
osl_closeDirectory(oslDirectory Directory)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
osl_getDirectoryItem(rtl_uString * ustrFileURL,oslDirectoryItem * pItem)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
osl_acquireDirectoryItem(oslDirectoryItem Item)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
osl_releaseDirectoryItem(oslDirectoryItem Item)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 ***************************************************************************/
osl_createFileHandleFromFD(int fd)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 ******************************************************************/
osl_file_adjustLockFlags(const char * path,int flags)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;
Locking_ImplLocking_Impl1340 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 };
osl_file_queryLocking(sal_uInt32 uFlags)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
osl_openFile(rtl_uString * ustrFileURL,oslFileHandle * pHandle,sal_uInt32 uFlags)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
osl_closeFile(oslFileHandle Handle)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
osl_syncFile(oslFileHandle Handle)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
osl_mapFile(oslFileHandle Handle,void ** ppAddr,sal_uInt64 uLength,sal_uInt64 uOffset,sal_uInt32 uFlags)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
osl_unmapFile(void * pAddr,sal_uInt64 uLength)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
osl_readLine(oslFileHandle Handle,sal_Sequence ** ppSequence)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
osl_readFile(oslFileHandle Handle,void * pBuffer,sal_uInt64 uBytesRequested,sal_uInt64 * pBytesRead)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
osl_writeFile(oslFileHandle Handle,const void * pBuffer,sal_uInt64 uBytesToWrite,sal_uInt64 * pBytesWritten)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
osl_readFileAt(oslFileHandle Handle,sal_uInt64 uOffset,void * pBuffer,sal_uInt64 uBytesRequested,sal_uInt64 * pBytesRead)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
osl_writeFileAt(oslFileHandle Handle,sal_uInt64 uOffset,const void * pBuffer,sal_uInt64 uBytesToWrite,sal_uInt64 * pBytesWritten)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
osl_isEndOfFile(oslFileHandle Handle,sal_Bool * pIsEOF)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
osl_getFilePos(oslFileHandle Handle,sal_uInt64 * pPos)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
osl_setFilePos(oslFileHandle Handle,sal_uInt32 uHow,sal_Int64 uOffset)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
osl_getFileSize(oslFileHandle Handle,sal_uInt64 * pSize)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
osl_setFileSize(oslFileHandle Handle,sal_uInt64 uSize)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
osl_moveFile(rtl_uString * ustrFileURL,rtl_uString * ustrDestURL)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
oslDoCopy(const sal_Char * pszSourceFileName,const sal_Char * pszDestFileName,mode_t nMode,size_t nSourceSize,int DestFileExists)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
oslChangeFileModes(const sal_Char * pszFileName,mode_t nMode,time_t nAcTime,time_t nModTime,uid_t nUID,gid_t nGID)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
oslDoCopyLink(const sal_Char * pszSourceFileName,const sal_Char * pszDestFileName)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
oslDoCopyFile(const sal_Char * pszSourceFileName,const sal_Char * pszDestFileName,size_t nSourceSize,mode_t mode)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
osl_psz_copyFile(const sal_Char * pszPath,const sal_Char * pszDestPath)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
osl_copyFile(rtl_uString * ustrFileURL,rtl_uString * ustrDestURL)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
osl_removeFile(rtl_uString * ustrFileURL)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 /*****************************************************************************/
GetCDInfo(CDInfo * pCDInfo)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 /*****************************************************************************/
DriveIsCDROM(UINT uiDrive,CDInfo * pCDInfo)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 /*****************************************************************************/
TxFsType(char * drive,char * fstype,char * details)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 /*****************************************************************************/
TxFsIsRemovable(char * drive)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
get_drive_type(const char * path,oslVolumeInfo * pInfo)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 //#############################################
is_volume_space_info_request(sal_uInt32 field_mask)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 //#############################################
get_volume_space_information(const char * path,oslVolumeInfo * pInfo)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 //#############################################
is_filesystem_attributes_request(sal_uInt32 field_mask)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 //#############################################
is_drivetype_request(sal_uInt32 field_mask)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 //#############################################
get_filesystem_attributes(const char * path,sal_uInt32 field_mask,oslVolumeInfo * pInfo)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
osl_getVolumeInformation(rtl_uString * ustrDirectoryURL,oslVolumeInfo * pInfo,sal_uInt32 uFieldMask)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 /****************************************************************************/
_osl_getDriveInfo(oslDirectoryItem Item,oslFileStatus * pStatus,sal_uInt32 uFieldMask)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
osl_getFileStatus(oslDirectoryItem Item,oslFileStatus * pStatus,sal_uInt32 uFieldMask)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
osl_createDirectory(rtl_uString * ustrDirectoryURL)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
osl_removeDirectory(rtl_uString * ustrDirectoryURL)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 //#############################################
path_make_parent(sal_Unicode * path)2864 int path_make_parent(sal_Unicode* path)
2865 {
2866 int i = rtl_ustr_lastIndexOfChar(path, '/');
2867 if (i == -1)
2868 i = rtl_ustr_lastIndexOfChar(path, '\\');
2869
2870 if (i > 0)
2871 {
2872 *(path + i) = 0;
2873 return i;
2874 }
2875 else
2876 return 0;
2877 }
2878
2879 //#############################################
create_dir_with_callback(sal_Unicode * directory_path,oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,void * pData)2880 int create_dir_with_callback(
2881 sal_Unicode* directory_path,
2882 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
2883 void* pData)
2884 {
2885 int mode = S_IRWXU | S_IRWXG | S_IRWXO;
2886
2887 if (osl::mkdir(directory_path, mode) == 0)
2888 {
2889 if (aDirectoryCreationCallbackFunc)
2890 {
2891 rtl::OUString url;
2892 osl::FileBase::getFileURLFromSystemPath(directory_path, url);
2893 aDirectoryCreationCallbackFunc(pData, url.pData);
2894 }
2895 return 0;
2896 }
2897 return errno;
2898 }
2899
2900 //#############################################
create_dir_recursively_(sal_Unicode * dir_path,oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,void * pData)2901 oslFileError create_dir_recursively_(
2902 sal_Unicode* dir_path,
2903 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
2904 void* pData)
2905 {
2906 OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \
2907 "Path must not end with a slash");
2908
2909 int native_err = create_dir_with_callback(
2910 dir_path, aDirectoryCreationCallbackFunc, pData);
2911
2912 if (native_err == 0)
2913 return osl_File_E_None;
2914
2915 if (native_err != ENOENT)
2916 return oslTranslateFileError(OSL_FET_ERROR, native_err);
2917
2918 // we step back until '/a_dir' at maximum because
2919 // we should get an error unequal ENOENT when
2920 // we try to create 'a_dir' at '/' and would so
2921 // return before
2922 int pos = path_make_parent(dir_path);
2923
2924 oslFileError osl_error = create_dir_recursively_(
2925 dir_path, aDirectoryCreationCallbackFunc, pData);
2926
2927 if (osl_File_E_None != osl_error)
2928 return osl_error;
2929
2930 dir_path[pos] = '/';
2931
2932 return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
2933 }
2934
2935 //#######################################
osl_createDirectoryPath(rtl_uString * aDirectoryUrl,oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,void * pData)2936 oslFileError SAL_CALL osl_createDirectoryPath(
2937 rtl_uString* aDirectoryUrl,
2938 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
2939 void* pData)
2940 {
2941 if (aDirectoryUrl == NULL)
2942 return osl_File_E_INVAL;
2943
2944 rtl::OUString sys_path;
2945 oslFileError osl_error = osl_getSystemPathFromFileURL_Ex(
2946 aDirectoryUrl, &sys_path.pData, sal_False);
2947
2948 if (osl_error != osl_File_E_None)
2949 return osl_error;
2950
2951 osl::systemPathRemoveSeparator(sys_path);
2952
2953 // const_cast because sys_path is a local copy which we want to modify inplace instead of
2954 // coyp it into another buffer on the heap again
2955 return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData);
2956 }
2957
2958 /****************************************************************************/
2959 /* osl_getCanonicalName */
2960 /****************************************************************************/
2961
osl_getCanonicalName(rtl_uString * ustrFileURL,rtl_uString ** pustrValidURL)2962 oslFileError osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uString** pustrValidURL )
2963 {
2964 OSL_ENSURE(sal_False, "osl_getCanonicalName not implemented");
2965
2966 rtl_uString_newFromString(pustrValidURL, ustrFileURL);
2967 return osl_File_E_None;
2968 }
2969
2970
2971 /****************************************************************************/
2972 /* osl_setFileAttributes */
2973 /****************************************************************************/
2974
osl_setFileAttributes(rtl_uString * ustrFileURL,sal_uInt64 uAttributes)2975 oslFileError osl_setFileAttributes( rtl_uString* ustrFileURL, sal_uInt64 uAttributes )
2976 {
2977 char path[PATH_MAX];
2978 oslFileError eRet;
2979 FILESTATUS3 fsts3ConfigInfo;
2980 ULONG ulBufSize = sizeof(FILESTATUS3);
2981 APIRET rc = NO_ERROR;
2982
2983 OSL_ASSERT( ustrFileURL );
2984
2985 /* convert file url to system path */
2986 eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
2987 if( eRet != osl_File_E_None )
2988 return eRet;
2989
2990 /* query current attributes */
2991 rc = DosQueryPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
2992 if (rc != NO_ERROR)
2993 return MapError( rc);
2994
2995 /* set/reset readonly/hidden (see w32\file.cxx) */
2996 fsts3ConfigInfo.attrFile &= ~(FILE_READONLY | FILE_HIDDEN);
2997 if ( uAttributes & osl_File_Attribute_ReadOnly )
2998 fsts3ConfigInfo.attrFile |= FILE_READONLY;
2999 if ( uAttributes & osl_File_Attribute_Hidden )
3000 fsts3ConfigInfo.attrFile |= FILE_HIDDEN;
3001
3002 /* write new attributes */
3003 rc = DosSetPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize, 0);
3004 if (rc != NO_ERROR)
3005 return MapError( rc);
3006
3007 /* everything ok */
3008 return osl_File_E_None;
3009 }
3010
3011 /****************************************************************************/
3012 /* osl_setFileTime */
3013 /****************************************************************************/
3014
osl_setFileTime(rtl_uString * ustrFileURL,const TimeValue * pCreationTime,const TimeValue * pLastAccessTime,const TimeValue * pLastWriteTime)3015 oslFileError osl_setFileTime( rtl_uString* ustrFileURL, const TimeValue* pCreationTime,
3016 const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime )
3017 {
3018 char path[PATH_MAX];
3019 oslFileError eRet;
3020
3021 OSL_ASSERT( ustrFileURL );
3022
3023 /* convert file url to system path */
3024 eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
3025 if( eRet != osl_File_E_None )
3026 return eRet;
3027
3028 return osl_psz_setFileTime( path, pCreationTime, pLastAccessTime, pLastWriteTime );
3029 }
3030
3031 /******************************************************************************
3032 *
3033 * Exported Module Functions
3034 * (independent of C or Unicode Strings)
3035 *
3036 *****************************************************************************/
3037
3038
3039
3040 /******************************************************************************
3041 *
3042 * C-String Versions of Exported Module Functions
3043 *
3044 *****************************************************************************/
3045
3046
3047 /******************************************
3048 * osl_psz_setFileTime
3049 *****************************************/
3050
osl_psz_setFileTime(const sal_Char * pszFilePath,const TimeValue *,const TimeValue * pLastAccessTime,const TimeValue * pLastWriteTime)3051 static oslFileError osl_psz_setFileTime( const sal_Char* pszFilePath,
3052 const TimeValue* /*pCreationTime*/,
3053 const TimeValue* pLastAccessTime,
3054 const TimeValue* pLastWriteTime )
3055 {
3056 int nRet=0;
3057 struct utimbuf aTimeBuffer;
3058 struct stat aFileStat;
3059 #ifdef DEBUG_OSL_FILE
3060 struct tm* pTM=0;
3061 #endif
3062
3063 nRet = lstat(pszFilePath,&aFileStat);
3064
3065 if ( nRet < 0 )
3066 {
3067 nRet=errno;
3068 return oslTranslateFileError(OSL_FET_ERROR, nRet);
3069 }
3070
3071 #ifdef DEBUG_OSL_FILE
3072 fprintf(stderr,"File Times are (in localtime):\n");
3073 pTM=localtime(&aFileStat.st_ctime);
3074 fprintf(stderr,"CreationTime is '%s'\n",asctime(pTM));
3075 pTM=localtime(&aFileStat.st_atime);
3076 fprintf(stderr,"AccessTime is '%s'\n",asctime(pTM));
3077 pTM=localtime(&aFileStat.st_mtime);
3078 fprintf(stderr,"Modification is '%s'\n",asctime(pTM));
3079
3080 fprintf(stderr,"File Times are (in UTC):\n");
3081 fprintf(stderr,"CreationTime is '%s'\n",ctime(&aFileStat.st_ctime));
3082 fprintf(stderr,"AccessTime is '%s'\n",ctime(&aTimeBuffer.actime));
3083 fprintf(stderr,"Modification is '%s'\n",ctime(&aTimeBuffer.modtime));
3084 #endif
3085
3086 if ( pLastAccessTime != 0 )
3087 {
3088 aTimeBuffer.actime=pLastAccessTime->Seconds;
3089 }
3090 else
3091 {
3092 aTimeBuffer.actime=aFileStat.st_atime;
3093 }
3094
3095 if ( pLastWriteTime != 0 )
3096 {
3097 aTimeBuffer.modtime=pLastWriteTime->Seconds;
3098 }
3099 else
3100 {
3101 aTimeBuffer.modtime=aFileStat.st_mtime;
3102 }
3103
3104 /* mfe: Creation time not used here! */
3105
3106 #ifdef DEBUG_OSL_FILE
3107 fprintf(stderr,"File Times are (in localtime):\n");
3108 pTM=localtime(&aFileStat.st_ctime);
3109 fprintf(stderr,"CreationTime now '%s'\n",asctime(pTM));
3110 pTM=localtime(&aTimeBuffer.actime);
3111 fprintf(stderr,"AccessTime now '%s'\n",asctime(pTM));
3112 pTM=localtime(&aTimeBuffer.modtime);
3113 fprintf(stderr,"Modification now '%s'\n",asctime(pTM));
3114
3115 fprintf(stderr,"File Times are (in UTC):\n");
3116 fprintf(stderr,"CreationTime now '%s'\n",ctime(&aFileStat.st_ctime));
3117 fprintf(stderr,"AccessTime now '%s'\n",ctime(&aTimeBuffer.actime));
3118 fprintf(stderr,"Modification now '%s'\n",ctime(&aTimeBuffer.modtime));
3119 #endif
3120
3121 nRet=utime(pszFilePath,&aTimeBuffer);
3122 if ( nRet < 0 )
3123 {
3124 nRet=errno;
3125 return oslTranslateFileError(OSL_FET_ERROR, nRet);
3126 }
3127
3128 return osl_File_E_None;
3129 }
3130
3131
3132 /******************************************************************************
3133 *
3134 * Utility Functions
3135 *
3136 *****************************************************************************/
3137
3138
3139 /*****************************************
3140 * oslMakeUStrFromPsz
3141 ****************************************/
3142
oslMakeUStrFromPsz(const sal_Char * pszStr,rtl_uString ** ustrValid)3143 rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr, rtl_uString** ustrValid)
3144 {
3145 rtl_string2UString(
3146 ustrValid,
3147 pszStr,
3148 rtl_str_getLength( pszStr ),
3149 osl_getThreadTextEncoding(),
3150 OUSTRING_TO_OSTRING_CVTFLAGS );
3151 OSL_ASSERT(*ustrValid != 0);
3152
3153 return *ustrValid;
3154 }
3155
3156 /*****************************************************************************
3157 * UnicodeToText
3158 * converting unicode to text manually saves us the penalty of a temporary
3159 * rtl_String object.
3160 ****************************************************************************/
3161
UnicodeToText(char * buffer,size_t bufLen,const sal_Unicode * uniText,sal_Int32 uniTextLen)3162 int UnicodeToText( char * buffer, size_t bufLen, const sal_Unicode * uniText, sal_Int32 uniTextLen )
3163 {
3164 rtl_UnicodeToTextConverter hConverter;
3165 sal_uInt32 nInfo;
3166 sal_Size nSrcChars, nDestBytes;
3167
3168 /* stolen from rtl/string.c */
3169 hConverter = rtl_createUnicodeToTextConverter( osl_getThreadTextEncoding() );
3170
3171 nDestBytes = rtl_convertUnicodeToText( hConverter, 0, uniText, uniTextLen,
3172 buffer, bufLen,
3173 OUSTRING_TO_OSTRING_CVTFLAGS | RTL_UNICODETOTEXT_FLAGS_FLUSH,
3174 &nInfo, &nSrcChars );
3175
3176 rtl_destroyUnicodeToTextConverter( hConverter );
3177
3178 if( nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL )
3179 {
3180 errno = EOVERFLOW;
3181 return 0;
3182 }
3183
3184 /* ensure trailing '\0' */
3185 buffer[nDestBytes] = '\0';
3186
3187 return nDestBytes;
3188 }
3189
3190 /*****************************************************************************
3191 TextToUnicode
3192
3193 @param text
3194 The text to convert.
3195
3196 @param text_buffer_size
3197 The number of characters.
3198
3199 @param unic_text
3200 The unicode buffer.
3201
3202 @param unic_text_buffer_size
3203 The size in characters of the unicode buffer.
3204
3205 ****************************************************************************/
3206
TextToUnicode(const char * text,size_t text_buffer_size,sal_Unicode * unic_text,sal_Int32 unic_text_buffer_size)3207 int TextToUnicode(
3208 const char* text,
3209 size_t text_buffer_size,
3210 sal_Unicode* unic_text,
3211 sal_Int32 unic_text_buffer_size)
3212 {
3213 rtl_TextToUnicodeConverter hConverter;
3214 sal_uInt32 nInfo;
3215 sal_Size nSrcChars;
3216 sal_Size nDestBytes;
3217
3218 /* stolen from rtl/string.c */
3219 hConverter = rtl_createTextToUnicodeConverter(osl_getThreadTextEncoding());
3220
3221 nDestBytes = rtl_convertTextToUnicode(hConverter,
3222 0,
3223 text, text_buffer_size,
3224 unic_text, unic_text_buffer_size,
3225 OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_FLUSH,
3226 &nInfo, &nSrcChars);
3227
3228 rtl_destroyTextToUnicodeConverter(hConverter);
3229
3230 if (nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL)
3231 {
3232 errno = EOVERFLOW;
3233 return 0;
3234 }
3235
3236 /* ensure trailing '\0' */
3237 unic_text[nDestBytes] = '\0';
3238
3239 return nDestBytes;
3240 }
3241
3242 /******************************************************************************
3243 *
3244 * GENERIC FLOPPY FUNCTIONS
3245 *
3246 *****************************************************************************/
3247
3248 /*****************************************
3249 * osl_unmountVolumeDevice
3250 ****************************************/
osl_unmountVolumeDevice(oslVolumeDeviceHandle Handle)3251 oslFileError osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle )
3252 {
3253 if ( Handle )
3254 return osl_File_E_None;
3255 else
3256 return osl_File_E_INVAL;
3257 }
3258
3259 /*****************************************
3260 * osl_automountVolumeDevice
3261 ****************************************/
osl_automountVolumeDevice(oslVolumeDeviceHandle Handle)3262 oslFileError osl_automountVolumeDevice( oslVolumeDeviceHandle Handle )
3263 {
3264 if ( Handle )
3265 return osl_File_E_None;
3266 else
3267 return osl_File_E_INVAL;
3268 }
3269
3270 /*****************************************
3271 * osl_getVolumeDeviceMountPath
3272 ****************************************/
osl_getVolumeDeviceMountPath(oslVolumeDeviceHandle Handle,rtl_uString ** pstrPath)3273 oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
3274 {
3275 if ( Handle && pstrPath )
3276 {
3277 rtl_uString_assign( pstrPath, (rtl_uString *)Handle );
3278 return osl_File_E_None;
3279 }
3280 else
3281 return osl_File_E_INVAL;
3282 }
3283
3284 /*****************************************
3285 * osl_acquireVolumeDeviceHandle
3286 ****************************************/
3287
osl_acquireVolumeDeviceHandle(oslVolumeDeviceHandle Handle)3288 oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
3289 {
3290 if ( Handle )
3291 {
3292 rtl_uString_acquire( (rtl_uString *)Handle );
3293 return osl_File_E_None;
3294 }
3295 else
3296 return osl_File_E_INVAL;
3297 }
3298
3299 /*****************************************
3300 * osl_releaseVolumeDeviceHandle
3301 ****************************************/
3302
osl_releaseVolumeDeviceHandle(oslVolumeDeviceHandle Handle)3303 oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
3304 {
3305 if ( Handle )
3306 {
3307 rtl_uString_release( (rtl_uString *)Handle );
3308 return osl_File_E_None;
3309 }
3310 else
3311 return osl_File_E_INVAL;
3312 }
3313
3314 /******************************************************************************
3315 *
3316 * OS/2 FLOPPY FUNCTIONS
3317 *
3318 *****************************************************************************/
osl_isFloppyDrive(const sal_Char * pszPath)3319 static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath)
3320 {
3321 return NULL;
3322 }
3323
3324