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