xref: /aoo42x/main/tools/source/fsys/os2.cxx (revision 27ead02a)
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 #define INCL_DOSEXCEPTIONS
25 
26 #include <stdlib.h>
27 
28 #ifdef __BORLANDC__
29 #include <alloc.h>
30 #else
31 #include <malloc.h>
32 #endif
33 #include <tools/debug.hxx>
34 #include <tools/list.hxx>
35 #include <tools/bigint.hxx>
36 #include <tools/fsys.hxx>
37 #include "comdep.hxx"
38 
39 #ifdef OS2
40 #ifndef _VOS_MUTEX_HXX //autogen
41 #include <vos/mutex.hxx>
42 #endif
43 #endif
44 
45 int Sys2SolarError_Impl( int nSysErr );
46 
47 DECLARE_LIST( DirEntryList, DirEntry* );
48 DECLARE_LIST( FSysSortList, FSysSort* );
49 DECLARE_LIST( FileStatList, FileStat* );
50 
51 static char sCaseMap[256];
52 static sal_Bool bCaseMap = FALSE;
53 static sal_Bool bDriveMap = FALSE;
54 
55 struct DriveMapItem
56 {
57     DirEntryKind    nKind;
58     char            cName;
59     FSysPathStyle   nStyle;
60 };
61 
62 void CreateCaseMapImpl();
63 void CreateDriveMapImpl();
64 
65 static DriveMapItem aDriveMap[26];
66 
67 static sal_Bool   bLastCaseSensitive    = FALSE;
68 
69 //====================================================================
70 
71 int ApiRet2ToSolarError_Impl( int nApiRet )
72 {
73     switch ( nApiRet )
74     {
75         case NO_ERROR:                      return ERRCODE_NONE;
76         case ERROR_FILE_NOT_FOUND:          return ERRCODE_IO_NOTEXISTS;
77         case ERROR_PATH_NOT_FOUND:          return ERRCODE_IO_NOTEXISTSPATH;
78         case ERROR_TOO_MANY_OPEN_FILES:     return ERRCODE_IO_TOOMANYOPENFILES;
79         case ERROR_ACCESS_DENIED:           return ERRCODE_IO_ACCESSDENIED;
80         case ERROR_NOT_ENOUGH_MEMORY:       return ERRCODE_IO_OUTOFMEMORY;
81         case ERROR_BAD_FORMAT:              return ERRCODE_IO_WRONGFORMAT;
82         case ERROR_NOT_SAME_DEVICE:         return ERRCODE_IO_INVALIDDEVICE;
83         case ERROR_WRITE_PROTECT:           return ERRCODE_IO_INVALIDDEVICE;
84         case ERROR_BAD_UNIT:                return ERRCODE_IO_INVALIDDEVICE;
85         case ERROR_CRC:                     return ERRCODE_IO_INVALIDDEVICE;
86         case ERROR_NOT_DOS_DISK:            return ERRCODE_IO_INVALIDDEVICE;
87         case ERROR_WRITE_FAULT:             return ERRCODE_IO_CANTWRITE;
88         case ERROR_READ_FAULT:              return ERRCODE_IO_CANTREAD;
89         case ERROR_SHARING_VIOLATION:       return ERRCODE_IO_LOCKVIOLATION;
90         case ERROR_LOCK_VIOLATION:          return ERRCODE_IO_LOCKVIOLATION;
91         case ERROR_WRONG_DISK:              return ERRCODE_IO_LOCKVIOLATION;
92         case ERROR_HANDLE_DISK_FULL:        return ERRCODE_IO_OUTOFSPACE;
93         case ERROR_NOT_SUPPORTED:           return ERRCODE_IO_NOTSUPPORTED;
94         case ERROR_DUP_NAME:                return ERRCODE_IO_ALREADYEXISTS;
95         case ERROR_BAD_NETPATH:             return ERRCODE_IO_NOTEXISTSPATH;
96         case ERROR_DEV_NOT_EXIST:           return ERRCODE_IO_NOTEXISTS;
97         case ERROR_NETWORK_ACCESS_DENIED:   return ERRCODE_IO_ACCESSDENIED;
98         case ERROR_INVALID_PARAMETER:       return ERRCODE_IO_INVALIDPARAMETER;
99         case ERROR_NET_WRITE_FAULT:         return ERRCODE_IO_CANTWRITE;
100         case ERROR_DEVICE_IN_USE:           return ERRCODE_IO_INVALIDPARAMETER;
101         case ERROR_DISK_FULL:               return ERRCODE_IO_OUTOFSPACE;
102         case ERROR_BAD_ARGUMENTS:           return ERRCODE_IO_INVALIDPARAMETER;
103         case ERROR_BAD_PATHNAME:            return ERRCODE_IO_NOTEXISTSPATH;
104         case ERROR_LOCK_FAILED:             return ERRCODE_IO_LOCKVIOLATION;
105         case ERROR_LOCKED:                  return ERRCODE_IO_LOCKVIOLATION;
106         case ERROR_DUPLICATE_NAME:          return ERRCODE_IO_ALREADYEXISTS;
107         case ERROR_DIRECTORY_IN_CDS:        return ERRCODE_IO_LOCKVIOLATION;
108         case ERROR_CURRENT_DIRECTORY:       return ERRCODE_IO_LOCKVIOLATION;
109         case ERROR_FILENAME_EXCED_RANGE:    return ERRCODE_IO_NAMETOOLONG;
110     }
111 
112     DBG_TRACE1( "FSys: unknown apiret error %d occured", nApiRet );
113     return FSYS_ERR_UNKNOWN;
114 }
115 
116 //--------------------------------------------------------------------
117 
118 char* volumeid( const char* pPfad )
119 {
120     static FSINFO   aFSInfoBuf;
121     ULONG           ulFSInfoLevel = FSIL_VOLSER;
122     ULONG           nDriveNumber;
123 
124     nDriveNumber = toupper(*pPfad) - 'A' + 1;
125 
126     if ( nDriveNumber >= 3 )
127     {
128         APIRET rc = DosQueryFSInfo(
129             nDriveNumber, ulFSInfoLevel, &aFSInfoBuf, sizeof(FSINFO) );
130         if ( rc )
131             return 0;
132         return (char*) aFSInfoBuf.vol.szVolLabel;
133     }
134     return 0;
135 }
136 
137 //--------------------------------------------------------------------
138 
139 /*************************************************************************
140 |*
141 |*    DirEntry::ToAbs()
142 |*
143 |*    Beschreibung      FSYS.SDW
144 |*    Ersterstellung    MI 26.04.91
145 |*    Letzte Aenderung  MA 02.12.91 13:30
146 |*
147 *************************************************************************/
148 
149 sal_Bool DirEntry::ToAbs()
150 {
151     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
152 
153     if ( FSYS_FLAG_VOLUME == eFlag )
154     {
155         eFlag = FSYS_FLAG_ABSROOT;
156         return TRUE;
157     }
158 
159     if ( IsAbs() )
160         return TRUE;
161 
162 	char sBuf[_MAX_PATH + 1];
163 	*this = DirEntry( String( getcwd( sBuf, _MAX_PATH ), osl_getThreadTextEncoding() ) ) + *this;
164 
165     return IsAbs();
166 }
167 
168 /*************************************************************************
169 |*
170 |*    DirEntry::GetVolume()
171 |*
172 |*    Beschreibung      FSYS.SDW
173 |*    Ersterstellung    MI 04.03.92
174 |*    Letzte Aenderung  MI 04.03.92
175 |*
176 *************************************************************************/
177 
178 String DirEntry::GetVolume() const
179 {
180     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
181 
182     String aRet;
183     const DirEntry *pTop = ImpGetTopPtr();
184     ByteString aName = ByteString( pTop->aName ).ToLowerAscii();
185 
186     if ( ( pTop->eFlag == FSYS_FLAG_ABSROOT ||
187            pTop->eFlag == FSYS_FLAG_RELROOT ||
188            pTop->eFlag == FSYS_FLAG_VOLUME )
189          && aName != "a:" && aName != "b:" && Exists() )
190     {
191         const char *pVol;
192         pVol = volumeid( (char*) pTop->aName.GetBuffer() );
193 		if (pVol)
194 			aRet = String( pVol, osl_getThreadTextEncoding());
195     }
196 
197     return aRet;
198 }
199 
200 /*************************************************************************
201 |*
202 |*    DirEntry::SetCWD()
203 |*
204 |*    Beschreibung      FSYS.SDW
205 |*    Ersterstellung    MI 26.04.91
206 |*    Letzte Aenderung  MI 21.05.92
207 |*
208 *************************************************************************/
209 
210 sal_Bool DirEntry::SetCWD( sal_Bool bSloppy ) const
211 {
212     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
213 
214     if ( eFlag == FSYS_FLAG_CURRENT && !aName.Len() )
215         return TRUE;
216 
217     if ( !chdir(ByteString(GetFull(), osl_getThreadTextEncoding()).GetBuffer()) )
218     {
219         //nError = FSYS_ERR_OK;
220         return TRUE;
221     }
222 
223     if ( bSloppy && pParent &&
224          !chdir(ByteString(pParent->GetFull(), osl_getThreadTextEncoding()).GetBuffer()) )
225     {
226         //nError = FSYS_ERR_OK;
227         return TRUE;
228     }
229 
230     //nError = FSYS_ERR_NOTADIRECTORY;
231     return FALSE;
232 }
233 
234 /*************************************************************************
235 |*
236 |*    DirEntry::MoveTo()
237 |*
238 |*    Beschreibung      FSYS.SDW
239 |*    Ersterstellung    MI 26.04.91
240 |*    Letzte Aenderung  MA 02.12.91 14:07
241 |*
242 *************************************************************************/
243 
244 #if 0 // YD see dirent.cxx
245 sal_Bool createLongNameEA( const PCSZ pszPath, ULONG ulAttributes, const String& aLongName );
246 
247 FSysError DirEntry::MoveTo( const DirEntry& rDest ) const
248 {
249     DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
250 
251     DirEntry aTmpDest(rDest);
252     FileStat aTmpStat(aTmpDest);
253     if ( aTmpStat.IsKind(FSYS_KIND_DIR) )
254         aTmpDest += DirEntry( GetName() );
255 
256     String aSource( GetFull() );
257     String aDest( aTmpDest.GetFull() );
258     String aShortSource("");
259     String aShortDest("");
260 
261     if (Folder::IsAvailable())
262     {
263         if  (IsLongNameOnFAT())
264         {
265             // in kurzen Pfad wandeln
266             ItemIDPath      aItemIDPath(aSource);
267             aShortSource = aItemIDPath.GetHostNotationPath();
268         }
269         if  (rDest.IsLongNameOnFAT())
270         {
271             // in kurzen Pfad wandeln
272             ItemIDPath      aItemIDPath(aDest);
273             aShortDest = aItemIDPath.GetHostNotationPath();
274         }
275     }
276 
277     APIRET nRet = DosMove( aShortSource.Len()>0?(PSZ)aShortSource.GetStr():(PSZ)aSource.GetStr(),
278                            aShortDest.Len()>0?(PSZ)aShortDest.GetStr():(PSZ)aDest.GetStr());
279 
280     if ( nRet == ERROR_DIRECTORY_IN_CDS ||
281          nRet == ERROR_CURRENT_DIRECTORY )
282     {
283         // 2nd chance with modified CWD
284         DosSetCurrentDir( (PSZ) "\\" );
285         nRet = DosMove( aShortSource.Len()>0?(PSZ)aShortSource.GetStr():(PSZ)aSource.GetStr(),
286                         aShortDest.Len()>0?(PSZ)aShortDest.GetStr():(PSZ)aDest.GetStr());
287     }
288     else if ( nRet == ERROR_NOT_SAME_DEVICE )
289     {
290         // other volume => copy+delete
291         FileCopier aMover( *this, rDest );
292         nRet = aMover.Execute( FSYS_ACTION_MOVE|FSYS_ACTION_RECURSIVE );
293         return nRet;
294     }
295 
296     if ( (nRet==NO_ERROR) && aShortDest.Len()>0)
297     {
298 	createLongNameEA((const char*)aShortDest,  FILE_NORMAL, rDest.GetName());
299     }
300 
301     return ApiRet2ToSolarError_Impl( nRet );
302 }
303 #endif // 0
304 
305 //-------------------------------------------------------------------------
306 
307 USHORT DirReader_Impl::Init()
308 {
309     // Block-Devices auflisten?
310     if ( pDir->eAttrMask & FSYS_KIND_BLOCK )
311     {
312         CreateDriveMapImpl();
313         // CWD merken
314         DirEntry aCurrentDir;
315         aCurrentDir.ToAbs();
316 
317         // einzeln auf Existenz und Masken-konformit"at pr"ufen
318         USHORT nRead = 0;
319         char sDrive[3] = { '?', ':', 0 };
320         char sRoot[4] = { '?', ':', '\\', 0 };
321         for ( char c = 'a'; c <= 'z'; c++ )
322         {
323             sDrive[0] = c;
324             sRoot[0] = c;
325             DirEntry* pDrive = new DirEntry( sDrive, FSYS_FLAG_VOLUME, FSYS_STYLE_HOST );
326             if ( pDir->aNameMask.Matches( String( ByteString(sDrive), osl_getThreadTextEncoding()))
327 				&& aDriveMap[c-'a'].nKind != FSYS_KIND_UNKNOWN )
328             {
329                 if ( pDir->pStatLst ) //Status fuer Sort gewuenscht?
330                 {
331                     FileStat *pNewStat = new FileStat( *pDrive );
332                     pDir->ImpSortedInsert( pDrive, pNewStat );
333                 }
334                 else
335                     pDir->ImpSortedInsert( pDrive, NULL );
336                 ++nRead;
337             }
338             else
339                 delete pDrive;
340         }
341 
342         // CWD restaurieren
343         aCurrentDir.SetCWD();
344         return nRead;
345     }
346 
347     return 0;
348 }
349 
350 //-------------------------------------------------------------------------
351 
352 USHORT DirReader_Impl::Read()
353 {
354 	if (!pDosDir)
355 	{
356 		pDosDir = opendir( (char*) ByteString(aPath, osl_getThreadTextEncoding()).GetBuffer() );
357 	}
358 
359 	if (!pDosDir)
360 	{
361 		bReady = TRUE;
362 		return 0;
363 	}
364 
365     // Directories und Files auflisten?
366 	if ( ( pDir->eAttrMask & FSYS_KIND_DIR || pDir->eAttrMask & FSYS_KIND_FILE ) &&
367 		 ( ( pDosEntry = readdir( pDosDir ) ) != NULL ) )
368 	{
369 		String aD_Name(pDosEntry->d_name, osl_getThreadTextEncoding());
370         if ( pDir->aNameMask.Matches( aD_Name  ) )
371         {
372 			DirEntryFlag eFlag =
373 					0 == strcmp( pDosEntry->d_name, "." ) ? FSYS_FLAG_CURRENT
374 				:	0 == strcmp( pDosEntry->d_name, ".." ) ? FSYS_FLAG_PARENT
375 				:	FSYS_FLAG_NORMAL;
376             DirEntry *pTemp = new DirEntry( ByteString(pDosEntry->d_name), eFlag, FSYS_STYLE_UNX );
377             if ( pParent )
378                 pTemp->ImpChangeParent( new DirEntry( *pParent ), FALSE);
379             FileStat aStat( *pTemp );
380             if ( ( ( ( pDir->eAttrMask & FSYS_KIND_DIR ) &&
381 					 ( aStat.IsKind( FSYS_KIND_DIR ) ) ) ||
382 				   ( ( pDir->eAttrMask & FSYS_KIND_FILE ) &&
383 					 !( aStat.IsKind( FSYS_KIND_DIR ) ) ) ) &&
384 				 !( pDir->eAttrMask & FSYS_KIND_VISIBLE &&
385 					pDosEntry->d_name[0] == '.' ) )
386             {
387                 if ( pDir->pStatLst ) //Status fuer Sort gewuenscht?
388                     pDir->ImpSortedInsert( pTemp, new FileStat( aStat ) );
389                 else
390                     pDir->ImpSortedInsert( pTemp, NULL );;
391 				return 1;
392             }
393             else
394                 delete pTemp;
395         }
396 	}
397 	else
398 		bReady = TRUE;
399 	return 0;
400 }
401 
402 /*************************************************************************
403 |*
404 |*    FileStat::FileStat()
405 |*
406 |*    Beschreibung      FSYS.SDW
407 |*    Ersterstellung    MA 05.11.91
408 |*    Letzte Aenderung  MA 07.11.91
409 |*
410 *************************************************************************/
411 
412 FileStat::FileStat( const void *pInfo,      // struct dirent
413                     const void * ):         // dummy
414         aDateCreated(0),
415         aTimeCreated(0),
416         aDateModified(0),
417         aTimeModified(0),
418         aDateAccessed(0),
419         aTimeAccessed(0)
420 {
421     struct dirent *pDirent = (struct dirent*) pInfo;
422 
423     nSize = pDirent->d_size;
424 
425     aDateCreated  = MsDos2Date( (FDATE*) &pDirent->d_date );
426     aTimeCreated  = MsDos2Time( (FTIME*) &pDirent->d_time );
427     aDateModified = aDateModified;
428     aTimeModified = aTimeModified;
429     aDateAccessed = aDateModified;
430     aTimeAccessed = aTimeModified;
431 
432     nKindFlags = FSYS_KIND_FILE;
433     if ( pDirent->d_type & DOS_DIRECT )
434         nKindFlags = FSYS_KIND_DIR;
435 }
436 
437 /*************************************************************************
438 |*
439 |*    FileStat::Update()
440 |*
441 |*    Beschreibung      FSYS.SDW
442 |*    Ersterstellung    MI 11.06.91
443 |*    Letzte Aenderung  MA 07.11.91
444 |*
445 *************************************************************************/
446 
447 struct _FSYS_FSQBUFFER
448 {
449     FSQBUFFER2  aBuf;
450     UCHAR       sBuf[256];
451 };
452 
453 sal_Bool FileStat::Update( const DirEntry& rDirEntry, sal_Bool bAccessRemovableDevice )
454 {
455     nSize = 0;
456     FSysPathStyle eStyle = FSYS_STYLE_UNKNOWN;
457     aCreator.Erase();
458     aType.Erase();
459     aDateCreated = Date(0);
460     aTimeCreated = Time(0);
461     aDateModified = Date(0);
462     aTimeModified = Time(0);
463     aDateAccessed = Date(0);
464     aTimeAccessed = Time(0);
465 
466 	if ( !rDirEntry.IsValid() )
467 	{
468 		nError = FSYS_ERR_NOTEXISTS;
469 		return FALSE;
470 	}
471 
472 	// Sonderbehandlung falls es sich um eine Root ohne Laufwerk handelt
473 	if ( !rDirEntry.aName.Len() && rDirEntry.eFlag == FSYS_FLAG_ABSROOT )
474 	{
475 		nKindFlags = FSYS_KIND_DIR;
476 		nError = FSYS_ERR_OK;
477 		return TRUE;
478 	}
479 
480     // Sonderbehandlung falls es sich um eine Wildcard handelt
481     ByteString aTempName( rDirEntry.GetName(), osl_getThreadTextEncoding() );
482     if ( strchr( aTempName.GetBuffer(), '?' ) ||
483          strchr( aTempName.GetBuffer(), '*' ) ||
484          strchr( aTempName.GetBuffer(), ';' ) )
485     {
486         nKindFlags = FSYS_KIND_WILD;
487         nError = FSYS_ERR_OK;
488         return TRUE;
489     }
490 
491     // Sonderbehandlung falls es sich um eine Root handelt
492     if ( rDirEntry.eFlag == FSYS_FLAG_VOLUME ||
493          rDirEntry.eFlag == FSYS_FLAG_ABSROOT )
494     {
495         if ( rDirEntry.eFlag == FSYS_FLAG_VOLUME )
496             nKindFlags = FSYS_KIND_DEV;
497         else
498             nKindFlags = FSYS_KIND_DIR;
499 
500         if ( rDirEntry.aName.Len() == 2 )
501         {
502             if ( !bDriveMap )
503                 CreateDriveMapImpl();
504 
505 			ByteString rDirEntryUpperCase = ByteString( rDirEntry.aName ).ToUpperAscii();
506             DriveMapItem &rItem = aDriveMap[rDirEntryUpperCase.GetChar(0) - 'A'];
507             if ( !rItem.nKind )
508             {
509                 nError = ERRCODE_IO_INVALIDDEVICE;
510                                 nKindFlags = FSYS_KIND_UNKNOWN;
511                 return FALSE;
512             }
513             else
514             {
515                 if ( rDirEntry.eFlag == FSYS_FLAG_VOLUME )
516                     nKindFlags |= FSYS_KIND_BLOCK | rItem.nKind;
517                 eStyle = rItem.nStyle;
518             }
519         }
520 
521         nError = FSYS_ERR_OK;
522         return TRUE;
523     }
524 
525     // disable error-boxes for hard-errors
526     DosError(FERR_DISABLEHARDERR);
527 
528     // Statusinformation vom Betriebssystem holen
529     DirEntry    aTempDirEntry( rDirEntry );
530     char*       p;
531 
532     aTempDirEntry.ToAbs();
533     ByteString aFullName( aTempDirEntry.GetFull(), osl_getThreadTextEncoding() );
534 
535 #if 0 // YD
536 	if (Folder::IsAvailable() && aTempDirEntry.IsLongNameOnFAT())
537 	{
538 		// in String mit kurzem Pfad wandeln
539 		ItemIDPath aItemIDPath(aTempDirEntry.GetFull());
540 		aFullName = ByteString( aItemIDPath.GetHostNotationPath(), osl_getThreadTextEncoding() );
541 	}
542 #endif
543 
544     p = (char *) aFullName.GetBuffer();
545 
546     FILESTATUS3 filestat;
547     memset( &filestat, 0, sizeof( filestat ) );
548     if( DosQueryPathInfo( (PSZ)p, 1, &filestat, sizeof( filestat ) ) )
549     {
550         nError = FSYS_ERR_NOTEXISTS;
551         nKindFlags = FSYS_KIND_UNKNOWN;
552         return FALSE;
553     }
554 
555     nError = FSYS_ERR_OK;
556     nSize = filestat.cbFile;
557 
558     nKindFlags = FSYS_KIND_UNKNOWN;
559     if( filestat.attrFile & FILE_DIRECTORY )
560         nKindFlags |= FSYS_KIND_DIR;
561     if ( nKindFlags == FSYS_KIND_UNKNOWN )
562         nKindFlags = nKindFlags | FSYS_KIND_FILE;
563 
564     aDateModified = Date( filestat.fdateLastWrite.day,
565                           filestat.fdateLastWrite.month,
566                           filestat.fdateLastWrite.year + 1980 );
567 
568     aTimeModified = Time( filestat.ftimeLastWrite.hours,
569                           filestat.ftimeLastWrite.minutes,
570                           filestat.ftimeLastWrite.twosecs*2 );
571 
572     if ( filestat.fdateCreation.day )
573     {
574         aDateCreated  = Date( filestat.fdateCreation.day,
575                               filestat.fdateCreation.month,
576                               filestat.fdateCreation.year + 1980 );
577 
578         aTimeCreated  = Time( filestat.ftimeCreation.hours,
579                               filestat.ftimeCreation.minutes,
580                               filestat.ftimeCreation.twosecs*2 );
581     }
582     else
583     {
584         aDateCreated = aDateModified;
585         aTimeCreated = aTimeModified;
586     }
587 
588     if ( filestat.fdateLastAccess.day > 0 )
589     {
590         aDateAccessed = Date( filestat.fdateLastAccess.day,
591                               filestat.fdateLastAccess.month,
592                               filestat.fdateLastAccess.year + 1980 );
593 
594         aTimeAccessed = Time( filestat.ftimeLastAccess.hours,
595                                 filestat.ftimeLastAccess.minutes,
596                                 filestat.ftimeLastAccess.twosecs*2 );
597     }
598     else
599     {
600         aDateAccessed = aDateModified;
601         aTimeAccessed = aTimeModified;
602     }
603 
604     return TRUE;
605 }
606 
607 sal_Bool IsRedirectable_Impl( const ByteString &rPath )
608 {
609     if ( rPath.Len() >= 3 && ':' == rPath.GetBuffer()[1] )
610     {
611         ByteString aVolume = rPath.Copy( 0, 3 );
612         DriveMapItem &rItem = aDriveMap[toupper(aVolume.GetChar(0)) - 'A'];
613         return FSYS_KIND_FIXED != rItem.nKind;
614     }
615     return FALSE;
616 }
617 
618 #if 0
619 sal_Bool IsRedirectable_Impl( const String &rPath )
620 {
621     if ( rPath.Len() >= 3 && ':' == rPath.GetStr()[1] )
622     {
623         DriveMapItem &rItem = aDriveMap[toupper(rPath[0]) - 'A'];
624         return FSYS_KIND_FIXED != rItem.nKind;
625     }
626     return FALSE;
627 }
628 #endif
629 
630 
631 /*************************************************************************
632 |*
633 |*    TempDirImpl()
634 |*
635 |*    Beschreibung      liefert den Namens des Directories fuer temporaere
636 |*                      Dateien
637 |*    Ersterstellung    MI 16.03.94
638 |*    Letzte Aenderung  MI 16.03.94
639 |*
640 *************************************************************************/
641 
642 const char* TempDirImpl( char *pBuf )
643 {
644     PSZ         pVar;
645     USHORT      nRet;
646     sal_Bool        bAppendTemp = FALSE; // mu\s noch \\temp angeh"angt werden
647 
648     // Erstmal sehen, ob TEMP oder TMP gesetzt sind
649     nRet = DosScanEnv( (PSZ)"TEMP", &pVar );
650     if( nRet )
651         nRet = DosScanEnv( (PSZ)"temp", &pVar );
652     if( nRet )
653         nRet = DosScanEnv( (PSZ)"TMP", &pVar );
654     if( nRet )
655         nRet = DosScanEnv( (PSZ)"tmp", &pVar );
656     if( nRet )
657         nRet = DosScanEnv( (PSZ)"TMPDIR", &pVar );
658 
659     // falls das geklappt hat, und ein Backslash dranhaengt,
660     // oder falls es bisher nicht geklappt hat,
661     // muessen wir nachher einen Backslash entfernen
662     sal_Bool bRemoveBS = nRet || *(pVar+strlen(pVar)-1) == '\\';
663 
664     // Keine temp-Variable gefunden, dann gehen wir mal auf die Suche
665     // nach dem System-Laufwerk
666     if( nRet )
667     {
668         nRet = DosScanEnv( (PSZ)"USER_INI",&pVar );
669         bAppendTemp = (0 == nRet);
670     }
671     if( nRet )
672     {
673         nRet = DosScanEnv( (PSZ)"SYSTEM_INI", &pVar );
674         bAppendTemp = (0 == nRet);
675     }
676     if( nRet )
677         // Wenn das immer noch nicht reicht nehmen wir eben die Root von C:
678 #ifdef __BORLANDC__
679         pVar = (PSZ)"c:\\temp\\";
680 #else
681         pVar = (PCSZ)"c:\\temp\\";
682 #endif
683     strcpy( pBuf, (const char*)pVar );
684 
685     // jetzt haengt ggf. ein Backlash dran, den wir abschneiden,
686     // ggf. inklusive dahinter haengendem Dateinamen
687     if ( bRemoveBS )
688     {
689         char *pTail = pBuf + strlen(pBuf) - 1;
690         for ( char cLast = *pTail; cLast != '\\'; cLast = *(--pTail) )
691             *pTail = 0;
692     }
693 
694     if ( bAppendTemp )
695         strcat( pBuf, "\\temp" );
696     DirEntry( pBuf ).MakeDir();
697 
698     return pBuf;
699 }
700 
701 #define CURRENT_COUNTRY 0
702 #define NLS_CODEPAGE 850
703 
704 /*====================================================================
705  * CreateCaseMapImpl()
706  * creates a map of each character to convert to lower
707  *--------------------------------------------------------------------*/
708 
709 #if 0
710 void CreateCaseMapImpl()
711 {
712     // build a string starting with code 0 as first character upto 255
713     char sTemp[256];
714 	USHORT n;
715 
716     for ( n = 0; n < 256; ++n )
717         sTemp[n] = (char) n;
718 
719     // convert string to upper case
720     COUNTRYCODE aCountry;
721     aCountry.country = CURRENT_COUNTRY;   /* Country code */
722     aCountry.codepage = NLS_CODEPAGE;     /* Code page */
723     DosMapCase( 255, &aCountry, sTemp+1 );
724 
725     // fill a global buffer starting with code 0 as first character upto 255
726     for ( n = 0; n < 256; ++n )
727         sCaseMap[n] = (char) n;
728 
729     // reorder by upper-code and store in a global buffer
730     for ( n = 255; n > 0; --n )
731         // was this character converted?
732         if ( sTemp[n] != (char) n )
733             // we found a convertion from upper to lower
734             sCaseMap[ (unsigned char) sTemp[n] ] = (char) n;
735 
736     bCaseMap = TRUE;
737 }
738 
739 String ToLowerImpl( const String& rSource )
740 {
741     if ( !bCaseMap )
742         CreateCaseMapImpl();
743 
744     // TH sagt: International ist zu langsam, also mit einer eigenen Map
745     ByteString aLower( rSource );
746     for ( USHORT n = 0; n < aLower.Len(); ++n )
747         aLower[n] = sCaseMap[ (unsigned char) aLower[n] ];
748     return aLower;
749 }
750 #endif // 0
751 
752 /*====================================================================
753  * CreateDriveMapImpl()
754  * creates a map of drive-infos like FileSystem (style) and Kind (remote)
755  *--------------------------------------------------------------------*/
756 typedef struct _FSQBUFFER_
757 {
758     FSQBUFFER2  aBuf;
759     UCHAR       sBuf[64];
760 } FSQBUFFER_;
761 
762 void CreateDriveMapImpl()
763 {
764 #ifdef POWERPC
765     // !!!!! Hack, da der untere Teil mit Beta 2 noch abstuertzt !!!!!
766     BYTE nFloppies = 1;
767     for ( USHORT nDrive = 0; nDrive < 26; ++nDrive )
768     {
769         if ( nDrive < nFloppies )
770         {
771             aDriveMap[nDrive].nKind = FSYS_KIND_REMOVEABLE;
772             aDriveMap[nDrive].nStyle = FSYS_STYLE_FAT;
773         }
774         else
775         {
776             aDriveMap[nDrive].nKind = FSYS_KIND_UNKNOWN;
777             aDriveMap[nDrive].nStyle = FSYS_STYLE_UNKNOWN;
778         }
779     }
780 
781     aDriveMap[2].nKind = FSYS_KIND_FIXED;
782     aDriveMap[2].nStyle = FSYS_STYLE_FAT;
783 #else
784     FSQBUFFER_	aBuf;
785     ULONG       nBufLen;
786     APIRET      nRet;
787 	USHORT 		nDrive;
788 
789     // disable error-boxes for hard-errors
790     DosError(FERR_DISABLEHARDERR);
791 
792     // determine number of floppy-drives
793     PM_BYTE nFloppies;
794     nRet = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY );
795 
796     // reset the map
797     for ( nDrive = 0; nDrive < 26; ++nDrive )
798     {
799         if ( nDrive < nFloppies )
800         {
801             aDriveMap[nDrive].nKind = FSYS_KIND_REMOVEABLE;
802             aDriveMap[nDrive].nStyle = FSYS_STYLE_FAT;
803         }
804         else
805         {
806             aDriveMap[nDrive].nKind = FSYS_KIND_UNKNOWN;
807             aDriveMap[nDrive].nStyle = FSYS_STYLE_UNKNOWN;
808         }
809     }
810 
811     // determine file-system via DosOpen/DocDevIOCtrl
812     for ( nDrive = 2; nDrive < 26; ++nDrive )
813     {
814         // open drive
815         sal_Bool bFixed;
816         HFILE nDevHandle;
817         char pDriveName[3] = "#:";
818         pDriveName[0] = nDrive+'a';
819         ULONG nAction;
820         nRet = DosOpen( (PSZ) pDriveName, &nDevHandle,
821             &nAction, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS,
822             OPEN_FLAGS_DASD|OPEN_SHARE_DENYNONE|OPEN_ACCESS_READONLY,
823             0 );
824 
825         // exists?
826         if ( !nRet )
827         {
828             // removeable?
829             PM_BYTE nDriveId = nDrive;
830             ULONG nParaOutLen, nDataOutLen;
831             nRet = DosDevIOCtl(nDevHandle, 8, 0x20,
832                 &nDriveId, sizeof(nDriveId), &nParaOutLen,
833                 &bFixed, sizeof(bFixed), &nDataOutLen );
834 
835             // prepare the drive-map
836             if ( !nRet && !bFixed )
837                 aDriveMap[nDrive].nKind = FSYS_KIND_REMOVEABLE;
838 
839             // close drive
840             DosClose(nDevHandle);
841         }
842         else if ( nRet == ERROR_NOT_READY )
843             aDriveMap[nDrive].nKind = FSYS_KIND_REMOVEABLE | FSYS_KIND_CDROM;
844     }
845 
846     // determine file-system via FSAttach
847     nRet = 0;
848     for ( USHORT n = 3; nRet != ERROR_NO_MORE_ITEMS; ++n )
849     {
850         nBufLen = sizeof( aBuf );
851         nRet = DosQueryFSAttach( 0, n, FSAIL_DRVNUMBER,
852             (_FSQBUFFER2*) &aBuf, &nBufLen );
853         if ( !nRet )
854         {
855             nDrive = toupper(aBuf.aBuf.szName[0]) - 'A';
856 
857             if ( aDriveMap[nDrive].nKind == FSYS_KIND_UNKNOWN )
858                 aDriveMap[nDrive].nKind =
859                     aBuf.aBuf.iType == 3 ? FSYS_KIND_FIXED :
860                     aBuf.aBuf.iType == 4 ? FSYS_KIND_REMOTE :
861                     FSYS_KIND_UNKNOWN;
862 
863             char *pType = (char*)(aBuf.aBuf.szName + aBuf.aBuf.cbName + 1);
864             aDriveMap[nDrive].nStyle =
865                 strcmp( pType, "FAT" ) == 0 ? FSYS_STYLE_FAT :
866                 strcmp( pType, "FAT32" ) == 0 ? FSYS_STYLE_VFAT :
867                 strcmp( pType, "NTFS" ) == 0 ? FSYS_STYLE_NTFS :
868                 strcmp( pType, "HPFS" ) == 0 ? FSYS_STYLE_HPFS :
869                 strcmp( pType, "JFS" ) == 0 ? FSYS_STYLE_HPFS :
870                 strcmp( pType, "RAMFS" ) == 0 ? FSYS_STYLE_HPFS :
871                 strcmp( pType, "NDFS32" ) == 0 ? FSYS_STYLE_HPFS :
872                 strcmp( pType, "NWFS" ) == 0 ? FSYS_STYLE_NWFS :
873 				strcmp( pType, "EXT2" ) == 0 ? FSYS_STYLE_UNX :
874 				strcmp( pType, "NFS" ) == 0 ? FSYS_STYLE_UNX :
875                 FSYS_STYLE_UNKNOWN;
876             if ( strcmp( pType, "CDFS" ) == 0 )
877                 aDriveMap[nDrive].nKind = FSYS_KIND_CDROM|FSYS_KIND_REMOVEABLE;
878         }
879     }
880 #endif
881 
882     bDriveMap = TRUE;
883 }
884 
885 Time MsDos2Time( const time_t *pTimeT )
886 {
887     tm *pTm = localtime( pTimeT );
888     if ( pTm )
889         return Time( pTm->tm_hour, pTm->tm_min, pTm->tm_sec );
890     else
891         return Time(0);
892 }
893 
894 Date MsDos2Date( const time_t *pTimeT )
895 {
896     tm *pTm = localtime( pTimeT );
897     if ( pTm )
898         return Date( pTm->tm_mday, pTm->tm_mon + 1, pTm->tm_year );
899     else
900         return Date(0);
901 }
902 
903 /*************************************************************************
904 |*
905 |*    DirEntry::GetPathStyle() const
906 |*
907 |*    Beschreibung
908 |*    Ersterstellung    MI 11.05.95
909 |*    Letzte Aenderung  MI 11.05.95
910 |*
911 *************************************************************************/
912 
913 FSysPathStyle DirEntry::GetPathStyle( const String &rDevice )
914 {
915     ByteString aRootDir(rDevice, osl_getThreadTextEncoding());
916     // UNC-Pathname?
917     if ( aRootDir.Len()==0 || ( aRootDir.Len() > 1 && aRootDir.GetChar(1) != ':' ) )
918         return FSYS_STYLE_UNKNOWN;
919 
920     if ( !bDriveMap )
921         CreateDriveMapImpl();
922     return aDriveMap[toupper(aRootDir.GetChar(0)) - 'A'].nStyle;
923 }
924 
925 /*************************************************************************
926 |*
927 |*    DirEntry::IsCaseSensitive() const
928 |*
929 |*    Beschreibung
930 |*    Ersterstellung    TPF 26.02.1999
931 |*    Letzte Aenderung
932 |*
933 *************************************************************************/
934 
935 sal_Bool DirEntry::IsCaseSensitive( FSysPathStyle eFormatter ) const
936 {
937 	if (eFormatter==FSYS_STYLE_HOST)
938 	{
939 		if 	(GetPathStyle(GetDevice().GetName()) == FSYS_STYLE_UNX)
940 		{
941 			return TRUE;
942 		}
943 		else
944 		{
945 			return FALSE;
946 		}
947 	}
948 	else
949 	{
950 		sal_Bool isCaseSensitive = FALSE;			// ich bin unter OS2, also ist der default im Zweifelsfall case insensitiv
951 		switch ( eFormatter )
952 		{
953 			case FSYS_STYLE_MAC:
954 			case FSYS_STYLE_FAT:
955 			case FSYS_STYLE_VFAT:
956 			case FSYS_STYLE_NTFS:
957 			case FSYS_STYLE_NWFS:
958 			case FSYS_STYLE_HPFS:
959 			case FSYS_STYLE_DETECT:
960 				{
961 					isCaseSensitive = FALSE;
962 					break;
963 				}
964 			case FSYS_STYLE_SYSV:
965 			case FSYS_STYLE_BSD:
966 				{
967 					isCaseSensitive = TRUE;
968 					break;
969 				}
970 			default:
971 				{
972 					isCaseSensitive = FALSE;	// ich bin unter OS2, also ist der default im Zweifelsfall case insensitiv
973 					break;
974 				}
975 		}
976 		return isCaseSensitive;
977 	}
978 }
979 
980 
981 
982 
983 //=========================================================================
984 
985 ErrCode FileStat::QueryDiskSpace( const String &rPath,
986                                   BigInt &rFreeBytes, BigInt &rTotalBytes )
987 {
988     FSALLOCATE aFSInfoBuf;
989     ByteString aVol( DirEntry(rPath).ImpGetTopPtr()->GetName(), osl_getThreadTextEncoding());
990     ULONG nDriveNumber = toupper( aVol.GetChar(0) ) - 'A' + 1;
991 
992     APIRET rc = DosQueryFSInfo( nDriveNumber, FSIL_ALLOC,
993                                 &aFSInfoBuf, sizeof(aFSInfoBuf) );
994     if ( rc )
995         return Sys2SolarError_Impl( rc );
996 
997     BigInt aBytesPerCluster( BigInt(aFSInfoBuf.cbSector) *
998                              BigInt(aFSInfoBuf.cSectorUnit) );
999     rFreeBytes = aBytesPerCluster * BigInt(aFSInfoBuf.cUnitAvail);
1000     rTotalBytes = aBytesPerCluster * BigInt(aFSInfoBuf.cUnit);
1001     return 0;
1002 }
1003 
1004 //=========================================================================
1005 
1006 void FSysEnableSysErrorBox( sal_Bool bEnable )
1007 {
1008     DosError( bEnable ? 0 : FERR_DISABLEHARDERR );
1009 }
1010 
1011