File: | sal/osl/unx/file.cxx |
Location: | line 746, column 9 |
Description: | Null pointer passed as an argument to a 'nonnull' parameter |
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 | ******************************************************************/ | |||
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 | FileHandle_Impl::Allocator::get() | |||
205 | { | |||
206 | static Allocator g_aBufferAllocator; | |||
207 | return g_aBufferAllocator; | |||
208 | } | |||
209 | ||||
210 | FileHandle_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 | } | |||
223 | FileHandle_Impl::Allocator::~Allocator() | |||
224 | { | |||
225 | rtl_cache_destroy (m_cache), m_cache = 0; | |||
226 | } | |||
227 | ||||
228 | 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")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 | } | |||
234 | void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer) | |||
235 | { | |||
236 | if (0 != pBuffer) | |||
237 | rtl_cache_free (m_cache, pBuffer); | |||
238 | } | |||
239 | ||||
240 | FileHandle_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 | } | |||
246 | FileHandle_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); | |||
250 | } | |||
251 | ||||
252 | 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 | 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 | } | |||
273 | FileHandle_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 | ||||
281 | void* FileHandle_Impl::operator new (size_t n) | |||
282 | { | |||
283 | return rtl_allocateMemory(n); | |||
284 | } | |||
285 | void FileHandle_Impl::operator delete (void * p) | |||
286 | { | |||
287 | rtl_freeMemory(p); | |||
288 | } | |||
289 | ||||
290 | 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 | return sal::static_int_cast< size_t >(::sysconf(_SC_PAGESIZE_SC_PAGESIZE)); | |||
297 | #endif /* xBSD || POSIX */ | |||
298 | } | |||
299 | ||||
300 | sal_uInt64 FileHandle_Impl::getPos() const | |||
301 | { | |||
302 | return sal::static_int_cast< sal_uInt64 >(m_fileptr); | |||
303 | } | |||
304 | ||||
305 | oslFileError 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 | ||||
312 | sal_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 | ||||
318 | oslFileError 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 | ||||
359 | 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")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 | ||||
426 | 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")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 | ||||
469 | oslFileError 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 | ||||
540 | oslFileError 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 | ||||
610 | oslFileError 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 | ||||
726 | oslFileError 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 | ||||
751 | oslFileError 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 | ||||
767 | oslFileHandle 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 | ******************************************************************/ | |||
801 | 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_NONBLOCK04000); | |||
823 | } | |||
824 | } | |||
825 | #endif /* MACOSX */ | |||
826 | ||||
827 | (void) path; | |||
828 | return flags; | |||
829 | } | |||
830 | ||||
831 | /**************************************************************************** | |||
832 | * osl_file_queryLocking | |||
833 | ***************************************************************************/ | |||
834 | struct 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 | }; | |||
844 | static 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 | ||||
859 | static oslFileError | |||
860 | osl_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 | ||||
882 | oslFileError | |||
883 | SAL_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 | ||||
901 | oslFileError | |||
902 | 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_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 | ||||
1089 | oslFileError | |||
1090 | SAL_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 | /****************************************************************************/ | |||
1114 | oslFileError | |||
1115 | SAL_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 | ***********************************************/ | |||
1156 | oslFileError | |||
1157 | SAL_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 | ***********************************************/ | |||
1182 | oslFileError | |||
1183 | SAL_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 | ********************************************/ | |||
1200 | oslFileError | |||
1201 | 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 | 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 | ||||
1289 | static | |||
1290 | oslFileError | |||
1291 | unmapFile (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 | ********************************************/ | |||
1317 | oslFileError | |||
1318 | SAL_CALL osl_unmapFile (void* pAddr, sal_uInt64 uLength) | |||
1319 | { | |||
1320 | return unmapFile (pAddr, uLength); | |||
1321 | } | |||
1322 | ||||
1323 | #endif | |||
1324 | ||||
1325 | /******************************************* | |||
1326 | osl_unmapMappedFile | |||
1327 | ********************************************/ | |||
1328 | oslFileError | |||
1329 | SAL_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 | ********************************************/ | |||
1347 | oslFileError | |||
1348 | SAL_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 | ********************************************/ | |||
1370 | oslFileError | |||
1371 | SAL_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 | ********************************************/ | |||
1399 | oslFileError | |||
1400 | SAL_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 | ********************************************/ | |||
1430 | oslFileError | |||
1431 | SAL_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 | ********************************************/ | |||
1463 | oslFileError | |||
1464 | 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 | 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 | /****************************************************************************/ | |||
1498 | oslFileError | |||
1499 | SAL_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 | ***********************************************/ | |||
1514 | oslFileError | |||
1515 | SAL_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 | ********************************************/ | |||
1530 | oslFileError | |||
1531 | SAL_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 | ****************************************************************************/ | |||
1577 | oslFileError | |||
1578 | SAL_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 | ***********************************************/ | |||
1593 | oslFileError | |||
1594 | SAL_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: */ |