Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "osl/file.hxx"
30 : : #include "osl/detail/file.h"
31 : :
32 : : #include "osl/diagnose.h"
33 : : #include "osl/thread.h"
34 : : #include <osl/signal.h>
35 : : #include "rtl/alloc.h"
36 : :
37 : : #include "system.h"
38 : : #include "file_impl.hxx"
39 : : #include "file_error_transl.h"
40 : : #include "file_path_helper.hxx"
41 : : #include "file_url.h"
42 : : #include "uunxapi.hxx"
43 : : #include "readwrite_helper.h"
44 : :
45 : : #include <sys/types.h>
46 : : #include <errno.h>
47 : : #include <dirent.h>
48 : : #include <limits.h>
49 : : #include <stdio.h>
50 : : #include <string.h>
51 : : #include <unistd.h>
52 : : #include <sys/stat.h>
53 : : #include <sys/mman.h>
54 : :
55 : : #include <algorithm>
56 : :
57 : : #ifdef ANDROID
58 : : #include <osl/detail/android-bootstrap.h>
59 : : #endif
60 : :
61 : : /************************************************************************
62 : : * ToDo
63 : : *
64 : : * - Fix: check for corresponding struct sizes in exported functions
65 : : * - check size/use of oslDirectory
66 : : * - check size/use of oslDirectoryItem
67 : : ***********************************************************************/
68 : : /******************************************************************************
69 : : *
70 : : * Data Type Definition
71 : : *
72 : : ******************************************************************************/
73 : :
74 : : typedef struct
75 : : {
76 : : rtl_uString* ustrPath; /* holds native directory path */
77 : : DIR* pDirStruct;
78 : : #ifdef ANDROID
79 : : enum Kind
80 : : {
81 : : KIND_DIRENT = 1,
82 : : KIND_ASSETS = 2
83 : : };
84 : : int eKind;
85 : : lo_apk_dir* pApkDirStruct;
86 : : #endif
87 : : } oslDirectoryImpl;
88 : :
89 : 304784 : DirectoryItem_Impl::DirectoryItem_Impl(
90 : : rtl_uString * ustrFilePath, unsigned char DType)
91 : : : m_RefCount (1),
92 : : m_ustrFilePath (ustrFilePath),
93 : 304784 : m_DType (DType)
94 : : {
95 [ + - ]: 304784 : if (m_ustrFilePath != 0)
96 : 304784 : rtl_uString_acquire(m_ustrFilePath);
97 : 304784 : }
98 : 304784 : DirectoryItem_Impl::~DirectoryItem_Impl()
99 : : {
100 [ + - ]: 304784 : if (m_ustrFilePath != 0)
101 : 304784 : rtl_uString_release(m_ustrFilePath);
102 : 304784 : }
103 : :
104 : 304784 : void * DirectoryItem_Impl::operator new(size_t n)
105 : : {
106 : 304784 : return rtl_allocateMemory(n);
107 : : }
108 : 304784 : void DirectoryItem_Impl::operator delete(void * p)
109 : : {
110 : 304784 : rtl_freeMemory(p);
111 : 304784 : }
112 : :
113 : 0 : void DirectoryItem_Impl::acquire()
114 : : {
115 : 0 : ++m_RefCount;
116 : 0 : }
117 : 304784 : void DirectoryItem_Impl::release()
118 : : {
119 [ + - ]: 304784 : if (0 == --m_RefCount)
120 [ + - ]: 304784 : delete this;
121 : 304784 : }
122 : :
123 : 370040 : oslFileType DirectoryItem_Impl::getFileType() const
124 : : {
125 [ + + + - : 370040 : switch (m_DType)
- - + ]
126 : : {
127 : : #ifdef _DIRENT_HAVE_D_TYPE
128 : : case DT_LNK:
129 : 21098 : return osl_File_Type_Link;
130 : : case DT_DIR:
131 : 14592 : return osl_File_Type_Directory;
132 : : case DT_REG:
133 : 185360 : return osl_File_Type_Regular;
134 : : case DT_FIFO:
135 : 0 : return osl_File_Type_Fifo;
136 : : case DT_SOCK:
137 : 0 : return osl_File_Type_Socket;
138 : : case DT_CHR:
139 : : case DT_BLK:
140 : 0 : return osl_File_Type_Special;
141 : : #endif /* _DIRENT_HAVE_D_TYPE */
142 : : default:
143 : 148990 : break;
144 : : }
145 : 370040 : return osl_File_Type_Unknown;
146 : : }
147 : :
148 : : /******************************************************************************
149 : : *
150 : : * C-String Function Declarations
151 : : *
152 : : *****************************************************************************/
153 : :
154 : : static oslFileError osl_psz_createDirectory(const sal_Char* pszPath);
155 : : static oslFileError osl_psz_removeDirectory(const sal_Char* pszPath);
156 : :
157 : : /*******************************************************************
158 : : * osl_openDirectory
159 : : ******************************************************************/
160 : :
161 : 63262 : oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirectory* pDirectory)
162 : : {
163 : 63262 : rtl_uString* ustrSystemPath = NULL;
164 : : oslFileError eRet;
165 : :
166 : : char path[PATH_MAX];
167 : :
168 [ + - ][ + + ]: 63262 : if ((0 == ustrDirectoryURL) || (0 == ustrDirectoryURL->length) || (0 == pDirectory))
[ - + ]
169 : 1554 : return osl_File_E_INVAL;
170 : :
171 : : /* convert file URL to system path */
172 [ + - ]: 61708 : eRet = osl_getSystemPathFromFileURL_Ex(ustrDirectoryURL, &ustrSystemPath, sal_False);
173 : :
174 [ + + ]: 61708 : if( osl_File_E_None != eRet )
175 : 268 : return eRet;
176 : :
177 [ + - ]: 61440 : osl_systemPathRemoveSeparator(ustrSystemPath);
178 : :
179 : : /* convert unicode path to text */
180 [ + - ][ + - ]: 61440 : if ( UnicodeToText( path, PATH_MAX, ustrSystemPath->buffer, ustrSystemPath->length )
181 : : #ifdef MACOSX
182 : : && macxp_resolveAlias( path, PATH_MAX ) == 0
183 : : #endif /* MACOSX */
184 : : )
185 : : {
186 : : #ifdef ANDROID
187 : : if( strncmp( path, "/assets/", sizeof( "/assets/" ) - 1) == 0 )
188 : : {
189 : : lo_apk_dir *pdir = lo_apk_opendir( path );
190 : :
191 : : if( pdir )
192 : : {
193 : : oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) );
194 : :
195 : : if( pDirImpl )
196 : : {
197 : : pDirImpl->eKind = oslDirectoryImpl::KIND_ASSETS;
198 : : pDirImpl->pApkDirStruct = pdir;
199 : : pDirImpl->ustrPath = ustrSystemPath;
200 : :
201 : : *pDirectory = (oslDirectory) pDirImpl;
202 : : return osl_File_E_None;
203 : : }
204 : : else
205 : : {
206 : : errno = ENOMEM;
207 : : lo_apk_closedir( pdir );
208 : : }
209 : : }
210 : : }
211 : : else
212 : : #endif
213 : : {
214 : : /* open directory */
215 [ + - ]: 61440 : DIR *pdir = opendir( path );
216 : :
217 [ + + ]: 61440 : if( pdir )
218 : : {
219 : : /* create and initialize impl structure */
220 : 59499 : oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) );
221 : :
222 [ + - ]: 59499 : if( pDirImpl )
223 : : {
224 : 59499 : pDirImpl->pDirStruct = pdir;
225 : 59499 : pDirImpl->ustrPath = ustrSystemPath;
226 : : #ifdef ANDROID
227 : : pDirImpl->eKind = oslDirectoryImpl::KIND_DIRENT;
228 : : #endif
229 : 59499 : *pDirectory = (oslDirectory) pDirImpl;
230 : 59499 : return osl_File_E_None;
231 : : }
232 : : else
233 : : {
234 : 0 : errno = ENOMEM;
235 [ # # ]: 0 : closedir( pdir );
236 : : }
237 : : }
238 : : else
239 : : {
240 : : #ifdef DEBUG_OSL_FILE
241 : : perror ("osl_openDirectory"); fprintf (stderr, path);
242 : : #endif
243 : : }
244 : : }
245 : : }
246 : :
247 : 1941 : rtl_uString_release( ustrSystemPath );
248 : :
249 [ + - ]: 63262 : return oslTranslateFileError(OSL_FET_ERROR, errno);
250 : : }
251 : :
252 : : /****************************************************************************/
253 : : /* osl_closeDirectory */
254 : : /****************************************************************************/
255 : :
256 : 59499 : oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory )
257 : : {
258 : 59499 : oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) Directory;
259 : 59499 : oslFileError err = osl_File_E_None;
260 : :
261 : : OSL_ASSERT( Directory );
262 : :
263 [ - + ]: 59499 : if( NULL == pDirImpl )
264 : 0 : return osl_File_E_INVAL;
265 : :
266 : : #ifdef ANDROID
267 : : if( pDirImpl->eKind == oslDirectoryImpl::KIND_ASSETS )
268 : : {
269 : : if (lo_apk_closedir( pDirImpl->pApkDirStruct ))
270 : : err = osl_File_E_IO;
271 : : }
272 : : else
273 : : #endif
274 : : {
275 [ - + ]: 59499 : if( closedir( pDirImpl->pDirStruct ) )
276 : 0 : err = oslTranslateFileError(OSL_FET_ERROR, errno);
277 : : }
278 : :
279 : : /* cleanup members */
280 : 59499 : rtl_uString_release( pDirImpl->ustrPath );
281 : :
282 : 59499 : rtl_freeMemory( pDirImpl );
283 : :
284 : 59499 : return err;
285 : : }
286 : :
287 : : /**********************************************
288 : : * osl_readdir_impl_
289 : : *
290 : : * readdir wrapper, filters out "." and ".."
291 : : * on request
292 : : *********************************************/
293 : :
294 : 193096 : static struct dirent* osl_readdir_impl_(DIR* pdir, sal_Bool bFilterLocalAndParentDir)
295 : : {
296 : : struct dirent* pdirent;
297 : :
298 [ + + ]: 270745 : while ((pdirent = readdir(pdir)) != NULL)
299 : : {
300 [ + - ][ + + ]: 231957 : if (bFilterLocalAndParentDir &&
[ + + ]
301 : 425098 : ((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, ".."))))
302 : 77649 : continue;
303 : : else
304 : 154308 : break;
305 : : }
306 : :
307 : 193096 : return pdirent;
308 : : }
309 : :
310 : : /****************************************************************************
311 : : * osl_getNextDirectoryItem
312 : : ***************************************************************************/
313 : :
314 : 193101 : oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, SAL_UNUSED_PARAMETER sal_uInt32 /*uHint*/)
315 : : {
316 : 193101 : oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*)Directory;
317 : 193101 : rtl_uString* ustrFileName = NULL;
318 : 193101 : rtl_uString* ustrFilePath = NULL;
319 : : struct dirent* pEntry;
320 : :
321 : : OSL_ASSERT(Directory);
322 : : OSL_ASSERT(pItem);
323 : :
324 [ + + ][ - + ]: 193101 : if ((NULL == Directory) || (NULL == pItem))
325 : 5 : return osl_File_E_INVAL;
326 : :
327 : : #ifdef ANDROID
328 : : if( pDirImpl->eKind == oslDirectoryImpl::KIND_ASSETS )
329 : : {
330 : : pEntry = lo_apk_readdir(pDirImpl->pApkDirStruct);
331 : : }
332 : : else
333 : : #endif
334 : : {
335 [ + - ]: 193096 : pEntry = osl_readdir_impl_(pDirImpl->pDirStruct, sal_True);
336 : : }
337 : :
338 [ + + ]: 193096 : if (NULL == pEntry)
339 : 38788 : return osl_File_E_NOENT;
340 : :
341 : :
342 : : #if defined(MACOSX)
343 : :
344 : : // convert decomposed filename to precomposed unicode
345 : : char composed_name[BUFSIZ];
346 : : CFMutableStringRef strRef = CFStringCreateMutable (NULL, 0 );
347 : : CFStringAppendCString( strRef, pEntry->d_name, kCFStringEncodingUTF8 ); //UTF8 is default on Mac OSX
348 : : CFStringNormalize( strRef, kCFStringNormalizationFormC );
349 : : CFStringGetCString( strRef, composed_name, BUFSIZ, kCFStringEncodingUTF8 );
350 : : CFRelease( strRef );
351 : : rtl_string2UString( &ustrFileName, composed_name, strlen( composed_name),
352 : : osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
353 : :
354 : : #else // not MACOSX
355 : : /* convert file name to unicode */
356 : 154308 : rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ),
357 [ + - ]: 154308 : osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
358 : : OSL_ASSERT(ustrFileName != 0);
359 : :
360 : : #endif
361 : :
362 [ + - ]: 154308 : osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &ustrFilePath);
363 : 154308 : rtl_uString_release( ustrFileName );
364 : :
365 : 154308 : DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(*pItem);
366 [ - + ]: 154308 : if (0 != pImpl)
367 : : {
368 : 0 : pImpl->release(), pImpl = 0;
369 : : }
370 : : #ifdef _DIRENT_HAVE_D_TYPE
371 : 154308 : pImpl = new DirectoryItem_Impl(ustrFilePath, pEntry->d_type);
372 : : #else
373 : : pImpl = new DirectoryItem_Impl(ustrFilePath);
374 : : #endif /* _DIRENT_HAVE_D_TYPE */
375 : 154308 : *pItem = pImpl;
376 : 154308 : rtl_uString_release( ustrFilePath );
377 : :
378 : 193101 : return osl_File_E_None;
379 : : }
380 : :
381 : : /****************************************************************************/
382 : : /* osl_getDirectoryItem */
383 : : /****************************************************************************/
384 : :
385 : 188268 : oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem )
386 : : {
387 : 188268 : rtl_uString* ustrSystemPath = NULL;
388 : 188268 : oslFileError osl_error = osl_File_E_INVAL;
389 : :
390 : : OSL_ASSERT((0 != ustrFileURL) && (0 != pItem));
391 [ + - ][ + + ]: 188268 : if ((0 == ustrFileURL) || (0 == ustrFileURL->length) || (0 == pItem))
[ - + ]
392 : 9 : return osl_File_E_INVAL;
393 : :
394 [ + - ]: 188259 : osl_error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &ustrSystemPath, sal_False);
395 [ + + ]: 188259 : if (osl_File_E_None != osl_error)
396 : 4197 : return osl_error;
397 : :
398 [ + - ]: 184062 : osl_systemPathRemoveSeparator(ustrSystemPath);
399 : :
400 [ + - ][ + + ]: 184062 : if (-1 == access_u(ustrSystemPath, F_OK))
401 : : {
402 [ + - ]: 33586 : osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
403 : : }
404 : : else
405 : : {
406 : 150476 : *pItem = new DirectoryItem_Impl(ustrSystemPath);
407 : : }
408 : 184062 : rtl_uString_release(ustrSystemPath);
409 : :
410 : 188268 : return osl_error;
411 : : }
412 : :
413 : :
414 : : /****************************************************************************/
415 : : /* osl_acquireDirectoryItem */
416 : : /****************************************************************************/
417 : :
418 : 0 : oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item )
419 : : {
420 : 0 : DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
421 [ # # ]: 0 : if (0 == pImpl)
422 : 0 : return osl_File_E_INVAL;
423 : :
424 : 0 : pImpl->acquire();
425 : 0 : return osl_File_E_None;
426 : : }
427 : :
428 : : /****************************************************************************/
429 : : /* osl_releaseDirectoryItem */
430 : : /****************************************************************************/
431 : :
432 : 304784 : oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item )
433 : : {
434 : 304784 : DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
435 [ - + ]: 304784 : if (0 == pImpl)
436 : 0 : return osl_File_E_INVAL;
437 : :
438 : 304784 : pImpl->release();
439 : 304784 : return osl_File_E_None;
440 : : }
441 : :
442 : : /****************************************************************************/
443 : : /* osl_createDirectory */
444 : : /****************************************************************************/
445 : :
446 : 6372 : oslFileError SAL_CALL osl_createDirectory( rtl_uString* ustrDirectoryURL )
447 : : {
448 : : char path[PATH_MAX];
449 : : oslFileError eRet;
450 : :
451 : : OSL_ASSERT( ustrDirectoryURL );
452 : :
453 : : /* convert directory url to system path */
454 [ + - ]: 6372 : eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
455 [ + + ]: 6372 : if( eRet != osl_File_E_None )
456 : 5 : return eRet;
457 : :
458 : : #ifdef MACOSX
459 : : if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
460 : : return oslTranslateFileError( OSL_FET_ERROR, errno );
461 : : #endif/* MACOSX */
462 : :
463 [ + - ]: 6372 : return osl_psz_createDirectory( path );
464 : : }
465 : :
466 : : /****************************************************************************/
467 : : /* osl_removeDirectory */
468 : : /****************************************************************************/
469 : :
470 : 1946 : oslFileError SAL_CALL osl_removeDirectory( rtl_uString* ustrDirectoryURL )
471 : : {
472 : : char path[PATH_MAX];
473 : : oslFileError eRet;
474 : :
475 : : OSL_ASSERT( ustrDirectoryURL );
476 : :
477 : : /* convert directory url to system path */
478 [ + - ]: 1946 : eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
479 [ + + ]: 1946 : if( eRet != osl_File_E_None )
480 : 5 : return eRet;
481 : :
482 : : #ifdef MACOSX
483 : : if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
484 : : return oslTranslateFileError( OSL_FET_ERROR, errno );
485 : : #endif/* MACOSX */
486 : :
487 [ + - ]: 1946 : return osl_psz_removeDirectory( path );
488 : : }
489 : :
490 : : /*****************************************
491 : : * osl_psz_createDirectory
492 : : ****************************************/
493 : :
494 : 6367 : static oslFileError osl_psz_createDirectory( const sal_Char* pszPath )
495 : : {
496 : 6367 : int nRet=0;
497 : 6367 : int mode = S_IRWXU | S_IRWXG | S_IRWXO;
498 : :
499 : 6367 : nRet = mkdir(pszPath,mode);
500 : :
501 [ + + ]: 6367 : if ( nRet < 0 )
502 : : {
503 : 573 : nRet=errno;
504 : 573 : return oslTranslateFileError(OSL_FET_ERROR, nRet);
505 : : }
506 : :
507 : 6367 : return osl_File_E_None;
508 : : }
509 : :
510 : : /*****************************************
511 : : * osl_psz_removeDirectory
512 : : ****************************************/
513 : :
514 : 1941 : static oslFileError osl_psz_removeDirectory( const sal_Char* pszPath )
515 : : {
516 : 1941 : int nRet=0;
517 : :
518 : 1941 : nRet = rmdir(pszPath);
519 : :
520 [ + + ]: 1941 : if ( nRet < 0 )
521 : : {
522 : 35 : nRet=errno;
523 : 35 : return oslTranslateFileError(OSL_FET_ERROR, nRet);
524 : : }
525 : :
526 : 1941 : return osl_File_E_None;
527 : : }
528 : :
529 : : /****************************************************************************/
530 : : /* osl_createDirectoryPath */
531 : : /****************************************************************************/
532 : :
533 : 134 : static int path_make_parent(sal_Unicode* path)
534 : : {
535 : 134 : int i = rtl_ustr_lastIndexOfChar(path, '/');
536 : :
537 [ + - ]: 134 : if (i > 0)
538 : : {
539 : 134 : *(path + i) = 0;
540 : 134 : return i;
541 : : }
542 : : else
543 : 134 : return 0;
544 : : }
545 : :
546 : 3399 : static int create_dir_with_callback(
547 : : sal_Unicode* directory_path,
548 : : oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
549 : : void* pData)
550 : : {
551 : 3399 : int mode = S_IRWXU | S_IRWXG | S_IRWXO;
552 : :
553 [ + - ][ + + ]: 3399 : if (osl::mkdir(directory_path, mode) == 0)
554 : : {
555 [ + + ]: 355 : if (aDirectoryCreationCallbackFunc)
556 : : {
557 : 10 : rtl::OUString url;
558 [ + - ]: 10 : osl::FileBase::getFileURLFromSystemPath(directory_path, url);
559 [ + - ]: 10 : aDirectoryCreationCallbackFunc(pData, url.pData);
560 : : }
561 : 355 : return 0;
562 : : }
563 : 3399 : return errno;
564 : : }
565 : :
566 : 3399 : static oslFileError create_dir_recursively_(
567 : : sal_Unicode* dir_path,
568 : : oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
569 : : void* pData)
570 : : {
571 : : OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \
572 : : "Path must not end with a slash");
573 : :
574 : : int native_err = create_dir_with_callback(
575 : 3399 : dir_path, aDirectoryCreationCallbackFunc, pData);
576 : :
577 [ + + ]: 3399 : if (native_err == 0)
578 : 355 : return osl_File_E_None;
579 : :
580 [ + + ]: 3044 : if (native_err != ENOENT)
581 : 2910 : return oslTranslateFileError(OSL_FET_ERROR, native_err);
582 : :
583 : : // we step back until '/a_dir' at maximum because
584 : : // we should get an error unequal ENOENT when
585 : : // we try to create 'a_dir' at '/' and would so
586 : : // return before
587 : 134 : int pos = path_make_parent(dir_path);
588 : :
589 : : oslFileError osl_error = create_dir_recursively_(
590 : 134 : dir_path, aDirectoryCreationCallbackFunc, pData);
591 : :
592 [ - + ]: 134 : if (osl_File_E_None != osl_error)
593 : 0 : return osl_error;
594 : :
595 : 134 : dir_path[pos] = '/';
596 : :
597 : 3399 : return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
598 : : }
599 : :
600 : 3141 : oslFileError SAL_CALL osl_createDirectoryPath(
601 : : rtl_uString* aDirectoryUrl,
602 : : oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
603 : : void* pData)
604 : : {
605 [ - + ]: 3141 : if (aDirectoryUrl == NULL)
606 : 0 : return osl_File_E_INVAL;
607 : :
608 : 3141 : rtl::OUString sys_path;
609 : : oslFileError osl_error = osl_getSystemPathFromFileURL_Ex(
610 [ + - ]: 3141 : aDirectoryUrl, &sys_path.pData, sal_False);
611 : :
612 [ + + ]: 3141 : if (osl_error != osl_File_E_None)
613 : 10 : return osl_error;
614 : :
615 [ + - ]: 3131 : osl::systemPathRemoveSeparator(sys_path);
616 : :
617 : : // const_cast because sys_path is a local copy which we want to modify inplace instead of
618 : : // coyp it into another buffer on the heap again
619 [ + - ]: 3141 : return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData);
620 : : }
621 : :
622 : : /******************************************************************************
623 : : *
624 : : * C-String Function Declarations
625 : : *
626 : : *****************************************************************************/
627 : :
628 : : static oslFileError osl_psz_removeFile(const sal_Char* pszPath);
629 : : static oslFileError osl_psz_copyFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
630 : : static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
631 : :
632 : :
633 : : /******************************************************************************
634 : : *
635 : : * Static Module Utility Function Declarations
636 : : *
637 : : *****************************************************************************/
638 : :
639 : : static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists);
640 : : static oslFileError oslChangeFileModes(const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID);
641 : : static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName);
642 : : static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode);
643 : : static oslFileError oslDoMoveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
644 : :
645 : : /****************************************************************************/
646 : : /* osl_moveFile */
647 : : /****************************************************************************/
648 : :
649 : 14535 : oslFileError SAL_CALL osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
650 : : {
651 : : char srcPath[PATH_MAX];
652 : : char destPath[PATH_MAX];
653 : : oslFileError eRet;
654 : :
655 : : OSL_ASSERT( ustrFileURL );
656 : : OSL_ASSERT( ustrDestURL );
657 : :
658 : : /* convert source url to system path */
659 [ + - ]: 14535 : eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
660 [ - + ]: 14535 : if( eRet != osl_File_E_None )
661 : 0 : return eRet;
662 : :
663 : : /* convert destination url to system path */
664 [ + - ]: 14535 : eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
665 [ - + ]: 14535 : if( eRet != osl_File_E_None )
666 : 0 : return eRet;
667 : :
668 : : #ifdef MACOSX
669 : : if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 )
670 : : return oslTranslateFileError( OSL_FET_ERROR, errno );
671 : : #endif/* MACOSX */
672 : :
673 [ + - ]: 14535 : return oslDoMoveFile( srcPath, destPath );
674 : : }
675 : :
676 : : /****************************************************************************/
677 : : /* osl_copyFile */
678 : : /****************************************************************************/
679 : :
680 : 3600 : oslFileError SAL_CALL osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
681 : : {
682 : : char srcPath[PATH_MAX];
683 : : char destPath[PATH_MAX];
684 : : oslFileError eRet;
685 : :
686 : : OSL_ASSERT( ustrFileURL );
687 : : OSL_ASSERT( ustrDestURL );
688 : :
689 : : /* convert source url to system path */
690 [ + - ]: 3600 : eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
691 [ - + ]: 3600 : if( eRet != osl_File_E_None )
692 : 0 : return eRet;
693 : :
694 : : /* convert destination url to system path */
695 [ + - ]: 3600 : eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
696 [ - + ]: 3600 : if( eRet != osl_File_E_None )
697 : 0 : return eRet;
698 : :
699 : : #ifdef MACOSX
700 : : if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 )
701 : : return oslTranslateFileError( OSL_FET_ERROR, errno );
702 : : #endif/* MACOSX */
703 : :
704 [ + - ]: 3600 : return osl_psz_copyFile( srcPath, destPath );
705 : : }
706 : :
707 : : /****************************************************************************/
708 : : /* osl_removeFile */
709 : : /****************************************************************************/
710 : :
711 : 12225 : oslFileError SAL_CALL osl_removeFile( rtl_uString* ustrFileURL )
712 : : {
713 : : char path[PATH_MAX];
714 : : oslFileError eRet;
715 : :
716 : : OSL_ASSERT( ustrFileURL );
717 : :
718 : : /* convert file url to system path */
719 [ + - ]: 12225 : eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
720 [ - + ]: 12225 : if( eRet != osl_File_E_None )
721 : 0 : return eRet;
722 : :
723 : : #ifdef MACOSX
724 : : if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
725 : : return oslTranslateFileError( OSL_FET_ERROR, errno );
726 : : #endif/* MACOSX */
727 : :
728 [ + - ]: 12225 : return osl_psz_removeFile( path );
729 : : }
730 : :
731 : : /******************************************************************************
732 : : *
733 : : * Utility Functions
734 : : *
735 : : *****************************************************************************/
736 : :
737 : : /*****************************************
738 : : * oslDoMoveFile
739 : : ****************************************/
740 : :
741 : 14535 : static oslFileError oslDoMoveFile( const sal_Char* pszPath, const sal_Char* pszDestPath)
742 : : {
743 : 14535 : oslFileError tErr=osl_File_E_invalidError;
744 : :
745 : 14535 : tErr = osl_psz_moveFile(pszPath,pszDestPath);
746 [ + - ]: 14535 : if ( tErr == osl_File_E_None )
747 : : {
748 : 14535 : return tErr;
749 : : }
750 : :
751 [ # # ]: 0 : if ( tErr != osl_File_E_XDEV )
752 : : {
753 : 0 : return tErr;
754 : : }
755 : :
756 : 0 : tErr=osl_psz_copyFile(pszPath,pszDestPath);
757 : :
758 [ # # ]: 0 : if ( tErr != osl_File_E_None )
759 : : {
760 : 0 : osl_psz_removeFile(pszDestPath);
761 : 0 : return tErr;
762 : : }
763 : :
764 : 0 : tErr=osl_psz_removeFile(pszPath);
765 : :
766 : 14535 : return tErr;
767 : : }
768 : :
769 : : /*****************************************
770 : : * osl_psz_removeFile
771 : : ****************************************/
772 : 12225 : static oslFileError osl_psz_removeFile( const sal_Char* pszPath )
773 : : {
774 : 12225 : int nRet=0;
775 : : struct stat aStat;
776 : :
777 [ + - ]: 12225 : nRet = lstat_c(pszPath,&aStat);
778 [ + + ]: 12225 : if ( nRet < 0 )
779 : : {
780 : 119 : nRet=errno;
781 [ + - ]: 119 : return oslTranslateFileError(OSL_FET_ERROR, nRet);
782 : : }
783 : :
784 [ - + ]: 12106 : if ( S_ISDIR(aStat.st_mode) )
785 : : {
786 : 0 : return osl_File_E_ISDIR;
787 : : }
788 : :
789 : 12106 : nRet = unlink(pszPath);
790 [ - + ]: 12106 : if ( nRet < 0 )
791 : : {
792 : 0 : nRet=errno;
793 [ # # ]: 0 : return oslTranslateFileError(OSL_FET_ERROR, nRet);
794 : : }
795 : :
796 : 12225 : return osl_File_E_None;
797 : : }
798 : :
799 : : /*****************************************
800 : : * osl_psz_moveFile
801 : : ****************************************/
802 : :
803 : 14535 : static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath)
804 : : {
805 : :
806 : 14535 : int nRet = 0;
807 : :
808 : 14535 : nRet = rename(pszPath,pszDestPath);
809 : :
810 [ - + ]: 14535 : if ( nRet < 0 )
811 : : {
812 : 0 : nRet=errno;
813 : 0 : return oslTranslateFileError(OSL_FET_ERROR, nRet);
814 : : }
815 : :
816 : 14535 : return osl_File_E_None;
817 : : }
818 : :
819 : : /*****************************************
820 : : * osl_psz_copyFile
821 : : ****************************************/
822 : :
823 : 3600 : static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath )
824 : : {
825 : 3600 : time_t nAcTime=0;
826 : 3600 : time_t nModTime=0;
827 : 3600 : uid_t nUID=0;
828 : 3600 : gid_t nGID=0;
829 : 3600 : int nRet=0;
830 : 3600 : mode_t nMode=0;
831 : : struct stat aFileStat;
832 : 3600 : oslFileError tErr=osl_File_E_invalidError;
833 : 3600 : size_t nSourceSize=0;
834 : 3600 : int DestFileExists=1;
835 : :
836 : : /* mfe: does the source file really exists? */
837 [ + - ]: 3600 : nRet = lstat_c(pszPath,&aFileStat);
838 : :
839 [ + + ]: 3600 : if ( nRet < 0 )
840 : : {
841 : 2 : nRet=errno;
842 [ + - ]: 2 : return oslTranslateFileError(OSL_FET_ERROR, nRet);
843 : : }
844 : :
845 : : /* mfe: we do only copy files here! */
846 [ - + ]: 3598 : if ( S_ISDIR(aFileStat.st_mode) )
847 : : {
848 : 0 : return osl_File_E_ISDIR;
849 : : }
850 : :
851 : 3598 : nSourceSize=(size_t)aFileStat.st_size;
852 : 3598 : nMode=aFileStat.st_mode;
853 : 3598 : nAcTime=aFileStat.st_atime;
854 : 3598 : nModTime=aFileStat.st_mtime;
855 : 3598 : nUID=aFileStat.st_uid;
856 : 3598 : nGID=aFileStat.st_gid;
857 : :
858 : 3598 : nRet = stat(pszDestPath,&aFileStat);
859 [ + - ]: 3598 : if ( nRet < 0 )
860 : : {
861 : 3598 : nRet=errno;
862 : :
863 [ + - ]: 3598 : if ( nRet == ENOENT )
864 : : {
865 : 3598 : DestFileExists=0;
866 : : }
867 : : /* return oslTranslateFileError(nRet);*/
868 : : }
869 : :
870 : : /* mfe: the destination file must not be a directory! */
871 [ - + ][ # # ]: 3598 : if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) )
872 : : {
873 : 0 : return osl_File_E_ISDIR;
874 : : }
875 : : else
876 : : {
877 : : /* mfe: file does not exists or is no dir */
878 : : }
879 : :
880 [ + - ]: 3598 : tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists);
881 : :
882 [ - + ]: 3598 : if ( tErr != osl_File_E_None )
883 : : {
884 : 0 : return tErr;
885 : : }
886 : :
887 : : /*
888 : : * mfe: ignore return code
889 : : * since only the success of the copy is
890 : : * important
891 : : */
892 [ + - ]: 3598 : oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID);
893 : :
894 : 3600 : return tErr;
895 : : }
896 : :
897 : :
898 : : /******************************************************************************
899 : : *
900 : : * Utility Functions
901 : : *
902 : : *****************************************************************************/
903 : :
904 : : /*****************************************
905 : : * oslDoCopy
906 : : ****************************************/
907 : :
908 : : #define TMP_DEST_FILE_EXTENSION ".osl-tmp"
909 : :
910 : 3598 : static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists)
911 : : {
912 : 3598 : int nRet=0;
913 : : sal_Char pszTmpDestFile[PATH_MAX];
914 : 3598 : size_t size_tmp_dest_buff = sizeof(pszTmpDestFile);
915 : :
916 : : /* Quick fix for #106048, the whole copy file function seems
917 : : to be erroneous anyway and needs to be rewritten.
918 : : */
919 : 3598 : memset(pszTmpDestFile, 0, size_tmp_dest_buff);
920 : :
921 [ - + ]: 3598 : if ( DestFileExists )
922 : : {
923 : 0 : strncpy(pszTmpDestFile, pszDestFileName, size_tmp_dest_buff - 1);
924 : :
925 [ # # ]: 0 : if ((strlen(pszTmpDestFile) + strlen(TMP_DEST_FILE_EXTENSION)) >= size_tmp_dest_buff)
926 : 0 : return osl_File_E_NAMETOOLONG;
927 : :
928 : 0 : strncat(pszTmpDestFile, TMP_DEST_FILE_EXTENSION, strlen(TMP_DEST_FILE_EXTENSION));
929 : :
930 : : /* FIXME: what if pszTmpDestFile already exists? */
931 : : /* with getcanonical??? */
932 : 0 : nRet=rename(pszDestFileName,pszTmpDestFile);
933 : : }
934 : :
935 : : /* mfe: should be S_ISREG */
936 [ + - ]: 3598 : if ( !S_ISLNK(nMode) )
937 : : {
938 : : /* copy SourceFile to DestFile */
939 [ + - ]: 3598 : nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode);
940 : : }
941 : : /* mfe: OK redundant at the moment */
942 [ # # ]: 0 : else if ( S_ISLNK(nMode) )
943 : : {
944 : 0 : nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName);
945 : : }
946 : : else
947 : : {
948 : : /* mfe: what to do here? */
949 : 0 : nRet=ENOSYS;
950 : : }
951 : :
952 [ - + ][ # # ]: 3598 : if ( nRet > 0 && DestFileExists == 1 )
953 : : {
954 : 0 : unlink(pszDestFileName);
955 : 0 : rename(pszTmpDestFile,pszDestFileName);
956 : : }
957 : :
958 [ - + ]: 3598 : if ( nRet > 0 )
959 : : {
960 [ # # ]: 0 : return oslTranslateFileError(OSL_FET_ERROR, nRet);
961 : : }
962 : :
963 [ - + ]: 3598 : if ( DestFileExists == 1 )
964 : : {
965 : 0 : unlink(pszTmpDestFile);
966 : : }
967 : :
968 : 3598 : return osl_File_E_None;
969 : : }
970 : :
971 : : /*****************************************
972 : : * oslChangeFileModes
973 : : ****************************************/
974 : :
975 : 3598 : static oslFileError oslChangeFileModes( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID)
976 : : {
977 : 3598 : int nRet=0;
978 : : struct utimbuf aTimeBuffer;
979 : :
980 : 3598 : nRet = chmod(pszFileName,nMode);
981 [ - + ]: 3598 : if ( nRet < 0 )
982 : : {
983 : 0 : nRet=errno;
984 [ # # ]: 0 : return oslTranslateFileError(OSL_FET_ERROR, nRet);
985 : : }
986 : :
987 : 3598 : aTimeBuffer.actime=nAcTime;
988 : 3598 : aTimeBuffer.modtime=nModTime;
989 : 3598 : nRet=utime(pszFileName,&aTimeBuffer);
990 [ - + ]: 3598 : if ( nRet < 0 )
991 : : {
992 : 0 : nRet=errno;
993 [ # # ]: 0 : return oslTranslateFileError(OSL_FET_ERROR, nRet);
994 : : }
995 : :
996 [ - + ]: 3598 : if ( nUID != getuid() )
997 : : {
998 : 0 : nUID=getuid();
999 : : }
1000 : :
1001 : 3598 : nRet=chown(pszFileName,nUID,nGID);
1002 [ - + ]: 3598 : if ( nRet < 0 )
1003 : : {
1004 : 0 : nRet=errno;
1005 : :
1006 : : /* mfe: do not return an error here! */
1007 : : /* return oslTranslateFileError(nRet);*/
1008 : : }
1009 : :
1010 : 3598 : return osl_File_E_None;
1011 : : }
1012 : :
1013 : : /*****************************************
1014 : : * oslDoCopyLink
1015 : : ****************************************/
1016 : :
1017 : 0 : static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName)
1018 : : {
1019 : 0 : int nRet=0;
1020 : :
1021 : : /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */
1022 : : /* mfe: if source is a link copy the link and not the file it points to (hro says so) */
1023 : : sal_Char pszLinkContent[PATH_MAX];
1024 : :
1025 : 0 : pszLinkContent[0] = '\0';
1026 : :
1027 : 0 : nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX);
1028 : :
1029 [ # # ]: 0 : if ( nRet < 0 )
1030 : : {
1031 : 0 : nRet=errno;
1032 : 0 : return nRet;
1033 : : }
1034 : : else
1035 : 0 : pszLinkContent[ nRet ] = 0;
1036 : :
1037 : 0 : nRet = symlink(pszLinkContent,pszDestFileName);
1038 : :
1039 [ # # ]: 0 : if ( nRet < 0 )
1040 : : {
1041 : 0 : nRet=errno;
1042 : 0 : return nRet;
1043 : : }
1044 : :
1045 : 0 : return 0;
1046 : : }
1047 : :
1048 : : /*****************************************
1049 : : * oslDoCopyFile
1050 : : ****************************************/
1051 : :
1052 : 3598 : static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode)
1053 : : {
1054 : 3598 : oslFileHandle SourceFileFH=0;
1055 : 3598 : int DestFileFD=0;
1056 : 3598 : int nRet=0;
1057 : :
1058 [ - + ]: 3598 : if (osl_openFilePath(pszSourceFileName,
1059 : : &SourceFileFH,
1060 [ + - ]: 3598 : osl_File_OpenFlag_Read|osl_File_OpenFlag_NoLock|osl_File_OpenFlag_NoExcl) != osl_File_E_None)
1061 : : {
1062 : : // Let's hope errno is still set relevantly after osl_openFilePath...
1063 : 0 : nRet=errno;
1064 : 0 : return nRet;
1065 : : }
1066 : :
1067 [ + - ]: 3598 : DestFileFD=open(pszDestFileName, O_WRONLY | O_CREAT, mode);
1068 : :
1069 [ - + ]: 3598 : if ( DestFileFD < 0 )
1070 : : {
1071 : 0 : nRet=errno;
1072 [ # # ]: 0 : osl_closeFile(SourceFileFH);
1073 : 0 : return nRet;
1074 : : }
1075 : :
1076 : 3598 : size_t nRemains = nSourceSize;
1077 : :
1078 [ + + ]: 3598 : if ( nRemains )
1079 : : {
1080 : : /* mmap has problems, try the direct streaming */
1081 : : char pBuffer[0x7FFF];
1082 : :
1083 [ + + ]: 5851 : do
1084 : : {
1085 [ + - ]: 5851 : size_t nToRead = std::min( sizeof(pBuffer), nRemains );
1086 : : sal_uInt64 nRead;
1087 : : sal_Bool succeeded;
1088 [ + - ][ + - ]: 5851 : if ( osl_readFile( SourceFileFH, pBuffer, nToRead, &nRead ) != osl_File_E_None || nRead > nToRead || nRead == 0 )
[ + - ][ - + ]
[ + - ]
1089 : : break;
1090 : :
1091 [ + - ]: 5851 : succeeded = safeWrite( DestFileFD, pBuffer, nRead );
1092 [ + - ]: 5851 : if ( !succeeded )
1093 : : break;
1094 : :
1095 : : // We know nRead <= nToRead, so it must fit in a size_t
1096 : 5851 : nRemains -= (size_t) nRead;
1097 : : }
1098 : : while( nRemains );
1099 : : }
1100 : :
1101 [ - + ]: 3598 : if ( nRemains )
1102 : : {
1103 [ # # ]: 0 : if ( errno )
1104 : 0 : nRet = errno;
1105 : : else
1106 : 0 : nRet = ENOSPC;
1107 : : }
1108 : :
1109 [ + - ]: 3598 : osl_closeFile( SourceFileFH );
1110 [ + - ][ - + ]: 3598 : if ( close( DestFileFD ) == -1 && nRet == 0 )
[ # # ][ - + ]
1111 : 0 : nRet = errno;
1112 : :
1113 : 3598 : return nRet;
1114 : : }
1115 : :
1116 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|