Bug Summary

File:sal/osl/unx/file.cxx
Location:line 249, column 12
Description:Null pointer passed as an argument to a 'nonnull' parameter

Annotated 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( stderrstderr, 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 ******************************************************************/
80struct 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
203FileHandle_Impl::Allocator &
204FileHandle_Impl::Allocator::get()
205{
206 static Allocator g_aBufferAllocator;
207 return g_aBufferAllocator;
208}
209
210FileHandle_Impl::Allocator::Allocator()
211 : m_cache (0),
212 m_bufsiz (0)
213{
214 size_t const pagesize = FileHandle_Impl::getpagesize();
215 if (size_t(-1) != pagesize)
216 {
217 m_cache = rtl_cache_create (
218 "osl_file_buffer_cache", pagesize, 0, 0, 0, 0, 0, 0, 0);
219 if (0 != m_cache)
220 m_bufsiz = pagesize;
221 }
222}
223FileHandle_Impl::Allocator::~Allocator()
224{
225 rtl_cache_destroy (m_cache), m_cache = 0;
226}
227
228void FileHandle_Impl::Allocator::allocate (sal_uInt8 ** ppBuffer, size_t * pnSize)
229{
230 OSL_PRECOND((0 != ppBuffer) && (0 != pnSize), "FileHandle_Impl::Allocator::allocate(): contract violation")do { if (true && (!((0 != ppBuffer) && (0 != pnSize
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx" ":" "230"
": "), "%s", "FileHandle_Impl::Allocator::allocate(): contract violation"
); } } while (false)
;
231 if ((0 != ppBuffer) && (0 != pnSize))
232 *ppBuffer = static_cast< sal_uInt8* >(rtl_cache_alloc(m_cache)), *pnSize = m_bufsiz;
233}
234void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer)
235{
236 if (0 != pBuffer)
237 rtl_cache_free (m_cache, pBuffer);
238}
239
240FileHandle_Impl::Guard::Guard(pthread_mutex_t * pMutex)
241 : m_mutex (pMutex)
242{
243 OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::Guard(): null pointer.")do { if (true && (!(m_mutex != 0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "243" ": "), "%s", "FileHandle_Impl::Guard::Guard(): null pointer."
); } } while (false)
;
244 (void) pthread_mutex_lock (m_mutex); // ignoring EINVAL ...
245}
246FileHandle_Impl::Guard::~Guard()
247{
248 OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::~Guard(): null pointer.")do { if (true && (!(m_mutex != 0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "248" ": "), "%s", "FileHandle_Impl::Guard::~Guard(): null pointer."
); } } while (false)
;
249 (void) pthread_mutex_unlock (m_mutex);
Null pointer passed as an argument to a 'nonnull' parameter
250}
251
252FileHandle_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 m_buffer (0)
264{
265 (void) pthread_mutex_init(&m_mutex, 0);
266 rtl_string_newFromStr (&m_strFilePath, path);
267 if (m_kind == KIND_FD) {
268 Allocator::get().allocate (&m_buffer, &m_bufsiz);
269 if (0 != m_buffer)
270 memset (m_buffer, 0, m_bufsiz);
271 }
272}
273FileHandle_Impl::~FileHandle_Impl()
274{
275 if (m_kind == KIND_FD)
276 Allocator::get().deallocate (m_buffer), m_buffer = 0;
277 rtl_string_release (m_strFilePath), m_strFilePath = 0;
278 (void) pthread_mutex_destroy(&m_mutex); // ignoring EBUSY ...
279}
280
281void* FileHandle_Impl::operator new (size_t n)
282{
283 return rtl_allocateMemory(n);
284}
285void FileHandle_Impl::operator delete (void * p)
286{
287 rtl_freeMemory(p);
288}
289
290size_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 return sal::static_int_cast< size_t >(::sysconf(_SC_PAGESIZE_SC_PAGESIZE));
297#endif /* xBSD || POSIX */
298}
299
300sal_uInt64 FileHandle_Impl::getPos() const
301{
302 return sal::static_int_cast< sal_uInt64 >(m_fileptr);
303}
304
305oslFileError FileHandle_Impl::setPos (sal_uInt64 uPos)
306{
307 OSL_FILE_TRACE("FileHandle_Impl::setPos(%d, %lld) => %lld", m_fd, getPos(), uPos);
308 m_fileptr = sal::static_int_cast< off_t >(uPos);
309 return osl_File_E_None;
310}
311
312sal_uInt64 FileHandle_Impl::getSize() const
313{
314 off_t const bufend = std::max((off_t)(0), m_bufptr) + m_buflen;
315 return std::max(m_size, sal::static_int_cast< sal_uInt64 >(bufend));
316}
317
318oslFileError FileHandle_Impl::setSize (sal_uInt64 uSize)
319{
320 off_t const nSize = sal::static_int_cast< off_t >(uSize);
321 if (-1 == ftruncate (m_fd, nSize))
322 {
323 /* Failure. Save original result. Try fallback algorithm */
324 oslFileError result = oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), errno(*__errno_location ()));
325
326 /* Check against current size. Fail upon 'shrink' */
327 if (uSize <= getSize())
328 {
329 /* Failure upon 'shrink'. Return original result */
330 return (result);
331 }
332
333 /* Save current position */
334 off_t const nCurPos = (off_t)lseek (m_fd, (off_t)0, SEEK_CUR1);
335 if (nCurPos == (off_t)(-1))
336 return (result);
337
338 /* Try 'expand' via 'lseek()' and 'write()' */
339 if (-1 == lseek (m_fd, (off_t)(nSize - 1), SEEK_SET0))
340 return (result);
341
342 if (-1 == write (m_fd, (char*)"", (size_t)1))
343 {
344 /* Failure. Restore saved position */
345 (void) lseek (m_fd, (off_t)(nCurPos), SEEK_SET0);
346 return (result);
347 }
348
349 /* Success. Restore saved position */
350 if (-1 == lseek (m_fd, (off_t)nCurPos, SEEK_SET0))
351 return (result);
352 }
353
354 OSL_FILE_TRACE("osl_setFileSize(%d, %lld) => %ld", m_fd, getSize(), nSize);
355 m_size = sal::static_int_cast< sal_uInt64 >(nSize);
356 return osl_File_E_None;
357}
358
359oslFileError 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")do { if (true && (!((m_state & STATE_SEEKABLE))))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx" ":" "365"
": "), "%s", "FileHandle_Impl::readAt(): not seekable"); } }
while (false)
;
366 if (!(m_state & STATE_SEEKABLE))
367 return osl_File_E_SPIPE;
368
369 OSL_PRECOND((m_state & STATE_READABLE), "FileHandle_Impl::readAt(): not readable")do { if (true && (!((m_state & STATE_READABLE))))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx" ":" "369"
": "), "%s", "FileHandle_Impl::readAt(): not readable"); } }
while (false)
;
370 if (!(m_state & STATE_READABLE))
371 return osl_File_E_BADF;
372
373 if (m_kind == KIND_MEM)
374 {
375 ssize_t nBytes;
376
377 m_offset = nOffset;
378
379 if ((sal_uInt64) m_offset >= m_size)
380 nBytes = 0;
381 else
382 {
383 nBytes = std::min(nBytesRequested, (size_t) (m_size - m_offset));
384 memmove(pBuffer, m_buffer + m_offset, nBytes);
385 m_offset += nBytes;
386 }
387 *pBytesRead = nBytes;
388 return osl_File_E_None;
389 }
390
391#if defined(LINUX1) || defined(SOLARIS)
392
393 ssize_t nBytes = ::pread (m_fd, pBuffer, nBytesRequested, nOffset);
394 if ((-1 == nBytes) && (EOVERFLOW75 == errno(*__errno_location ())))
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 nBytes = 0;
401 }
402 if (-1 == nBytes)
403 return oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), errno(*__errno_location ()));
404
405#else /* !(LINUX || SOLARIS) */
406
407 if (nOffset != m_offset)
408 {
409 if (-1 == ::lseek (m_fd, nOffset, SEEK_SET0))
410 return oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), errno(*__errno_location ()));
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((sal_Bool)1), errno(*__errno_location ()));
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 *pBytesRead = nBytes;
423 return osl_File_E_None;
424}
425
426oslFileError 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")do { if (true && (!((m_state & STATE_SEEKABLE))))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx" ":" "432"
": "), "%s", "FileHandle_Impl::writeAt(): not seekable"); } }
while (false)
;
433 if (!(m_state & STATE_SEEKABLE))
434 return osl_File_E_SPIPE;
435
436 OSL_PRECOND((m_state & STATE_WRITEABLE), "FileHandle_Impl::writeAt(): not writeable")do { if (true && (!((m_state & STATE_WRITEABLE)))
) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx" ":" "436"
": "), "%s", "FileHandle_Impl::writeAt(): not writeable"); }
} while (false)
;
437 if (!(m_state & STATE_WRITEABLE))
438 return osl_File_E_BADF;
439
440#if defined(LINUX1) || defined(SOLARIS)
441
442 ssize_t nBytes = ::pwrite (m_fd, pBuffer, nBytesToWrite, nOffset);
443 if (-1 == nBytes)
444 return oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), errno(*__errno_location ()));
445
446#else /* !(LINUX || SOLARIS) */
447
448 if (nOffset != m_offset)
449 {
450 if (-1 == ::lseek (m_fd, nOffset, SEEK_SET0))
451 return oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), errno(*__errno_location ()));
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((sal_Bool)1), errno(*__errno_location ()));
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 m_size = std::max (m_size, sal::static_int_cast< sal_uInt64 >(nOffset + nBytes));
464
465 *pBytesWritten = nBytes;
466 return osl_File_E_None;
467}
468
469oslFileError FileHandle_Impl::readFileAt (
470 off_t nOffset,
471 void * pBuffer,
472 size_t nBytesRequested,
473 sal_uInt64 * pBytesRead)
474{
475 if (0 == (m_state & STATE_SEEKABLE))
476 {
477 // not seekable (pipe)
478 ssize_t nBytes = ::read (m_fd, pBuffer, nBytesRequested);
479 if (-1 == nBytes)
480 return oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), errno(*__errno_location ()));
481 *pBytesRead = nBytes;
482 return osl_File_E_None;
483 }
484 else if (m_kind == KIND_MEM || 0 == m_buffer)
485 {
486 // not buffered
487 return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
488 }
489 else
490 {
491 sal_uInt8 * buffer = static_cast<sal_uInt8*>(pBuffer);
492 for (*pBytesRead = 0; nBytesRequested > 0; )
493 {
494 off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
495 size_t const bufpos = (nOffset % m_bufsiz);
496
497 if (bufptr != m_bufptr)
498 {
499 // flush current buffer
500 oslFileError result = syncFile();
501 if (result != osl_File_E_None)
502 return (result);
503 m_bufptr = -1, m_buflen = 0;
504
505 if (nBytesRequested >= m_bufsiz)
506 {
507 // buffer too small, read through from file
508 sal_uInt64 uDone = 0;
509 result = readAt (nOffset, &(buffer[*pBytesRead]), nBytesRequested, &uDone);
510 if (result != osl_File_E_None)
511 return (result);
512
513 nBytesRequested -= uDone, *pBytesRead += uDone;
514 return osl_File_E_None;
515 }
516
517 // update buffer (pointer)
518 sal_uInt64 uDone = 0;
519 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
520 if (result != osl_File_E_None)
521 return (result);
522 m_bufptr = bufptr, m_buflen = uDone;
523 }
524 if (bufpos >= m_buflen)
525 {
526 // end of file
527 return osl_File_E_None;
528 }
529
530 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 memcpy (&(buffer[*pBytesRead]), &(m_buffer[bufpos]), bytes);
534 nBytesRequested -= bytes, *pBytesRead += bytes, nOffset += bytes;
535 }
536 return osl_File_E_None;
537 }
538}
539
540oslFileError FileHandle_Impl::writeFileAt (
541 off_t nOffset,
542 void const * pBuffer,
543 size_t nBytesToWrite,
544 sal_uInt64 * pBytesWritten)
545{
546 if (0 == (m_state & STATE_SEEKABLE))
547 {
548 // not seekable (pipe)
549 ssize_t nBytes = ::write (m_fd, pBuffer, nBytesToWrite);
550 if (-1 == nBytes)
551 return oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), errno(*__errno_location ()));
552 *pBytesWritten = nBytes;
553 return osl_File_E_None;
554 }
555 else if (0 == m_buffer)
556 {
557 // not buffered
558 return writeAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten);
559 }
560 else
561 {
562 sal_uInt8 const * buffer = static_cast<sal_uInt8 const *>(pBuffer);
563 for (*pBytesWritten = 0; nBytesToWrite > 0; )
564 {
565 off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
566 size_t const bufpos = (nOffset % m_bufsiz);
567 if (bufptr != m_bufptr)
568 {
569 // flush current buffer
570 oslFileError result = syncFile();
571 if (result != osl_File_E_None)
572 return (result);
573 m_bufptr = -1, m_buflen = 0;
574
575 if (nBytesToWrite >= m_bufsiz)
576 {
577 // buffer to small, write through to file
578 sal_uInt64 uDone = 0;
579 result = writeAt (nOffset, &(buffer[*pBytesWritten]), nBytesToWrite, &uDone);
580 if (result != osl_File_E_None)
581 return (result);
582 if (uDone != nBytesToWrite)
583 return osl_File_E_IO;
584
585 nBytesToWrite -= uDone, *pBytesWritten += uDone;
586 return osl_File_E_None;
587 }
588
589 // update buffer (pointer)
590 sal_uInt64 uDone = 0;
591 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
592 if (result != osl_File_E_None)
593 return (result);
594 m_bufptr = bufptr, m_buflen = uDone;
595 }
596
597 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 memcpy (&(m_buffer[bufpos]), &(buffer[*pBytesWritten]), bytes);
601 nBytesToWrite -= bytes, *pBytesWritten += bytes, nOffset += bytes;
602
603 m_buflen = std::max(m_buflen, bufpos + bytes);
604 m_state |= STATE_MODIFIED;
605 }
606 return osl_File_E_None;
607 }
608}
609
610oslFileError FileHandle_Impl::readLineAt (
611 off_t nOffset,
612 sal_Sequence ** ppSequence,
613 sal_uInt64 * pBytesRead)
614{
615 oslFileError result = osl_File_E_None;
616
617 off_t bufptr = nOffset / m_bufsiz * m_bufsiz;
618 if (bufptr != m_bufptr)
619 {
620 /* flush current buffer */
621 result = syncFile();
622 if (result != osl_File_E_None)
623 return (result);
624
625 /* update buffer (pointer) */
626 sal_uInt64 uDone = 0;
627 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
628 if (result != osl_File_E_None)
629 return (result);
630
631 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 size_t bufpos = nOffset - m_bufptr, curpos = bufpos, dstpos = 0;
639 int state = (bufpos >= m_buflen) ? LINE_STATE_LF : LINE_STATE_BEGIN;
640
641 for ( ; state != LINE_STATE_LF; )
642 {
643 if (curpos >= m_buflen)
644 {
645 /* buffer examined */
646 if (0 < (curpos - bufpos))
647 {
648 /* flush buffer to sequence */
649 result = writeSequence_Impl (
650 ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos);
651 if (result != osl_File_E_None)
652 return (result);
653 *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
654 }
655
656 bufptr = nOffset / m_bufsiz * m_bufsiz;
657 if (bufptr != m_bufptr)
658 {
659 /* update buffer (pointer) */
660 sal_uInt64 uDone = 0;
661 result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
662 if (result != osl_File_E_None)
663 return (result);
664 m_bufptr = bufptr, m_buflen = uDone;
665 }
666
667 bufpos = nOffset - m_bufptr, curpos = bufpos;
668 if (bufpos >= m_buflen)
669 break;
670 }
671 switch (state)
672 {
673 case LINE_STATE_CR:
674 state = LINE_STATE_LF;
675 switch (m_buffer[curpos])
676 {
677 case 0x0A: /* CRLF */
678 /* eat current char */
679 curpos++;
680 break;
681 default: /* single CR */
682 /* keep current char */
683 break;
684 }
685 break;
686 default:
687 /* determine next state */
688 switch (m_buffer[curpos])
689 {
690 case 0x0A: /* single LF */
691 state = LINE_STATE_LF;
692 break;
693 case 0x0D: /* CR */
694 state = LINE_STATE_CR;
695 break;
696 default: /* advance to next char */
697 curpos++;
698 break;
699 }
700 if (state != LINE_STATE_BEGIN)
701 {
702 /* skip the newline char */
703 curpos++;
704
705 /* flush buffer to sequence */
706 result = writeSequence_Impl (
707 ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos - 1);
708 if (result != osl_File_E_None)
709 return (result);
710 *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
711 }
712 break;
713 }
714 }
715
716 result = writeSequence_Impl (ppSequence, &dstpos, 0, 0);
717 if (result != osl_File_E_None)
718 return (result);
719 if (0 < dstpos)
720 return osl_File_E_None;
721 if (bufpos >= m_buflen)
722 return osl_File_E_AGAIN;
723 return osl_File_E_None;
724}
725
726oslFileError FileHandle_Impl::writeSequence_Impl (
727 sal_Sequence ** ppSequence,
728 size_t * pnOffset,
729 const void * pBuffer,
730 size_t nBytes)
731{
732 sal_Int32 nElements = *pnOffset + nBytes;
733 if (!*ppSequence)
734 {
735 /* construct sequence */
736 rtl_byte_sequence_constructNoDefault(ppSequence, nElements);
737 }
738 else if (nElements != (*ppSequence)->nElements)
739 {
740 /* resize sequence */
741 rtl_byte_sequence_realloc(ppSequence, nElements);
742 }
743 if (*ppSequence != 0)
744 {
745 /* fill sequence */
746 memcpy(&((*ppSequence)->elements[*pnOffset]), pBuffer, nBytes), *pnOffset += nBytes;
747 }
748 return (*ppSequence != 0) ? osl_File_E_None : osl_File_E_NOMEM;
749}
750
751oslFileError FileHandle_Impl::syncFile()
752{
753 oslFileError result = osl_File_E_None;
754 if (m_state & STATE_MODIFIED)
755 {
756 sal_uInt64 uDone = 0;
757 result = writeAt (m_bufptr, m_buffer, m_buflen, &uDone);
758 if (result != osl_File_E_None)
759 return (result);
760 if (uDone != m_buflen)
761 return osl_File_E_IO;
762 m_state &= ~STATE_MODIFIED;
763 }
764 return (result);
765}
766
767oslFileHandle osl::detail::createFileHandleFromFD( int fd )
768{
769 if (-1 == fd)
770 return 0; // EINVAL
771
772 struct stat aFileStat;
773 if (-1 == fstat (fd, &aFileStat))
774 return 0; // EBADF
775
776 FileHandle_Impl * pImpl = new FileHandle_Impl (fd);
777 if (0 == pImpl)
778 return 0; // ENOMEM
779
780 // assume writeable
781 pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE;
782 if (!S_ISREG(aFileStat.st_mode)((((aFileStat.st_mode)) & 0170000) == (0100000)))
783 {
784 /* not a regular file, mark not seekable */
785 pImpl->m_state &= ~FileHandle_Impl::STATE_SEEKABLE;
786 }
787 else
788 {
789 /* regular file, init current size */
790 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 return (oslFileHandle)(pImpl);
796}
797
798/*******************************************************************
799 * osl_file_adjustLockFlags
800 ******************************************************************/
801static 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_NONBLOCK04000);
823 }
824 }
825#endif /* MACOSX */
826
827 (void) path;
828 return flags;
829}
830
831/****************************************************************************
832 * osl_file_queryLocking
833 ***************************************************************************/
834struct Locking_Impl
835{
836 int m_enabled;
837 Locking_Impl() : m_enabled(0)
838 {
839#ifndef HAVE_O_EXLOCK
840 m_enabled = (getenv("SAL_ENABLE_FILE_LOCKING") != 0);
841#endif /* HAVE_O_EXLOCK */
842 }
843};
844static int osl_file_queryLocking (sal_uInt32 uFlags)
845{
846 if (!(uFlags & osl_File_OpenFlag_NoLock0x00000008L))
847 {
848 if ((uFlags & osl_File_OpenFlag_Write0x00000002L) || (uFlags & osl_File_OpenFlag_Create0x00000004L))
849 {
850 static Locking_Impl g_locking;
851 return (g_locking.m_enabled != 0);
852 }
853 }
854 return 0;
855}
856
857#ifdef UNX1
858
859static oslFileError
860osl_openMemoryAsFile( void *address, size_t size, oslFileHandle *pHandle, const char *path )
861{
862 oslFileError eRet;
863 FileHandle_Impl * pImpl = new FileHandle_Impl (-1, FileHandle_Impl::KIND_MEM, path);
864 if (!pImpl)
865 {
866 eRet = oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), ENOMEM12);
867 return eRet;
868 }
869 pImpl->m_size = sal::static_int_cast< sal_uInt64 >(size);
870
871 *pHandle = (oslFileHandle)(pImpl);
872
873 pImpl->m_bufptr = 0;
874 pImpl->m_buflen = size;
875
876 pImpl->m_bufsiz = size;
877 pImpl->m_buffer = (sal_uInt8*) address;
878
879 return osl_File_E_None;
880}
881
882oslFileError
883SAL_CALL osl_openMemoryAsFile( void *address, size_t size, oslFileHandle *pHandle )
884{
885 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( 02 ) ( O_RDWR02 | O_EXLOCK | O_NONBLOCK04000 )
895#define OPEN_CREATE_FLAGS( 0100 | 02 ) ( O_CREAT0100 | O_RDWR02 | O_EXLOCK | O_NONBLOCK04000 )
896#else
897#define OPEN_WRITE_FLAGS( 02 ) ( O_RDWR02 )
898#define OPEN_CREATE_FLAGS( 0100 | 02 ) ( O_CREAT0100 | O_RDWR02 )
899#endif
900
901oslFileError
902SAL_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_Write0x00000002L)
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)do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "916" ": "), "osl_openFile(%s, writeable), not possible!"
, cpFilePath); } } while (false)
;
917 errno(*__errno_location ()) = EPERM1;
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",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "924" ": "), "osl_openFile(%s) => %p", cpFilePath, address
); } } while (false)
924 cpFilePath, address)do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "924" ": "), "osl_openFile(%s) => %p", cpFilePath, address
); } } while (false)
;
925 if (address == NULL__null)
926 {
927 errno(*__errno_location ()) = ENOENT2;
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 int mode = S_IRUSR0400 | S_IRGRP(0400 >> 3) | S_IROTH((0400 >> 3) >> 3);
936 int flags = O_RDONLY00;
937 if (uFlags & osl_File_OpenFlag_Write0x00000002L)
938 {
939 mode |= S_IWUSR0200 | S_IWGRP(0200 >> 3) | S_IWOTH((0200 >> 3) >> 3);
940 flags = OPEN_WRITE_FLAGS( 02 );
941 }
942 if (uFlags & osl_File_OpenFlag_Create0x00000004L)
943 {
944 mode |= S_IWUSR0200 | S_IWGRP(0200 >> 3) | S_IWOTH((0200 >> 3) >> 3);
945 flags = OPEN_CREATE_FLAGS( 0100 | 02 );
946 }
947
948 /* Check for flags passed in from SvFileStream::Open() */
949 if (uFlags & osl_File_OpenFlag_Trunc0x00000010L)
950 flags |= O_TRUNC01000;
951 if (!(uFlags & osl_File_OpenFlag_NoExcl0x00000020L))
952 flags |= O_EXCL0200;
953
954 if (uFlags & osl_File_OpenFlag_NoLock0x00000008L)
955 {
956#ifdef HAVE_O_EXLOCK
957 flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK04000);
958#endif /* HAVE_O_EXLOCK */
959 }
960 else
961 {
962 flags = osl_file_adjustLockFlags (cpFilePath, flags);
963 }
964
965 /* open the file */
966 int fd = open( cpFilePath, flags, mode );
967 if (-1 == fd)
968 {
969 int saved_errno = errno(*__errno_location ());
970 OSL_TRACE("osl_openFile(%s, %s) failed: %s",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "973" ": "), "osl_openFile(%s, %s) failed: %s", cpFilePath
, flags & 02 ? "writeable":"readonly", strerror(saved_errno
)); } } while (false)
971 cpFilePath,do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "973" ": "), "osl_openFile(%s, %s) failed: %s", cpFilePath
, flags & 02 ? "writeable":"readonly", strerror(saved_errno
)); } } while (false)
972 flags & O_RDWR ? "writeable":"readonly",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "973" ": "), "osl_openFile(%s, %s) failed: %s", cpFilePath
, flags & 02 ? "writeable":"readonly", strerror(saved_errno
)); } } while (false)
973 strerror(saved_errno))do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "973" ": "), "osl_openFile(%s, %s) failed: %s", cpFilePath
, flags & 02 ? "writeable":"readonly", strerror(saved_errno
)); } } while (false)
;
974 return oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), saved_errno);
975 }
976
977 /* reset O_NONBLOCK flag */
978 if (flags & O_NONBLOCK04000)
979 {
980 int f = fcntl (fd, F_GETFL3, 0);
981 if (-1 == f)
982 {
983 int saved_errno = errno(*__errno_location ());
984 OSL_TRACE("osl_openFile(%s, %s): fcntl(%d, F_GETFL) failed: %s",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "988" ": "), "osl_openFile(%s, %s): fcntl(%d, F_GETFL) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
985 cpFilePath,do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "988" ": "), "osl_openFile(%s, %s): fcntl(%d, F_GETFL) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
986 flags & O_RDWR ? "writeable":"readonly",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "988" ": "), "osl_openFile(%s, %s): fcntl(%d, F_GETFL) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
987 fd,do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "988" ": "), "osl_openFile(%s, %s): fcntl(%d, F_GETFL) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
988 strerror(saved_errno))do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "988" ": "), "osl_openFile(%s, %s): fcntl(%d, F_GETFL) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
;
989 eRet = oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), saved_errno);
990 (void) close(fd);
991 return eRet;
992 }
993 if (-1 == fcntl (fd, F_SETFL4, (f & ~O_NONBLOCK04000)))
994 {
995 int saved_errno = errno(*__errno_location ());
996 OSL_TRACE("osl_openFile(%s, %s): fcntl(%d, F_SETFL) failed: %s",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1000" ": "), "osl_openFile(%s, %s): fcntl(%d, F_SETFL) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
997 cpFilePath,do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1000" ": "), "osl_openFile(%s, %s): fcntl(%d, F_SETFL) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
998 flags & O_RDWR ? "writeable":"readonly",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1000" ": "), "osl_openFile(%s, %s): fcntl(%d, F_SETFL) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
999 fd,do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1000" ": "), "osl_openFile(%s, %s): fcntl(%d, F_SETFL) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
1000 strerror(saved_errno))do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1000" ": "), "osl_openFile(%s, %s): fcntl(%d, F_SETFL) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
;
1001 eRet = oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), saved_errno);
1002 (void) close(fd);
1003 return eRet;
1004 }
1005 }
1006
1007 /* get file status (mode, size) */
1008 struct stat aFileStat;
1009 if (-1 == fstat (fd, &aFileStat))
1010 {
1011 int saved_errno = errno(*__errno_location ());
1012 OSL_TRACE("osl_openFile(%s, %s): fstat(%d) failed: %s",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1016" ": "), "osl_openFile(%s, %s): fstat(%d) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
1013 cpFilePath,do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1016" ": "), "osl_openFile(%s, %s): fstat(%d) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
1014 flags & O_RDWR ? "writeable":"readonly",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1016" ": "), "osl_openFile(%s, %s): fstat(%d) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
1015 fd,do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1016" ": "), "osl_openFile(%s, %s): fstat(%d) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
1016 strerror(saved_errno))do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1016" ": "), "osl_openFile(%s, %s): fstat(%d) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
;
1017 eRet = oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), saved_errno);
1018 (void) close(fd);
1019 return eRet;
1020 }
1021 if (!S_ISREG(aFileStat.st_mode)((((aFileStat.st_mode)) & 0170000) == (0100000)))
1022 {
1023 /* we only open regular files here */
1024 OSL_TRACE("osl_openFile(%s): not a regular file",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1025" ": "), "osl_openFile(%s): not a regular file", cpFilePath
); } } while (false)
1025 cpFilePath)do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1025" ": "), "osl_openFile(%s): not a regular file", cpFilePath
); } } while (false)
;
1026 (void) close(fd);
1027 return osl_File_E_INVAL;
1028 }
1029
1030 if (osl_file_queryLocking (uFlags))
1031 {
1032#ifdef MACOSX
1033 if (-1 == flock (fd, LOCK_EX2 | LOCK_NB4))
1034 {
1035 /* Mac OSX returns ENOTSUP for webdav drives. We should try read lock */
1036 if ((errno(*__errno_location ()) != ENOTSUP95) || ((-1 == flock (fd, LOCK_SH1 | LOCK_NB4)) && (errno(*__errno_location ()) != ENOTSUP95)))
1037 {
1038 eRet = oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), errno(*__errno_location ()));
1039 (void) close(fd);
1040 return eRet;
1041 }
1042 }
1043#else /* F_SETLK */
1044 {
1045 struct flock aflock;
1046
1047 aflock.l_type = F_WRLCK1;
1048 aflock.l_whence = SEEK_SET0;
1049 aflock.l_start = 0;
1050 aflock.l_len = 0;
1051
1052 if (-1 == fcntl (fd, F_SETLK13, &aflock))
1053 {
1054 int saved_errno = errno(*__errno_location ());
1055 OSL_TRACE("osl_openFile(%s, %s): fcntl(%d, F_SETLK) failed: %s",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1059" ": "), "osl_openFile(%s, %s): fcntl(%d, F_SETLK) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
1056 cpFilePath,do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1059" ": "), "osl_openFile(%s, %s): fcntl(%d, F_SETLK) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
1057 flags & O_RDWR ? "writeable":"readonly",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1059" ": "), "osl_openFile(%s, %s): fcntl(%d, F_SETLK) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
1058 fd,do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1059" ": "), "osl_openFile(%s, %s): fcntl(%d, F_SETLK) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
1059 strerror(saved_errno))do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1059" ": "), "osl_openFile(%s, %s): fcntl(%d, F_SETLK) failed: %s"
, cpFilePath, flags & 02 ? "writeable":"readonly", fd, strerror
(saved_errno)); } } while (false)
;
1060 eRet = oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), saved_errno);
1061 (void) close(fd);
1062 return eRet;
1063 }
1064 }
1065#endif /* F_SETLK */
1066 }
1067
1068 /* allocate memory for impl structure */
1069 FileHandle_Impl * pImpl = new FileHandle_Impl (fd, FileHandle_Impl::KIND_FD, cpFilePath);
1070 if (!pImpl)
1071 {
1072 eRet = oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), ENOMEM12);
1073 (void) close(fd);
1074 return eRet;
1075 }
1076 if (flags & O_RDWR02)
1077 pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE;
1078 pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size);
1079
1080 OSL_TRACE("osl_openFile(%s, %s) => %d",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1083" ": "), "osl_openFile(%s, %s) => %d", rtl_string_getStr
(pImpl->m_strFilePath), flags & 02 ? "writeable":"readonly"
, pImpl->m_fd); } } while (false)
1081 rtl_string_getStr(pImpl->m_strFilePath),do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1083" ": "), "osl_openFile(%s, %s) => %d", rtl_string_getStr
(pImpl->m_strFilePath), flags & 02 ? "writeable":"readonly"
, pImpl->m_fd); } } while (false)
1082 flags & O_RDWR ? "writeable":"readonly",do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1083" ": "), "osl_openFile(%s, %s) => %d", rtl_string_getStr
(pImpl->m_strFilePath), flags & 02 ? "writeable":"readonly"
, pImpl->m_fd); } } while (false)
1083 pImpl->m_fd)do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1083" ": "), "osl_openFile(%s, %s) => %d", rtl_string_getStr
(pImpl->m_strFilePath), flags & 02 ? "writeable":"readonly"
, pImpl->m_fd); } } while (false)
;
1084
1085 *pHandle = (oslFileHandle)(pImpl);
1086 return osl_File_E_None;
1087}
1088
1089oslFileError
1090SAL_CALL osl_openFile( rtl_uString* ustrFileURL, oslFileHandle* pHandle, sal_uInt32 uFlags )
1091{
1092 oslFileError eRet;
1093
1094 if ((ustrFileURL == 0) || (ustrFileURL->length == 0) || (pHandle == 0))
1095 return osl_File_E_INVAL;
1096
1097 /* convert file URL to system path */
1098 char buffer[PATH_MAX4096];
1099 eRet = FileURLToPath (buffer, sizeof(buffer), ustrFileURL);
1100 if (eRet != osl_File_E_None)
1101 return eRet;
1102
1103#ifdef MACOSX
1104 if (macxp_resolveAlias (buffer, sizeof(buffer)) != 0)
1105 return oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), errno(*__errno_location ()));
1106#endif /* MACOSX */
1107
1108 return osl_openFilePath (buffer, pHandle, uFlags);
1109}
1110
1111/****************************************************************************/
1112/* osl_closeFile */
1113/****************************************************************************/
1114oslFileError
1115SAL_CALL osl_closeFile( oslFileHandle Handle )
1116{
1117 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1118
1119 if (pImpl == 0)
1120 return osl_File_E_INVAL;
1121
1122 OSL_TRACE("osl_closeFile(%s:%d)", rtl_string_getStr(pImpl->m_strFilePath), pImpl->m_fd)do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1122" ": "), "osl_closeFile(%s:%d)", rtl_string_getStr(
pImpl->m_strFilePath), pImpl->m_fd); } } while (false)
;
1123
1124 if (pImpl->m_kind == FileHandle_Impl::KIND_MEM)
1125 {
1126 delete pImpl;
1127 return osl_File_E_None;
1128 }
1129
1130 if (pImpl->m_fd < 0)
1131 return osl_File_E_INVAL;
1132
1133 (void) pthread_mutex_lock (&(pImpl->m_mutex));
1134
1135 /* close(2) implicitly (and unconditionally) unlocks */
1136 oslFileError result = pImpl->syncFile();
1137 if (result != osl_File_E_None)
1138 {
1139 /* close, ignoring double failure */
1140 (void) close (pImpl->m_fd);
1141 }
1142 else if (-1 == close (pImpl->m_fd))
1143 {
1144 /* translate error code */
1145 result = oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), errno(*__errno_location ()));
1146 }
1147
1148 (void) pthread_mutex_unlock (&(pImpl->m_mutex));
1149 delete pImpl;
1150 return (result);
1151}
1152
1153/************************************************
1154 * osl_syncFile
1155 ***********************************************/
1156oslFileError
1157SAL_CALL osl_syncFile(oslFileHandle Handle)
1158{
1159 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1160
1161 if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)))
1162 return osl_File_E_INVAL;
1163
1164 if (pImpl->m_kind == FileHandle_Impl::KIND_MEM)
1165 return osl_File_E_None;
1166
1167 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1168
1169 OSL_TRACE("osl_syncFile(%d)", pImpl->m_fd)do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1169" ": "), "osl_syncFile(%d)", pImpl->m_fd); } } while
(false)
;
1170 oslFileError result = pImpl->syncFile();
1171 if (result != osl_File_E_None)
1172 return (result);
1173 if (-1 == fsync (pImpl->m_fd))
1174 return oslTranslateFileError (OSL_FET_ERROR((sal_Bool)1), errno(*__errno_location ()));
1175
1176 return osl_File_E_None;
1177}
1178
1179/************************************************
1180 * osl_fileGetOSHandle
1181 ***********************************************/
1182oslFileError
1183SAL_CALL osl_getFileOSHandle(
1184 oslFileHandle Handle,
1185 sal_IntPtr *piFileHandle )
1186{
1187 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1188
1189 if (0 == pImpl || pImpl->m_kind != FileHandle_Impl::KIND_FD || -1 == pImpl->m_fd)
1190 return osl_File_E_INVAL;
1191
1192 *piFileHandle = pImpl->m_fd;
1193
1194 return osl_File_E_None;
1195}
1196
1197/*******************************************
1198 osl_mapFile
1199********************************************/
1200oslFileError
1201SAL_CALL osl_mapFile (
1202 oslFileHandle Handle,
1203 void** ppAddr,
1204 sal_uInt64 uLength,
1205 sal_uInt64 uOffset,
1206 sal_uInt32 uFlags
1207)
1208{
1209 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1210
1211 if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == ppAddr))
1212 return osl_File_E_INVAL;
1213 *ppAddr = 0;
1214
1215 static sal_uInt64 const g_limit_size_t = std::numeric_limits< size_t >::max();
1216 if (g_limit_size_t < uLength)
1217 return osl_File_E_OVERFLOW;
1218 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 if (g_limit_off_t < uOffset)
1222 return osl_File_E_OVERFLOW;
1223
1224 if (pImpl->m_kind == FileHandle_Impl::KIND_MEM)
1225 {
1226 *ppAddr = pImpl->m_buffer + uOffset;
1227 return osl_File_E_None;
1228 }
1229
1230 off_t const nOffset = sal::static_int_cast< off_t >(uOffset);
1231
1232 void* p = mmap(NULL__null, nLength, PROT_READ0x1, MAP_SHARED0x01, pImpl->m_fd, nOffset);
1233 if (MAP_FAILED((void *) -1) == p)
1234 return oslTranslateFileError(OSL_FET_ERROR((sal_Bool)1), errno(*__errno_location ()));
1235 *ppAddr = p;
1236
1237 if (uFlags & osl_File_MapFlag_RandomAccess((sal_uInt32)(0x1)))
1238 {
1239 // Determine memory pagesize.
1240 size_t const nPageSize = FileHandle_Impl::getpagesize();
1241 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 sal_uInt8 * pData (reinterpret_cast<sal_uInt8*>(*ppAddr));
1248 size_t nSize (nLength);
1249
1250 volatile sal_uInt8 c = 0;
1251 while (nSize > nPageSize)
1252 {
1253 c ^= pData[0];
1254 pData += nPageSize;
1255 nSize -= nPageSize;
1256 }
1257 if (nSize > 0)
1258 {
1259 c^= pData[0];
1260 }
1261 }
1262 }
1263 if (uFlags & osl_File_MapFlag_WillNeed((sal_uInt32)(0x2)))
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_WILLNEED3);
1274 if (e != 0)
1275 {
1276 OSL_TRACE(do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1277" ": "), "posix_madvise(..., POSIX_MADV_WILLNEED) failed with %d"
, e); } } while (false)
1277 "posix_madvise(..., POSIX_MADV_WILLNEED) failed with %d", e)do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1277" ": "), "posix_madvise(..., POSIX_MADV_WILLNEED) failed with %d"
, e); } } while (false)
;
1278 }
1279#elif defined SOLARIS
1280 if (madvise(static_cast< caddr_t >(p), nLength, MADV_WILLNEED3) != 0)
1281 {
1282 OSL_TRACE("madvise(..., MADV_WILLNEED) failed with %d", errno)do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/sal/osl/unx/file.cxx"
":" "1282" ": "), "madvise(..., MADV_WILLNEED) failed with %d"
, (*__errno_location ())); } } while (false)
;
1283 }
1284#endif
1285 }
1286 return osl_File_E_None;
1287}
1288
1289static
1290oslFileError
1291unmapFile (void* pAddr, sal_uInt64 uLength)
1292{
1293 if (0 == pAddr)
1294 return osl_File_E_INVAL;
1295
1296 static sal_uInt64 const g_limit_size_t = std::numeric_limits< size_t >::max();
1297 if (g_limit_size_t < uLength)
1298 return osl_File_E_OVERFLOW;
1299 size_t const nLength = sal::static_int_cast< size_t >(uLength);
1300
1301 if (-1 == munmap(static_cast<char*>(pAddr), nLength))
1302 return oslTranslateFileError(OSL_FET_ERROR((sal_Bool)1), errno(*__errno_location ()));
1303
1304 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********************************************/
1317oslFileError
1318SAL_CALL osl_unmapFile (void* pAddr, sal_uInt64 uLength)
1319{
1320 return unmapFile (pAddr, uLength);
1321}
1322
1323#endif
1324
1325/*******************************************
1326 osl_unmapMappedFile
1327********************************************/
1328oslFileError
1329SAL_CALL osl_unmapMappedFile (oslFileHandle Handle, void* pAddr, sal_uInt64 uLength)
1330{
1331 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
1332
1333 if (pImpl == 0)
1334 return osl_File_E_INVAL;
1335
1336 if (pImpl->m_kind == FileHandle_Impl::KIND_FD)
1337 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 return osl_File_E_None;
1342}
1343
1344/*******************************************
1345 osl_readLine
1346********************************************/
1347oslFileError
1348SAL_CALL osl_readLine (
1349 oslFileHandle Handle,
1350 sal_Sequence ** ppSequence)
1351{
1352 FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
1353
1354 if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == ppSequence))
1355 return osl_File_E_INVAL;
1356 sal_uInt64 uBytesRead = 0;
1357
1358 // read at current fileptr; fileptr += uBytesRead;
1359 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1360 oslFileError result = pImpl->readLineAt (
1361 pImpl->m_fileptr, ppSequence, &uBytesRead);
1362 if (result == osl_File_E_None)
1363 pImpl->m_fileptr += uBytesRead;
1364 return (result);
1365}
1366
1367/*******************************************
1368 osl_readFile
1369********************************************/
1370oslFileError
1371SAL_CALL osl_readFile (
1372 oslFileHandle Handle,
1373 void * pBuffer,
1374 sal_uInt64 uBytesRequested,
1375 sal_uInt64 * pBytesRead)
1376{
1377 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1378
1379 if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pBuffer) || (0 == pBytesRead))
1380 return osl_File_E_INVAL;
1381
1382 static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
1383 if (g_limit_ssize_t < uBytesRequested)
1384 return osl_File_E_OVERFLOW;
1385 size_t const nBytesRequested = sal::static_int_cast< size_t >(uBytesRequested);
1386
1387 // read at current fileptr; fileptr += *pBytesRead;
1388 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1389 oslFileError result = pImpl->readFileAt (
1390 pImpl->m_fileptr, pBuffer, nBytesRequested, pBytesRead);
1391 if (result == osl_File_E_None)
1392 pImpl->m_fileptr += *pBytesRead;
1393 return (result);
1394}
1395
1396/*******************************************
1397 osl_writeFile
1398********************************************/
1399oslFileError
1400SAL_CALL osl_writeFile (
1401 oslFileHandle Handle,
1402 const void * pBuffer,
1403 sal_uInt64 uBytesToWrite,
1404 sal_uInt64 * pBytesWritten)
1405{
1406 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1407
1408 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesWritten))
1409 return osl_File_E_INVAL;
1410 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
1411 return osl_File_E_BADF;
1412
1413 static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
1414 if (g_limit_ssize_t < uBytesToWrite)
1415 return osl_File_E_OVERFLOW;
1416 size_t const nBytesToWrite = sal::static_int_cast< size_t >(uBytesToWrite);
1417
1418 // write at current fileptr; fileptr += *pBytesWritten;
1419 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1420 oslFileError result = pImpl->writeFileAt (
1421 pImpl->m_fileptr, pBuffer, nBytesToWrite, pBytesWritten);
1422 if (result == osl_File_E_None)
1423 pImpl->m_fileptr += *pBytesWritten;
1424 return (result);
1425}
1426
1427/*******************************************
1428 osl_readFileAt
1429********************************************/
1430oslFileError
1431SAL_CALL osl_readFileAt (
1432 oslFileHandle Handle,
1433 sal_uInt64 uOffset,
1434 void* pBuffer,
1435 sal_uInt64 uBytesRequested,
1436 sal_uInt64* pBytesRead)
1437{
1438 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1439
1440 if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pBuffer) || (0 == pBytesRead))
1441 return osl_File_E_INVAL;
1442 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
1443 return osl_File_E_SPIPE;
1444
1445 static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
1446 if (g_limit_off_t < uOffset)
1447 return osl_File_E_OVERFLOW;
1448 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 if (g_limit_ssize_t < uBytesRequested)
1452 return osl_File_E_OVERFLOW;
1453 size_t const nBytesRequested = sal::static_int_cast< size_t >(uBytesRequested);
1454
1455 // read at specified fileptr
1456 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1457 return pImpl->readFileAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
1458}
1459
1460/*******************************************
1461 osl_writeFileAt
1462********************************************/
1463oslFileError
1464SAL_CALL osl_writeFileAt (
1465 oslFileHandle Handle,
1466 sal_uInt64 uOffset,
1467 const void* pBuffer,
1468 sal_uInt64 uBytesToWrite,
1469 sal_uInt64* pBytesWritten)
1470{
1471 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1472
1473 if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesWritten))
1474 return osl_File_E_INVAL;
1475 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
1476 return osl_File_E_SPIPE;
1477 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
1478 return osl_File_E_BADF;
1479
1480 static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
1481 if (g_limit_off_t < uOffset)
1482 return osl_File_E_OVERFLOW;
1483 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 if (g_limit_ssize_t < uBytesToWrite)
1487 return osl_File_E_OVERFLOW;
1488 size_t const nBytesToWrite = sal::static_int_cast< size_t >(uBytesToWrite);
1489
1490 // write at specified fileptr
1491 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1492 return pImpl->writeFileAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten);
1493}
1494
1495/****************************************************************************/
1496/* osl_isEndOfFile */
1497/****************************************************************************/
1498oslFileError
1499SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF )
1500{
1501 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1502
1503 if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pIsEOF))
1504 return osl_File_E_INVAL;
1505
1506 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1507 *pIsEOF = (pImpl->getPos() == pImpl->getSize());
1508 return osl_File_E_None;
1509}
1510
1511/************************************************
1512 * osl_getFilePos
1513 ***********************************************/
1514oslFileError
1515SAL_CALL osl_getFilePos( oslFileHandle Handle, sal_uInt64* pPos )
1516{
1517 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1518
1519 if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pPos))
1520 return osl_File_E_INVAL;
1521
1522 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1523 *pPos = pImpl->getPos();
1524 return osl_File_E_None;
1525}
1526
1527/*******************************************
1528 osl_setFilePos
1529********************************************/
1530oslFileError
1531SAL_CALL osl_setFilePos (oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uOffset)
1532{
1533 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1534
1535 if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)))
1536 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 off_t nPos = 0, nOffset = sal::static_int_cast< off_t >(uOffset);
1542
1543 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1544 switch(uHow)
1545 {
1546 case osl_Pos_Absolut1:
1547 if (0 > nOffset)
1548 return osl_File_E_INVAL;
1549 break;
1550
1551 case osl_Pos_Current2:
1552 nPos = sal::static_int_cast< off_t >(pImpl->getPos());
1553 if ((0 > nOffset) && (-1*nOffset > nPos))
1554 return osl_File_E_INVAL;
1555 if (g_limit_off_t < (sal_Int64) nPos + nOffset)
1556 return osl_File_E_OVERFLOW;
1557 break;
1558
1559 case osl_Pos_End3:
1560 nPos = sal::static_int_cast< off_t >(pImpl->getSize());
1561 if ((0 > nOffset) && (-1*nOffset > nPos))
1562 return osl_File_E_INVAL;
1563 if (g_limit_off_t < (sal_Int64) nPos + nOffset)
1564 return osl_File_E_OVERFLOW;
1565 break;
1566
1567 default:
1568 return osl_File_E_INVAL;
1569 }
1570
1571 return pImpl->setPos (nPos + nOffset);
1572}
1573
1574/****************************************************************************
1575 * osl_getFileSize
1576 ****************************************************************************/
1577oslFileError
1578SAL_CALL osl_getFileSize( oslFileHandle Handle, sal_uInt64* pSize )
1579{
1580 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1581
1582 if ((0 == pImpl) || ((pImpl->m_kind == FileHandle_Impl::KIND_FD) && (-1 == pImpl->m_fd)) || (0 == pSize))
1583 return osl_File_E_INVAL;
1584
1585 FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
1586 *pSize = pImpl->getSize();
1587 return osl_File_E_None;
1588}
1589
1590/************************************************
1591 * osl_setFileSize
1592 ***********************************************/
1593oslFileError
1594SAL_CALL osl_setFileSize( oslFileHandle Handle, sal_uInt64 uSize )
1595{
1596 FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
1597
1598 if ((0 == pImpl) || (-1 == pImpl->m_fd))
1599 return osl_File_E_INVAL;
1600 if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
1601 return osl_File_E_BADF;
1602
1603 static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
1604 if (g_limit_off_t < uSize)
1605 return osl_File_E_OVERFLOW;
1606
1607 oslFileError result = pImpl->syncFile();
1608 if (result != osl_File_E_None)
1609 return (result);
1610 pImpl->m_bufptr = -1, pImpl->m_buflen = 0;
1611
1612 return pImpl->setSize (uSize);
1613}
1614
1615/* vim:set shiftwidth=4 softtabstop=4 expandtab: */