Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "osl/file.hxx"
31 : : #include "osl/detail/file.h"
32 : :
33 : : #include "osl/diagnose.h"
34 : : #include "rtl/alloc.h"
35 : :
36 : : #include "system.h"
37 : : #include "createfilehandlefromfd.hxx"
38 : : #include "file_error_transl.h"
39 : : #include "file_url.h"
40 : :
41 : : #include <algorithm>
42 : : #include <limits>
43 : :
44 : : #include <string.h>
45 : : #include <pthread.h>
46 : : #include <sys/mman.h>
47 : :
48 : : #if defined(MACOSX)
49 : :
50 : : #include <sys/param.h>
51 : : #include <sys/mount.h>
52 : : #define HAVE_O_EXLOCK
53 : :
54 : : // add MACOSX Time Value
55 : : #define TimeValue CFTimeValue
56 : : #include <CoreFoundation/CoreFoundation.h>
57 : : #undef TimeValue
58 : :
59 : : #endif /* MACOSX */
60 : :
61 : : #ifdef ANDROID
62 : : #include <osl/detail/android-bootstrap.h>
63 : : #endif
64 : :
65 : : #ifdef DEBUG_OSL_FILE
66 : : # define OSL_FILE_TRACE osl_trace
67 : : # define PERROR( a, b ) perror( a ); fprintf( stderr, b )
68 : : #else
69 : : # define OSL_FILE_TRACE(fmt, ...)
70 : : # define PERROR( a, b )
71 : : #endif
72 : :
73 : :
74 : :
75 : : /*******************************************************************
76 : : *
77 : : * FileHandle_Impl interface
78 : : *
79 : : ******************************************************************/
80 : : struct FileHandle_Impl
81 : : {
82 : : pthread_mutex_t m_mutex;
83 : : rtl_String * m_strFilePath; /* holds native file path */
84 : : int m_fd;
85 : :
86 : : enum Kind
87 : : {
88 : : KIND_FD = 1,
89 : : KIND_MEM = 2
90 : : };
91 : : int m_kind;
92 : : /** State
93 : : */
94 : : enum StateBits
95 : : {
96 : : STATE_SEEKABLE = 1, /* default */
97 : : STATE_READABLE = 2, /* default */
98 : : STATE_WRITEABLE = 4, /* open() sets, write() requires, else osl_File_E_BADF */
99 : : STATE_MODIFIED = 8 /* write() sets, flush() resets */
100 : : };
101 : : int m_state;
102 : :
103 : : sal_uInt64 m_size; /* file size */
104 : : off_t m_offset; /* physical offset from begin of file */
105 : : off_t m_fileptr; /* logical offset from begin of file */
106 : :
107 : : off_t m_bufptr; /* buffer offset from begin of file */
108 : : size_t m_buflen; /* buffer filled [0, m_bufsiz - 1] */
109 : :
110 : : size_t m_bufsiz;
111 : : sal_uInt8 * m_buffer;
112 : :
113 : : explicit FileHandle_Impl (int fd, Kind kind = KIND_FD, char const * path = "<anon>");
114 : : ~FileHandle_Impl();
115 : :
116 : : static void* operator new (size_t n);
117 : : static void operator delete (void * p);
118 : :
119 : : static size_t getpagesize();
120 : :
121 : : sal_uInt64 getPos() const;
122 : : oslFileError setPos (sal_uInt64 uPos);
123 : :
124 : : sal_uInt64 getSize() const;
125 : : oslFileError setSize (sal_uInt64 uSize);
126 : :
127 : : oslFileError readAt (
128 : : off_t nOffset,
129 : : void * pBuffer,
130 : : size_t nBytesRequested,
131 : : sal_uInt64 * pBytesRead);
132 : :
133 : : oslFileError writeAt (
134 : : off_t nOffset,
135 : : void const * pBuffer,
136 : : size_t nBytesToWrite,
137 : : sal_uInt64 * pBytesWritten);
138 : :
139 : : oslFileError readFileAt (
140 : : off_t nOffset,
141 : : void * pBuffer,
142 : : size_t nBytesRequested,
143 : : sal_uInt64 * pBytesRead);
144 : :
145 : : oslFileError writeFileAt (
146 : : off_t nOffset,
147 : : void const * pBuffer,
148 : : size_t nBytesToWrite,
149 : : sal_uInt64 * pBytesWritten);
150 : :
151 : : oslFileError readLineAt (
152 : : off_t nOffset,
153 : : sal_Sequence ** ppSequence,
154 : : sal_uInt64 * pBytesRead);
155 : :
156 : : oslFileError writeSequence_Impl (
157 : : sal_Sequence ** ppSequence,
158 : : size_t * pnOffset,
159 : : const void * pBuffer,
160 : : size_t nBytes);
161 : :
162 : : oslFileError syncFile();
163 : :
164 : : /** Buffer cache / allocator.
165 : : */
166 : : class Allocator
167 : : {
168 : : rtl_cache_type * m_cache;
169 : : size_t m_bufsiz;
170 : :
171 : : Allocator (Allocator const &);
172 : : Allocator & operator= (Allocator const &);
173 : :
174 : : public:
175 : : static Allocator & get();
176 : :
177 : : void allocate (sal_uInt8 ** ppBuffer, size_t * pnSize);
178 : : void deallocate (sal_uInt8 * pBuffer);
179 : :
180 : : protected:
181 : : Allocator();
182 : : ~Allocator();
183 : : };
184 : :
185 : : /** Guard.
186 : : */
187 : : class Guard
188 : : {
189 : : pthread_mutex_t * m_mutex;
190 : :
191 : : public:
192 : : explicit Guard(pthread_mutex_t * pMutex);
193 : : ~Guard();
194 : : };
195 : : };
196 : :
197 : : /*******************************************************************
198 : : *
199 : : * FileHandle_Impl implementation
200 : : *
201 : : ******************************************************************/
202 : :
203 : : FileHandle_Impl::Allocator &
204 : 398655 : FileHandle_Impl::Allocator::get()
205 : : {
206 [ + + ][ + - ]: 398655 : static Allocator g_aBufferAllocator;
[ + - ][ # # ]
207 : 398655 : return g_aBufferAllocator;
208 : : }
209 : :
210 : 2648 : FileHandle_Impl::Allocator::Allocator()
211 : : : m_cache (0),
212 : 2648 : m_bufsiz (0)
213 : : {
214 : 2648 : size_t const pagesize = FileHandle_Impl::getpagesize();
215 [ + - ]: 2648 : if (size_t(-1) != pagesize)
216 : : {
217 : : m_cache = rtl_cache_create (
218 : 2648 : "osl_file_buffer_cache", pagesize, 0, 0, 0, 0, 0, 0, 0);
219 [ + - ]: 2648 : if (0 != m_cache)
220 : 2648 : m_bufsiz = pagesize;
221 : : }
222 : 2648 : }
223 : 2648 : FileHandle_Impl::Allocator::~Allocator()
224 : : {
225 : 2648 : rtl_cache_destroy (m_cache), m_cache = 0;
226 : 2648 : }
227 : :
228 : 200355 : void FileHandle_Impl::Allocator::allocate (sal_uInt8 ** ppBuffer, size_t * pnSize)
229 : : {
230 : : OSL_PRECOND((0 != ppBuffer) && (0 != pnSize), "FileHandle_Impl::Allocator::allocate(): contract violation");
231 [ + - ][ + - ]: 200355 : if ((0 != ppBuffer) && (0 != pnSize))
232 : 200355 : *ppBuffer = static_cast< sal_uInt8* >(rtl_cache_alloc(m_cache)), *pnSize = m_bufsiz;
233 : 200355 : }
234 : 198300 : void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer)
235 : : {
236 [ + - ]: 198300 : if (0 != pBuffer)
237 : 198300 : rtl_cache_free (m_cache, pBuffer);
238 : 198300 : }
239 : :
240 : 27207150 : FileHandle_Impl::Guard::Guard(pthread_mutex_t * pMutex)
241 : 27207150 : : m_mutex (pMutex)
242 : : {
243 : : OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::Guard(): null pointer.");
244 : 27207150 : (void) pthread_mutex_lock (m_mutex); // ignoring EINVAL ...
245 : 27207150 : }
246 : 27207150 : FileHandle_Impl::Guard::~Guard()
247 : : {
248 : : OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::~Guard(): null pointer.");
249 : 27207150 : (void) pthread_mutex_unlock (m_mutex);
250 : 27207149 : }
251 : :
252 : 200355 : FileHandle_Impl::FileHandle_Impl (int fd, enum Kind kind, char const * path)
253 : : : m_strFilePath (0),
254 : : m_fd (fd),
255 : : m_kind (kind),
256 : : m_state (STATE_SEEKABLE | STATE_READABLE),
257 : : m_size (0),
258 : : m_offset (0),
259 : : m_fileptr (0),
260 : : m_bufptr (-1),
261 : : m_buflen (0),
262 : : m_bufsiz (0),
263 : 200355 : m_buffer (0)
264 : : {
265 : 200355 : (void) pthread_mutex_init(&m_mutex, 0);
266 : 200355 : rtl_string_newFromStr (&m_strFilePath, path);
267 [ + - ]: 200355 : if (m_kind == KIND_FD) {
268 : 200355 : Allocator::get().allocate (&m_buffer, &m_bufsiz);
269 [ + - ]: 200355 : if (0 != m_buffer)
270 : 200355 : memset (m_buffer, 0, m_bufsiz);
271 : : }
272 : 200355 : }
273 : 198300 : FileHandle_Impl::~FileHandle_Impl()
274 : : {
275 [ + - ]: 198300 : if (m_kind == KIND_FD)
276 : 198300 : Allocator::get().deallocate (m_buffer), m_buffer = 0;
277 : 198300 : rtl_string_release (m_strFilePath), m_strFilePath = 0;
278 : 198300 : (void) pthread_mutex_destroy(&m_mutex); // ignoring EBUSY ...
279 : 198300 : }
280 : :
281 : 200355 : void* FileHandle_Impl::operator new (size_t n)
282 : : {
283 : 200355 : return rtl_allocateMemory(n);
284 : : }
285 : 198300 : void FileHandle_Impl::operator delete (void * p)
286 : : {
287 : 198300 : rtl_freeMemory(p);
288 : 198300 : }
289 : :
290 : 14058 : size_t FileHandle_Impl::getpagesize()
291 : : {
292 : : #if defined(FREEBSD) || defined(NETBSD) || defined(MACOSX) || \
293 : : defined(OPENBSD) || defined(DRAGONFLY)
294 : : return sal::static_int_cast< size_t >(::getpagesize());
295 : : #else /* POSIX */
296 : 14058 : return sal::static_int_cast< size_t >(::sysconf(_SC_PAGESIZE));
297 : : #endif /* xBSD || POSIX */
298 : : }
299 : :
300 : 1229119 : sal_uInt64 FileHandle_Impl::getPos() const
301 : : {
302 : 1229119 : return sal::static_int_cast< sal_uInt64 >(m_fileptr);
303 : : }
304 : :
305 : 867097 : oslFileError FileHandle_Impl::setPos (sal_uInt64 uPos)
306 : : {
307 : : OSL_FILE_TRACE("FileHandle_Impl::setPos(%d, %lld) => %lld", m_fd, getPos(), uPos);
308 : 867097 : m_fileptr = sal::static_int_cast< off_t >(uPos);
309 : 867097 : return osl_File_E_None;
310 : : }
311 : :
312 : 122803 : sal_uInt64 FileHandle_Impl::getSize() const
313 : : {
314 [ + - ]: 122803 : off_t const bufend = std::max((off_t)(0), m_bufptr) + m_buflen;
315 [ + - ]: 122803 : return std::max(m_size, sal::static_int_cast< sal_uInt64 >(bufend));
316 : : }
317 : :
318 : 12244 : oslFileError FileHandle_Impl::setSize (sal_uInt64 uSize)
319 : : {
320 : 12244 : off_t const nSize = sal::static_int_cast< off_t >(uSize);
321 [ - + ]: 12244 : if (-1 == ftruncate (m_fd, nSize))
322 : : {
323 : : /* Failure. Save original result. Try fallback algorithm */
324 : 0 : oslFileError result = oslTranslateFileError (OSL_FET_ERROR, errno);
325 : :
326 : : /* Check against current size. Fail upon 'shrink' */
327 [ # # ]: 0 : if (uSize <= getSize())
328 : : {
329 : : /* Failure upon 'shrink'. Return original result */
330 : 0 : return (result);
331 : : }
332 : :
333 : : /* Save current position */
334 : 0 : off_t const nCurPos = (off_t)lseek (m_fd, (off_t)0, SEEK_CUR);
335 [ # # ]: 0 : if (nCurPos == (off_t)(-1))
336 : 0 : return (result);
337 : :
338 : : /* Try 'expand' via 'lseek()' and 'write()' */
339 [ # # ]: 0 : if (-1 == lseek (m_fd, (off_t)(nSize - 1), SEEK_SET))
340 : 0 : return (result);
341 : :
342 [ # # ]: 0 : if (-1 == write (m_fd, (char*)"", (size_t)1))
343 : : {
344 : : /* Failure. Restore saved position */
345 : 0 : (void) lseek (m_fd, (off_t)(nCurPos), SEEK_SET);
346 : 0 : return (result);
347 : : }
348 : :
349 : : /* Success. Restore saved position */
350 [ # # ]: 0 : if (-1 == lseek (m_fd, (off_t)nCurPos, SEEK_SET))
351 : 0 : return (result);
352 : : }
353 : :
354 : : OSL_FILE_TRACE("osl_setFileSize(%d, %lld) => %ld", m_fd, getSize(), nSize);
355 : 12244 : m_size = sal::static_int_cast< sal_uInt64 >(nSize);
356 : 12244 : return osl_File_E_None;
357 : : }
358 : :
359 : 559717 : oslFileError FileHandle_Impl::readAt (
360 : : off_t nOffset,
361 : : void * pBuffer,
362 : : size_t nBytesRequested,
363 : : sal_uInt64 * pBytesRead)
364 : : {
365 : : OSL_PRECOND((m_state & STATE_SEEKABLE), "FileHandle_Impl::readAt(): not seekable");
366 [ - + ]: 559717 : if (!(m_state & STATE_SEEKABLE))
367 : 0 : return osl_File_E_SPIPE;
368 : :
369 : : OSL_PRECOND((m_state & STATE_READABLE), "FileHandle_Impl::readAt(): not readable");
370 [ - + ]: 559717 : if (!(m_state & STATE_READABLE))
371 : 0 : return osl_File_E_BADF;
372 : :
373 [ - + ]: 559717 : if (m_kind == KIND_MEM)
374 : : {
375 : : ssize_t nBytes;
376 : :
377 : 0 : m_offset = nOffset;
378 : :
379 [ # # ]: 0 : if ((sal_uInt64) m_offset >= m_size)
380 : 0 : nBytes = 0;
381 : : else
382 : : {
383 [ # # ]: 0 : nBytes = std::min(nBytesRequested, (size_t) (m_size - m_offset));
384 : 0 : memmove(pBuffer, m_buffer + m_offset, nBytes);
385 : 0 : m_offset += nBytes;
386 : : }
387 : 0 : *pBytesRead = nBytes;
388 : 0 : return osl_File_E_None;
389 : : }
390 : :
391 : : #if defined(LINUX) || defined(SOLARIS)
392 : :
393 : 559717 : ssize_t nBytes = ::pread (m_fd, pBuffer, nBytesRequested, nOffset);
394 [ # # ][ - + ]: 559717 : if ((-1 == nBytes) && (EOVERFLOW == errno))
395 : : {
396 : : /* Some 'pread()'s fail with EOVERFLOW when reading at (or past)
397 : : * end-of-file, different from 'lseek() + read()' behaviour.
398 : : * Returning '0 bytes read' and 'osl_File_E_None' instead.
399 : : */
400 : 0 : nBytes = 0;
401 : : }
402 [ - + ]: 559717 : if (-1 == nBytes)
403 : 0 : return oslTranslateFileError (OSL_FET_ERROR, errno);
404 : :
405 : : #else /* !(LINUX || SOLARIS) */
406 : :
407 : : if (nOffset != m_offset)
408 : : {
409 : : if (-1 == ::lseek (m_fd, nOffset, SEEK_SET))
410 : : return oslTranslateFileError (OSL_FET_ERROR, errno);
411 : : m_offset = nOffset;
412 : : }
413 : :
414 : : ssize_t nBytes = ::read (m_fd, pBuffer, nBytesRequested);
415 : : if (-1 == nBytes)
416 : : return oslTranslateFileError (OSL_FET_ERROR, errno);
417 : : m_offset += nBytes;
418 : :
419 : : #endif /* !(LINUX || SOLARIS) */
420 : :
421 : : OSL_FILE_TRACE("FileHandle_Impl::readAt(%d, %lld, %ld)", m_fd, nOffset, nBytes);
422 : 559717 : *pBytesRead = nBytes;
423 : 559717 : return osl_File_E_None;
424 : : }
425 : :
426 : 373764 : oslFileError FileHandle_Impl::writeAt (
427 : : off_t nOffset,
428 : : void const * pBuffer,
429 : : size_t nBytesToWrite,
430 : : sal_uInt64 * pBytesWritten)
431 : : {
432 : : OSL_PRECOND((m_state & STATE_SEEKABLE), "FileHandle_Impl::writeAt(): not seekable");
433 [ - + ]: 373764 : if (!(m_state & STATE_SEEKABLE))
434 : 0 : return osl_File_E_SPIPE;
435 : :
436 : : OSL_PRECOND((m_state & STATE_WRITEABLE), "FileHandle_Impl::writeAt(): not writeable");
437 [ - + ]: 373764 : if (!(m_state & STATE_WRITEABLE))
438 : 0 : return osl_File_E_BADF;
439 : :
440 : : #if defined(LINUX) || defined(SOLARIS)
441 : :
442 : 373764 : ssize_t nBytes = ::pwrite (m_fd, pBuffer, nBytesToWrite, nOffset);
443 [ - + ]: 373764 : if (-1 == nBytes)
444 : 0 : return oslTranslateFileError (OSL_FET_ERROR, errno);
445 : :
446 : : #else /* !(LINUX || SOLARIS) */
447 : :
448 : : if (nOffset != m_offset)
449 : : {
450 : : if (-1 == ::lseek (m_fd, nOffset, SEEK_SET))
451 : : return oslTranslateFileError (OSL_FET_ERROR, errno);
452 : : m_offset = nOffset;
453 : : }
454 : :
455 : : ssize_t nBytes = ::write (m_fd, pBuffer, nBytesToWrite);
456 : : if (-1 == nBytes)
457 : : return oslTranslateFileError (OSL_FET_ERROR, errno);
458 : : m_offset += nBytes;
459 : :
460 : : #endif /* !(LINUX || SOLARIS) */
461 : :
462 : : OSL_FILE_TRACE("FileHandle_Impl::writeAt(%d, %lld, %ld)", m_fd, nOffset, nBytes);
463 [ + - ]: 373764 : m_size = std::max (m_size, sal::static_int_cast< sal_uInt64 >(nOffset + nBytes));
464 : :
465 : 373764 : *pBytesWritten = nBytes;
466 : 373764 : return osl_File_E_None;
467 : : }
468 : :
469 : 1208747 : oslFileError FileHandle_Impl::readFileAt (
470 : : off_t nOffset,
471 : : void * pBuffer,
472 : : size_t nBytesRequested,
473 : : sal_uInt64 * pBytesRead)
474 : : {
475 [ + + ]: 1208747 : if (0 == (m_state & STATE_SEEKABLE))
476 : : {
477 : : // not seekable (pipe)
478 : 224866 : ssize_t nBytes = ::read (m_fd, pBuffer, nBytesRequested);
479 [ - + ]: 224866 : if (-1 == nBytes)
480 : 0 : return oslTranslateFileError (OSL_FET_ERROR, errno);
481 : 224866 : *pBytesRead = nBytes;
482 : 224866 : return osl_File_E_None;
483 : : }
484 [ + - ][ - + ]: 983881 : else if (m_kind == KIND_MEM || 0 == m_buffer)
485 : : {
486 : : // not buffered
487 : 0 : return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
488 : : }
489 : : else
490 : : {
491 : 983881 : sal_uInt8 * buffer = static_cast<sal_uInt8*>(pBuffer);
492 [ + + ]: 1527902 : for (*pBytesRead = 0; nBytesRequested > 0; )
493 : : {
494 : 1048875 : off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
495 : 1048875 : size_t const bufpos = (nOffset % m_bufsiz);
496 : :
497 [ + + ]: 1048875 : if (bufptr != m_bufptr)
498 : : {
499 : : // flush current buffer
500 [ + - ]: 213652 : oslFileError result = syncFile();
501 [ - + ]: 213652 : if (result != osl_File_E_None)
502 : 0 : return (result);
503 : 213652 : m_bufptr = -1, m_buflen = 0;
504 : :
505 [ + + ]: 213652 : if (nBytesRequested >= m_bufsiz)
506 : : {
507 : : // buffer too small, read through from file
508 : 113885 : sal_uInt64 uDone = 0;
509 [ + - ]: 113885 : result = readAt (nOffset, &(buffer[*pBytesRead]), nBytesRequested, &uDone);
510 [ - + ]: 113885 : if (result != osl_File_E_None)
511 : 0 : return (result);
512 : :
513 : 113885 : nBytesRequested -= uDone, *pBytesRead += uDone;
514 : 113885 : return osl_File_E_None;
515 : : }
516 : :
517 : : // update buffer (pointer)
518 : 99767 : sal_uInt64 uDone = 0;
519 [ + - ]: 99767 : result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
520 [ - + ]: 99767 : if (result != osl_File_E_None)
521 : 0 : return (result);
522 : 213652 : m_bufptr = bufptr, m_buflen = uDone;
523 : : }
524 [ + + ]: 934990 : if (bufpos >= m_buflen)
525 : : {
526 : : // end of file
527 : 390969 : return osl_File_E_None;
528 : : }
529 : :
530 [ + - ]: 544021 : size_t const bytes = std::min (m_buflen - bufpos, nBytesRequested);
531 : : OSL_FILE_TRACE("FileHandle_Impl::readFileAt(%d, %lld, %ld)", m_fd, nOffset, bytes);
532 : :
533 : 544021 : memcpy (&(buffer[*pBytesRead]), &(m_buffer[bufpos]), bytes);
534 : 544021 : nBytesRequested -= bytes, *pBytesRead += bytes, nOffset += bytes;
535 : : }
536 : 1208747 : return osl_File_E_None;
537 : : }
538 : : }
539 : :
540 : 23740912 : oslFileError FileHandle_Impl::writeFileAt (
541 : : off_t nOffset,
542 : : void const * pBuffer,
543 : : size_t nBytesToWrite,
544 : : sal_uInt64 * pBytesWritten)
545 : : {
546 [ + + ]: 23740912 : if (0 == (m_state & STATE_SEEKABLE))
547 : : {
548 : : // not seekable (pipe)
549 : 15 : ssize_t nBytes = ::write (m_fd, pBuffer, nBytesToWrite);
550 [ - + ]: 15 : if (-1 == nBytes)
551 : 0 : return oslTranslateFileError (OSL_FET_ERROR, errno);
552 : 15 : *pBytesWritten = nBytes;
553 : 15 : return osl_File_E_None;
554 : : }
555 [ - + ]: 23740897 : else if (0 == m_buffer)
556 : : {
557 : : // not buffered
558 : 0 : return writeAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten);
559 : : }
560 : : else
561 : : {
562 : 23740897 : sal_uInt8 const * buffer = static_cast<sal_uInt8 const *>(pBuffer);
563 [ + + ]: 47447730 : for (*pBytesWritten = 0; nBytesToWrite > 0; )
564 : : {
565 : 23722503 : off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
566 : 23722503 : size_t const bufpos = (nOffset % m_bufsiz);
567 [ + + ]: 23722503 : if (bufptr != m_bufptr)
568 : : {
569 : : // flush current buffer
570 [ + - ]: 359224 : oslFileError result = syncFile();
571 [ - + ]: 359224 : if (result != osl_File_E_None)
572 : 0 : return (result);
573 : 359224 : m_bufptr = -1, m_buflen = 0;
574 : :
575 [ + + ]: 359224 : if (nBytesToWrite >= m_bufsiz)
576 : : {
577 : : // buffer to small, write through to file
578 : 15670 : sal_uInt64 uDone = 0;
579 [ + - ]: 15670 : result = writeAt (nOffset, &(buffer[*pBytesWritten]), nBytesToWrite, &uDone);
580 [ - + ]: 15670 : if (result != osl_File_E_None)
581 : 0 : return (result);
582 [ - + ]: 15670 : if (uDone != nBytesToWrite)
583 : 0 : return osl_File_E_IO;
584 : :
585 : 15670 : nBytesToWrite -= uDone, *pBytesWritten += uDone;
586 : 15670 : return osl_File_E_None;
587 : : }
588 : :
589 : : // update buffer (pointer)
590 : 343554 : sal_uInt64 uDone = 0;
591 [ + - ]: 343554 : result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
592 [ - + ]: 343554 : if (result != osl_File_E_None)
593 : 0 : return (result);
594 : 359224 : m_bufptr = bufptr, m_buflen = uDone;
595 : : }
596 : :
597 [ + - ]: 23706833 : size_t const bytes = std::min (m_bufsiz - bufpos, nBytesToWrite);
598 : : OSL_FILE_TRACE("FileHandle_Impl::writeFileAt(%d, %lld, %ld)", m_fd, nOffset, bytes);
599 : :
600 : 23706833 : memcpy (&(m_buffer[bufpos]), &(buffer[*pBytesWritten]), bytes);
601 : 23706833 : nBytesToWrite -= bytes, *pBytesWritten += bytes, nOffset += bytes;
602 : :
603 [ + - ]: 23706833 : m_buflen = std::max(m_buflen, bufpos + bytes);
604 : 23706833 : m_state |= STATE_MODIFIED;
605 : : }
606 : 23740912 : return osl_File_E_None;
607 : : }
608 : : }
609 : :
610 : 41567 : oslFileError FileHandle_Impl::readLineAt (
611 : : off_t nOffset,
612 : : sal_Sequence ** ppSequence,
613 : : sal_uInt64 * pBytesRead)
614 : : {
615 : 41567 : oslFileError result = osl_File_E_None;
616 : :
617 : 41567 : off_t bufptr = nOffset / m_bufsiz * m_bufsiz;
618 [ + + ]: 41567 : if (bufptr != m_bufptr)
619 : : {
620 : : /* flush current buffer */
621 [ + - ]: 2511 : result = syncFile();
622 [ - + ]: 2511 : if (result != osl_File_E_None)
623 : 0 : return (result);
624 : :
625 : : /* update buffer (pointer) */
626 : 2511 : sal_uInt64 uDone = 0;
627 [ + - ]: 2511 : result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
628 [ - + ]: 2511 : if (result != osl_File_E_None)
629 : 0 : return (result);
630 : :
631 : 2511 : m_bufptr = bufptr, m_buflen = uDone;
632 : : }
633 : :
634 : : static int const LINE_STATE_BEGIN = 0;
635 : : static int const LINE_STATE_CR = 1;
636 : : static int const LINE_STATE_LF = 2;
637 : :
638 : 41567 : size_t bufpos = nOffset - m_bufptr, curpos = bufpos, dstpos = 0;
639 [ + + ]: 41567 : int state = (bufpos >= m_buflen) ? LINE_STATE_LF : LINE_STATE_BEGIN;
640 : :
641 [ + + ]: 2343006 : for ( ; state != LINE_STATE_LF; )
642 : : {
643 [ + + ]: 2301535 : if (curpos >= m_buflen)
644 : : {
645 : : /* buffer examined */
646 [ + - ]: 96 : if (0 < (curpos - bufpos))
647 : : {
648 : : /* flush buffer to sequence */
649 : : result = writeSequence_Impl (
650 : 96 : ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos);
651 [ - + ]: 96 : if (result != osl_File_E_None)
652 : 0 : return (result);
653 : 96 : *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
654 : : }
655 : :
656 : 96 : bufptr = nOffset / m_bufsiz * m_bufsiz;
657 [ - + ]: 96 : if (bufptr != m_bufptr)
658 : : {
659 : : /* update buffer (pointer) */
660 : 0 : sal_uInt64 uDone = 0;
661 [ # # ]: 0 : result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
662 [ # # ]: 0 : if (result != osl_File_E_None)
663 : 0 : return (result);
664 : 0 : m_bufptr = bufptr, m_buflen = uDone;
665 : : }
666 : :
667 : 96 : bufpos = nOffset - m_bufptr, curpos = bufpos;
668 [ + - ]: 96 : if (bufpos >= m_buflen)
669 : 96 : break;
670 : : }
671 [ - + ]: 2301439 : switch (state)
672 : : {
673 : : case LINE_STATE_CR:
674 : 0 : state = LINE_STATE_LF;
675 [ # # ]: 0 : switch (m_buffer[curpos])
676 : : {
677 : : case 0x0A: /* CRLF */
678 : : /* eat current char */
679 : 0 : curpos++;
680 : 0 : break;
681 : : default: /* single CR */
682 : : /* keep current char */
683 : 0 : break;
684 : : }
685 : 0 : break;
686 : : default:
687 : : /* determine next state */
688 [ + - + ]: 2301439 : switch (m_buffer[curpos])
689 : : {
690 : : case 0x0A: /* single LF */
691 : 39056 : state = LINE_STATE_LF;
692 : 39056 : break;
693 : : case 0x0D: /* CR */
694 : 0 : state = LINE_STATE_CR;
695 : 0 : break;
696 : : default: /* advance to next char */
697 : 2262383 : curpos++;
698 : 2262383 : break;
699 : : }
700 [ + + ]: 2301439 : if (state != LINE_STATE_BEGIN)
701 : : {
702 : : /* skip the newline char */
703 : 39056 : curpos++;
704 : :
705 : : /* flush buffer to sequence */
706 : : result = writeSequence_Impl (
707 : 39056 : ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos - 1);
708 [ - + ]: 39056 : if (result != osl_File_E_None)
709 : 0 : return (result);
710 : 39056 : *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
711 : : }
712 : 2301439 : break;
713 : : }
714 : : }
715 : :
716 : 41567 : result = writeSequence_Impl (ppSequence, &dstpos, 0, 0);
717 [ - + ]: 41567 : if (result != osl_File_E_None)
718 : 0 : return (result);
719 [ + + ]: 41567 : if (0 < dstpos)
720 : 38570 : return osl_File_E_None;
721 [ + + ]: 2997 : if (bufpos >= m_buflen)
722 : 2415 : return osl_File_E_AGAIN;
723 : 41567 : return osl_File_E_None;
724 : : }
725 : :
726 : 80719 : oslFileError FileHandle_Impl::writeSequence_Impl (
727 : : sal_Sequence ** ppSequence,
728 : : size_t * pnOffset,
729 : : const void * pBuffer,
730 : : size_t nBytes)
731 : : {
732 : 80719 : sal_Int32 nElements = *pnOffset + nBytes;
733 [ - + ]: 80719 : if (!*ppSequence)
734 : : {
735 : : /* construct sequence */
736 : 0 : rtl_byte_sequence_constructNoDefault(ppSequence, nElements);
737 : : }
738 [ + + ]: 80719 : else if (nElements != (*ppSequence)->nElements)
739 : : {
740 : : /* resize sequence */
741 : 39729 : rtl_byte_sequence_realloc(ppSequence, nElements);
742 : : }
743 [ + - ]: 80719 : if (*ppSequence != 0)
744 : : {
745 : : /* fill sequence */
746 : 80719 : memcpy(&((*ppSequence)->elements[*pnOffset]), pBuffer, nBytes), *pnOffset += nBytes;
747 : : }
748 [ + - ]: 80719 : return (*ppSequence != 0) ? osl_File_E_None : osl_File_E_NOMEM;
749 : : }
750 : :
751 : 786586 : oslFileError FileHandle_Impl::syncFile()
752 : : {
753 : 786586 : oslFileError result = osl_File_E_None;
754 [ + + ]: 786586 : if (m_state & STATE_MODIFIED)
755 : : {
756 : 358094 : sal_uInt64 uDone = 0;
757 [ + - ]: 358094 : result = writeAt (m_bufptr, m_buffer, m_buflen, &uDone);
758 [ - + ]: 358094 : if (result != osl_File_E_None)
759 : 0 : return (result);
760 [ - + ]: 358094 : if (uDone != m_buflen)
761 : 0 : return osl_File_E_IO;
762 : 358094 : m_state &= ~STATE_MODIFIED;
763 : : }
764 : 786586 : return (result);
765 : : }
766 : :
767 : 57 : oslFileHandle osl::detail::createFileHandleFromFD( int fd )
768 : : {
769 [ - + ]: 57 : if (-1 == fd)
770 : 0 : return 0; // EINVAL
771 : :
772 : : struct stat aFileStat;
773 [ - + ]: 57 : if (-1 == fstat (fd, &aFileStat))
774 : 0 : return 0; // EBADF
775 : :
776 [ + - ]: 57 : FileHandle_Impl * pImpl = new FileHandle_Impl (fd);
777 [ - + ]: 57 : if (0 == pImpl)
778 : 0 : return 0; // ENOMEM
779 : :
780 : : // assume writeable
781 : 57 : pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE;
782 [ + - ]: 57 : if (!S_ISREG(aFileStat.st_mode))
783 : : {
784 : : /* not a regular file, mark not seekable */
785 : 57 : pImpl->m_state &= ~FileHandle_Impl::STATE_SEEKABLE;
786 : : }
787 : : else
788 : : {
789 : : /* regular file, init current size */
790 : 0 : pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size);
791 : : }
792 : :
793 : : OSL_FILE_TRACE("osl::detail::createFileHandleFromFD(%d, writeable) => %s",
794 : : pImpl->m_fd, rtl_string_getStr(pImpl->m_strFilePath));
795 : 57 : return (oslFileHandle)(pImpl);
796 : : }
797 : :
798 : : /*******************************************************************
799 : : * osl_file_adjustLockFlags
800 : : ******************************************************************/
801 : 188278 : static int osl_file_adjustLockFlags (const char * path, int flags)
802 : : {
803 : : #ifdef MACOSX
804 : : /*
805 : : * The AFP implementation of MacOS X 10.4 treats O_EXLOCK in a way
806 : : * that makes it impossible for OOo to create a backup copy of the
807 : : * file it keeps opened. OTOH O_SHLOCK for AFP behaves as desired by
808 : : * the OOo file handling, so we need to check the path of the file
809 : : * for the filesystem name.
810 : : */
811 : : struct statfs s;
812 : : if( 0 <= statfs( path, &s ) )
813 : : {
814 : : if( 0 == strncmp("afpfs", s.f_fstypename, 5) )
815 : : {
816 : : flags &= ~O_EXLOCK;
817 : : flags |= O_SHLOCK;
818 : : }
819 : : else
820 : : {
821 : : /* Needed flags to allow opening a webdav file */
822 : : flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK);
823 : : }
824 : : }
825 : : #endif /* MACOSX */
826 : :
827 : : (void) path;
828 : 188278 : return flags;
829 : : }
830 : :
831 : : /****************************************************************************
832 : : * osl_file_queryLocking
833 : : ***************************************************************************/
834 : : struct Locking_Impl
835 : : {
836 : : int m_enabled;
837 : 1963 : Locking_Impl() : m_enabled(0)
838 : : {
839 : : #ifndef HAVE_O_EXLOCK
840 : 1963 : m_enabled = (getenv("SAL_ENABLE_FILE_LOCKING") != 0);
841 : : #endif /* HAVE_O_EXLOCK */
842 : 1963 : }
843 : : };
844 : 200298 : static int osl_file_queryLocking (sal_uInt32 uFlags)
845 : : {
846 [ + + ]: 200298 : if (!(uFlags & osl_File_OpenFlag_NoLock))
847 : : {
848 [ + + ][ + + ]: 176141 : if ((uFlags & osl_File_OpenFlag_Write) || (uFlags & osl_File_OpenFlag_Create))
849 : : {
850 [ + + ][ + - ]: 76547 : static Locking_Impl g_locking;
851 : 76547 : return (g_locking.m_enabled != 0);
852 : : }
853 : : }
854 : 200298 : return 0;
855 : : }
856 : :
857 : : #ifdef UNX
858 : :
859 : : static oslFileError
860 : 0 : osl_openMemoryAsFile( void *address, size_t size, oslFileHandle *pHandle, const char *path )
861 : : {
862 : : oslFileError eRet;
863 [ # # ]: 0 : FileHandle_Impl * pImpl = new FileHandle_Impl (-1, FileHandle_Impl::KIND_MEM, path);
864 [ # # ]: 0 : if (!pImpl)
865 : : {
866 : 0 : eRet = oslTranslateFileError (OSL_FET_ERROR, ENOMEM);
867 : 0 : return eRet;
868 : : }
869 : 0 : pImpl->m_size = sal::static_int_cast< sal_uInt64 >(size);
870 : :
871 : 0 : *pHandle = (oslFileHandle)(pImpl);
872 : :
873 : 0 : pImpl->m_bufptr = 0;
874 : 0 : pImpl->m_buflen = size;
875 : :
876 : 0 : pImpl->m_bufsiz = size;
877 : 0 : pImpl->m_buffer = (sal_uInt8*) address;
878 : :
879 : 0 : return osl_File_E_None;
880 : : }
881 : :
882 : : oslFileError
883 : 0 : SAL_CALL osl_openMemoryAsFile( void *address, size_t size, oslFileHandle *pHandle )
884 : : {
885 : 0 : return osl_openMemoryAsFile( address, size, pHandle, "<anon>" );
886 : : }
887 : :
888 : : #endif
889 : :
890 : : /****************************************************************************
891 : : * osl_openFile
892 : : ***************************************************************************/
893 : : #ifdef HAVE_O_EXLOCK
894 : : #define OPEN_WRITE_FLAGS ( O_RDWR | O_EXLOCK | O_NONBLOCK )
895 : : #define OPEN_CREATE_FLAGS ( O_CREAT | O_RDWR | O_EXLOCK | O_NONBLOCK )
896 : : #else
897 : : #define OPEN_WRITE_FLAGS ( O_RDWR )
898 : : #define OPEN_CREATE_FLAGS ( O_CREAT | O_RDWR )
899 : : #endif
900 : :
901 : : oslFileError
902 : 213290 : SAL_CALL osl_openFilePath( const char *cpFilePath, oslFileHandle* pHandle, sal_uInt32 uFlags )
903 : : {
904 : : oslFileError eRet;
905 : :
906 : : #ifdef ANDROID
907 : : /* Opening a file from /assets read-only means
908 : : * we should mmap it from the .apk file
909 : : */
910 : : if (strncmp (cpFilePath, "/assets/", sizeof ("/assets/") - 1) == 0)
911 : : {
912 : : if (uFlags & osl_File_OpenFlag_Write)
913 : : {
914 : : // Or should we just silently "open" it read-only and let write
915 : : // attempts, if any, fail then later?
916 : : OSL_TRACE("osl_openFile(%s, writeable), not possible!", cpFilePath);
917 : : errno = EPERM;
918 : : return osl_File_E_PERM;
919 : : }
920 : : void *address;
921 : : size_t size;
922 : : address = lo_apkentry(cpFilePath, &size);
923 : : OSL_TRACE("osl_openFile(%s) => %p",
924 : : cpFilePath, address);
925 : : if (address == NULL)
926 : : {
927 : : errno = ENOENT;
928 : : return osl_File_E_NOENT;
929 : : }
930 : : return osl_openMemoryAsFile(address, size, pHandle, cpFilePath);
931 : : }
932 : : #endif
933 : :
934 : : /* set mode and flags */
935 : 213290 : int mode = S_IRUSR | S_IRGRP | S_IROTH;
936 : 213290 : int flags = O_RDONLY;
937 [ + + ]: 213290 : if (uFlags & osl_File_OpenFlag_Write)
938 : : {
939 : 84460 : mode |= S_IWUSR | S_IWGRP | S_IWOTH;
940 : 84460 : flags = OPEN_WRITE_FLAGS;
941 : : }
942 [ + + ]: 213290 : if (uFlags & osl_File_OpenFlag_Create)
943 : : {
944 : 75290 : mode |= S_IWUSR | S_IWGRP | S_IWOTH;
945 : 75290 : flags = OPEN_CREATE_FLAGS;
946 : : }
947 : :
948 : : /* Check for flags passed in from SvFileStream::Open() */
949 [ + + ]: 213290 : if (uFlags & osl_File_OpenFlag_Trunc)
950 : 1601 : flags |= O_TRUNC;
951 [ + + ]: 213290 : if (!(uFlags & osl_File_OpenFlag_NoExcl))
952 : 201406 : flags |= O_EXCL;
953 : :
954 [ + + ]: 213290 : if (uFlags & osl_File_OpenFlag_NoLock)
955 : : {
956 : : #ifdef HAVE_O_EXLOCK
957 : : flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK);
958 : : #endif /* HAVE_O_EXLOCK */
959 : : }
960 : : else
961 : : {
962 : 188278 : flags = osl_file_adjustLockFlags (cpFilePath, flags);
963 : : }
964 : :
965 : : /* open the file */
966 [ + - ]: 213290 : int fd = open( cpFilePath, flags, mode );
967 [ + + ]: 213290 : if (-1 == fd)
968 : : {
969 : 12992 : int saved_errno = errno;
970 : : OSL_TRACE("osl_openFile(%s, %s) failed: %s",
971 : : cpFilePath,
972 : : flags & O_RDWR ? "writeable":"readonly",
973 : : strerror(saved_errno));
974 [ + - ]: 12992 : return oslTranslateFileError (OSL_FET_ERROR, saved_errno);
975 : : }
976 : :
977 : : /* reset O_NONBLOCK flag */
978 [ - + ]: 200298 : if (flags & O_NONBLOCK)
979 : : {
980 [ # # ]: 0 : int f = fcntl (fd, F_GETFL, 0);
981 [ # # ]: 0 : if (-1 == f)
982 : : {
983 : 0 : int saved_errno = errno;
984 : : OSL_TRACE("osl_openFile(%s, %s): fcntl(%d, F_GETFL) failed: %s",
985 : : cpFilePath,
986 : : flags & O_RDWR ? "writeable":"readonly",
987 : : fd,
988 : : strerror(saved_errno));
989 [ # # ]: 0 : eRet = oslTranslateFileError (OSL_FET_ERROR, saved_errno);
990 [ # # ]: 0 : (void) close(fd);
991 : 0 : return eRet;
992 : : }
993 [ # # ][ # # ]: 0 : if (-1 == fcntl (fd, F_SETFL, (f & ~O_NONBLOCK)))
994 : : {
995 : 0 : int saved_errno = errno;
996 : : OSL_TRACE("osl_openFile(%s, %s): fcntl(%d, F_SETFL) failed: %s",
997 : : cpFilePath,
998 : : flags & O_RDWR ? "writeable":"readonly",
999 : : fd,
1000 : : strerror(saved_errno));
1001 [ # # ]: 0 : eRet = oslTranslateFileError (OSL_FET_ERROR, saved_errno);
1002 [ # # ]: 0 : (void) close(fd);
1003 : 0 : return eRet;
1004 : : }
1005 : : }
1006 : :
1007 : : /* get file status (mode, size) */
1008 : : struct stat aFileStat;
1009 [ - + ]: 200298 : if (-1 == fstat (fd, &aFileStat))
1010 : : {
1011 : 0 : int saved_errno = errno;
1012 : : OSL_TRACE("osl_openFile(%s, %s): fstat(%d) failed: %s",
1013 : : cpFilePath,
1014 : : flags & O_RDWR ? "writeable":"readonly",
1015 : : fd,
1016 : : strerror(saved_errno));
1017 [ # # ]: 0 : eRet = oslTranslateFileError (OSL_FET_ERROR, saved_errno);
1018 [ # # ]: 0 : (void) close(fd);
1019 : 0 : return eRet;
1020 : : }
1021 [ - + ]: 200298 : if (!S_ISREG(aFileStat.st_mode))
1022 : : {
1023 : : /* we only open regular files here */
1024 : : OSL_TRACE("osl_openFile(%s): not a regular file",
1025 : : cpFilePath);
1026 [ # # ]: 0 : (void) close(fd);
1027 : 0 : return osl_File_E_INVAL;
1028 : : }
1029 : :
1030 [ + + ]: 200298 : if (osl_file_queryLocking (uFlags))
1031 : : {
1032 : : #ifdef MACOSX
1033 : : if (-1 == flock (fd, LOCK_EX | LOCK_NB))
1034 : : {
1035 : : /* Mac OSX returns ENOTSUP for webdav drives. We should try read lock */
1036 : : if ((errno != ENOTSUP) || ((-1 == flock (fd, LOCK_SH | LOCK_NB)) && (errno != ENOTSUP)))
1037 : : {
1038 : : eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
1039 : : (void) close(fd);
1040 : : return eRet;
1041 : : }
1042 : : }
1043 : : #else /* F_SETLK */
1044 : : {
1045 : : struct flock aflock;
1046 : :
1047 : 76547 : aflock.l_type = F_WRLCK;
1048 : 76547 : aflock.l_whence = SEEK_SET;
1049 : 76547 : aflock.l_start = 0;
1050 : 76547 : aflock.l_len = 0;
1051 : :
1052 [ + - ][ - + ]: 76547 : if (-1 == fcntl (fd, F_SETLK, &aflock))
1053 : : {
1054 : 0 : int saved_errno = errno;
1055 : : OSL_TRACE("osl_openFile(%s, %s): fcntl(%d, F_SETLK) failed: %s",
1056 : : cpFilePath,
1057 : : flags & O_RDWR ? "writeable":"readonly",
1058 : : fd,
1059 : : strerror(saved_errno));
1060 [ # # ]: 0 : eRet = oslTranslateFileError (OSL_FET_ERROR, saved_errno);
1061 [ # # ]: 0 : (void) close(fd);
1062 : 76547 : return eRet;
1063 : : }
1064 : : }
1065 : : #endif /* F_SETLK */
1066 : : }
1067 : :
1068 : : /* allocate memory for impl structure */
1069 [ + - ]: 200298 : FileHandle_Impl * pImpl = new FileHandle_Impl (fd, FileHandle_Impl::KIND_FD, cpFilePath);
1070 [ - + ]: 200298 : if (!pImpl)
1071 : : {
1072 [ # # ]: 0 : eRet = oslTranslateFileError (OSL_FET_ERROR, ENOMEM);
1073 [ # # ]: 0 : (void) close(fd);
1074 : 0 : return eRet;
1075 : : }
1076 [ + + ]: 200298 : if (flags & O_RDWR)
1077 : 88106 : pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE;
1078 : 200298 : pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size);
1079 : :
1080 : : OSL_TRACE("osl_openFile(%s, %s) => %d",
1081 : : rtl_string_getStr(pImpl->m_strFilePath),
1082 : : flags & O_RDWR ? "writeable":"readonly",
1083 : : pImpl->m_fd);
1084 : :
1085 : 200298 : *pHandle = (oslFileHandle)(pImpl);
1086 : 213290 : return osl_File_E_None;
1087 : : }
1088 : :
1089 : : oslFileError
1090 : 209771 : SAL_CALL osl_openFile( rtl_uString* ustrFileURL, oslFileHandle* pHandle, sal_uInt32 uFlags )
1091 : : {
1092 : : oslFileError eRet;
1093 : :
1094 [ + - ][ + + ]: 209771 : if ((ustrFileURL == 0) || (ustrFileURL->length == 0) || (pHandle == 0))
[ - + ]
1095 : 5 : return osl_File_E_INVAL;
1096 : :
1097 : : /* convert file URL to system path */
1098 : : char buffer[PATH_MAX];
1099 [ + - ]: 209766 : eRet = FileURLToPath (buffer, sizeof(buffer), ustrFileURL);
1100 [ + + ]: 209766 : if (eRet != osl_File_E_None)
1101 : 74 : return eRet;
1102 : :
1103 : : #ifdef MACOSX
1104 : : if (macxp_resolveAlias (buffer, sizeof(buffer)) != 0)
1105 : : return oslTranslateFileError (OSL_FET_ERROR, errno);
1106 : : #endif /* MACOSX */
1107 : :
1108 [ + - ]: 209771 : return osl_openFilePath (buffer, pHandle, uFlags);
1109 : : }
1110 : :
1111 : : /****************************************************************************/
1112 : : /* osl_closeFile */
1113 : : /****************************************************************************/
1114 : : oslFileError
1115 : 198300 : SAL_CALL osl_closeFile( oslFileHandle Handle )
1116 : : {
1117 : 198300 : FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1118 : :
1119 [ - + ]: 198300 : if (pImpl == 0)
1120 : 0 : return osl_File_E_INVAL;
1121 : :
1122 : : OSL_TRACE("osl_closeFile(%s:%d)", rtl_string_getStr(pImpl->m_strFilePath), pImpl->m_fd);
1123 : :
1124 [ - + ]: 198300 : if (pImpl->m_kind == FileHandle_Impl::KIND_MEM)
1125 : : {
1126 [ # # ]: 0 : delete pImpl;
1127 : 0 : return osl_File_E_None;
1128 : : }
1129 : :
1130 [ - + ]: 198300 : if (pImpl->m_fd < 0)
1131 : 0 : return osl_File_E_INVAL;
1132 : :
1133 : 198300 : (void) pthread_mutex_lock (&(pImpl->m_mutex));
1134 : :
1135 : : /* close(2) implicitly (and unconditionally) unlocks */
1136 : 198300 : oslFileError result = pImpl->syncFile();
1137 [ - + ]: 198300 : if (result != osl_File_E_None)
1138 : : {
1139 : : /* close, ignoring double failure */
1140 : 0 : (void) close (pImpl->m_fd);
1141 : : }
1142 [ - + ]: 198300 : else if (-1 == close (pImpl->m_fd))
1143 : : {
1144 : : /* translate error code */
1145 : 0 : result = oslTranslateFileError (OSL_FET_ERROR, errno);
1146 : : }
1147 : :
1148 : 198300 : (void) pthread_mutex_unlock (&(pImpl->m_mutex));
1149 [ + - ]: 198300 : delete pImpl;
1150 : 198300 : return (result);
1151 : : }
1152 : :
1153 : : /************************************************
1154 : : * osl_syncFile
1155 : : ***********************************************/
1156 : : oslFileError
1157 : 660 : SAL_CALL osl_syncFile(oslFileHandle Handle)
1158 : : {
1159 : 660 : FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1160 : :
1161 [ + + ][ + - ]: 660 : if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)))
[ - + ]
1162 : 5 : return osl_File_E_INVAL;
1163 : :
1164 [ - + ]: 655 : if (pImpl->m_kind == FileHandle_Impl::KIND_MEM)
1165 : 0 : return osl_File_E_None;
1166 : :
1167 : 655 : FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1168 : :
1169 : : OSL_TRACE("osl_syncFile(%d)", pImpl->m_fd);
1170 [ + - ]: 655 : oslFileError result = pImpl->syncFile();
1171 [ - + ]: 655 : if (result != osl_File_E_None)
1172 : 0 : return (result);
1173 [ + - ][ - + ]: 655 : if (-1 == fsync (pImpl->m_fd))
1174 [ # # ]: 0 : return oslTranslateFileError (OSL_FET_ERROR, errno);
1175 : :
1176 : 660 : return osl_File_E_None;
1177 : : }
1178 : :
1179 : : /************************************************
1180 : : * osl_fileGetOSHandle
1181 : : ***********************************************/
1182 : : oslFileError
1183 : 2640 : SAL_CALL osl_getFileOSHandle(
1184 : : oslFileHandle Handle,
1185 : : sal_IntPtr *piFileHandle )
1186 : : {
1187 : 2640 : FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1188 : :
1189 [ + - ][ + - ]: 2640 : if (0 == pImpl || pImpl->m_kind != FileHandle_Impl::KIND_FD || -1 == pImpl->m_fd)
[ - + ]
1190 : 0 : return osl_File_E_INVAL;
1191 : :
1192 : 2640 : *piFileHandle = pImpl->m_fd;
1193 : :
1194 : 2640 : return osl_File_E_None;
1195 : : }
1196 : :
1197 : : /*******************************************
1198 : : osl_mapFile
1199 : : ********************************************/
1200 : : oslFileError
1201 : 60409 : SAL_CALL osl_mapFile (
1202 : : oslFileHandle Handle,
1203 : : void** ppAddr,
1204 : : sal_uInt64 uLength,
1205 : : sal_uInt64 uOffset,
1206 : : sal_uInt32 uFlags
1207 : : )
1208 : : {
1209 : 60409 : FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1210 : :
1211 [ + - ][ + - ]: 60409 : if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == ppAddr))
[ + - ][ - + ]
1212 : 0 : return osl_File_E_INVAL;
1213 : 60409 : *ppAddr = 0;
1214 : :
1215 : : static sal_uInt64 const g_limit_size_t = std::numeric_limits< size_t >::max();
1216 [ - + ]: 60409 : if (g_limit_size_t < uLength)
1217 : 0 : return osl_File_E_OVERFLOW;
1218 : 60409 : size_t const nLength = sal::static_int_cast< size_t >(uLength);
1219 : :
1220 : : static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
1221 [ - + ]: 60409 : if (g_limit_off_t < uOffset)
1222 : 0 : return osl_File_E_OVERFLOW;
1223 : :
1224 [ - + ]: 60409 : if (pImpl->m_kind == FileHandle_Impl::KIND_MEM)
1225 : : {
1226 : 0 : *ppAddr = pImpl->m_buffer + uOffset;
1227 : 0 : return osl_File_E_None;
1228 : : }
1229 : :
1230 : 60409 : off_t const nOffset = sal::static_int_cast< off_t >(uOffset);
1231 : :
1232 : 60409 : void* p = mmap(NULL, nLength, PROT_READ, MAP_SHARED, pImpl->m_fd, nOffset);
1233 [ + + ]: 60409 : if (MAP_FAILED == p)
1234 : 8 : return oslTranslateFileError(OSL_FET_ERROR, errno);
1235 : 60401 : *ppAddr = p;
1236 : :
1237 [ + + ]: 60401 : if (uFlags & osl_File_MapFlag_RandomAccess)
1238 : : {
1239 : : // Determine memory pagesize.
1240 : 11410 : size_t const nPageSize = FileHandle_Impl::getpagesize();
1241 [ + - ]: 11410 : if (size_t(-1) != nPageSize)
1242 : : {
1243 : : /*
1244 : : * Pagein, touching first byte of every memory page.
1245 : : * Note: volatile disables optimizing the loop away.
1246 : : */
1247 : 11410 : sal_uInt8 * pData (reinterpret_cast<sal_uInt8*>(*ppAddr));
1248 : 11410 : size_t nSize (nLength);
1249 : :
1250 : 11410 : volatile sal_uInt8 c = 0;
1251 [ + + ]: 1552679 : while (nSize > nPageSize)
1252 : : {
1253 : 1541269 : c ^= pData[0];
1254 : 1541269 : pData += nPageSize;
1255 : 1541269 : nSize -= nPageSize;
1256 : : }
1257 [ + - ]: 11410 : if (nSize > 0)
1258 : : {
1259 : 11410 : c^= pData[0];
1260 : : }
1261 : : }
1262 : : }
1263 : 60401 : if (uFlags & osl_File_MapFlag_WillNeed)
1264 : : {
1265 : : // On Linux, madvise(..., MADV_WILLNEED) appears to have the undesirable
1266 : : // effect of not returning until the data has actually been paged in, so
1267 : : // that its net effect would typically be to slow down the process
1268 : : // (which could start processing at the beginning of the data while the
1269 : : // OS simultaneously pages in the rest); on other platforms, it remains
1270 : : // to be evaluated whether madvise or equivalent is available and
1271 : : // actually useful:
1272 : : #if defined MACOSX
1273 : : int e = posix_madvise(p, nLength, POSIX_MADV_WILLNEED);
1274 : : if (e != 0)
1275 : : {
1276 : : OSL_TRACE(
1277 : : "posix_madvise(..., POSIX_MADV_WILLNEED) failed with %d", e);
1278 : : }
1279 : : #elif defined SOLARIS
1280 : : if (madvise(static_cast< caddr_t >(p), nLength, MADV_WILLNEED) != 0)
1281 : : {
1282 : : OSL_TRACE("madvise(..., MADV_WILLNEED) failed with %d", errno);
1283 : : }
1284 : : #endif
1285 : : }
1286 : 60409 : return osl_File_E_None;
1287 : : }
1288 : :
1289 : : static
1290 : : oslFileError
1291 : 59650 : unmapFile (void* pAddr, sal_uInt64 uLength)
1292 : : {
1293 [ - + ]: 59650 : if (0 == pAddr)
1294 : 0 : return osl_File_E_INVAL;
1295 : :
1296 : : static sal_uInt64 const g_limit_size_t = std::numeric_limits< size_t >::max();
1297 [ - + ]: 59650 : if (g_limit_size_t < uLength)
1298 : 0 : return osl_File_E_OVERFLOW;
1299 : 59650 : size_t const nLength = sal::static_int_cast< size_t >(uLength);
1300 : :
1301 [ - + ]: 59650 : if (-1 == munmap(static_cast<char*>(pAddr), nLength))
1302 : 0 : return oslTranslateFileError(OSL_FET_ERROR, errno);
1303 : :
1304 : 59650 : return osl_File_E_None;
1305 : : }
1306 : :
1307 : : #ifndef ANDROID
1308 : :
1309 : : // Note that osl_unmapFile() just won't work on Android in general
1310 : : // where for (uncompressed) files inside the .apk, in the /assets
1311 : : // folder osl_mapFile just returns a pointer to the file inside the
1312 : : // already mmapped .apk archive.
1313 : :
1314 : : /*******************************************
1315 : : osl_unmapFile
1316 : : ********************************************/
1317 : : oslFileError
1318 : 0 : SAL_CALL osl_unmapFile (void* pAddr, sal_uInt64 uLength)
1319 : : {
1320 : 0 : return unmapFile (pAddr, uLength);
1321 : : }
1322 : :
1323 : : #endif
1324 : :
1325 : : /*******************************************
1326 : : osl_unmapMappedFile
1327 : : ********************************************/
1328 : : oslFileError
1329 : 59650 : SAL_CALL osl_unmapMappedFile (oslFileHandle Handle, void* pAddr, sal_uInt64 uLength)
1330 : : {
1331 : 59650 : FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
1332 : :
1333 [ - + ]: 59650 : if (pImpl == 0)
1334 : 0 : return osl_File_E_INVAL;
1335 : :
1336 [ + - ]: 59650 : if (pImpl->m_kind == FileHandle_Impl::KIND_FD)
1337 : 59650 : return unmapFile (pAddr, uLength);
1338 : :
1339 : : // For parts of already mmapped "parent" files, whose mapping we
1340 : : // can't change, not much we can or should do...
1341 : 59650 : return osl_File_E_None;
1342 : : }
1343 : :
1344 : : /*******************************************
1345 : : osl_readLine
1346 : : ********************************************/
1347 : : oslFileError
1348 : 41567 : SAL_CALL osl_readLine (
1349 : : oslFileHandle Handle,
1350 : : sal_Sequence ** ppSequence)
1351 : : {
1352 : 41567 : FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
1353 : :
1354 [ + - ][ + - ]: 41567 : if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == ppSequence))
[ + - ][ - + ]
1355 : 0 : return osl_File_E_INVAL;
1356 : 41567 : sal_uInt64 uBytesRead = 0;
1357 : :
1358 : : // read at current fileptr; fileptr += uBytesRead;
1359 : 41567 : FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1360 : : oslFileError result = pImpl->readLineAt (
1361 [ + - ]: 41567 : pImpl->m_fileptr, ppSequence, &uBytesRead);
1362 [ + + ]: 41567 : if (result == osl_File_E_None)
1363 : 39152 : pImpl->m_fileptr += uBytesRead;
1364 : 41567 : return (result);
1365 : : }
1366 : :
1367 : : /*******************************************
1368 : : osl_readFile
1369 : : ********************************************/
1370 : : oslFileError
1371 : 1154713 : SAL_CALL osl_readFile (
1372 : : oslFileHandle Handle,
1373 : : void * pBuffer,
1374 : : sal_uInt64 uBytesRequested,
1375 : : sal_uInt64 * pBytesRead)
1376 : : {
1377 : 1154713 : FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1378 : :
1379 [ + - ][ + - ]: 1154713 : if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pBuffer) || (0 == pBytesRead))
[ + - ][ + - ]
[ - + ]
1380 : 0 : return osl_File_E_INVAL;
1381 : :
1382 : : static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
1383 [ - + ]: 1154713 : if (g_limit_ssize_t < uBytesRequested)
1384 : 0 : return osl_File_E_OVERFLOW;
1385 : 1154713 : size_t const nBytesRequested = sal::static_int_cast< size_t >(uBytesRequested);
1386 : :
1387 : : // read at current fileptr; fileptr += *pBytesRead;
1388 : 1154713 : FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1389 : : oslFileError result = pImpl->readFileAt (
1390 [ + - ]: 1154713 : pImpl->m_fileptr, pBuffer, nBytesRequested, pBytesRead);
1391 [ + - ]: 1154713 : if (result == osl_File_E_None)
1392 : 1154713 : pImpl->m_fileptr += *pBytesRead;
1393 : 1154713 : return (result);
1394 : : }
1395 : :
1396 : : /*******************************************
1397 : : osl_writeFile
1398 : : ********************************************/
1399 : : oslFileError
1400 : 23325922 : SAL_CALL osl_writeFile (
1401 : : oslFileHandle Handle,
1402 : : const void * pBuffer,
1403 : : sal_uInt64 uBytesToWrite,
1404 : : sal_uInt64 * pBytesWritten)
1405 : : {
1406 : 23325922 : FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1407 : :
1408 [ + + ][ + - ]: 23325922 : if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesWritten))
[ + - ][ - + ]
1409 : 5 : return osl_File_E_INVAL;
1410 [ - + ]: 23325917 : if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
1411 : 0 : return osl_File_E_BADF;
1412 : :
1413 : : static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
1414 [ - + ]: 23325917 : if (g_limit_ssize_t < uBytesToWrite)
1415 : 0 : return osl_File_E_OVERFLOW;
1416 : 23325917 : size_t const nBytesToWrite = sal::static_int_cast< size_t >(uBytesToWrite);
1417 : :
1418 : : // write at current fileptr; fileptr += *pBytesWritten;
1419 : 23325917 : FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1420 : : oslFileError result = pImpl->writeFileAt (
1421 [ + - ]: 23325917 : pImpl->m_fileptr, pBuffer, nBytesToWrite, pBytesWritten);
1422 [ + - ]: 23325917 : if (result == osl_File_E_None)
1423 : 23325917 : pImpl->m_fileptr += *pBytesWritten;
1424 : 23325922 : return (result);
1425 : : }
1426 : :
1427 : : /*******************************************
1428 : : osl_readFileAt
1429 : : ********************************************/
1430 : : oslFileError
1431 : 54034 : SAL_CALL osl_readFileAt (
1432 : : oslFileHandle Handle,
1433 : : sal_uInt64 uOffset,
1434 : : void* pBuffer,
1435 : : sal_uInt64 uBytesRequested,
1436 : : sal_uInt64* pBytesRead)
1437 : : {
1438 : 54034 : FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1439 : :
1440 [ + - ][ + - ]: 54034 : if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pBuffer) || (0 == pBytesRead))
[ + - ][ + - ]
[ - + ]
1441 : 0 : return osl_File_E_INVAL;
1442 [ - + ]: 54034 : if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
1443 : 0 : return osl_File_E_SPIPE;
1444 : :
1445 : : static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
1446 [ - + ]: 54034 : if (g_limit_off_t < uOffset)
1447 : 0 : return osl_File_E_OVERFLOW;
1448 : 54034 : off_t const nOffset = sal::static_int_cast< off_t >(uOffset);
1449 : :
1450 : : static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
1451 [ - + ]: 54034 : if (g_limit_ssize_t < uBytesRequested)
1452 : 0 : return osl_File_E_OVERFLOW;
1453 : 54034 : size_t const nBytesRequested = sal::static_int_cast< size_t >(uBytesRequested);
1454 : :
1455 : : // read at specified fileptr
1456 : 54034 : FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1457 [ + - ]: 54034 : return pImpl->readFileAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
1458 : : }
1459 : :
1460 : : /*******************************************
1461 : : osl_writeFileAt
1462 : : ********************************************/
1463 : : oslFileError
1464 : 414995 : SAL_CALL osl_writeFileAt (
1465 : : oslFileHandle Handle,
1466 : : sal_uInt64 uOffset,
1467 : : const void* pBuffer,
1468 : : sal_uInt64 uBytesToWrite,
1469 : : sal_uInt64* pBytesWritten)
1470 : : {
1471 : 414995 : FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1472 : :
1473 [ + - ][ + - ]: 414995 : if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesWritten))
[ + - ][ - + ]
1474 : 0 : return osl_File_E_INVAL;
1475 [ - + ]: 414995 : if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
1476 : 0 : return osl_File_E_SPIPE;
1477 [ - + ]: 414995 : if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
1478 : 0 : return osl_File_E_BADF;
1479 : :
1480 : : static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
1481 [ - + ]: 414995 : if (g_limit_off_t < uOffset)
1482 : 0 : return osl_File_E_OVERFLOW;
1483 : 414995 : off_t const nOffset = sal::static_int_cast< off_t >(uOffset);
1484 : :
1485 : : static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
1486 [ - + ]: 414995 : if (g_limit_ssize_t < uBytesToWrite)
1487 : 0 : return osl_File_E_OVERFLOW;
1488 : 414995 : size_t const nBytesToWrite = sal::static_int_cast< size_t >(uBytesToWrite);
1489 : :
1490 : : // write at specified fileptr
1491 : 414995 : FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1492 [ + - ]: 414995 : return pImpl->writeFileAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten);
1493 : : }
1494 : :
1495 : : /****************************************************************************/
1496 : : /* osl_isEndOfFile */
1497 : : /****************************************************************************/
1498 : : oslFileError
1499 : 0 : SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF )
1500 : : {
1501 : 0 : FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1502 : :
1503 [ # # ][ # # ]: 0 : if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pIsEOF))
[ # # ][ # # ]
1504 : 0 : return osl_File_E_INVAL;
1505 : :
1506 : 0 : FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1507 [ # # ][ # # ]: 0 : *pIsEOF = (pImpl->getPos() == pImpl->getSize());
1508 : 0 : return osl_File_E_None;
1509 : : }
1510 : :
1511 : : /************************************************
1512 : : * osl_getFilePos
1513 : : ***********************************************/
1514 : : oslFileError
1515 : 1229103 : SAL_CALL osl_getFilePos( oslFileHandle Handle, sal_uInt64* pPos )
1516 : : {
1517 : 1229103 : FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1518 : :
1519 [ + - ][ + - ]: 1229103 : if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pPos))
[ + - ][ - + ]
1520 : 0 : return osl_File_E_INVAL;
1521 : :
1522 : 1229103 : FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1523 [ + - ]: 1229103 : *pPos = pImpl->getPos();
1524 : 1229103 : return osl_File_E_None;
1525 : : }
1526 : :
1527 : : /*******************************************
1528 : : osl_setFilePos
1529 : : ********************************************/
1530 : : oslFileError
1531 : 867097 : SAL_CALL osl_setFilePos (oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uOffset)
1532 : : {
1533 : 867097 : FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1534 : :
1535 [ + - ][ + - ]: 867097 : if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)))
[ - + ]
1536 : 0 : return osl_File_E_INVAL;
1537 : :
1538 : : static sal_Int64 const g_limit_off_t = std::numeric_limits< off_t >::max();
1539 : : if (g_limit_off_t < uOffset)
1540 : : return osl_File_E_OVERFLOW;
1541 : 867097 : off_t nPos = 0, nOffset = sal::static_int_cast< off_t >(uOffset);
1542 : :
1543 : 867097 : FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1544 [ + + + - ]: 867097 : switch(uHow)
1545 : : {
1546 : : case osl_Pos_Absolut:
1547 [ - + ]: 863347 : if (0 > nOffset)
1548 : 0 : return osl_File_E_INVAL;
1549 : 863347 : break;
1550 : :
1551 : : case osl_Pos_Current:
1552 [ + - ]: 16 : nPos = sal::static_int_cast< off_t >(pImpl->getPos());
1553 [ # # ][ - + ]: 16 : if ((0 > nOffset) && (-1*nOffset > nPos))
1554 : 0 : return osl_File_E_INVAL;
1555 : : if (g_limit_off_t < (sal_Int64) nPos + nOffset)
1556 : : return osl_File_E_OVERFLOW;
1557 : 16 : break;
1558 : :
1559 : : case osl_Pos_End:
1560 [ + - ]: 3734 : nPos = sal::static_int_cast< off_t >(pImpl->getSize());
1561 [ # # ][ - + ]: 3734 : if ((0 > nOffset) && (-1*nOffset > nPos))
1562 : 0 : return osl_File_E_INVAL;
1563 : : if (g_limit_off_t < (sal_Int64) nPos + nOffset)
1564 : : return osl_File_E_OVERFLOW;
1565 : 3734 : break;
1566 : :
1567 : : default:
1568 : 0 : return osl_File_E_INVAL;
1569 : : }
1570 : :
1571 [ + - ]: 867097 : return pImpl->setPos (nPos + nOffset);
1572 : : }
1573 : :
1574 : : /****************************************************************************
1575 : : * osl_getFileSize
1576 : : ****************************************************************************/
1577 : : oslFileError
1578 : 119069 : SAL_CALL osl_getFileSize( oslFileHandle Handle, sal_uInt64* pSize )
1579 : : {
1580 : 119069 : FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1581 : :
1582 [ + - ][ + - ]: 119069 : if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pSize))
[ + - ][ - + ]
1583 : 0 : return osl_File_E_INVAL;
1584 : :
1585 : 119069 : FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1586 [ + - ]: 119069 : *pSize = pImpl->getSize();
1587 : 119069 : return osl_File_E_None;
1588 : : }
1589 : :
1590 : : /************************************************
1591 : : * osl_setFileSize
1592 : : ***********************************************/
1593 : : oslFileError
1594 : 12244 : SAL_CALL osl_setFileSize( oslFileHandle Handle, sal_uInt64 uSize )
1595 : : {
1596 : 12244 : FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1597 : :
1598 [ + - ][ - + ]: 12244 : if ((0 == pImpl) || (-1 == pImpl->m_fd))
1599 : 0 : return osl_File_E_INVAL;
1600 [ - + ]: 12244 : if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
1601 : 0 : return osl_File_E_BADF;
1602 : :
1603 : : static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
1604 [ - + ]: 12244 : if (g_limit_off_t < uSize)
1605 : 0 : return osl_File_E_OVERFLOW;
1606 : :
1607 : 12244 : oslFileError result = pImpl->syncFile();
1608 [ - + ]: 12244 : if (result != osl_File_E_None)
1609 : 0 : return (result);
1610 : 12244 : pImpl->m_bufptr = -1, pImpl->m_buflen = 0;
1611 : :
1612 : 12244 : return pImpl->setSize (uSize);
1613 : : }
1614 : :
1615 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|