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