xref: /trunk/main/sal/osl/os2/file.cxx (revision 336e7b3a)
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     //#####################################################
MapError(APIRET dwError)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 &
get()265 FileHandle_Impl::Allocator::get()
266 {
267 	static Allocator g_aBufferAllocator;
268 	return g_aBufferAllocator;
269 }
270 
Allocator()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 
~Allocator()282 FileHandle_Impl::Allocator::~Allocator()
283 {
284 	rtl_cache_destroy(m_cache), m_cache = 0;
285 }
286 
allocate(sal_uInt8 ** ppBuffer,size_t * pnSize)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 
deallocate(sal_uInt8 * pBuffer)293 void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer)
294 {
295 	if (0 != pBuffer)
296 		rtl_cache_free (m_cache, pBuffer);
297 }
298 
FileHandle_Impl(int fd,char const * path)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 
~FileHandle_Impl()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 
operator new(size_t n)323 void * FileHandle_Impl::operator new(size_t n)
324 {
325 	return rtl_allocateMemory(n);
326 }
327 
operator delete(void * p,size_t)328 void FileHandle_Impl::operator delete(void * p, size_t)
329 {
330 	rtl_freeMemory(p);
331 }
332 
getpagesize()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 
getPos() const340 sal_uInt64 FileHandle_Impl::getPos() const
341 {
342 	return sal::static_int_cast< sal_uInt64 >(m_fileptr);
343 }
344 
setPos(sal_uInt64 uPos)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 
getSize() const351 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 
setSize(sal_uInt64 uSize)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 
readAt(off_t nOffset,void * pBuffer,size_t nBytesRequested,sal_uInt64 * pBytesRead)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 
writeAt(off_t nOffset,void const * pBuffer,size_t nBytesToWrite,sal_uInt64 * pBytesWritten)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 
readFileAt(off_t nOffset,void * pBuffer,size_t nBytesRequested,sal_uInt64 * pBytesRead)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 
writeFileAt(off_t nOffset,void const * pBuffer,size_t nBytesToWrite,sal_uInt64 * pBytesWritten)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 
readLineAt(LONGLONG nOffset,sal_Sequence ** ppSequence,sal_uInt64 * pBytesRead)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 
writeSequence_Impl(sal_Sequence ** ppSequence,size_t * pnOffset,const void * pBuffer,size_t nBytes)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 
syncFile()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  *********************************************/
_osl_openLocalRoot(rtl_uString * strDirectoryPath,oslDirectory * pDirectory)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  *********************************************/
_osl_getNextDrive(oslDirectory Directory,oslDirectoryItem * pItem,sal_uInt32 uHint)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 
_osl_readdir_impl_(DIR * pdir,sal_Bool bFilterLocalAndParentDir)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 
osl_openDirectory(rtl_uString * ustrDirectoryURL,oslDirectory * pDirectory)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 
osl_getNextDirectoryItem(oslDirectory Directory,oslDirectoryItem * pItem,sal_uInt32 uHint)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 
osl_closeDirectory(oslDirectory Directory)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 
osl_getDirectoryItem(rtl_uString * ustrFileURL,oslDirectoryItem * pItem)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 
osl_acquireDirectoryItem(oslDirectoryItem Item)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 
osl_releaseDirectoryItem(oslDirectoryItem Item)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  ***************************************************************************/
osl_createFileHandleFromFD(int fd)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  ******************************************************************/
osl_file_adjustLockFlags(const char * path,int flags)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;
Locking_ImplLocking_Impl1340     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 };
osl_file_queryLocking(sal_uInt32 uFlags)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
osl_openFile(rtl_uString * ustrFileURL,oslFileHandle * pHandle,sal_uInt32 uFlags)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
osl_closeFile(oslFileHandle Handle)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
osl_syncFile(oslFileHandle Handle)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
osl_mapFile(oslFileHandle Handle,void ** ppAddr,sal_uInt64 uLength,sal_uInt64 uOffset,sal_uInt32 uFlags)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
osl_unmapFile(void * pAddr,sal_uInt64 uLength)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
osl_readLine(oslFileHandle Handle,sal_Sequence ** ppSequence)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
osl_readFile(oslFileHandle Handle,void * pBuffer,sal_uInt64 uBytesRequested,sal_uInt64 * pBytesRead)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
osl_writeFile(oslFileHandle Handle,const void * pBuffer,sal_uInt64 uBytesToWrite,sal_uInt64 * pBytesWritten)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
osl_readFileAt(oslFileHandle Handle,sal_uInt64 uOffset,void * pBuffer,sal_uInt64 uBytesRequested,sal_uInt64 * pBytesRead)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
osl_writeFileAt(oslFileHandle Handle,sal_uInt64 uOffset,const void * pBuffer,sal_uInt64 uBytesToWrite,sal_uInt64 * pBytesWritten)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
osl_isEndOfFile(oslFileHandle Handle,sal_Bool * pIsEOF)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
osl_getFilePos(oslFileHandle Handle,sal_uInt64 * pPos)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
osl_setFilePos(oslFileHandle Handle,sal_uInt32 uHow,sal_Int64 uOffset)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
osl_getFileSize(oslFileHandle Handle,sal_uInt64 * pSize)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
osl_setFileSize(oslFileHandle Handle,sal_uInt64 uSize)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 
osl_moveFile(rtl_uString * ustrFileURL,rtl_uString * ustrDestURL)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 
oslDoCopy(const sal_Char * pszSourceFileName,const sal_Char * pszDestFileName,mode_t nMode,size_t nSourceSize,int DestFileExists)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 
oslChangeFileModes(const sal_Char * pszFileName,mode_t nMode,time_t nAcTime,time_t nModTime,uid_t nUID,gid_t nGID)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 
oslDoCopyLink(const sal_Char * pszSourceFileName,const sal_Char * pszDestFileName)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 
oslDoCopyFile(const sal_Char * pszSourceFileName,const sal_Char * pszDestFileName,size_t nSourceSize,mode_t mode)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 
osl_psz_copyFile(const sal_Char * pszPath,const sal_Char * pszDestPath)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 
osl_copyFile(rtl_uString * ustrFileURL,rtl_uString * ustrDestURL)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 
osl_removeFile(rtl_uString * ustrFileURL)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 /*****************************************************************************/
GetCDInfo(CDInfo * pCDInfo)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 /*****************************************************************************/
DriveIsCDROM(UINT uiDrive,CDInfo * pCDInfo)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 /*****************************************************************************/
TxFsType(char * drive,char * fstype,char * details)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 /*****************************************************************************/
TxFsIsRemovable(char * drive)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 
get_drive_type(const char * path,oslVolumeInfo * pInfo)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 //#############################################
is_volume_space_info_request(sal_uInt32 field_mask)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 //#############################################
get_volume_space_information(const char * path,oslVolumeInfo * pInfo)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 //#############################################
is_filesystem_attributes_request(sal_uInt32 field_mask)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 //#############################################
is_drivetype_request(sal_uInt32 field_mask)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 //#############################################
get_filesystem_attributes(const char * path,sal_uInt32 field_mask,oslVolumeInfo * pInfo)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 
osl_getVolumeInformation(rtl_uString * ustrDirectoryURL,oslVolumeInfo * pInfo,sal_uInt32 uFieldMask)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 /****************************************************************************/
_osl_getDriveInfo(oslDirectoryItem Item,oslFileStatus * pStatus,sal_uInt32 uFieldMask)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 
osl_getFileStatus(oslDirectoryItem Item,oslFileStatus * pStatus,sal_uInt32 uFieldMask)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 
osl_createDirectory(rtl_uString * ustrDirectoryURL)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 
osl_removeDirectory(rtl_uString * ustrDirectoryURL)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 //#############################################
path_make_parent(sal_Unicode * path)2864 int path_make_parent(sal_Unicode* path)
2865 {
2866 	int i = rtl_ustr_lastIndexOfChar(path, '/');
2867 	if (i == -1)
2868 		i = rtl_ustr_lastIndexOfChar(path, '\\');
2869 
2870 	if (i > 0)
2871 	{
2872 		*(path + i) = 0;
2873 		return i;
2874 	}
2875 	else
2876 		return 0;
2877 }
2878 
2879 //#############################################
create_dir_with_callback(sal_Unicode * directory_path,oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,void * pData)2880 int create_dir_with_callback(
2881 	sal_Unicode* directory_path,
2882     oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
2883     void* pData)
2884 {
2885 	int mode = S_IRWXU | S_IRWXG | S_IRWXO;
2886 
2887 	if (osl::mkdir(directory_path, mode) == 0)
2888     {
2889     	if (aDirectoryCreationCallbackFunc)
2890         {
2891         	rtl::OUString url;
2892             osl::FileBase::getFileURLFromSystemPath(directory_path, url);
2893             aDirectoryCreationCallbackFunc(pData, url.pData);
2894         }
2895         return 0;
2896     }
2897     return errno;
2898 }
2899 
2900 //#############################################
create_dir_recursively_(sal_Unicode * dir_path,oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,void * pData)2901 oslFileError create_dir_recursively_(
2902 	sal_Unicode* dir_path,
2903     oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
2904     void* pData)
2905 {
2906 	OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \
2907 	"Path must not end with a slash");
2908 
2909 	int native_err = create_dir_with_callback(
2910     	dir_path, aDirectoryCreationCallbackFunc, pData);
2911 
2912 	if (native_err == 0)
2913         return osl_File_E_None;
2914 
2915     if (native_err != ENOENT)
2916     	return oslTranslateFileError(OSL_FET_ERROR, native_err);
2917 
2918 	// we step back until '/a_dir' at maximum because
2919 	// we should get an error unequal ENOENT when
2920 	// we try to create 'a_dir' at '/' and would so
2921 	// return before
2922 	int pos = path_make_parent(dir_path);
2923 
2924     oslFileError osl_error = create_dir_recursively_(
2925     	dir_path, aDirectoryCreationCallbackFunc, pData);
2926 
2927     if (osl_File_E_None != osl_error)
2928     	return osl_error;
2929 
2930    	dir_path[pos] = '/';
2931 
2932     return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
2933 }
2934 
2935 //#######################################
osl_createDirectoryPath(rtl_uString * aDirectoryUrl,oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,void * pData)2936 oslFileError SAL_CALL osl_createDirectoryPath(
2937 	rtl_uString* aDirectoryUrl,
2938     oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
2939     void* pData)
2940 {
2941     if (aDirectoryUrl == NULL)
2942         return osl_File_E_INVAL;
2943 
2944     rtl::OUString sys_path;
2945     oslFileError osl_error = osl_getSystemPathFromFileURL_Ex(
2946         aDirectoryUrl, &sys_path.pData, sal_False);
2947 
2948     if (osl_error != osl_File_E_None)
2949         return osl_error;
2950 
2951     osl::systemPathRemoveSeparator(sys_path);
2952 
2953     // const_cast because sys_path is a local copy which we want to modify inplace instead of
2954     // coyp it into another buffer on the heap again
2955 	return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData);
2956 }
2957 
2958 /****************************************************************************/
2959 /*	osl_getCanonicalName */
2960 /****************************************************************************/
2961 
osl_getCanonicalName(rtl_uString * ustrFileURL,rtl_uString ** pustrValidURL)2962 oslFileError osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uString** pustrValidURL )
2963 {
2964 	OSL_ENSURE(sal_False, "osl_getCanonicalName not implemented");
2965 
2966 	rtl_uString_newFromString(pustrValidURL, ustrFileURL);
2967 	return osl_File_E_None;
2968 }
2969 
2970 
2971 /****************************************************************************/
2972 /*	osl_setFileAttributes */
2973 /****************************************************************************/
2974 
osl_setFileAttributes(rtl_uString * ustrFileURL,sal_uInt64 uAttributes)2975 oslFileError osl_setFileAttributes( rtl_uString* ustrFileURL, sal_uInt64 uAttributes )
2976 {
2977     char         path[PATH_MAX];
2978     oslFileError eRet;
2979     FILESTATUS3  fsts3ConfigInfo;
2980     ULONG        ulBufSize     = sizeof(FILESTATUS3);
2981     APIRET       rc            = NO_ERROR;
2982 
2983     OSL_ASSERT( ustrFileURL );
2984 
2985     /* convert file url to system path */
2986     eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
2987     if( eRet != osl_File_E_None )
2988         return eRet;
2989 
2990     /* query current attributes */
2991     rc = DosQueryPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
2992     if (rc != NO_ERROR)
2993         return MapError( rc);
2994 
2995     /* set/reset readonly/hidden (see w32\file.cxx) */
2996     fsts3ConfigInfo.attrFile &= ~(FILE_READONLY | FILE_HIDDEN);
2997     if ( uAttributes & osl_File_Attribute_ReadOnly )
2998         fsts3ConfigInfo.attrFile |= FILE_READONLY;
2999     if ( uAttributes & osl_File_Attribute_Hidden )
3000         fsts3ConfigInfo.attrFile |= FILE_HIDDEN;
3001 
3002     /* write new attributes */
3003     rc = DosSetPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize, 0);
3004     if (rc != NO_ERROR)
3005         return MapError( rc);
3006 
3007     /* everything ok */
3008     return osl_File_E_None;
3009 }
3010 
3011 /****************************************************************************/
3012 /*	osl_setFileTime */
3013 /****************************************************************************/
3014 
osl_setFileTime(rtl_uString * ustrFileURL,const TimeValue * pCreationTime,const TimeValue * pLastAccessTime,const TimeValue * pLastWriteTime)3015 oslFileError osl_setFileTime( rtl_uString* ustrFileURL, const TimeValue* pCreationTime,
3016                               const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime )
3017 {
3018     char path[PATH_MAX];
3019     oslFileError eRet;
3020 
3021     OSL_ASSERT( ustrFileURL );
3022 
3023     /* convert file url to system path */
3024     eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
3025     if( eRet != osl_File_E_None )
3026         return eRet;
3027 
3028     return osl_psz_setFileTime( path, pCreationTime, pLastAccessTime, pLastWriteTime );
3029 }
3030 
3031 /******************************************************************************
3032  *
3033  *                  Exported Module Functions
3034  *             (independent of C or Unicode Strings)
3035  *
3036  *****************************************************************************/
3037 
3038 
3039 
3040 /******************************************************************************
3041  *
3042  *                  C-String Versions of Exported Module Functions
3043  *
3044  *****************************************************************************/
3045 
3046 
3047 /******************************************
3048  * osl_psz_setFileTime
3049  *****************************************/
3050 
osl_psz_setFileTime(const sal_Char * pszFilePath,const TimeValue *,const TimeValue * pLastAccessTime,const TimeValue * pLastWriteTime)3051 static oslFileError osl_psz_setFileTime( const sal_Char* pszFilePath,
3052                                   const TimeValue* /*pCreationTime*/,
3053                                   const TimeValue* pLastAccessTime,
3054                                   const TimeValue* pLastWriteTime )
3055 {
3056     int nRet=0;
3057     struct utimbuf aTimeBuffer;
3058     struct stat aFileStat;
3059 #ifdef DEBUG_OSL_FILE
3060     struct tm* pTM=0;
3061 #endif
3062 
3063     nRet = lstat(pszFilePath,&aFileStat);
3064 
3065     if ( nRet < 0 )
3066     {
3067         nRet=errno;
3068         return oslTranslateFileError(OSL_FET_ERROR, nRet);
3069     }
3070 
3071 #ifdef DEBUG_OSL_FILE
3072     fprintf(stderr,"File Times are (in localtime):\n");
3073     pTM=localtime(&aFileStat.st_ctime);
3074     fprintf(stderr,"CreationTime is '%s'\n",asctime(pTM));
3075     pTM=localtime(&aFileStat.st_atime);
3076     fprintf(stderr,"AccessTime   is '%s'\n",asctime(pTM));
3077     pTM=localtime(&aFileStat.st_mtime);
3078     fprintf(stderr,"Modification is '%s'\n",asctime(pTM));
3079 
3080     fprintf(stderr,"File Times are (in UTC):\n");
3081     fprintf(stderr,"CreationTime is '%s'\n",ctime(&aFileStat.st_ctime));
3082     fprintf(stderr,"AccessTime   is '%s'\n",ctime(&aTimeBuffer.actime));
3083     fprintf(stderr,"Modification is '%s'\n",ctime(&aTimeBuffer.modtime));
3084 #endif
3085 
3086     if ( pLastAccessTime != 0 )
3087     {
3088         aTimeBuffer.actime=pLastAccessTime->Seconds;
3089     }
3090     else
3091     {
3092         aTimeBuffer.actime=aFileStat.st_atime;
3093     }
3094 
3095     if ( pLastWriteTime != 0 )
3096     {
3097         aTimeBuffer.modtime=pLastWriteTime->Seconds;
3098     }
3099     else
3100     {
3101         aTimeBuffer.modtime=aFileStat.st_mtime;
3102     }
3103 
3104     /* mfe: Creation time not used here! */
3105 
3106 #ifdef DEBUG_OSL_FILE
3107     fprintf(stderr,"File Times are (in localtime):\n");
3108     pTM=localtime(&aFileStat.st_ctime);
3109     fprintf(stderr,"CreationTime now '%s'\n",asctime(pTM));
3110     pTM=localtime(&aTimeBuffer.actime);
3111     fprintf(stderr,"AccessTime   now '%s'\n",asctime(pTM));
3112     pTM=localtime(&aTimeBuffer.modtime);
3113     fprintf(stderr,"Modification now '%s'\n",asctime(pTM));
3114 
3115     fprintf(stderr,"File Times are (in UTC):\n");
3116     fprintf(stderr,"CreationTime now '%s'\n",ctime(&aFileStat.st_ctime));
3117     fprintf(stderr,"AccessTime   now '%s'\n",ctime(&aTimeBuffer.actime));
3118     fprintf(stderr,"Modification now '%s'\n",ctime(&aTimeBuffer.modtime));
3119 #endif
3120 
3121     nRet=utime(pszFilePath,&aTimeBuffer);
3122     if ( nRet < 0 )
3123     {
3124         nRet=errno;
3125         return oslTranslateFileError(OSL_FET_ERROR, nRet);
3126     }
3127 
3128     return osl_File_E_None;
3129 }
3130 
3131 
3132 /******************************************************************************
3133  *
3134  *                  Utility Functions
3135  *
3136  *****************************************************************************/
3137 
3138 
3139 /*****************************************
3140  * oslMakeUStrFromPsz
3141  ****************************************/
3142 
oslMakeUStrFromPsz(const sal_Char * pszStr,rtl_uString ** ustrValid)3143 rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr, rtl_uString** ustrValid)
3144 {
3145     rtl_string2UString(
3146         ustrValid,
3147         pszStr,
3148         rtl_str_getLength( pszStr ),
3149         osl_getThreadTextEncoding(),
3150         OUSTRING_TO_OSTRING_CVTFLAGS );
3151     OSL_ASSERT(*ustrValid != 0);
3152 
3153     return *ustrValid;
3154 }
3155 
3156 /*****************************************************************************
3157  * UnicodeToText
3158  * converting unicode to text manually saves us the penalty of a temporary
3159  * rtl_String object.
3160  ****************************************************************************/
3161 
UnicodeToText(char * buffer,size_t bufLen,const sal_Unicode * uniText,sal_Int32 uniTextLen)3162 int UnicodeToText( char * buffer, size_t bufLen, const sal_Unicode * uniText, sal_Int32 uniTextLen )
3163 {
3164     rtl_UnicodeToTextConverter hConverter;
3165     sal_uInt32   nInfo;
3166     sal_Size   nSrcChars, nDestBytes;
3167 
3168     /* stolen from rtl/string.c */
3169     hConverter = rtl_createUnicodeToTextConverter( osl_getThreadTextEncoding() );
3170 
3171 	nDestBytes = rtl_convertUnicodeToText( hConverter, 0, uniText, uniTextLen,
3172                                            buffer, bufLen,
3173                                            OUSTRING_TO_OSTRING_CVTFLAGS | RTL_UNICODETOTEXT_FLAGS_FLUSH,
3174                                            &nInfo, &nSrcChars );
3175 
3176     rtl_destroyUnicodeToTextConverter( hConverter );
3177 
3178     if( nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL )
3179     {
3180         errno = EOVERFLOW;
3181         return 0;
3182     }
3183 
3184     /* ensure trailing '\0' */
3185     buffer[nDestBytes] = '\0';
3186 
3187     return nDestBytes;
3188 }
3189 
3190 /*****************************************************************************
3191    TextToUnicode
3192 
3193    @param text
3194           The text to convert.
3195 
3196    @param text_buffer_size
3197           The number of characters.
3198 
3199    @param unic_text
3200           The unicode buffer.
3201 
3202    @param unic_text_buffer_size
3203    		  The size in characters of the unicode buffer.
3204 
3205  ****************************************************************************/
3206 
TextToUnicode(const char * text,size_t text_buffer_size,sal_Unicode * unic_text,sal_Int32 unic_text_buffer_size)3207 int TextToUnicode(
3208 	const char*  text,
3209 	size_t       text_buffer_size,
3210 	sal_Unicode* unic_text,
3211 	sal_Int32    unic_text_buffer_size)
3212 {
3213     rtl_TextToUnicodeConverter hConverter;
3214     sal_uInt32 nInfo;
3215     sal_Size nSrcChars;
3216     sal_Size nDestBytes;
3217 
3218     /* stolen from rtl/string.c */
3219     hConverter = rtl_createTextToUnicodeConverter(osl_getThreadTextEncoding());
3220 
3221 	nDestBytes = rtl_convertTextToUnicode(hConverter,
3222 										  0,
3223 										  text,  text_buffer_size,
3224                                           unic_text, unic_text_buffer_size,
3225                                           OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_FLUSH,
3226                                           &nInfo, &nSrcChars);
3227 
3228     rtl_destroyTextToUnicodeConverter(hConverter);
3229 
3230     if (nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL)
3231     {
3232         errno = EOVERFLOW;
3233         return 0;
3234     }
3235 
3236     /* ensure trailing '\0' */
3237     unic_text[nDestBytes] = '\0';
3238 
3239     return nDestBytes;
3240 }
3241 
3242 /******************************************************************************
3243  *
3244  *                  GENERIC FLOPPY FUNCTIONS
3245  *
3246  *****************************************************************************/
3247 
3248 /*****************************************
3249  * osl_unmountVolumeDevice
3250  ****************************************/
osl_unmountVolumeDevice(oslVolumeDeviceHandle Handle)3251 oslFileError osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle )
3252 {
3253 	if ( Handle )
3254 		return osl_File_E_None;
3255 	else
3256 		return osl_File_E_INVAL;
3257 }
3258 
3259 /*****************************************
3260  * osl_automountVolumeDevice
3261  ****************************************/
osl_automountVolumeDevice(oslVolumeDeviceHandle Handle)3262 oslFileError osl_automountVolumeDevice( oslVolumeDeviceHandle Handle )
3263 {
3264 	if ( Handle )
3265 		return osl_File_E_None;
3266 	else
3267 		return osl_File_E_INVAL;
3268 }
3269 
3270 /*****************************************
3271  * osl_getVolumeDeviceMountPath
3272  ****************************************/
osl_getVolumeDeviceMountPath(oslVolumeDeviceHandle Handle,rtl_uString ** pstrPath)3273 oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
3274 {
3275 	if ( Handle && pstrPath )
3276 	{
3277 		rtl_uString_assign( pstrPath, (rtl_uString *)Handle );
3278 		return osl_File_E_None;
3279 	}
3280 	else
3281 		return osl_File_E_INVAL;
3282 }
3283 
3284 /*****************************************
3285  * osl_acquireVolumeDeviceHandle
3286  ****************************************/
3287 
osl_acquireVolumeDeviceHandle(oslVolumeDeviceHandle Handle)3288 oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
3289 {
3290 	if ( Handle )
3291 	{
3292 		rtl_uString_acquire( (rtl_uString *)Handle );
3293 		return osl_File_E_None;
3294 	}
3295 	else
3296 		return osl_File_E_INVAL;
3297 }
3298 
3299 /*****************************************
3300  * osl_releaseVolumeDeviceHandle
3301  ****************************************/
3302 
osl_releaseVolumeDeviceHandle(oslVolumeDeviceHandle Handle)3303 oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
3304 {
3305 	if ( Handle )
3306 	{
3307 		rtl_uString_release( (rtl_uString *)Handle );
3308 		return osl_File_E_None;
3309 	}
3310 	else
3311 		return osl_File_E_INVAL;
3312 }
3313 
3314 /******************************************************************************
3315  *
3316  *                  OS/2 FLOPPY FUNCTIONS
3317  *
3318  *****************************************************************************/
osl_isFloppyDrive(const sal_Char * pszPath)3319 static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath)
3320 {
3321     return NULL;
3322 }
3323 
3324