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