xref: /trunk/main/sal/osl/os2/file.cxx (revision 87d2adbc)
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 
25 /************************************************************************
26  *   ToDo
27  *
28  *   Fix osl_getCanonicalName
29  *
30  *   - Fix: check for corresponding struct sizes in exported functions
31  *   - check size/use of oslDirectory
32  *   - check size/use of oslDirectoryItem
33  *   - check size/use of oslFileStatus
34  *   - check size/use of oslVolumeDeviceHandle
35  *   - check size/use of oslVolumeInfo
36  *   - check size/use of oslFileHandle
37  ***********************************************************************/
38 
39 #define INCL_DOSDEVIOCTL                        // OS2 device definitions
40 
41 #include "system.h"
42 #include <rtl/alloc.h>
43 
44 #include "osl/file.hxx"
45 
46 
47 #include <sal/types.h>
48 #include <osl/thread.h>
49 #include <osl/diagnose.h>
50 #include "file_error_transl.h"
51 #include <osl/time.h>
52 
53 #ifndef _FILE_URL_H_
54 #include "file_url.h"
55 #endif
56 
57 #include "file_path_helper.hxx"
58 #include "uunxapi.hxx"
59 
60 #ifndef	_STRING_H_
61 #include <string.h>
62 #endif
63 
64 #ifndef	_CTYPE_H_
65 #include <ctype.h>
66 #endif
67 
68 #ifndef	_WCHAR_H_
69 #include <wchar.h>
70 #endif
71 
72 #if OSL_DEBUG_LEVEL > 1
73 	extern void debug_ustring(rtl_uString*);
74 #endif
75 
76 
77 #ifdef DEBUG_OSL_FILE
78 #	define PERROR( a, b ) perror( a ); fprintf( stderr, b )
79 #else
80 #	define PERROR( a, b )
81 #endif
82 
83 extern "C" oslFileHandle osl_createFileHandleFromFD( int fd );
84 
85     struct errentry errtable[] = {
86         {  NO_ERROR,			 osl_File_E_None     },  /* 0 */
87         {  ERROR_INVALID_FUNCTION,       osl_File_E_INVAL    },  /* 1 */
88         {  ERROR_FILE_NOT_FOUND,         osl_File_E_NOENT    },  /* 2 */
89         {  ERROR_PATH_NOT_FOUND,         osl_File_E_NOENT    },  /* 3 */
90         {  ERROR_TOO_MANY_OPEN_FILES,    osl_File_E_MFILE    },  /* 4 */
91         {  ERROR_ACCESS_DENIED,          osl_File_E_ACCES    },  /* 5 */
92         {  ERROR_INVALID_HANDLE,         osl_File_E_BADF     },  /* 6 */
93         {  ERROR_ARENA_TRASHED,          osl_File_E_NOMEM    },  /* 7 */
94         {  ERROR_NOT_ENOUGH_MEMORY,      osl_File_E_NOMEM    },  /* 8 */
95         {  ERROR_INVALID_BLOCK,          osl_File_E_NOMEM    },  /* 9 */
96         {  ERROR_BAD_ENVIRONMENT,        osl_File_E_2BIG     },  /* 10 */
97         {  ERROR_BAD_FORMAT,             osl_File_E_NOEXEC   },  /* 11 */
98         {  ERROR_INVALID_ACCESS,         osl_File_E_INVAL    },  /* 12 */
99         {  ERROR_INVALID_DATA,           osl_File_E_INVAL    },  /* 13 */
100         {  ERROR_INVALID_DRIVE,          osl_File_E_NOENT    },  /* 15 */
101         {  ERROR_CURRENT_DIRECTORY,      osl_File_E_ACCES    },  /* 16 */
102         {  ERROR_NOT_SAME_DEVICE,        osl_File_E_XDEV     },  /* 17 */
103         {  ERROR_NO_MORE_FILES,          osl_File_E_NOENT    },  /* 18 */
104         {  ERROR_NOT_READY,              osl_File_E_NOTREADY },  /* 21 */
105         {  ERROR_LOCK_VIOLATION,         osl_File_E_ACCES    },  /* 33 */
106         {  ERROR_BAD_NETPATH,            osl_File_E_NOENT    },  /* 53 */
107         {  ERROR_NETWORK_ACCESS_DENIED,  osl_File_E_ACCES    },  /* 65 */
108         {  ERROR_BAD_NET_NAME,           osl_File_E_NOENT    },  /* 67 */
109         {  ERROR_FILE_EXISTS,            osl_File_E_EXIST    },  /* 80 */
110         {  ERROR_CANNOT_MAKE,            osl_File_E_ACCES    },  /* 82 */
111         {  ERROR_FAIL_I24,               osl_File_E_ACCES    },  /* 83 */
112         {  ERROR_INVALID_PARAMETER,      osl_File_E_INVAL    },  /* 87 */
113         {  ERROR_NO_PROC_SLOTS,          osl_File_E_AGAIN    },  /* 89 */
114         {  ERROR_DRIVE_LOCKED,           osl_File_E_ACCES    },  /* 108 */
115         {  ERROR_BROKEN_PIPE,            osl_File_E_PIPE     },  /* 109 */
116         {  ERROR_DISK_FULL,              osl_File_E_NOSPC    },  /* 112 */
117         {  ERROR_INVALID_TARGET_HANDLE,  osl_File_E_BADF     },  /* 114 */
118         {  ERROR_INVALID_HANDLE,         osl_File_E_INVAL    },  /* 124 */
119         {  ERROR_WAIT_NO_CHILDREN,       osl_File_E_CHILD    },  /* 128 */
120         {  ERROR_CHILD_NOT_COMPLETE,     osl_File_E_CHILD    },  /* 129 */
121         {  ERROR_DIRECT_ACCESS_HANDLE,   osl_File_E_BADF     },  /* 130 */
122         {  ERROR_NEGATIVE_SEEK,          osl_File_E_INVAL    },  /* 131 */
123         {  ERROR_SEEK_ON_DEVICE,         osl_File_E_ACCES    },  /* 132 */
124         {  ERROR_DIR_NOT_EMPTY,          osl_File_E_NOTEMPTY },  /* 145 */
125         {  ERROR_NOT_LOCKED,             osl_File_E_ACCES    },  /* 158 */
126         {  ERROR_BAD_PATHNAME,           osl_File_E_NOENT    },  /* 161 */
127         {  ERROR_MAX_THRDS_REACHED,      osl_File_E_AGAIN    },  /* 164 */
128         {  ERROR_LOCK_FAILED,            osl_File_E_ACCES    },  /* 167 */
129         {  ERROR_ALREADY_EXISTS,         osl_File_E_EXIST    },  /* 183 */
130         {  ERROR_FILENAME_EXCED_RANGE,   osl_File_E_NOENT    },  /* 206 */
131         {  ERROR_NESTING_NOT_ALLOWED,    osl_File_E_AGAIN    },  /* 215 */
132         {  ERROR_DIRECTORY,              osl_File_E_NOENT    },  /* 267 */
133         //{  ERROR_NOT_ENOUGH_QUOTA,       osl_File_E_NOMEM    }    /* 1816 */
134     };
135 
136     #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
137 
138     //#####################################################
139     oslFileError MapError(APIRET dwError)
140     {
141         for (int i = 0; i < ELEMENTS_OF_ARRAY(errtable); ++i )
142 	    {
143 		    if (dwError == errtable[i].oscode)
144 			    return static_cast<oslFileError>(errtable[i].errnocode);
145         }
146         return osl_File_E_INVAL;
147     }
148 
149 /******************************************************************************
150  *
151  *                  static members
152  *
153  *****************************************************************************/
154 
155 static const char * pFileLockEnvVar = (char *) -1;
156 
157 
158 /******************************************************************************
159  *
160  *                  C-String Function Declarations
161  *
162  *****************************************************************************/
163 
164 static oslFileError osl_psz_getVolumeInformation(const sal_Char* , oslVolumeInfo* pInfo, sal_uInt32 uFieldMask);
165 static oslFileError osl_psz_removeFile(const sal_Char* pszPath);
166 static oslFileError osl_psz_createDirectory(const sal_Char* pszPath);
167 static oslFileError osl_psz_removeDirectory(const sal_Char* pszPath);
168 static oslFileError osl_psz_copyFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
169 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
170 static oslFileError osl_psz_setFileTime(const sal_Char* strFilePath, const TimeValue* pCreationTime, const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime);
171 
172 
173 /******************************************************************************
174  *
175  *                  Static Module Utility Function Declarations
176  *
177  *****************************************************************************/
178 
179 static oslFileError  oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists);
180 static oslFileError  oslChangeFileModes(const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID);
181 static int           oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName);
182 static int           oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode);
183 static oslFileError  oslDoMoveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
184 rtl_uString*  oslMakeUStrFromPsz(const sal_Char* pszStr,rtl_uString** uStr);
185 
186 /******************************************************************************
187  *
188  *                  Non-Static Utility Function Declarations
189  *
190  *****************************************************************************/
191 
192 extern "C" int UnicodeToText( char *, size_t, const sal_Unicode *, sal_Int32 );
193 extern "C" int TextToUnicode(
194     const char* text, size_t text_buffer_size,	sal_Unicode* unic_text, sal_Int32 unic_text_buffer_size);
195 
196 /******************************************************************************
197  *
198  *                  'removeable device' aka floppy functions
199  *
200  *****************************************************************************/
201 
202 static oslVolumeDeviceHandle  osl_isFloppyDrive(const sal_Char* pszPath);
203 static oslFileError   osl_mountFloppy(oslVolumeDeviceHandle hFloppy);
204 static oslFileError   osl_unmountFloppy(oslVolumeDeviceHandle hFloppy);
205 
206 #ifdef DEBUG_OSL_FILE
207 static void           osl_printFloppyHandle(oslVolumeDeviceHandleImpl* hFloppy);
208 #endif
209 
210 /**********************************************
211  * _osl_openLocalRoot
212  * enumerate available drives
213  *********************************************/
214 static oslFileError _osl_openLocalRoot( rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
215 {
216 	rtl_uString		*ustrSystemPath = NULL;
217 	oslFileError	error;
218 
219 	if ( !pDirectory )
220 		return osl_File_E_INVAL;
221 
222 	*pDirectory = NULL;
223 
224 	error = osl_getSystemPathFromFileURL_Ex( strDirectoryPath, &ustrSystemPath, sal_False );
225 
226 	if ( osl_File_E_None == error )
227 	{
228 		/* create and initialize impl structure */
229 		DirectoryImpl* pDirImpl = (DirectoryImpl*) rtl_allocateMemory( sizeof(DirectoryImpl) );
230 		if( pDirImpl )
231 		{
232 			ULONG   ulDriveNum;
233 			APIRET  rc;
234 			pDirImpl->uType = DIRECTORYTYPE_LOCALROOT;
235 			pDirImpl->ustrPath = ustrSystemPath;
236 			rc = DosQueryCurrentDisk (&ulDriveNum, &pDirImpl->ulDriveMap);
237 			pDirImpl->pDirStruct = 0;
238 			pDirImpl->ulNextDrive = 1;
239 			pDirImpl->ulNextDriveMask = 1;
240 
241 			// determine number of floppy-drives
242 			BYTE nFloppies;
243 			rc = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY );
244 			if (nFloppies == 0) {
245 				// if no floppies, start with 3rd drive (C:)
246 				pDirImpl->ulNextDrive = 3;
247 				pDirImpl->ulNextDriveMask <<= 2;
248 			} else if (nFloppies == 1) {
249 				// mask drive B (second bit) in this case
250 				pDirImpl->ulDriveMap &= ~0x02;
251 			}
252 			*pDirectory = (oslDirectory) pDirImpl;
253 			return osl_File_E_None;
254 		}
255 		else
256 		{
257 			errno = osl_File_E_NOMEM;
258 		}
259 
260 	}
261 
262     rtl_uString_release( ustrSystemPath );
263 	return error;
264 }
265 
266 /**********************************************
267  * _osl_getNextDrive
268  *********************************************/
269 static oslFileError SAL_CALL _osl_getNextDrive(
270 	oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint )
271 {
272 	DirectoryImpl	*pDirImpl = (DirectoryImpl *)Directory;
273 	DirectoryItem_Impl	*pItemImpl = NULL;
274     rtl_uString			* ustrDrive = NULL;
275 	BOOL				fSuccess;
276 	char				buffer[3];
277 
278 	uHint = uHint; /* avoid warnings */
279 
280 	if ( !pItem )
281 		return osl_File_E_INVAL;
282 
283 	*pItem = NULL;
284 
285 	if ( !pDirImpl )
286 		return osl_File_E_INVAL;
287 
288 	while( pDirImpl->ulNextDrive <= 26)
289 	{
290 		// exit if  bit==1 -> drive found
291 		if (pDirImpl->ulDriveMap & pDirImpl->ulNextDriveMask) {
292 
293 			/* convert file name to unicode */
294 			buffer[0] = '@' + pDirImpl->ulNextDrive;
295 			buffer[1] = ':';
296 			buffer[2] = 0;
297 
298 			pItemImpl = (DirectoryItem_Impl*) rtl_allocateMemory(sizeof(DirectoryItem_Impl));
299 			if ( !pItemImpl )
300 				return osl_File_E_NOMEM;
301 
302 			memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
303 			pItemImpl->uType = DIRECTORYITEM_DRIVE;
304 			pItemImpl->nRefCount = 1;
305 
306 			rtl_string2UString( &pItemImpl->ustrDrive, buffer, 3,
307 				osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
308 			OSL_ASSERT(pItemImpl->ustrDrive != 0);
309 
310 			/* use drive as directory item */
311 			*pItem = (oslDirectoryItem) pItemImpl;
312 		}
313 		// scan next bit position
314 		pDirImpl->ulNextDrive++;
315 		pDirImpl->ulNextDriveMask <<= 1;
316 
317 		if (*pItem)	// item assigned, return now.
318 			return osl_File_E_None;
319 	}
320 
321 	// no more items
322 	return osl_File_E_NOENT;
323 }
324 
325 /**********************************************
326  * _osl_readdir_impl_
327  *
328  * readdir wrapper, filters out "." and ".."
329  * on request
330  *********************************************/
331 
332 static struct dirent* _osl_readdir_impl_(DIR* pdir, sal_Bool bFilterLocalAndParentDir)
333 {
334 	struct dirent* pdirent;
335 
336 	while ((pdirent = readdir(pdir)) != NULL)
337 	{
338 		if (bFilterLocalAndParentDir &&
339 			((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, ".."))))
340 			continue;
341 		else
342 			break;
343 	}
344 
345 	return pdirent;
346 }
347 
348 /*******************************************************************
349  *	osl_openDirectory
350  ******************************************************************/
351 
352 oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirectory* pDirectory)
353 {
354     rtl_uString* ustrSystemPath = NULL;
355     oslFileError eRet;
356 
357     char path[PATH_MAX];
358 
359     OSL_ASSERT(ustrDirectoryURL && (ustrDirectoryURL->length > 0));
360     OSL_ASSERT(pDirectory);
361 
362     if (0 == ustrDirectoryURL->length )
363         return osl_File_E_INVAL;
364 
365 	if ( 0 == rtl_ustr_compareIgnoreAsciiCase( ustrDirectoryURL->buffer, (const sal_Unicode*)L"file:///" ) )
366 		return _osl_openLocalRoot( ustrDirectoryURL, pDirectory );
367 
368     /* convert file URL to system path */
369     eRet = osl_getSystemPathFromFileURL_Ex(ustrDirectoryURL, &ustrSystemPath, sal_False);
370 
371 	if( osl_File_E_None != eRet )
372         return eRet;
373 
374 	osl_systemPathRemoveSeparator(ustrSystemPath);
375 
376     /* convert unicode path to text */
377     if ( UnicodeToText( path, PATH_MAX, ustrSystemPath->buffer, ustrSystemPath->length ) )
378     {
379 		// if only the drive is specified (x:), add a \ (x:\) otherwise current
380 		// directory is browsed instead of root.
381 		if (strlen( path) == 2 && path[1] == ':')
382 			strcat( path, "\\");
383         /* open directory */
384         DIR *pdir = opendir( path );
385 
386         if( pdir )
387         {
388             /* create and initialize impl structure */
389             DirectoryImpl* pDirImpl = (DirectoryImpl*) rtl_allocateMemory( sizeof(DirectoryImpl) );
390 
391             if( pDirImpl )
392             {
393 				pDirImpl->uType = DIRECTORYTYPE_FILESYSTEM;
394                 pDirImpl->pDirStruct = pdir;
395                 pDirImpl->ustrPath = ustrSystemPath;
396 
397                 *pDirectory = (oslDirectory) pDirImpl;
398                 return osl_File_E_None;
399             }
400             else
401             {
402                 errno = ENOMEM;
403                 closedir( pdir );
404             }
405         }
406         else
407             /* should be removed by optimizer in product version */
408             PERROR( "osl_openDirectory", path );
409     }
410 
411     rtl_uString_release( ustrSystemPath );
412 
413     return oslTranslateFileError(OSL_FET_ERROR, errno);
414 }
415 
416 
417 /****************************************************************************
418  *	osl_getNextDirectoryItem
419  ***************************************************************************/
420 
421 oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, sal_uInt32 uHint)
422 {
423     DirectoryImpl* pDirImpl     = (DirectoryImpl*)Directory;
424 	DirectoryItem_Impl	*pItemImpl = NULL;
425     rtl_uString*      ustrFileName = NULL;
426     rtl_uString*      ustrFilePath = NULL;
427     struct dirent*    pEntry;
428 
429     OSL_ASSERT(Directory);
430     OSL_ASSERT(pItem);
431 
432     if ((NULL == Directory) || (NULL == pItem))
433         return osl_File_E_INVAL;
434 
435 	if ( pDirImpl->uType == DIRECTORYTYPE_LOCALROOT)
436 		return _osl_getNextDrive( Directory, pItem, uHint );
437 
438     pEntry = _osl_readdir_impl_(pDirImpl->pDirStruct, sal_True);
439 
440     if (NULL == pEntry)
441         return osl_File_E_NOENT;
442 
443 	pItemImpl = (DirectoryItem_Impl*) rtl_allocateMemory(sizeof(DirectoryItem_Impl));
444 	if ( !pItemImpl )
445 		return osl_File_E_NOMEM;
446 
447 	memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
448 	pItemImpl->uType = DIRECTORYITEM_FILE;
449 	pItemImpl->nRefCount = 1;
450 	pItemImpl->d_attr = pEntry->d_attr;
451 
452     /* convert file name to unicode */
453     rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ),
454         osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
455     OSL_ASSERT(ustrFileName != 0);
456 
457 	osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &pItemImpl->ustrFilePath);
458     rtl_uString_release( ustrFileName );
459 
460 	*pItem = (oslDirectoryItem)pItemImpl;
461 	return osl_File_E_None;
462 }
463 
464 /****************************************************************************/
465 /*	osl_closeDirectory */
466 /****************************************************************************/
467 
468 oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory )
469 {
470     DirectoryImpl* pDirImpl = (DirectoryImpl*) Directory;
471     oslFileError err = osl_File_E_None;
472 
473     OSL_ASSERT( Directory );
474 
475     if( NULL == pDirImpl )
476         return osl_File_E_INVAL;
477 
478 	switch ( pDirImpl->uType )
479 	{
480 	case DIRECTORYTYPE_FILESYSTEM:
481 		if( closedir( pDirImpl->pDirStruct ) )
482 			err = oslTranslateFileError(OSL_FET_ERROR, errno);
483 		break;
484 	case DIRECTORYTYPE_LOCALROOT:
485 		err = osl_File_E_None;
486 		break;
487 #if 0
488 	case DIRECTORYTYPE_NETROOT:
489 		{
490 			DWORD err = WNetCloseEnum(pDirImpl->hDirectory);
491 			eError = (err == NO_ERROR) ? osl_File_E_None : MapError(err);
492 		}
493 		break;
494 #endif
495 	default:
496 		OSL_ENSURE( 0, "Invalid directory type" );
497 		break;
498 	}
499 
500     /* cleanup members */
501     rtl_uString_release( pDirImpl->ustrPath );
502 
503     rtl_freeMemory( pDirImpl );
504 
505     return err;
506 }
507 
508 /****************************************************************************/
509 /*	osl_getDirectoryItem */
510 /****************************************************************************/
511 
512 oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem )
513 {
514     rtl_uString* 	strSysFilePath = NULL;
515     oslFileError 	error      = osl_File_E_INVAL;
516 	ULONG			dwPathType;
517 	PATHTYPE		type = PATHTYPE_FILE;
518 
519     OSL_ASSERT(ustrFileURL);
520     OSL_ASSERT(pItem);
521 
522 	/* Assume failure */
523 	if ( !pItem )
524 		return osl_File_E_INVAL;
525 	*pItem = NULL;
526 
527     if (0 == ustrFileURL->length || NULL == pItem)
528         return osl_File_E_INVAL;
529 
530     error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &strSysFilePath, sal_False);
531 
532     if (osl_File_E_None != error)
533         return error;
534 
535 	dwPathType = IsValidFilePath( strSysFilePath->buffer, NULL, VALIDATEPATH_NORMAL );
536 
537 	if ( dwPathType & PATHTYPE_IS_VOLUME )
538 		type = PATHTYPE_VOLUME;
539 	else if ( dwPathType & PATHTYPE_IS_SERVER )
540 		type = PATHTYPE_NETSERVER;
541 	else
542 		type = PATHTYPE_FILE;
543 
544 	switch ( type )
545 	{
546 	case PATHTYPE_NETSERVER:
547 		{
548 			DirectoryItem_Impl*	pItemImpl =
549 			    reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
550 
551 			if ( !pItemImpl )
552 				error = osl_File_E_NOMEM;
553 
554 			if ( osl_File_E_None == error )
555 			{
556 				memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
557 				pItemImpl->uType = DIRECTORYITEM_SERVER;
558 				pItemImpl->nRefCount = 1;
559 				rtl_uString_assign( &pItemImpl->ustrFilePath, strSysFilePath );
560 
561 				*pItem = pItemImpl;
562 			}
563 		}
564 		break;
565 	case PATHTYPE_VOLUME:
566 		{
567 			DirectoryItem_Impl*	pItemImpl =
568 			    reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
569 
570 			if ( !pItemImpl )
571 				error = osl_File_E_NOMEM;
572 
573 			if ( osl_File_E_None == error )
574 			{
575 				memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
576 				pItemImpl->uType = DIRECTORYITEM_DRIVE;
577 				pItemImpl->nRefCount = 1;
578 				rtl_uString_assign( &pItemImpl->ustrDrive, strSysFilePath );
579 
580 				if ( pItemImpl->ustrDrive->buffer[pItemImpl->ustrDrive->length-1] != sal_Unicode('\\') )
581 					rtl_uString_newConcat( &pItemImpl->ustrDrive,
582 											pItemImpl->ustrDrive, rtl::OUString::createFromAscii( "\\" ).pData);
583 
584 				*pItem = pItemImpl;
585 			}
586 		}
587 		break;
588 	default:
589 	case PATHTYPE_FILE:
590 		{
591 			if ( strSysFilePath->length > 0 && strSysFilePath->buffer[strSysFilePath->length - 1] == '\\' )
592 				rtl_uString_newFromStr_WithLength( &strSysFilePath, strSysFilePath->buffer, strSysFilePath->length - 1 );
593 
594 			if (0 == access_u(strSysFilePath, F_OK))
595 			{
596 				DirectoryItem_Impl	*pItemImpl =
597 				    reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
598 
599 				memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
600 				pItemImpl->uType = DIRECTORYITEM_FILE;
601 				pItemImpl->nRefCount = 1;
602 				rtl_uString_assign( &pItemImpl->ustrFilePath, strSysFilePath );
603 
604 				*pItem = pItemImpl;
605 			}
606 			else
607 				error = oslTranslateFileError(OSL_FET_ERROR, errno);
608 		}
609 		break;
610 	}
611 
612 	if ( strSysFilePath )
613 		rtl_uString_release( strSysFilePath );
614 
615 	return error;
616 }
617 
618 /****************************************************************************/
619 /*	osl_acquireDirectoryItem */
620 /****************************************************************************/
621 
622 oslFileError osl_acquireDirectoryItem( oslDirectoryItem Item )
623 {
624     OSL_ASSERT( Item );
625 	DirectoryItem_Impl	*pItemImpl = (DirectoryItem_Impl *)Item;
626 
627 	if ( !pItemImpl )
628 		return osl_File_E_INVAL;
629 
630 	pItemImpl->nRefCount++;
631     return osl_File_E_None;
632 }
633 
634 /****************************************************************************/
635 /*	osl_releaseDirectoryItem */
636 /****************************************************************************/
637 
638 oslFileError osl_releaseDirectoryItem( oslDirectoryItem Item )
639 {
640     OSL_ASSERT( Item );
641 	DirectoryItem_Impl	*pItemImpl = (DirectoryItem_Impl *)Item;
642 
643 	if ( !pItemImpl )
644 		return osl_File_E_INVAL;
645 
646 	if ( ! --pItemImpl->nRefCount )
647 	{
648 		if (pItemImpl->ustrFilePath)
649 			rtl_uString_release( pItemImpl->ustrFilePath );
650 		if (pItemImpl->ustrDrive)
651 			rtl_uString_release( pItemImpl->ustrDrive );
652 		rtl_freeMemory( pItemImpl );
653 	}
654 	return osl_File_E_None;
655 }
656 
657 /****************************************************************************
658  *	osl_createFileHandleFromFD
659  ***************************************************************************/
660 
661 oslFileHandle osl_createFileHandleFromFD( int fd )
662 {
663 	oslFileHandleImpl* pHandleImpl = NULL;
664 
665 	if ( fd >= 0 )
666 	{
667 		pHandleImpl = (oslFileHandleImpl*) rtl_allocateMemory( sizeof(oslFileHandleImpl) );
668 
669 		if( pHandleImpl )
670 		{
671 			pHandleImpl->ustrFilePath = NULL;
672 			rtl_uString_new( &pHandleImpl->ustrFilePath );
673 			pHandleImpl->fd = fd;
674 
675             /* FIXME: should detect whether the file has been locked */
676 			pHandleImpl->bLocked = sal_True;
677 		}
678 	}
679 
680 	return (oslFileHandle)pHandleImpl;
681 }
682 
683 /****************************************************************************
684  *	osl_openFile
685  ***************************************************************************/
686 
687 oslFileError osl_openFile( rtl_uString* ustrFileURL, oslFileHandle* pHandle, sal_uInt32 uFlags )
688 {
689     oslFileHandleImpl* pHandleImpl = NULL;
690     oslFileError eRet;
691     rtl_uString* ustrFilePath = NULL;
692 
693     char buffer[PATH_MAX];
694     int  fd;
695     int  mode  = S_IRUSR | S_IRGRP | S_IROTH;
696     int  flags = O_RDONLY;
697 
698     struct flock aflock;
699 
700     /* locking the complete file */
701     aflock.l_type = 0;
702 	aflock.l_whence = SEEK_SET;
703     aflock.l_start = 0;
704 	aflock.l_len = 0;
705 
706     OSL_ASSERT( ustrFileURL );
707     OSL_ASSERT( pHandle );
708 
709     if( ( 0 == ustrFileURL->length ) )
710         return osl_File_E_INVAL;
711 
712     /* convert file URL to system path */
713     eRet = osl_getSystemPathFromFileURL( ustrFileURL, &ustrFilePath );
714 
715     if( osl_File_E_None != eRet )
716         return eRet;
717 
718 	osl_systemPathRemoveSeparator(ustrFilePath);
719 
720     /* convert unicode path to text */
721     if( UnicodeToText( buffer, PATH_MAX, ustrFilePath->buffer, ustrFilePath->length ) )
722     {
723         /* we do not open devices or such here */
724         if( !( uFlags & osl_File_OpenFlag_Create ) )
725         {
726             struct stat aFileStat;
727 
728             if( 0 > stat( buffer, &aFileStat ) )
729             {
730                 PERROR( "osl_openFile", buffer );
731                 eRet = oslTranslateFileError(OSL_FET_ERROR, errno );
732             }
733 
734             else if( !S_ISREG( aFileStat.st_mode ) )
735             {
736                 eRet = osl_File_E_INVAL;
737             }
738         }
739 
740         if( osl_File_E_None == eRet )
741         {
742             /*
743              * set flags and mode
744              */
745 
746             if ( uFlags & osl_File_OpenFlag_Write )
747             {
748                 mode |= S_IWUSR | S_IWGRP | S_IWOTH;
749                 flags = O_RDWR;
750                 aflock.l_type = F_WRLCK;
751             }
752 
753             if ( uFlags & osl_File_OpenFlag_Create )
754             {
755                 mode |= S_IWUSR | S_IWGRP | S_IWOTH;
756                 flags = O_CREAT | O_EXCL | O_RDWR;
757             }
758 
759             /* open the file */
760             fd = open( buffer, flags | O_BINARY, mode);
761             if ( fd >= 0 )
762             {
763                 sal_Bool bNeedsLock = ( ( uFlags & osl_File_OpenFlag_NoLock ) == 0 );
764                 sal_Bool bLocked = sal_False;
765                 if( bNeedsLock )
766                 {
767                     /* check if file lock is enabled and clear l_type member of flock otherwise */
768                     if( (char *) -1 == pFileLockEnvVar )
769                     {
770                         /* FIXME: this is not MT safe */
771                         pFileLockEnvVar = getenv("SAL_ENABLE_FILE_LOCKING");
772 
773                         if( NULL == pFileLockEnvVar)
774                             pFileLockEnvVar = getenv("STAR_ENABLE_FILE_LOCKING");
775                     }
776 
777                     if( NULL == pFileLockEnvVar )
778                         aflock.l_type = 0;
779 
780                     /* lock the file if flock.l_type is set */
781                     bLocked = ( F_WRLCK != aflock.l_type || -1 != fcntl( fd, F_SETLK, &aflock ) );
782                 }
783 
784                 if ( !bNeedsLock || bLocked )
785                 {
786                     /* allocate memory for impl structure */
787                     pHandleImpl = (oslFileHandleImpl*) rtl_allocateMemory( sizeof(oslFileHandleImpl) );
788                     if( pHandleImpl )
789                     {
790                         pHandleImpl->ustrFilePath = ustrFilePath;
791                         pHandleImpl->fd = fd;
792                         pHandleImpl->bLocked = bLocked;
793 
794                         *pHandle = (oslFileHandle) pHandleImpl;
795 
796                         return osl_File_E_None;
797                     }
798                     else
799                     {
800                         errno = ENOMEM;
801                     }
802                 }
803 
804                 close( fd );
805             }
806 
807             PERROR( "osl_openFile", buffer );
808             eRet = oslTranslateFileError(OSL_FET_ERROR, errno );
809         }
810     }
811     else
812         eRet = osl_File_E_INVAL;
813 
814     rtl_uString_release( ustrFilePath );
815     return eRet;
816 }
817 
818 /****************************************************************************/
819 /*	osl_closeFile */
820 /****************************************************************************/
821 
822 oslFileError osl_closeFile( oslFileHandle Handle )
823 {
824     oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl *) Handle;
825     oslFileError eRet = osl_File_E_INVAL;
826 
827     OSL_ASSERT( Handle );
828 
829     if( pHandleImpl )
830     {
831         rtl_uString_release( pHandleImpl->ustrFilePath );
832 
833         /* release file lock if locking is enabled */
834         if( pFileLockEnvVar )
835         {
836             struct flock aflock;
837 
838             aflock.l_type = F_UNLCK;
839             aflock.l_whence = SEEK_SET;
840             aflock.l_start = 0;
841             aflock.l_len = 0;
842 
843             if ( pHandleImpl->bLocked )
844             {
845                 /* FIXME: check if file is really locked ?  */
846 
847                 /* release the file share lock on this file */
848                 if( -1 == fcntl( pHandleImpl->fd, F_SETLK, &aflock ) )
849                     PERROR( "osl_closeFile", "unlock failed" );
850             }
851         }
852 
853         if( 0 > close( pHandleImpl->fd ) )
854         {
855             eRet = oslTranslateFileError(OSL_FET_ERROR, errno );
856         }
857         else
858             eRet = osl_File_E_None;
859 
860         rtl_freeMemory( pHandleImpl );
861     }
862 
863     return eRet;
864 }
865 
866 /****************************************************************************/
867 /*	osl_isEndOfFile */
868 /****************************************************************************/
869 
870 oslFileError SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF )
871 {
872     oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl *) Handle;
873     oslFileError eRet = osl_File_E_INVAL;
874 
875 	if ( pHandleImpl)
876 	{
877 		long curPos = lseek( pHandleImpl->fd, 0, SEEK_CUR );
878 
879 		if ( curPos >= 0 )
880 		{
881 			long endPos = lseek( pHandleImpl->fd, 0, SEEK_END  );
882 
883 			if ( endPos >= 0 )
884 			{
885 				*pIsEOF = ( curPos == endPos );
886 				curPos = lseek( pHandleImpl->fd, curPos, SEEK_SET );
887 
888 				if ( curPos >= 0 )
889 					eRet = osl_File_E_None;
890 				else
891 					eRet = oslTranslateFileError(OSL_FET_ERROR, errno );
892 			}
893 			else
894 				eRet = oslTranslateFileError(OSL_FET_ERROR, errno );
895 		}
896 		else
897 			eRet = oslTranslateFileError(OSL_FET_ERROR, errno );
898 	}
899 
900 	return eRet;
901 }
902 
903 
904 /****************************************************************************/
905 /*	osl_moveFile */
906 /****************************************************************************/
907 
908 oslFileError osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
909 {
910     char srcPath[PATH_MAX];
911     char destPath[PATH_MAX];
912     oslFileError eRet;
913     APIRET rc;
914 
915     OSL_ASSERT( ustrFileURL );
916     OSL_ASSERT( ustrDestURL );
917 
918     /* convert source url to system path */
919     eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
920     if( eRet != osl_File_E_None )
921         return eRet;
922 
923     /* convert destination url to system path */
924     eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
925     if( eRet != osl_File_E_None )
926         return eRet;
927 
928     //YD 01/05/06 rename() can overwrite existing files.
929     rc = DosDelete( (PCSZ)destPath);
930     rc = DosMove( (PCSZ)srcPath, (PCSZ)destPath);
931     if (!rc)
932         eRet = osl_File_E_None;
933     else
934         eRet = MapError( rc);
935 
936     return eRet;
937 }
938 
939 /****************************************************************************/
940 /*	osl_copyFile */
941 /****************************************************************************/
942 
943 #define TMP_DEST_FILE_EXTENSION ".osl-tmp"
944 
945 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists)
946 {
947     int      nRet=0;
948     sal_Char pszTmpDestFile[PATH_MAX];
949 	size_t   size_tmp_dest_buff = sizeof(pszTmpDestFile);
950 
951 	/* Quick fix for #106048, the whole copy file function seems
952 	   to be erroneous anyway and needs to be rewritten.
953 	   Besides osl_copyFile	is currently not used from OO/SO code.
954 	*/
955 	memset(pszTmpDestFile, 0, size_tmp_dest_buff);
956 
957     if ( DestFileExists )
958     {
959 		strncpy(pszTmpDestFile, pszDestFileName, size_tmp_dest_buff - 1);
960 
961 		if ((strlen(pszTmpDestFile) + strlen(TMP_DEST_FILE_EXTENSION)) >= size_tmp_dest_buff)
962 			return osl_File_E_NAMETOOLONG;
963 
964 		strncat(pszTmpDestFile, TMP_DEST_FILE_EXTENSION, strlen(TMP_DEST_FILE_EXTENSION));
965 
966         /* FIXME: what if pszTmpDestFile already exists? */
967         /*        with getcanonical??? */
968         nRet=rename(pszDestFileName,pszTmpDestFile);
969     }
970 
971     /* mfe: should be S_ISREG */
972     if ( !S_ISLNK(nMode) )
973     {
974         /* copy SourceFile to DestFile */
975         nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode);
976     }
977     /* mfe: OK redundant at the moment */
978     else if ( S_ISLNK(nMode) )
979     {
980         nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName);
981     }
982     else
983     {
984         /* mfe: what to do here? */
985         nRet=ENOSYS;
986     }
987 
988     if ( nRet > 0 && DestFileExists == 1 )
989     {
990         unlink(pszDestFileName);
991         rename(pszTmpDestFile,pszDestFileName);
992     }
993 
994     if ( nRet > 0 )
995     {
996         return oslTranslateFileError(OSL_FET_ERROR, nRet);
997     }
998 
999     if ( DestFileExists == 1 )
1000     {
1001         unlink(pszTmpDestFile);
1002     }
1003 
1004     return osl_File_E_None;
1005 }
1006 
1007 /*****************************************
1008  * oslChangeFileModes
1009  ****************************************/
1010 
1011 static oslFileError oslChangeFileModes( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID)
1012 {
1013     int nRet=0;
1014     struct utimbuf aTimeBuffer;
1015 
1016     nRet = chmod(pszFileName,nMode);
1017     if ( nRet < 0 )
1018     {
1019         nRet=errno;
1020         return oslTranslateFileError(OSL_FET_ERROR, nRet);
1021     }
1022 
1023     aTimeBuffer.actime=nAcTime;
1024     aTimeBuffer.modtime=nModTime;
1025     nRet=utime(pszFileName,&aTimeBuffer);
1026     if ( nRet < 0 )
1027     {
1028         nRet=errno;
1029         return oslTranslateFileError(OSL_FET_ERROR, nRet);
1030     }
1031 
1032     if ( nUID != getuid() )
1033     {
1034         nUID=getuid();
1035     }
1036 
1037     nRet=chown(pszFileName,nUID,nGID);
1038     if ( nRet < 0 )
1039     {
1040         nRet=errno;
1041 
1042         /* mfe: do not return an error here! */
1043         /* return oslTranslateFileError(nRet);*/
1044     }
1045 
1046     return osl_File_E_None;
1047 }
1048 
1049 /*****************************************
1050  * oslDoCopyLink
1051  ****************************************/
1052 
1053 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName)
1054 {
1055     int nRet=0;
1056 
1057     /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */
1058     /* mfe: if source is a link copy the link and not the file it points to (hro says so) */
1059     sal_Char pszLinkContent[PATH_MAX];
1060 
1061     pszLinkContent[0] = '\0';
1062 
1063     nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX);
1064 
1065     if ( nRet < 0 )
1066     {
1067         nRet=errno;
1068         return nRet;
1069     }
1070 	else
1071 		pszLinkContent[ nRet ] = 0;
1072 
1073     nRet = symlink(pszLinkContent,pszDestFileName);
1074 
1075     if ( nRet < 0 )
1076     {
1077         nRet=errno;
1078         return nRet;
1079     }
1080 
1081     return 0;
1082 }
1083 
1084 /*****************************************
1085  * oslDoCopyFile
1086  ****************************************/
1087 
1088 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode)
1089 {
1090     int SourceFileFD=0;
1091     int DestFileFD=0;
1092     int nRet=0;
1093     void* pSourceFile=0;
1094 	char	buffer[ 4096];
1095 
1096     SourceFileFD=open(pszSourceFileName,O_RDONLY | O_BINARY);
1097     if ( SourceFileFD < 0 )
1098     {
1099         nRet=errno;
1100         return nRet;
1101     }
1102 
1103     DestFileFD=open(pszDestFileName, O_WRONLY | O_CREAT | O_BINARY, mode);
1104     if ( DestFileFD < 0 )
1105     {
1106         nRet=errno;
1107         close(SourceFileFD);
1108         return nRet;
1109     }
1110 
1111 	/* HACK: because memory mapping fails on various
1112 	   platforms if the size of the source file is  0 byte */
1113 	if (0 == nSourceSize)
1114 	{
1115 		close(SourceFileFD);
1116 		close(DestFileFD);
1117 		return 0;
1118 	}
1119 
1120 	while( (nRet = read(SourceFileFD, buffer, sizeof(buffer))) !=0 )
1121 	{
1122 		nRet = write( DestFileFD, buffer, nRet);
1123 	}
1124 
1125     close(SourceFileFD);
1126     close(DestFileFD);
1127 
1128     return nRet;
1129 }
1130 
1131 static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath )
1132 {
1133     time_t nAcTime=0;
1134     time_t nModTime=0;
1135     uid_t nUID=0;
1136     gid_t nGID=0;
1137     int nRet=0;
1138     mode_t nMode=0;
1139     struct stat aFileStat;
1140     oslFileError tErr=osl_File_E_invalidError;
1141     size_t nSourceSize=0;
1142     int DestFileExists=1;
1143 
1144     /* mfe: does the source file really exists? */
1145     nRet = lstat(pszPath,&aFileStat);
1146 
1147     if ( nRet < 0 )
1148     {
1149         nRet=errno;
1150         return oslTranslateFileError(OSL_FET_ERROR, nRet);
1151     }
1152 
1153     /* mfe: we do only copy files here! */
1154     if ( S_ISDIR(aFileStat.st_mode) )
1155     {
1156         return osl_File_E_ISDIR;
1157     }
1158 
1159     nSourceSize=(size_t)aFileStat.st_size;
1160     nMode=aFileStat.st_mode;
1161     nAcTime=aFileStat.st_atime;
1162     nModTime=aFileStat.st_mtime;
1163     nUID=aFileStat.st_uid;
1164     nGID=aFileStat.st_gid;
1165 
1166     nRet = stat(pszDestPath,&aFileStat);
1167     if ( nRet < 0 )
1168     {
1169         nRet=errno;
1170 
1171         if ( nRet == ENOENT )
1172         {
1173             DestFileExists=0;
1174         }
1175 /*        return oslTranslateFileError(nRet);*/
1176     }
1177 
1178     /* mfe: the destination file must not be a directory! */
1179     if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) )
1180     {
1181         return osl_File_E_ISDIR;
1182     }
1183     else
1184     {
1185         /* mfe: file does not exists or is no dir */
1186     }
1187 
1188     tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists);
1189 
1190     if ( tErr != osl_File_E_None )
1191     {
1192         return tErr;
1193     }
1194 
1195     /*
1196      *   mfe: ignore return code
1197      *        since only  the success of the copy is
1198      *        important
1199      */
1200     oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID);
1201 
1202     return tErr;
1203 }
1204 
1205 oslFileError osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
1206 {
1207     char srcPath[PATH_MAX];
1208     char destPath[PATH_MAX];
1209     oslFileError eRet;
1210     APIRET rc;
1211 
1212     OSL_ASSERT( ustrFileURL );
1213     OSL_ASSERT( ustrDestURL );
1214 
1215     /* convert source url to system path */
1216     eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
1217     if( eRet != osl_File_E_None )
1218         return eRet;
1219 
1220     /* convert destination url to system path */
1221     eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
1222     if( eRet != osl_File_E_None )
1223         return eRet;
1224 
1225     return osl_psz_copyFile( srcPath, destPath );
1226 }
1227 
1228 /****************************************************************************/
1229 /*	osl_removeFile */
1230 /****************************************************************************/
1231 
1232 oslFileError osl_removeFile( rtl_uString* ustrFileURL )
1233 {
1234     char path[PATH_MAX];
1235     oslFileError eRet;
1236     APIRET rc;
1237 
1238     OSL_ASSERT( ustrFileURL );
1239 
1240     /* convert file url to system path */
1241     eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
1242     if( eRet != osl_File_E_None )
1243         return eRet;
1244 
1245     rc = DosDelete( (PCSZ)path);
1246     if (!rc)
1247         eRet = osl_File_E_None;
1248     else
1249         eRet = MapError( rc);
1250 
1251     return eRet;
1252 }
1253 
1254 /****************************************************************************/
1255 /*	osl_getVolumeInformation */
1256 /****************************************************************************/
1257 
1258 #define TXFSDC_BLOCKR         0x00              // block device removable
1259 #define TXFSDC_GETBPB         0x00              // get device bpb info
1260 #define TXFSBPB_REMOVABLE     0x08              // BPB attribute for removable
1261 
1262 typedef struct drivecmd
1263 {
1264    BYTE                cmd;                     // 0=unlock 1=lock 2=eject
1265    BYTE                drv;                     // 0=A, 1=B 2=C ...
1266 } DRIVECMD;                                     // end of struct "drivecmd"
1267 
1268 #pragma pack(push, 1)                           // byte packing
1269 typedef struct txfs_ebpb                        // ext. boot parameter block
1270 {                                               // at offset 0x0b in bootsector
1271    USHORT              SectSize;                // 0B bytes per sector
1272    BYTE                ClustSize;               // 0D sectors per cluster
1273    USHORT              FatOffset;               // 0E sectors to 1st FAT
1274    BYTE                NrOfFats;                // 10 nr of FATS     (FAT only)
1275    USHORT              RootEntries;             // 11 Max entries \ (FAT only)
1276    USHORT              Sectors;                 // 13 nr of sectors if <  64K
1277    BYTE                MediaType;               // 15 mediatype (F8 for HD)
1278    USHORT              FatSectors;              // 16 sectors/FAT (FAT only)
1279    USHORT              LogGeoSect;              // 18 sectors/Track
1280    USHORT              LogGeoHead;              // 1a nr of heads
1281    ULONG               HiddenSectors;           // 1c sector-offset from MBR/EBR
1282    ULONG               BigSectors;              // 20 nr of sectors if >= 64K
1283 } TXFS_EBPB;                                    // last byte is at offset 0x23
1284 
1285 typedef struct drivebpb
1286 {
1287    TXFS_EBPB           ebpb;                    // extended BPB
1288    BYTE                reserved[6];
1289    USHORT              cyls;
1290    BYTE                type;
1291    USHORT              attributes;              // device attributes
1292    BYTE                fill[6];                 // documented for IOCtl
1293 } DRIVEBPB;                                     // end of struct "drivebpb"
1294 
1295 struct CDInfo {
1296     USHORT usCount;
1297     USHORT usFirst;
1298 };
1299 
1300 #pragma pack(pop)
1301 
1302 /*****************************************************************************/
1303 // Get number of cdrom readers
1304 /*****************************************************************************/
1305 BOOL GetCDInfo( CDInfo * pCDInfo )
1306 {
1307     HFILE hFileCD;
1308     ULONG ulAction;
1309 
1310     if( NO_ERROR == DosOpen( (PCSZ)"\\DEV\\CD-ROM2$",
1311                             &hFileCD, &ulAction, 0, FILE_NORMAL,
1312                             OPEN_ACTION_OPEN_IF_EXISTS,
1313                             OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL )) {
1314         ULONG  ulDataSize = sizeof(CDInfo);
1315         APIRET rc = DosDevIOCtl( hFileCD, 0x82, 0x60, NULL, 0,
1316                                  NULL, (PVOID)pCDInfo, ulDataSize, &ulDataSize);
1317         DosClose( hFileCD);
1318         if(rc == NO_ERROR)
1319             return TRUE;
1320     }
1321 	// failed
1322     pCDInfo->usFirst = 0;
1323     pCDInfo->usCount = 0;
1324     return FALSE;
1325 }
1326 
1327 /*****************************************************************************/
1328 // Determine if unit is a cdrom or not
1329 /*****************************************************************************/
1330 BOOL DriveIsCDROM(UINT uiDrive, CDInfo *pCDInfo)
1331 {
1332 	return (uiDrive >= pCDInfo->usFirst)
1333 			&& (uiDrive < (pCDInfo->usFirst + pCDInfo->usCount));
1334 }
1335 
1336 /*****************************************************************************/
1337 // Determine attached fstype, e.g. HPFS for specified drive
1338 /*****************************************************************************/
1339 BOOL TxFsType                                   // RET   FS type resolved
1340 (
1341    char               *drive,                   // IN    Drive specification
1342    char               *fstype,                  // OUT   Attached FS type
1343    char               *details                  // OUT   details (UNC) or NULL
1344 )
1345 {
1346    BOOL                rc = FALSE;
1347    FSQBUFFER2         *fsinfo;                     // Attached FS info
1348    ULONG               fsdlen = 2048;              // Fs info data length
1349 
1350    strcpy(fstype, "none");
1351    if (details)
1352    {
1353       strcpy(details, "");
1354    }
1355    if ((fsinfo = (FSQBUFFER2*)calloc(1, fsdlen)) != NULL)
1356    {
1357       if (DosQFSAttach((PCSZ)drive, 0, 1, fsinfo, &fsdlen) == NO_ERROR)
1358       {
1359          strcpy(fstype, (char*) fsinfo->szName + fsinfo->cbName +1);
1360          if (details && (fsinfo->cbFSAData != 0))
1361          {
1362             strcpy( details, (char*) fsinfo->szName + fsinfo->cbName +
1363                                               fsinfo->cbFSDName +2);
1364          }
1365          rc = TRUE;
1366       }
1367       free(fsinfo);
1368    }
1369    return (rc);
1370 }                                               // end 'TxFsType'
1371 /*---------------------------------------------------------------------------*/
1372 
1373 
1374 /*****************************************************************************/
1375 // Determine if a driveletter represents a removable medium/device
1376 /*****************************************************************************/
1377 BOOL TxFsIsRemovable                            // RET   drive is removable
1378 (
1379    char               *drive                    // IN    Driveletter to test
1380 )
1381 {
1382    BOOL                rc = FALSE;
1383    DRIVECMD            IOCtl;
1384    DRIVEBPB            RemAt;
1385    ULONG               DataLen;
1386    ULONG               ParmLen;
1387    BYTE                NoRem;
1388 
1389    DosError( FERR_DISABLEHARDERR);              // avoid 'not ready' popups
1390 
1391    ParmLen   = sizeof(IOCtl);
1392    IOCtl.cmd = TXFSDC_BLOCKR;
1393    IOCtl.drv = toupper(drive[0]) - 'A';
1394    DataLen   = sizeof(NoRem);
1395 
1396    if (DosDevIOCtl((HFILE) -1, IOCTL_DISK,
1397                                DSK_BLOCKREMOVABLE,
1398                                &IOCtl, ParmLen, &ParmLen,
1399                                &NoRem, DataLen, &DataLen) == NO_ERROR)
1400    {
1401       if (NoRem)                                // non-removable sofar, check
1402       {                                         // BPB as well (USB devices)
1403          ParmLen   = sizeof(IOCtl);
1404          IOCtl.cmd = TXFSDC_GETBPB;
1405          IOCtl.drv = toupper(drive[0]) - 'A';
1406          DataLen   = sizeof(RemAt);
1407 
1408          if (DosDevIOCtl((HFILE) -1, IOCTL_DISK,
1409                                      DSK_GETDEVICEPARAMS,
1410                                      &IOCtl, ParmLen, &ParmLen,
1411                                      &RemAt, DataLen, &DataLen) == NO_ERROR)
1412 
1413          {
1414             if (RemAt.attributes & TXFSBPB_REMOVABLE)
1415             {
1416                rc = TRUE;                       // removable, probably USB
1417             }
1418          }
1419       }
1420       else
1421       {
1422          rc = TRUE;                             // removable block device
1423       }
1424    }
1425    DosError( FERR_ENABLEHARDERR);               // enable criterror handler
1426    return (rc);
1427 }                                               // end 'TxFsIsRemovable'
1428 /*---------------------------------------------------------------------------*/
1429 
1430 static oslFileError get_drive_type(const char* path, oslVolumeInfo* pInfo)
1431 {
1432 	char		Drive_Letter = toupper( *path);
1433 	char		fstype[ 64];
1434 
1435 	pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
1436 
1437 	// check for floppy A/B
1438     BYTE 	nFloppies;
1439 	APIRET	rc;
1440     rc = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY );
1441 	if ((Drive_Letter - 'A') < nFloppies) {
1442 		pInfo->uAttributes |= osl_Volume_Attribute_Removeable;
1443 		pInfo->uAttributes |= osl_Volume_Attribute_FloppyDisk;
1444 		return osl_File_E_None;
1445 	}
1446 
1447 	// query system for CD drives
1448 	CDInfo cdInfo;
1449 	GetCDInfo(&cdInfo);
1450 
1451 	// query if drive is a CDROM
1452 	if (DriveIsCDROM( Drive_Letter - 'A', &cdInfo))
1453 		pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable;
1454 
1455 	if (TxFsIsRemovable( (char*)path))
1456 		pInfo->uAttributes |= osl_Volume_Attribute_Removeable;
1457 
1458 	if (TxFsType( (char*)path, fstype, NULL) == FALSE) {
1459 		// query failed, assume fixed disk
1460 		pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk;
1461 		return osl_File_E_None;
1462 	}
1463 
1464 	//- Note, connected Win-NT drives use the REAL FS-name like NTFS!
1465 	if ((strncasecmp( fstype, "LAN", 3) == 0) 			//- OS/2 LAN drives
1466 		|| (strncasecmp( fstype, "NDFS", 4) == 0)  	//- NetDrive
1467 		|| (strncasecmp( fstype, "REMOTE", 5) == 0)  )  //- NT disconnected
1468 		pInfo->uAttributes |= osl_Volume_Attribute_Remote;
1469 	else if (strncasecmp( fstype, "RAMFS", 5) == 0)
1470 		pInfo->uAttributes |= osl_Volume_Attribute_RAMDisk;
1471 	else if ((strncasecmp( fstype, "CD",  2) == 0)	 	// OS2:CDFS, DOS/WIN:CDROM
1472 		|| (strncasecmp( fstype, "UDF", 3) == 0)   ) 	// OS2:UDF DVD's
1473 		pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable;
1474 	else
1475 		pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk;
1476 
1477 	return osl_File_E_None;
1478 }
1479 
1480 //#############################################
1481 inline bool is_volume_space_info_request(sal_uInt32 field_mask)
1482 {
1483 	return (field_mask &
1484 			(osl_VolumeInfo_Mask_TotalSpace |
1485 			 osl_VolumeInfo_Mask_UsedSpace  |
1486 			 osl_VolumeInfo_Mask_FreeSpace));
1487 }
1488 
1489 //#############################################
1490 static void get_volume_space_information(const char* path, oslVolumeInfo *pInfo)
1491 {
1492     FSALLOCATE aFSInfoBuf;
1493     ULONG nDriveNumber = toupper( *path) - 'A' + 1;
1494 
1495 	// disable error popups
1496 	DosError(FERR_DISABLEHARDERR);
1497     APIRET rc = DosQueryFSInfo( nDriveNumber, FSIL_ALLOC,
1498                                 &aFSInfoBuf, sizeof(aFSInfoBuf) );
1499 	// enable error popups
1500 	DosError(FERR_ENABLEHARDERR);
1501 	if (!rc)
1502 	{
1503 		uint64_t aBytesPerCluster( uint64_t(aFSInfoBuf.cbSector) *
1504 								 uint64_t(aFSInfoBuf.cSectorUnit) );
1505 		pInfo->uFreeSpace = aBytesPerCluster * uint64_t(aFSInfoBuf.cUnitAvail);
1506 		pInfo->uTotalSpace = aBytesPerCluster * uint64_t(aFSInfoBuf.cUnit);
1507 		pInfo->uUsedSpace    = pInfo->uTotalSpace - pInfo->uFreeSpace;
1508 		pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace |
1509 							   osl_VolumeInfo_Mask_UsedSpace |
1510 							   osl_VolumeInfo_Mask_FreeSpace;
1511 	}
1512 }
1513 
1514 //#############################################
1515 inline bool is_filesystem_attributes_request(sal_uInt32 field_mask)
1516 {
1517 	return (field_mask &
1518 			(osl_VolumeInfo_Mask_MaxNameLength |
1519 			 osl_VolumeInfo_Mask_MaxPathLength |
1520 			 osl_VolumeInfo_Mask_FileSystemName |
1521 			 osl_VolumeInfo_Mask_FileSystemCaseHandling));
1522 }
1523 
1524 //#############################################
1525 inline bool is_drivetype_request(sal_uInt32 field_mask)
1526 {
1527 	return (field_mask & osl_VolumeInfo_Mask_Attributes);
1528 }
1529 
1530 typedef struct _FSQBUFFER_
1531 {
1532     FSQBUFFER2  aBuf;
1533     UCHAR       sBuf[64];
1534 } FSQBUFFER_;
1535 
1536 //#############################################
1537 static oslFileError get_filesystem_attributes(const char* path, sal_uInt32 field_mask, oslVolumeInfo* pInfo)
1538 {
1539 	pInfo->uAttributes = 0;
1540 
1541 	oslFileError osl_error = osl_File_E_None;
1542 
1543 	// osl_get_drive_type must be called first because
1544 	// this function resets osl_VolumeInfo_Mask_Attributes
1545 	// on failure
1546 	if (is_drivetype_request(field_mask))
1547 		osl_error = get_drive_type(path, pInfo);
1548 
1549 	if ((osl_File_E_None == osl_error) && is_filesystem_attributes_request(field_mask))
1550 	{
1551 		FSQBUFFER_	aBuf;
1552 		ULONG       nBufLen;
1553 		APIRET      nRet;
1554 
1555         nBufLen = sizeof( aBuf );
1556 		// disable error popups
1557 		DosError(FERR_DISABLEHARDERR);
1558         nRet = DosQueryFSAttach( (PCSZ)path, 0, FSAIL_QUERYNAME, (_FSQBUFFER2*) &aBuf, &nBufLen );
1559         if ( !nRet )
1560         {
1561             char *pType = (char*)(aBuf.aBuf.szName + aBuf.aBuf.cbName + 1);
1562 			pInfo->uValidFields   |= osl_VolumeInfo_Mask_MaxNameLength;
1563 			pInfo->uMaxNameLength  = _MAX_FNAME;
1564 
1565 			pInfo->uValidFields   |= osl_VolumeInfo_Mask_MaxPathLength;
1566 			pInfo->uMaxPathLength  = _MAX_PATH;
1567 
1568 			pInfo->uValidFields   |= osl_VolumeInfo_Mask_FileSystemName;
1569 			rtl_uString_newFromAscii(&pInfo->ustrFileSystemName, pType);
1570 
1571 			// case is preserved always except for FAT
1572 			if (strcmp( pType, "FAT" ))
1573 				pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
1574 
1575 			pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
1576 		}
1577 		// enable error popups
1578 		DosError(FERR_ENABLEHARDERR);
1579 	}
1580 	return osl_error;
1581 }
1582 
1583 oslFileError SAL_CALL osl_getVolumeInformation( rtl_uString* ustrDirectoryURL, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask )
1584 {
1585     char volume_root[PATH_MAX];
1586     oslFileError error;
1587 
1588     OSL_ASSERT( ustrDirectoryURL );
1589     OSL_ASSERT( pInfo );
1590 
1591     /* convert directory url to system path */
1592     error = FileURLToPath( volume_root, PATH_MAX, ustrDirectoryURL );
1593     if( error != osl_File_E_None )
1594         return error;
1595 
1596 	if (!pInfo)
1597 		return osl_File_E_INVAL;
1598 
1599 	pInfo->uValidFields = 0;
1600 
1601     if ((error = get_filesystem_attributes(volume_root, uFieldMask, pInfo)) != osl_File_E_None)
1602         return error;
1603 
1604 	if (is_volume_space_info_request(uFieldMask))
1605 	    get_volume_space_information(volume_root, pInfo);
1606 
1607 	if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle)
1608 	{
1609 		pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle;
1610 		rtl_uString* uVolumeRoot;
1611 		rtl_uString_newFromAscii( &uVolumeRoot, volume_root);
1612 		osl_getFileURLFromSystemPath( uVolumeRoot, (rtl_uString**)&pInfo->pDeviceHandle);
1613 		rtl_uString_release( uVolumeRoot);
1614 	}
1615 
1616 	return osl_File_E_None;
1617 }
1618 
1619 /****************************************************************************/
1620 /*	osl_getFileStatus */
1621 /****************************************************************************/
1622 static oslFileError _osl_getDriveInfo(
1623 	oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask)
1624 {
1625 	DirectoryItem_Impl	*pItemImpl = (DirectoryItem_Impl *)Item;
1626 	sal_Unicode			cDrive[3];
1627 	sal_Unicode			cRoot[4];
1628 
1629 	if ( !pItemImpl )
1630 		return osl_File_E_INVAL;
1631 
1632 	pStatus->uValidFields = 0;
1633 
1634 	cDrive[0] = pItemImpl->ustrDrive->buffer[0];
1635 	cDrive[1] = (sal_Unicode)':';
1636 	cDrive[2] = 0;
1637 	cRoot[0] = pItemImpl->ustrDrive->buffer[0];
1638 	cRoot[1] = (sal_Unicode)':';
1639 	cRoot[2] = 0;
1640 
1641 	if ( uFieldMask & osl_FileStatus_Mask_FileName )
1642 	{
1643 		if ( pItemImpl->ustrDrive->buffer[0] == '\\' &&
1644 			pItemImpl->ustrDrive->buffer[1] == '\\' )
1645 		{
1646 			LPCWSTR	lpFirstBkSlash = wcschr( (const wchar_t*)&pItemImpl->ustrDrive->buffer[2], '\\' );
1647 
1648 			if ( lpFirstBkSlash && lpFirstBkSlash[1] )
1649 			{
1650 				LPCWSTR	lpLastBkSlash = wcschr( (const wchar_t*)&lpFirstBkSlash[1], '\\' );
1651 
1652 				if ( lpLastBkSlash )
1653 					rtl_uString_newFromStr_WithLength( &pStatus->ustrFileName, (sal_Unicode*)&lpFirstBkSlash[1], lpLastBkSlash - lpFirstBkSlash - 1 );
1654 				else
1655 					rtl_uString_newFromStr( &pStatus->ustrFileName, (sal_Unicode*)&lpFirstBkSlash[1] );
1656 				pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1657 			}
1658 		}
1659 		else
1660 		{
1661 			FSINFO	aFSInfoBuf;
1662 			ULONG   ulFSInfoLevel = FSIL_VOLSER;
1663 			ULONG   nDriveNumber;
1664 			char	szFileName[ _MAX_PATH];
1665 
1666 			nDriveNumber = toupper(*cDrive) - 'A' + 1;
1667 			memset( &aFSInfoBuf, 0, sizeof(FSINFO) );
1668 			// disable error popups
1669 			DosError(FERR_DISABLEHARDERR);
1670 			APIRET rc = DosQueryFSInfo( nDriveNumber, ulFSInfoLevel, &aFSInfoBuf, sizeof(FSINFO) );
1671 			// enable error popups
1672 			DosError(FERR_ENABLEHARDERR);
1673 			memset( szFileName, 0, sizeof( szFileName));
1674 			*szFileName = toupper(*cDrive);
1675 			strcat( szFileName, ": [");
1676 			if ( !rc || aFSInfoBuf.vol.cch)
1677 				strncat( szFileName, aFSInfoBuf.vol.szVolLabel, aFSInfoBuf.vol.cch);
1678 			strcat( szFileName, "]");
1679 			rtl_uString_newFromAscii( &pStatus->ustrFileName, szFileName );
1680 
1681 			pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1682 		}
1683 	}
1684 
1685 	pStatus->eType = osl_File_Type_Volume;
1686 	pStatus->uValidFields |= osl_FileStatus_Mask_Type;
1687 
1688 	if ( uFieldMask & osl_FileStatus_Mask_FileURL )
1689 	{
1690 		rtl_uString	*ustrSystemPath = NULL;
1691 
1692 		rtl_uString_newFromStr( &ustrSystemPath, pItemImpl->ustrDrive->buffer );
1693 		osl_getFileURLFromSystemPath( ustrSystemPath, &pStatus->ustrFileURL );
1694 		rtl_uString_release( ustrSystemPath );
1695 		pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
1696 	}
1697 
1698 	return osl_File_E_None;
1699 }
1700 
1701 oslFileError SAL_CALL osl_getFileStatus(
1702     oslDirectoryItem Item,
1703     oslFileStatus *pStatus,
1704     sal_uInt32 uFieldMask )
1705 {
1706 	DirectoryItem_Impl	*pItemImpl = (DirectoryItem_Impl *)Item;
1707 	struct stat file_stat;
1708 
1709 	if ( !pItemImpl )
1710 		return osl_File_E_INVAL;
1711 
1712 	if ( pItemImpl->uType == DIRECTORYITEM_DRIVE)
1713 		return _osl_getDriveInfo( Item, pStatus, uFieldMask );
1714 
1715 	osl::lstat(pItemImpl->ustrFilePath, file_stat);
1716 	if ( uFieldMask & osl_FileStatus_Mask_Validate )
1717 	{
1718 		uFieldMask &= ~	osl_FileStatus_Mask_Validate;
1719 	}
1720 
1721 	/* If no fields to retrieve left ignore pStatus */
1722 	if ( !uFieldMask )
1723 		return osl_File_E_None;
1724 
1725 	/* Otherwise, this must be a valid pointer */
1726 	if ( !pStatus )
1727 		return osl_File_E_INVAL;
1728 
1729 	if ( pStatus->uStructSize != sizeof(oslFileStatus) )
1730 		return osl_File_E_INVAL;
1731 
1732 	pStatus->uValidFields = 0;
1733 
1734 	/* File time stamps */
1735 
1736 	if ( (uFieldMask & osl_FileStatus_Mask_ModifyTime))
1737 	{
1738 	    pStatus->aModifyTime.Seconds  = file_stat.st_mtime;
1739     	pStatus->aModifyTime.Nanosec  = 0;
1740 		pStatus->uValidFields |= osl_FileStatus_Mask_ModifyTime;
1741 	}
1742 
1743 	if ( (uFieldMask & osl_FileStatus_Mask_AccessTime))
1744 	{
1745 		pStatus->aAccessTime.Seconds  = file_stat.st_atime;
1746     	pStatus->aAccessTime.Nanosec  = 0;
1747 		pStatus->uValidFields |= osl_FileStatus_Mask_AccessTime;
1748 	}
1749 
1750 	if ( (uFieldMask & osl_FileStatus_Mask_CreationTime))
1751 	{
1752 		pStatus->aAccessTime.Seconds  = file_stat.st_birthtime;
1753     	pStatus->aAccessTime.Nanosec  = 0;
1754 		pStatus->uValidFields |= osl_FileStatus_Mask_CreationTime;
1755 	}
1756 
1757 	/* Most of the fields are already set, regardless of requiered fields */
1758 
1759 	osl_systemPathGetFileNameOrLastDirectoryPart(pItemImpl->ustrFilePath, &pStatus->ustrFileName);
1760 	pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
1761 
1762 	if (S_ISLNK(file_stat.st_mode))
1763 	   pStatus->eType = osl_File_Type_Link;
1764 	else if (S_ISDIR(file_stat.st_mode))
1765 	   pStatus->eType = osl_File_Type_Directory;
1766 	else if (S_ISREG(file_stat.st_mode))
1767 	   pStatus->eType = osl_File_Type_Regular;
1768 	else if (S_ISFIFO(file_stat.st_mode))
1769 	   pStatus->eType = osl_File_Type_Fifo;
1770 	else if (S_ISSOCK(file_stat.st_mode))
1771 	   pStatus->eType = osl_File_Type_Socket;
1772 	else if (S_ISCHR(file_stat.st_mode) || S_ISBLK(file_stat.st_mode))
1773 	   pStatus->eType = osl_File_Type_Special;
1774 	else
1775 	   pStatus->eType = osl_File_Type_Unknown;
1776 
1777 	pStatus->uValidFields |= osl_FileStatus_Mask_Type;
1778 
1779 	pStatus->uAttributes = pItemImpl->d_attr;
1780 	pStatus->uValidFields |= osl_FileStatus_Mask_Attributes;
1781 
1782 	pStatus->uFileSize = file_stat.st_size;
1783 	pStatus->uValidFields |= osl_FileStatus_Mask_FileSize;
1784 
1785 	if ( uFieldMask & osl_FileStatus_Mask_LinkTargetURL )
1786 	{
1787 		rtl_uString	*ustrFullPath = NULL;
1788 
1789 		rtl_uString_newFromStr( &ustrFullPath, rtl_uString_getStr(pItemImpl->ustrFilePath) );
1790 		osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrLinkTargetURL );
1791 		rtl_uString_release( ustrFullPath );
1792 
1793 		pStatus->uValidFields |= osl_FileStatus_Mask_LinkTargetURL;
1794 	}
1795 
1796 	if ( uFieldMask & osl_FileStatus_Mask_FileURL )
1797 	{
1798 		rtl_uString	*ustrFullPath = NULL;
1799 
1800 		rtl_uString_newFromStr( &ustrFullPath, rtl_uString_getStr(pItemImpl->ustrFilePath) );
1801 		osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrFileURL );
1802 		rtl_uString_release( ustrFullPath );
1803 		pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
1804 	}
1805 
1806 	return osl_File_E_None;
1807 }
1808 
1809 /****************************************************************************/
1810 /*	osl_createDirectory */
1811 /****************************************************************************/
1812 
1813 oslFileError osl_createDirectory( rtl_uString* ustrDirectoryURL )
1814 {
1815     char path[PATH_MAX];
1816     oslFileError eRet;
1817 	APIRET rc;
1818 
1819     OSL_ASSERT( ustrDirectoryURL );
1820 
1821     /* convert directory url to system path */
1822     eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
1823     if( eRet != osl_File_E_None )
1824         return eRet;
1825 
1826     rc = DosCreateDir( (PCSZ)path, NULL);
1827     if (rc == ERROR_ACCESS_DENIED)
1828        rc=ERROR_FILE_EXISTS;
1829 
1830     if (!rc)
1831         eRet = osl_File_E_None;
1832     else
1833         eRet = MapError( rc);
1834 
1835     return eRet;
1836 }
1837 
1838 /****************************************************************************/
1839 /*	osl_removeDirectory */
1840 /****************************************************************************/
1841 
1842 oslFileError osl_removeDirectory( rtl_uString* ustrDirectoryURL )
1843 {
1844     char path[PATH_MAX];
1845     oslFileError eRet;
1846 	APIRET rc;
1847 
1848     OSL_ASSERT( ustrDirectoryURL );
1849 
1850     /* convert directory url to system path */
1851     eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
1852     if( eRet != osl_File_E_None )
1853         return eRet;
1854 
1855     rc = DosDeleteDir( (PCSZ)path);
1856     if (!rc)
1857         eRet = osl_File_E_None;
1858     else
1859         eRet = MapError( rc);
1860 
1861     return eRet;
1862 }
1863 
1864 //#############################################
1865 int path_make_parent(sal_Unicode* path)
1866 {
1867 	int i = rtl_ustr_lastIndexOfChar(path, '/');
1868 
1869 	if (i > 0)
1870 	{
1871 		*(path + i) = 0;
1872 		return i;
1873 	}
1874 	else
1875 		return 0;
1876 }
1877 
1878 //#############################################
1879 int create_dir_with_callback(
1880 	sal_Unicode* directory_path,
1881     oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
1882     void* pData)
1883 {
1884 	int mode = S_IRWXU | S_IRWXG | S_IRWXO;
1885 
1886 	if (osl::mkdir(directory_path, mode) == 0)
1887     {
1888     	if (aDirectoryCreationCallbackFunc)
1889         {
1890         	rtl::OUString url;
1891             osl::FileBase::getFileURLFromSystemPath(directory_path, url);
1892             aDirectoryCreationCallbackFunc(pData, url.pData);
1893         }
1894         return 0;
1895     }
1896     return errno;
1897 }
1898 
1899 //#############################################
1900 oslFileError create_dir_recursively_(
1901 	sal_Unicode* dir_path,
1902     oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
1903     void* pData)
1904 {
1905 	OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \
1906 	"Path must not end with a slash");
1907 
1908 	int native_err = create_dir_with_callback(
1909     	dir_path, aDirectoryCreationCallbackFunc, pData);
1910 
1911 	if (native_err == 0)
1912         return osl_File_E_None;
1913 
1914     if (native_err != ENOENT)
1915     	return oslTranslateFileError(OSL_FET_ERROR, native_err);
1916 
1917 	// we step back until '/a_dir' at maximum because
1918 	// we should get an error unequal ENOENT when
1919 	// we try to create 'a_dir' at '/' and would so
1920 	// return before
1921 	int pos = path_make_parent(dir_path);
1922 
1923     oslFileError osl_error = create_dir_recursively_(
1924     	dir_path, aDirectoryCreationCallbackFunc, pData);
1925 
1926     if (osl_File_E_None != osl_error)
1927     	return osl_error;
1928 
1929    	dir_path[pos] = '/';
1930 
1931     return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
1932 }
1933 
1934 //#######################################
1935 oslFileError SAL_CALL osl_createDirectoryPath(
1936 	rtl_uString* aDirectoryUrl,
1937     oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
1938     void* pData)
1939 {
1940     if (aDirectoryUrl == NULL)
1941         return osl_File_E_INVAL;
1942 
1943     rtl::OUString sys_path;
1944     oslFileError osl_error = osl_getSystemPathFromFileURL_Ex(
1945         aDirectoryUrl, &sys_path.pData, sal_False);
1946 
1947     if (osl_error != osl_File_E_None)
1948         return osl_error;
1949 
1950     osl::systemPathRemoveSeparator(sys_path);
1951 
1952     // const_cast because sys_path is a local copy which we want to modify inplace instead of
1953     // coyp it into another buffer on the heap again
1954 	return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData);
1955 }
1956 
1957 /****************************************************************************/
1958 /*	osl_getCanonicalName */
1959 /****************************************************************************/
1960 
1961 oslFileError osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uString** pustrValidURL )
1962 {
1963 	OSL_ENSURE(sal_False, "osl_getCanonicalName not implemented");
1964 
1965 	rtl_uString_newFromString(pustrValidURL, ustrFileURL);
1966 	return osl_File_E_None;
1967 }
1968 
1969 
1970 /****************************************************************************/
1971 /*	osl_setFileAttributes */
1972 /****************************************************************************/
1973 
1974 oslFileError osl_setFileAttributes( rtl_uString* ustrFileURL, sal_uInt64 uAttributes )
1975 {
1976     char         path[PATH_MAX];
1977     oslFileError eRet;
1978     FILESTATUS3  fsts3ConfigInfo;
1979     ULONG        ulBufSize     = sizeof(FILESTATUS3);
1980     APIRET       rc            = NO_ERROR;
1981 
1982     OSL_ASSERT( ustrFileURL );
1983 
1984     /* convert file url to system path */
1985     eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
1986     if( eRet != osl_File_E_None )
1987         return eRet;
1988 
1989     /* query current attributes */
1990     rc = DosQueryPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
1991     if (rc != NO_ERROR)
1992         return MapError( rc);
1993 
1994     /* set/reset readonly/hidden (see w32\file.cxx) */
1995     fsts3ConfigInfo.attrFile &= ~(FILE_READONLY | FILE_HIDDEN);
1996     if ( uAttributes & osl_File_Attribute_ReadOnly )
1997         fsts3ConfigInfo.attrFile |= FILE_READONLY;
1998     if ( uAttributes & osl_File_Attribute_Hidden )
1999         fsts3ConfigInfo.attrFile |= FILE_HIDDEN;
2000 
2001     /* write new attributes */
2002     rc = DosSetPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize, 0);
2003     if (rc != NO_ERROR)
2004         return MapError( rc);
2005 
2006     /* everything ok */
2007     return osl_File_E_None;
2008 }
2009 
2010 /****************************************************************************/
2011 /*	osl_setFileTime */
2012 /****************************************************************************/
2013 
2014 oslFileError osl_setFileTime( rtl_uString* ustrFileURL, const TimeValue* pCreationTime,
2015                               const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime )
2016 {
2017     char path[PATH_MAX];
2018     oslFileError eRet;
2019 
2020     OSL_ASSERT( ustrFileURL );
2021 
2022     /* convert file url to system path */
2023     eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
2024     if( eRet != osl_File_E_None )
2025         return eRet;
2026 
2027     return osl_psz_setFileTime( path, pCreationTime, pLastAccessTime, pLastWriteTime );
2028 }
2029 
2030 /******************************************************************************
2031  *
2032  *                  Exported Module Functions
2033  *             (independent of C or Unicode Strings)
2034  *
2035  *****************************************************************************/
2036 
2037 
2038 /*******************************************
2039     osl_readFile
2040 ********************************************/
2041 
2042 oslFileError osl_readFile(oslFileHandle Handle, void* pBuffer, sal_uInt64 uBytesRequested, sal_uInt64* pBytesRead)
2043 {
2044     ssize_t            nBytes      = 0;
2045     oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl*)Handle;
2046 
2047     if ((0 == pHandleImpl) || (pHandleImpl->fd < 0) || (0 == pBuffer) || (0 == pBytesRead))
2048         return osl_File_E_INVAL;
2049 
2050     nBytes = read(pHandleImpl->fd, pBuffer, uBytesRequested);
2051 
2052     if (-1 == nBytes)
2053         return oslTranslateFileError(OSL_FET_ERROR, errno);
2054 
2055     *pBytesRead = nBytes;
2056     return osl_File_E_None;
2057 }
2058 
2059 /*******************************************
2060     osl_writeFile
2061 ********************************************/
2062 
2063 oslFileError osl_writeFile(oslFileHandle Handle, const void* pBuffer, sal_uInt64 uBytesToWrite, sal_uInt64* pBytesWritten)
2064 {
2065     ssize_t            nBytes      = 0;
2066     oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl*)Handle;
2067 
2068     OSL_ASSERT(pHandleImpl);
2069     OSL_ASSERT(pBuffer);
2070     OSL_ASSERT(pBytesWritten);
2071 
2072     if ((0 == pHandleImpl) || (0 == pBuffer) || (0 == pBytesWritten))
2073         return osl_File_E_INVAL;
2074 
2075     OSL_ASSERT(pHandleImpl->fd >= 0);
2076 
2077     if (pHandleImpl->fd < 0)
2078         return osl_File_E_INVAL;
2079 
2080     nBytes = write(pHandleImpl->fd, pBuffer, uBytesToWrite);
2081 
2082     if (-1 == nBytes)
2083         return oslTranslateFileError(OSL_FET_ERROR, errno);
2084 
2085     *pBytesWritten = nBytes;
2086     return osl_File_E_None;
2087 }
2088 
2089 /*******************************************
2090     osl_writeFile
2091 ********************************************/
2092 
2093 oslFileError osl_setFilePos( oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uPos )
2094 {
2095     oslFileHandleImpl* pHandleImpl=0;
2096     int nRet=0;
2097     off_t nOffset=0;
2098 
2099     pHandleImpl = (oslFileHandleImpl*) Handle;
2100     if ( pHandleImpl == 0 )
2101     {
2102         return osl_File_E_INVAL;
2103     }
2104 
2105     if ( pHandleImpl->fd < 0 )
2106     {
2107         return osl_File_E_INVAL;
2108     }
2109 
2110     /* FIXME mfe: setFilePos: Do we have any runtime function to determine LONG_MAX? */
2111     if ( uPos > LONG_MAX )
2112     {
2113         return osl_File_E_OVERFLOW;
2114     }
2115 
2116     nOffset=(off_t)uPos;
2117 
2118     switch(uHow)
2119     {
2120         case osl_Pos_Absolut:
2121             nOffset = lseek(pHandleImpl->fd,nOffset,SEEK_SET);
2122             break;
2123 
2124         case osl_Pos_Current:
2125             nOffset = lseek(pHandleImpl->fd,nOffset,SEEK_CUR);
2126             break;
2127 
2128         case osl_Pos_End:
2129             nOffset = lseek(pHandleImpl->fd,nOffset,SEEK_END);
2130             break;
2131 
2132         default:
2133             return osl_File_E_INVAL;
2134     }
2135 
2136     if ( nOffset < 0 )
2137     {
2138         nRet=errno;
2139         return oslTranslateFileError(OSL_FET_ERROR, nRet);
2140     }
2141 
2142     return osl_File_E_None;
2143 }
2144 
2145 /************************************************
2146  * osl_getFilePos
2147  ***********************************************/
2148 
2149 oslFileError osl_getFilePos( oslFileHandle Handle, sal_uInt64* pPos )
2150 {
2151     oslFileHandleImpl* pHandleImpl=0;
2152     off_t nOffset=0;
2153     int nRet=0;
2154 
2155     pHandleImpl = (oslFileHandleImpl*) Handle;
2156     if ( pHandleImpl == 0 || pPos == 0)
2157     {
2158         return osl_File_E_INVAL;
2159     }
2160 
2161     if ( pHandleImpl->fd < 0 )
2162     {
2163         return osl_File_E_INVAL;
2164     }
2165 
2166     nOffset = lseek(pHandleImpl->fd,0,SEEK_CUR);
2167 
2168     if (nOffset < 0)
2169     {
2170         nRet  =errno;
2171 
2172         /* *pPos =0; */
2173 
2174         return oslTranslateFileError(OSL_FET_ERROR, nRet);
2175     }
2176 
2177     *pPos=nOffset;
2178 
2179     return osl_File_E_None;
2180 }
2181 
2182 /****************************************************************************
2183  *	osl_getFileSize
2184  ****************************************************************************/
2185 
2186 oslFileError osl_getFileSize( oslFileHandle Handle, sal_uInt64* pSize )
2187 {
2188     oslFileHandleImpl* pHandleImpl=(oslFileHandleImpl*) Handle;
2189     if (pHandleImpl == 0)
2190         return osl_File_E_INVAL;
2191 
2192     struct stat file_stat;
2193     if (fstat(pHandleImpl->fd, &file_stat) == -1)
2194         return oslTranslateFileError(OSL_FET_ERROR, errno);
2195 
2196     *pSize = file_stat.st_size;
2197     return osl_File_E_None;
2198 }
2199 
2200 /************************************************
2201  * osl_setFileSize
2202  ***********************************************/
2203 
2204 oslFileError osl_setFileSize( oslFileHandle Handle, sal_uInt64 uSize )
2205 {
2206     oslFileHandleImpl* pHandleImpl=0;
2207     off_t nOffset=0;
2208 
2209     pHandleImpl = (oslFileHandleImpl*) Handle;
2210     if ( pHandleImpl == 0 )
2211     {
2212         return osl_File_E_INVAL;
2213     }
2214 
2215     if ( pHandleImpl->fd < 0 )
2216     {
2217         return osl_File_E_INVAL;
2218     }
2219 
2220     /* FIXME: mfe: setFileSize: Do we have any runtime function to determine LONG_MAX? */
2221     if ( uSize > LONG_MAX )
2222     {
2223         return osl_File_E_OVERFLOW;
2224     }
2225 
2226     nOffset = (off_t)uSize;
2227 	if (ftruncate (pHandleImpl->fd, nOffset) < 0)
2228 	{
2229 		/* Failure. Try fallback algorithm */
2230 		oslFileError result;
2231 		struct stat  aStat;
2232 		off_t        nCurPos;
2233 
2234 		/* Save original result */
2235 		result = oslTranslateFileError (OSL_FET_ERROR, errno);
2236 		PERROR("ftruncate", "Try osl_setFileSize [fallback]\n");
2237 
2238 		/* Check against current size. Fail upon 'shrink' */
2239 		if (fstat (pHandleImpl->fd, &aStat) < 0)
2240 		{
2241 			PERROR("ftruncate: fstat", "Out osl_setFileSize [error]\n");
2242 			return (result);
2243 		}
2244 		if ((0 <= nOffset) && (nOffset <= aStat.st_size))
2245 		{
2246 			/* Failure upon 'shrink'. Return original result */
2247 			return (result);
2248 		}
2249 
2250 		/* Save current position */
2251 		nCurPos = (off_t)lseek (pHandleImpl->fd, (off_t)0, SEEK_CUR);
2252 		if (nCurPos == (off_t)(-1))
2253 		{
2254 			PERROR("ftruncate: lseek", "Out osl_setFileSize [error]\n");
2255 			return (result);
2256 		}
2257 
2258 		/* Try 'expand' via 'lseek()' and 'write()' */
2259 		if (lseek (pHandleImpl->fd, (off_t)(nOffset - 1), SEEK_SET) < 0)
2260 		{
2261 			PERROR("ftruncate: lseek", "Out osl_setFileSize [error]\n");
2262 			return (result);
2263 		}
2264 		if (write (pHandleImpl->fd, (char*)"", (size_t)1) < 0)
2265 		{
2266 			/* Failure. Restore saved position */
2267 			PERROR("ftruncate: write", "Out osl_setFileSize [error]\n");
2268 			if (lseek (pHandleImpl->fd, (off_t)nCurPos, SEEK_SET) < 0)
2269 			{
2270 #ifdef DEBUG_OSL_FILE
2271 				perror("ftruncate: lseek");
2272 #endif /* DEBUG_OSL_FILE */
2273 			}
2274 			return (result);
2275 		}
2276 
2277 		/* Success. Restore saved position */
2278 		if (lseek (pHandleImpl->fd, (off_t)nCurPos, SEEK_SET) < 0)
2279 		{
2280 			PERROR("ftruncate: lseek", "Out osl_setFileSize [error]");
2281 			return (result);
2282 		}
2283 	}
2284 
2285 	return (osl_File_E_None);
2286 }
2287 
2288 /*###############################################*/
2289 oslFileError SAL_CALL osl_syncFile(oslFileHandle Handle)
2290 {
2291     oslFileHandleImpl* handle_impl = (oslFileHandleImpl*)Handle;
2292 
2293     if (handle_impl == 0)
2294         return osl_File_E_INVAL;
2295 
2296     if (fsync(handle_impl->fd) == -1)
2297         return oslTranslateFileError(OSL_FET_ERROR, errno);
2298 
2299     return osl_File_E_None;
2300 }
2301 
2302 /******************************************************************************
2303  *
2304  *                  C-String Versions of Exported Module Functions
2305  *
2306  *****************************************************************************/
2307 
2308 #ifdef HAVE_STATFS_H
2309 
2310 #if defined(FREEBSD) || defined(NETBSD) || defined(MACOSX)
2311 #   define __OSL_STATFS_STRUCT      			struct statfs
2312 #   define __OSL_STATFS(dir, sfs)   			statfs((dir), (sfs))
2313 #   define __OSL_STATFS_BLKSIZ(a)   			((sal_uInt64)((a).f_bsize))
2314 #   define __OSL_STATFS_TYPENAME(a) 			((a).f_fstypename)
2315 #   define __OSL_STATFS_ISREMOTE(a) 			(((a).f_type & MNT_LOCAL) == 0)
2316 
2317 /* always return true if queried for the properties of
2318    the file system. If you think this is wrong under any
2319    of the target platforms fix it!!!! */
2320 #	define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a)	 (1)
2321 #	define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
2322 #endif /* FREEBSD || NETBSD */
2323 
2324 #if defined(LINUX)
2325 #	define __OSL_NFS_SUPER_MAGIC				 0x6969
2326 #	define __OSL_SMB_SUPER_MAGIC				 0x517B
2327 #	define __OSL_MSDOS_SUPER_MAGIC  			 0x4d44
2328 #	define __OSL_NTFS_SUPER_MAGIC				 0x5346544e
2329 #   define __OSL_STATFS_STRUCT       		     struct statfs
2330 #   define __OSL_STATFS(dir, sfs)    			 statfs((dir), (sfs))
2331 #   define __OSL_STATFS_BLKSIZ(a)    			 ((sal_uInt64)((a).f_bsize))
2332 #   define __OSL_STATFS_IS_NFS(a)     			 (__OSL_NFS_SUPER_MAGIC == (a).f_type)
2333 #   define __OSL_STATFS_IS_SMB(a)     			 (__OSL_SMB_SUPER_MAGIC == (a).f_type)
2334 #   define __OSL_STATFS_ISREMOTE(a)  			 (__OSL_STATFS_IS_NFS((a)) || __OSL_STATFS_IS_SMB((a)))
2335 #	define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a)  ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type) && (__OSL_NTFS_SUPER_MAGIC != (a).f_type))
2336 #	define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type))
2337 #endif /* LINUX */
2338 
2339 #if defined(SOLARIS)
2340 #   define __OSL_STATFS_STRUCT          		 struct statvfs
2341 #   define __OSL_STATFS(dir, sfs)	    		 statvfs((dir), (sfs))
2342 #   define __OSL_STATFS_BLKSIZ(a)       		 ((sal_uInt64)((a).f_frsize))
2343 #   define __OSL_STATFS_TYPENAME(a)     		 ((a).f_basetype)
2344 #   define __OSL_STATFS_ISREMOTE(a)     		 (rtl_str_compare((a).f_basetype, "nfs") == 0)
2345 
2346 /* always return true if queried for the properties of
2347    the file system. If you think this is wrong under any
2348    of the target platforms fix it!!!! */
2349 #	define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a)	 (1)
2350 #	define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
2351 #endif /* SOLARIS */
2352 
2353 #   define __OSL_STATFS_INIT(a) 	    (memset(&(a), 0, sizeof(__OSL_STATFS_STRUCT)))
2354 
2355 #else /* no statfs available */
2356 
2357 #   define __OSL_STATFS_STRUCT        			 struct dummy {int i;}
2358 #   define __OSL_STATFS_INIT(a)       			 ((void)0)
2359 #   define __OSL_STATFS(dir, sfs)     		     (1)
2360 #   define __OSL_STATFS_ISREMOTE(sfs) 			 (0)
2361 #	define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a)	 (1)
2362 #	define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
2363 #endif /* HAVE_STATFS_H */
2364 
2365 
2366 static oslFileError osl_psz_getVolumeInformation (
2367 	const sal_Char* pszDirectory, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask)
2368 {
2369     __OSL_STATFS_STRUCT sfs;
2370 
2371     if (!pInfo)
2372         return osl_File_E_INVAL;
2373 
2374     __OSL_STATFS_INIT(sfs);
2375 
2376     pInfo->uValidFields = 0;
2377     pInfo->uAttributes  = 0;
2378 
2379 	if ((__OSL_STATFS(pszDirectory, &sfs)) < 0)
2380 	{
2381 		oslFileError result = oslTranslateFileError(OSL_FET_ERROR, errno);
2382 		return (result);
2383 	}
2384 
2385     /* FIXME: how to detect the kind of storage (fixed, cdrom, ...) */
2386 	if (uFieldMask & osl_VolumeInfo_Mask_Attributes)
2387 	{
2388 	    if (__OSL_STATFS_ISREMOTE(sfs))
2389 			pInfo->uAttributes  |= osl_Volume_Attribute_Remote;
2390 
2391 		pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
2392 	}
2393 
2394 	if (uFieldMask & osl_VolumeInfo_Mask_FileSystemCaseHandling)
2395 	{
2396 		if (__OSL_STATFS_IS_CASE_SENSITIVE_FS(sfs))
2397 			pInfo->uAttributes |= osl_Volume_Attribute_Case_Sensitive;
2398 
2399 		if (__OSL_STATFS_IS_CASE_PRESERVING_FS(sfs))
2400 			pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
2401 
2402 		pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
2403 	}
2404 
2405 	pInfo->uTotalSpace = 0;
2406     pInfo->uFreeSpace  = 0;
2407     pInfo->uUsedSpace  = 0;
2408 
2409 #if defined(__OSL_STATFS_BLKSIZ)
2410 
2411 	if ((uFieldMask & osl_VolumeInfo_Mask_TotalSpace) ||
2412 		(uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
2413 	{
2414 		pInfo->uTotalSpace   = __OSL_STATFS_BLKSIZ(sfs);
2415 		pInfo->uTotalSpace  *= (sal_uInt64)(sfs.f_blocks);
2416 		pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace;
2417 	}
2418 
2419 	if ((uFieldMask & osl_VolumeInfo_Mask_FreeSpace) ||
2420 		(uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
2421 	{
2422 		pInfo->uFreeSpace = __OSL_STATFS_BLKSIZ(sfs);
2423 
2424 		if (getuid() == 0)
2425 			pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bfree);
2426 		else
2427 			pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bavail);
2428 
2429 		pInfo->uValidFields |= osl_VolumeInfo_Mask_FreeSpace;
2430 	}
2431 
2432 #endif  /* __OSL_STATFS_BLKSIZ */
2433 
2434 	if ((pInfo->uValidFields & osl_VolumeInfo_Mask_TotalSpace) &&
2435 		(pInfo->uValidFields & osl_VolumeInfo_Mask_FreeSpace ))
2436 	{
2437 		pInfo->uUsedSpace    = pInfo->uTotalSpace - pInfo->uFreeSpace;
2438 		pInfo->uValidFields |= osl_VolumeInfo_Mask_UsedSpace;
2439 	}
2440 
2441 	pInfo->uMaxNameLength = 0;
2442 	if (uFieldMask & osl_VolumeInfo_Mask_MaxNameLength)
2443 	{
2444 		long nLen = pathconf(pszDirectory, _PC_NAME_MAX);
2445 		if (nLen > 0)
2446 		{
2447 			pInfo->uMaxNameLength = (sal_uInt32)nLen;
2448 			pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength;
2449 		}
2450 	}
2451 
2452 	pInfo->uMaxPathLength = 0;
2453 	if (uFieldMask & osl_VolumeInfo_Mask_MaxPathLength)
2454 	{
2455 		long nLen = pathconf (pszDirectory, _PC_PATH_MAX);
2456 		if (nLen > 0)
2457 		{
2458 			pInfo->uMaxPathLength  = (sal_uInt32)nLen;
2459 			pInfo->uValidFields   |= osl_VolumeInfo_Mask_MaxPathLength;
2460 		}
2461 	}
2462 
2463 #if defined(__OSL_STATFS_TYPENAME)
2464 
2465 	if (uFieldMask & osl_VolumeInfo_Mask_FileSystemName)
2466 	{
2467     	rtl_string2UString(
2468         	&(pInfo->ustrFileSystemName),
2469         	__OSL_STATFS_TYPENAME(sfs),
2470         	rtl_str_getLength(__OSL_STATFS_TYPENAME(sfs)),
2471         	osl_getThreadTextEncoding(),
2472         	OUSTRING_TO_OSTRING_CVTFLAGS);
2473         OSL_ASSERT(pInfo->ustrFileSystemName != 0);
2474 
2475 		pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName;
2476 	}
2477 
2478 #endif /* __OSL_STATFS_TYPENAME */
2479 
2480     if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle)
2481     {
2482         /* FIXME: check also entries in mntent for the device
2483 		   and fill it with correct values */
2484 
2485         *pInfo->pDeviceHandle = osl_isFloppyDrive(pszDirectory);
2486 
2487         if (*pInfo->pDeviceHandle)
2488         {
2489             pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle;
2490             pInfo->uAttributes  |= osl_Volume_Attribute_Removeable;
2491 			pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
2492         }
2493     }
2494     return osl_File_E_None;
2495 }
2496 
2497 /******************************************
2498  * osl_psz_setFileTime
2499  *****************************************/
2500 
2501 static oslFileError osl_psz_setFileTime( const sal_Char* pszFilePath,
2502                                   const TimeValue* /*pCreationTime*/,
2503                                   const TimeValue* pLastAccessTime,
2504                                   const TimeValue* pLastWriteTime )
2505 {
2506     int nRet=0;
2507     struct utimbuf aTimeBuffer;
2508     struct stat aFileStat;
2509 #ifdef DEBUG_OSL_FILE
2510     struct tm* pTM=0;
2511 #endif
2512 
2513     nRet = lstat(pszFilePath,&aFileStat);
2514 
2515     if ( nRet < 0 )
2516     {
2517         nRet=errno;
2518         return oslTranslateFileError(OSL_FET_ERROR, nRet);
2519     }
2520 
2521 #ifdef DEBUG_OSL_FILE
2522     fprintf(stderr,"File Times are (in localtime):\n");
2523     pTM=localtime(&aFileStat.st_ctime);
2524     fprintf(stderr,"CreationTime is '%s'\n",asctime(pTM));
2525     pTM=localtime(&aFileStat.st_atime);
2526     fprintf(stderr,"AccessTime   is '%s'\n",asctime(pTM));
2527     pTM=localtime(&aFileStat.st_mtime);
2528     fprintf(stderr,"Modification is '%s'\n",asctime(pTM));
2529 
2530     fprintf(stderr,"File Times are (in UTC):\n");
2531     fprintf(stderr,"CreationTime is '%s'\n",ctime(&aFileStat.st_ctime));
2532     fprintf(stderr,"AccessTime   is '%s'\n",ctime(&aTimeBuffer.actime));
2533     fprintf(stderr,"Modification is '%s'\n",ctime(&aTimeBuffer.modtime));
2534 #endif
2535 
2536     if ( pLastAccessTime != 0 )
2537     {
2538         aTimeBuffer.actime=pLastAccessTime->Seconds;
2539     }
2540     else
2541     {
2542         aTimeBuffer.actime=aFileStat.st_atime;
2543     }
2544 
2545     if ( pLastWriteTime != 0 )
2546     {
2547         aTimeBuffer.modtime=pLastWriteTime->Seconds;
2548     }
2549     else
2550     {
2551         aTimeBuffer.modtime=aFileStat.st_mtime;
2552     }
2553 
2554     /* mfe: Creation time not used here! */
2555 
2556 #ifdef DEBUG_OSL_FILE
2557     fprintf(stderr,"File Times are (in localtime):\n");
2558     pTM=localtime(&aFileStat.st_ctime);
2559     fprintf(stderr,"CreationTime now '%s'\n",asctime(pTM));
2560     pTM=localtime(&aTimeBuffer.actime);
2561     fprintf(stderr,"AccessTime   now '%s'\n",asctime(pTM));
2562     pTM=localtime(&aTimeBuffer.modtime);
2563     fprintf(stderr,"Modification now '%s'\n",asctime(pTM));
2564 
2565     fprintf(stderr,"File Times are (in UTC):\n");
2566     fprintf(stderr,"CreationTime now '%s'\n",ctime(&aFileStat.st_ctime));
2567     fprintf(stderr,"AccessTime   now '%s'\n",ctime(&aTimeBuffer.actime));
2568     fprintf(stderr,"Modification now '%s'\n",ctime(&aTimeBuffer.modtime));
2569 #endif
2570 
2571     nRet=utime(pszFilePath,&aTimeBuffer);
2572     if ( nRet < 0 )
2573     {
2574         nRet=errno;
2575         return oslTranslateFileError(OSL_FET_ERROR, nRet);
2576     }
2577 
2578     return osl_File_E_None;
2579 }
2580 
2581 
2582 /*****************************************
2583  * osl_psz_removeFile
2584  ****************************************/
2585 #if 0
2586 static oslFileError osl_psz_removeFile( const sal_Char* pszPath )
2587 {
2588     int nRet=0;
2589     struct stat aStat;
2590 
2591     nRet = stat(pszPath,&aStat);
2592     if ( nRet < 0 )
2593     {
2594         nRet=errno;
2595         return oslTranslateFileError(OSL_FET_ERROR, nRet);
2596     }
2597 
2598     if ( S_ISDIR(aStat.st_mode) )
2599     {
2600         return osl_File_E_ISDIR;
2601     }
2602 
2603     nRet = unlink(pszPath);
2604     if ( nRet < 0 )
2605     {
2606         nRet=errno;
2607         return oslTranslateFileError(OSL_FET_ERROR, nRet);
2608     }
2609 
2610     return osl_File_E_None;
2611 }
2612 #endif
2613 
2614 /*****************************************
2615  * osl_psz_createDirectory
2616  ****************************************/
2617 #if 0
2618 static oslFileError osl_psz_createDirectory( const sal_Char* pszPath )
2619 {
2620     int nRet=0;
2621     int mode = S_IRWXU | S_IRWXG | S_IRWXO;
2622 
2623     nRet = mkdir(pszPath,mode);
2624 
2625     if ( nRet < 0 )
2626     {
2627         nRet=errno;
2628         return oslTranslateFileError(OSL_FET_ERROR, nRet);
2629     }
2630 
2631     return osl_File_E_None;
2632 }
2633 #endif
2634 /*****************************************
2635  * osl_psz_removeDirectory
2636  ****************************************/
2637 #if 0
2638 static oslFileError osl_psz_removeDirectory( const sal_Char* pszPath )
2639 {
2640     int nRet=0;
2641 
2642     nRet = rmdir(pszPath);
2643 
2644     if ( nRet < 0 )
2645     {
2646         nRet=errno;
2647         return oslTranslateFileError(OSL_FET_ERROR, nRet);
2648     }
2649 
2650     return osl_File_E_None;
2651 }
2652 #endif
2653 /*****************************************
2654  * oslDoMoveFile
2655  ****************************************/
2656 #if 0
2657 static oslFileError oslDoMoveFile( const sal_Char* pszPath, const sal_Char* pszDestPath)
2658 {
2659     oslFileError tErr=osl_File_E_invalidError;
2660 
2661     tErr = osl_psz_moveFile(pszPath,pszDestPath);
2662     if ( tErr == osl_File_E_None )
2663     {
2664         return tErr;
2665     }
2666 
2667     if ( tErr != osl_File_E_XDEV )
2668     {
2669         return tErr;
2670     }
2671 
2672     tErr=osl_psz_copyFile(pszPath,pszDestPath);
2673 
2674     if ( tErr != osl_File_E_None )
2675     {
2676         oslFileError tErrRemove;
2677         tErrRemove=osl_psz_removeFile(pszDestPath);
2678         return tErr;
2679     }
2680 
2681     tErr=osl_psz_removeFile(pszPath);
2682 
2683     return tErr;
2684 }
2685 #endif
2686 /*****************************************
2687  * osl_psz_moveFile
2688  ****************************************/
2689 #if 0
2690 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath)
2691 {
2692 
2693     int nRet = 0;
2694 
2695     nRet = rename(pszPath,pszDestPath);
2696 
2697     if ( nRet < 0 )
2698     {
2699         nRet=errno;
2700         return oslTranslateFileError(OSL_FET_ERROR, nRet);
2701     }
2702 
2703     return osl_File_E_None;
2704 }
2705 #endif
2706 /*****************************************
2707  * osl_psz_copyFile
2708  ****************************************/
2709 #if 0
2710 static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath )
2711 {
2712     time_t nAcTime=0;
2713     time_t nModTime=0;
2714     uid_t nUID=0;
2715     gid_t nGID=0;
2716     int nRet=0;
2717     mode_t nMode=0;
2718     struct stat aFileStat;
2719     oslFileError tErr=osl_File_E_invalidError;
2720     size_t nSourceSize=0;
2721     int DestFileExists=1;
2722 
2723     /* mfe: does the source file really exists? */
2724     nRet = lstat(pszPath,&aFileStat);
2725 
2726     if ( nRet < 0 )
2727     {
2728         nRet=errno;
2729         return oslTranslateFileError(OSL_FET_ERROR, nRet);
2730     }
2731 
2732     /* mfe: we do only copy files here! */
2733     if ( S_ISDIR(aFileStat.st_mode) )
2734     {
2735         return osl_File_E_ISDIR;
2736     }
2737 
2738     nSourceSize=(size_t)aFileStat.st_size;
2739     nMode=aFileStat.st_mode;
2740     nAcTime=aFileStat.st_atime;
2741     nModTime=aFileStat.st_mtime;
2742     nUID=aFileStat.st_uid;
2743     nGID=aFileStat.st_gid;
2744 
2745     nRet = stat(pszDestPath,&aFileStat);
2746     if ( nRet < 0 )
2747     {
2748         nRet=errno;
2749 
2750         if ( nRet == ENOENT )
2751         {
2752             DestFileExists=0;
2753         }
2754 /*        return oslTranslateFileError(nRet);*/
2755     }
2756 
2757     /* mfe: the destination file must not be a directory! */
2758     if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) )
2759     {
2760         return osl_File_E_ISDIR;
2761     }
2762     else
2763     {
2764         /* mfe: file does not exists or is no dir */
2765     }
2766 
2767     tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists);
2768 
2769     if ( tErr != osl_File_E_None )
2770     {
2771         return tErr;
2772     }
2773 
2774     /*
2775      *   mfe: ignore return code
2776      *        since only  the success of the copy is
2777      *        important
2778      */
2779     oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID);
2780 
2781     return tErr;
2782 }
2783 #endif
2784 
2785 /******************************************************************************
2786  *
2787  *                  Utility Functions
2788  *
2789  *****************************************************************************/
2790 
2791 
2792 /*****************************************
2793  * oslMakeUStrFromPsz
2794  ****************************************/
2795 
2796 rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr, rtl_uString** ustrValid)
2797 {
2798     rtl_string2UString(
2799         ustrValid,
2800         pszStr,
2801         rtl_str_getLength( pszStr ),
2802         osl_getThreadTextEncoding(),
2803         OUSTRING_TO_OSTRING_CVTFLAGS );
2804     OSL_ASSERT(*ustrValid != 0);
2805 
2806     return *ustrValid;
2807 }
2808 
2809 /*****************************************************************************
2810  * UnicodeToText
2811  * converting unicode to text manually saves us the penalty of a temporary
2812  * rtl_String object.
2813  ****************************************************************************/
2814 
2815 int UnicodeToText( char * buffer, size_t bufLen, const sal_Unicode * uniText, sal_Int32 uniTextLen )
2816 {
2817     rtl_UnicodeToTextConverter hConverter;
2818     sal_uInt32   nInfo;
2819     sal_Size   nSrcChars, nDestBytes;
2820 
2821     /* stolen from rtl/string.c */
2822     hConverter = rtl_createUnicodeToTextConverter( osl_getThreadTextEncoding() );
2823 
2824 	nDestBytes = rtl_convertUnicodeToText( hConverter, 0, uniText, uniTextLen,
2825                                            buffer, bufLen,
2826                                            OUSTRING_TO_OSTRING_CVTFLAGS | RTL_UNICODETOTEXT_FLAGS_FLUSH,
2827                                            &nInfo, &nSrcChars );
2828 
2829     rtl_destroyUnicodeToTextConverter( hConverter );
2830 
2831     if( nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL )
2832     {
2833         errno = EOVERFLOW;
2834         return 0;
2835     }
2836 
2837     /* ensure trailing '\0' */
2838     buffer[nDestBytes] = '\0';
2839 
2840     return nDestBytes;
2841 }
2842 
2843 /*****************************************************************************
2844    TextToUnicode
2845 
2846    @param text
2847           The text to convert.
2848 
2849    @param text_buffer_size
2850           The number of characters.
2851 
2852    @param unic_text
2853           The unicode buffer.
2854 
2855    @param unic_text_buffer_size
2856    		  The size in characters of the unicode buffer.
2857 
2858  ****************************************************************************/
2859 
2860 int TextToUnicode(
2861 	const char*  text,
2862 	size_t       text_buffer_size,
2863 	sal_Unicode* unic_text,
2864 	sal_Int32    unic_text_buffer_size)
2865 {
2866     rtl_TextToUnicodeConverter hConverter;
2867     sal_uInt32 nInfo;
2868     sal_Size nSrcChars;
2869     sal_Size nDestBytes;
2870 
2871     /* stolen from rtl/string.c */
2872     hConverter = rtl_createTextToUnicodeConverter(osl_getThreadTextEncoding());
2873 
2874 	nDestBytes = rtl_convertTextToUnicode(hConverter,
2875 										  0,
2876 										  text,  text_buffer_size,
2877                                           unic_text, unic_text_buffer_size,
2878                                           OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_FLUSH,
2879                                           &nInfo, &nSrcChars);
2880 
2881     rtl_destroyTextToUnicodeConverter(hConverter);
2882 
2883     if (nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL)
2884     {
2885         errno = EOVERFLOW;
2886         return 0;
2887     }
2888 
2889     /* ensure trailing '\0' */
2890     unic_text[nDestBytes] = '\0';
2891 
2892     return nDestBytes;
2893 }
2894 
2895 /******************************************************************************
2896  *
2897  *                  GENERIC FLOPPY FUNCTIONS
2898  *
2899  *****************************************************************************/
2900 
2901 
2902 /*****************************************
2903  * osl_unmountVolumeDevice
2904  ****************************************/
2905 
2906 oslFileError osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle )
2907 {
2908     oslFileError tErr = osl_File_E_NOSYS;
2909 
2910     tErr = osl_unmountFloppy(Handle);
2911 
2912  	/* Perhaps current working directory is set to mount point */
2913 
2914  	if ( tErr )
2915 	{
2916 		sal_Char *pszHomeDir = getenv("HOME");
2917 
2918 		if ( pszHomeDir && strlen( pszHomeDir ) && 0 == chdir( pszHomeDir ) )
2919 		{
2920 			/* try again */
2921 
2922     		tErr = osl_unmountFloppy(Handle);
2923 
2924 			OSL_ENSURE( tErr, "osl_unmountvolumeDevice: CWD was set to volume mount point" );
2925 		}
2926 	}
2927 
2928     return tErr;
2929 }
2930 
2931 /*****************************************
2932  * osl_automountVolumeDevice
2933  ****************************************/
2934 
2935 oslFileError osl_automountVolumeDevice( oslVolumeDeviceHandle Handle )
2936 {
2937     oslFileError tErr = osl_File_E_NOSYS;
2938 
2939     tErr = osl_mountFloppy(Handle);
2940 
2941     return tErr;
2942 }
2943 
2944 /*****************************************
2945  * osl_getVolumeDeviceMountPath
2946  ****************************************/
2947 
2948 oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
2949 {
2950     oslVolumeDeviceHandleImpl* pItem = (oslVolumeDeviceHandleImpl*) Handle;
2951     sal_Char Buffer[PATH_MAX];
2952 
2953     Buffer[0] = '\0';
2954 
2955     if ( pItem == 0 || pstrPath == 0 )
2956     {
2957         return osl_File_E_INVAL;
2958     }
2959 
2960     if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
2961     {
2962         return osl_File_E_INVAL;
2963     }
2964 
2965 #ifdef DEBUG_OSL_FILE
2966     fprintf(stderr,"Handle is:\n");
2967     osl_printFloppyHandle(pItem);
2968 #endif
2969 
2970 	snprintf(Buffer, sizeof(Buffer), "file://%s", pItem->pszMountPoint);
2971 
2972 #ifdef DEBUG_OSL_FILE
2973     fprintf(stderr,"Mount Point is: '%s'\n",Buffer);
2974 #endif
2975 
2976     oslMakeUStrFromPsz(Buffer, pstrPath);
2977 
2978     return osl_File_E_None;
2979 }
2980 
2981 /*****************************************
2982  * osl_acquireVolumeDeviceHandle
2983  ****************************************/
2984 
2985 oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
2986 {
2987     oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
2988 
2989     if ( pItem == 0 )
2990     {
2991         return osl_File_E_INVAL;
2992     }
2993 
2994     if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
2995     {
2996         return osl_File_E_INVAL;
2997     }
2998 
2999     ++pItem->RefCount;
3000 
3001     return osl_File_E_None;
3002 }
3003 
3004 /*****************************************
3005  * osl_releaseVolumeDeviceHandle
3006  ****************************************/
3007 
3008 oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
3009 {
3010     oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
3011 
3012     if ( pItem == 0 )
3013     {
3014         return osl_File_E_INVAL;
3015     }
3016 
3017     if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
3018     {
3019         return osl_File_E_INVAL;
3020     }
3021 
3022     --pItem->RefCount;
3023 
3024     if ( pItem->RefCount == 0 )
3025     {
3026         rtl_freeMemory(pItem);
3027     }
3028 
3029     return osl_File_E_None;
3030 }
3031 
3032 /*****************************************
3033  * osl_newVolumeDeviceHandleImpl
3034  ****************************************/
3035 
3036 static oslVolumeDeviceHandleImpl* osl_newVolumeDeviceHandleImpl()
3037 {
3038     oslVolumeDeviceHandleImpl* pHandle;
3039     const size_t               nSizeOfHandle = sizeof(oslVolumeDeviceHandleImpl);
3040 
3041     pHandle = (oslVolumeDeviceHandleImpl*) rtl_allocateMemory (nSizeOfHandle);
3042     if (pHandle != NULL)
3043     {
3044         pHandle->ident[0]         = 'O';
3045         pHandle->ident[1]         = 'V';
3046         pHandle->ident[2]         = 'D';
3047         pHandle->ident[3]         = 'H';
3048         pHandle->pszMountPoint[0] = '\0';
3049         pHandle->pszFilePath[0]   = '\0';
3050         pHandle->pszDevice[0]     = '\0';
3051         pHandle->RefCount         = 1;
3052     }
3053     return pHandle;
3054 }
3055 
3056 /*****************************************
3057  * osl_freeVolumeDeviceHandleImpl
3058  ****************************************/
3059 
3060 static void osl_freeVolumeDeviceHandleImpl (oslVolumeDeviceHandleImpl* pHandle)
3061 {
3062     if (pHandle != NULL)
3063         rtl_freeMemory (pHandle);
3064 }
3065 
3066 
3067 /******************************************************************************
3068  *
3069  *                  OS/2 FLOPPY FUNCTIONS
3070  *
3071  *****************************************************************************/
3072 
3073 #if defined(OS2)
3074 static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath)
3075 {
3076     return NULL;
3077 }
3078 
3079 static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy)
3080 {
3081     return osl_File_E_BUSY;
3082 }
3083 
3084 static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy)
3085 {
3086     return osl_File_E_BUSY;
3087 }
3088 
3089 static sal_Bool osl_getFloppyMountEntry(const sal_Char* pszPath, oslVolumeDeviceHandleImpl* pItem)
3090 {
3091     return sal_False;
3092 }
3093 
3094 static sal_Bool osl_isFloppyMounted(oslVolumeDeviceHandleImpl* pDevice)
3095 {
3096     return sal_False;
3097 }
3098 
3099 
3100 #ifdef DEBUG_OSL_FILE
3101 static void osl_printFloppyHandle(oslVolumeDeviceHandleImpl* pItem)
3102 {
3103     if (pItem == 0 )
3104     {
3105         fprintf(stderr,"NULL Handle\n");
3106         return;
3107     }
3108     if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
3109     {
3110 #ifdef TRACE_OSL_FILE
3111         fprintf(stderr,"Invalid Handle]\n");
3112 #endif
3113         return;
3114     }
3115 
3116 
3117     fprintf(stderr,"MountPoint : '%s'\n",pItem->pszMountPoint);
3118     fprintf(stderr,"FilePath   : '%s'\n",pItem->pszFilePath);
3119     fprintf(stderr,"Device     : '%s'\n",pItem->pszDevice);
3120 
3121     return;
3122 }
3123 #endif
3124 
3125 #endif /* OS2 */
3126