xref: /trunk/main/sal/osl/unx/file_misc.cxx (revision 0170220d)
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