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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_tools.hxx"
26
27 #include <stdio.h>
28 #include <ctype.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <utime.h>
32 #if defined HPUX || defined LINUX
33 #include <mntent.h>
34 #define mnttab mntent
35 #elif defined SCO
36 #include <mnttab.h>
37 #elif defined AIX
38 #include <sys/mntctl.h>
39 #include <sys/vmount.h>
40 extern "C" int mntctl( int cmd, size_t size, char* buf );
41 #elif defined(NETBSD)
42 #include <sys/mount.h>
43 #elif defined(FREEBSD) || defined(MACOSX)
44 #elif defined DECUNIX
45 struct mnttab
46 {
47 char *mnt_dir;
48 char *mnt_fsname;
49 };
50 #else
51 #include <sys/mnttab.h>
52 #endif
53
54 #ifndef MAXPATHLEN
55 #define MAXPATHLEN 1024
56 #endif
57
58 #include <tools/debug.hxx>
59 #include <tools/list.hxx>
60 #include <tools/fsys.hxx>
61 #include "comdep.hxx"
62 #include <rtl/instance.hxx>
63
64 DECLARE_LIST( DirEntryList, DirEntry* )
65 DECLARE_LIST( FSysSortList, FSysSort* )
66 DECLARE_LIST( FileStatList, FileStat* )
67
68 #if defined SOLARIS || defined SINIX
69 #define MOUNTSPECIAL mnt_special
70 #define MOUNTPOINT mnt_mountp
71 #define MOUNTOPTS mnt_mntopts
72 #define MOUNTFS mnt_fstype
73 #elif defined SCO
74 #define MNTTAB "/etc/mnttab"
75 #define MOUNTSPECIAL mt_dev
76 #define MOUNTPOINT mt_filsys
77 #else
78 #define MOUNTSPECIAL mnt_fsname
79 #define MOUNTPOINT mnt_dir
80 #define MOUNTFS mnt_type
81 #endif
82
83 struct mymnttab
84 {
85 dev_t mountdevice;
86 ByteString mountspecial;
87 ByteString mountpoint;
88 ByteString mymnttab_filesystem;
mymnttabmymnttab89 mymnttab() { mountdevice = (dev_t) -1; }
90 };
91
92
93 #if defined(NETBSD) || defined(FREEBSD) || defined(MACOSX)
GetMountEntry(dev_t,struct mymnttab *)94 sal_Bool GetMountEntry(dev_t /* dev */, struct mymnttab * /* mytab */ )
95 {
96 DBG_WARNING( "Sorry, not implemented: GetMountEntry" );
97 return sal_False;
98 }
99
100 #elif defined AIX
GetMountEntry(dev_t dev,struct mymnttab * mytab)101 sal_Bool GetMountEntry(dev_t dev, struct mymnttab *mytab)
102 {
103 int bufsize;
104 if (mntctl (MCTL_QUERY, sizeof bufsize, (char*) &bufsize))
105 return sal_False;
106
107 char* buffer = (char *)malloc( bufsize * sizeof(char) );
108 if (mntctl (MCTL_QUERY, bufsize, buffer) != -1)
109 for ( char* vmt = buffer;
110 vmt < buffer + bufsize;
111 vmt += ((struct vmount*)vmt)->vmt_length)
112 {
113 struct stat buf;
114 char *mountp = vmt2dataptr((struct vmount*)vmt, VMT_STUB);
115 if ((stat (mountp, &buf) != -1) && (buf.st_dev == dev))
116 {
117 mytab->mountpoint = mountp;
118 mytab->mountspecial
119 = vmt2dataptr((struct vmount*)vmt, VMT_HOSTNAME);
120 if (mytab->mountspecial.Len())
121 mytab->mountspecial += ':';
122 mytab->mountspecial
123 += vmt2dataptr((struct vmount*)vmt, VMT_OBJECT);
124 mytab->mountdevice = dev;
125 free( buffer );
126 return sal_True;
127 }
128 }
129 free( buffer );
130 return sal_False;
131 }
132
133 #else
134
135
GetMountEntry(dev_t dev,struct mymnttab * mytab)136 static sal_Bool GetMountEntry(dev_t dev, struct mymnttab *mytab)
137 {
138 #if defined SOLARIS || defined SINIX
139 FILE *fp = fopen (MNTTAB, "r");
140 if (! fp)
141 return sal_False;
142 struct mnttab mnt[1];
143 while (getmntent (fp, mnt) != -1)
144 #elif defined SCO
145 FILE *fp = fopen (MNTTAB, "r");
146 if (! fp)
147 return sal_False;
148 struct mnttab mnt[1];
149 while (fread (&mnt, sizeof mnt, 1, fp) > 0)
150 #elif defined DECUNIX || defined AIX
151 FILE *fp = NULL;
152 if (! fp)
153 return sal_False;
154 struct mnttab mnt[1];
155 while ( 0 )
156 #else
157 FILE *fp = setmntent (MOUNTED, "r");
158 if (! fp)
159 return sal_False;
160 struct mnttab *mnt;
161 while ((mnt = getmntent (fp)) != NULL)
162 #endif
163 {
164 #ifdef SOLARIS
165 char *devopt = NULL;
166 if ( mnt->MOUNTOPTS != NULL )
167 devopt = strstr (mnt->MOUNTOPTS, "dev=");
168 if (devopt)
169 {
170 if (dev != (dev_t) strtoul (devopt+4, NULL, 16))
171 continue;
172 }
173 else
174 #endif
175 {
176 struct stat buf;
177 if ((stat (mnt->MOUNTPOINT, &buf) == -1) || (buf.st_dev != dev))
178 continue;
179 }
180 # ifdef LINUX
181 /* #61624# File mit setmntent oeffnen und mit fclose schliessen stoesst
182 bei der glibc-2.1 auf wenig Gegenliebe */
183 endmntent( fp );
184 # else
185 fclose (fp);
186 # endif
187 mytab->mountspecial = mnt->MOUNTSPECIAL;
188 mytab->mountpoint = mnt->MOUNTPOINT;
189 mytab->mountdevice = dev;
190 #ifndef SCO
191 mytab->mymnttab_filesystem = mnt->MOUNTFS;
192 #else
193 mytab->mymnttab_filesystem = "ext2"; //default ist case sensitiv unter unix
194 #endif
195 return sal_True;
196 }
197 # ifdef LINUX
198 /* #61624# dito */
199 endmntent( fp );
200 # else
201 fclose (fp);
202 # endif
203 return sal_False;
204 }
205
206 #endif
207
208 /************************************************************************
209 |*
210 |* DirEntry::IsCaseSensitive()
211 |*
212 |* Beschreibung
213 |* Ersterstellung TPF 25.02.1999
214 |* Letzte Aenderung TPF 25.02.1999
215 |*
216 *************************************************************************/
217
IsCaseSensitive(FSysPathStyle eFormatter) const218 sal_Bool DirEntry::IsCaseSensitive( FSysPathStyle eFormatter ) const
219 {
220
221 if (eFormatter==FSYS_STYLE_HOST)
222 {
223 #ifdef NETBSD
224 return sal_True;
225 #else
226 struct stat buf;
227 DirEntry aPath(*this);
228 aPath.ToAbs();
229
230 while (stat (ByteString(aPath.GetFull(), osl_getThreadTextEncoding()).GetBuffer(), &buf))
231 {
232 if (aPath.Level() == 1)
233 {
234 return sal_True; // ich bin unter UNIX, also ist der default im Zweifelsfall case sensitiv
235 }
236 aPath = aPath [1];
237 }
238
239 struct mymnttab fsmnt;
240 GetMountEntry(buf.st_dev, &fsmnt);
241 if ((fsmnt.mymnttab_filesystem.CompareTo("msdos")==COMPARE_EQUAL) ||
242 (fsmnt.mymnttab_filesystem.CompareTo("umsdos")==COMPARE_EQUAL) ||
243 (fsmnt.mymnttab_filesystem.CompareTo("vfat")==COMPARE_EQUAL) ||
244 (fsmnt.mymnttab_filesystem.CompareTo("hpfs")==COMPARE_EQUAL) ||
245 (fsmnt.mymnttab_filesystem.CompareTo("smb") ==COMPARE_EQUAL) ||
246 (fsmnt.mymnttab_filesystem.CompareTo("ncpfs")==COMPARE_EQUAL))
247 {
248 return sal_False;
249 }
250 else
251 {
252 return sal_True;
253 }
254 #endif
255 }
256 else
257 {
258 sal_Bool isCaseSensitive = sal_True; // ich bin unter UNIX, also ist der default im Zweifelsfall case sensitiv
259 switch ( eFormatter )
260 {
261 case FSYS_STYLE_MAC:
262 case FSYS_STYLE_FAT:
263 case FSYS_STYLE_VFAT:
264 case FSYS_STYLE_NTFS:
265 case FSYS_STYLE_NWFS:
266 case FSYS_STYLE_HPFS:
267 {
268 isCaseSensitive = sal_False;
269 break;
270 }
271 case FSYS_STYLE_SYSV:
272 case FSYS_STYLE_BSD:
273 case FSYS_STYLE_DETECT:
274 {
275 isCaseSensitive = sal_True;
276 break;
277 }
278 default:
279 {
280 isCaseSensitive = sal_True; // ich bin unter UNIX, also ist der default im Zweifelsfall case sensitiv
281 break;
282 }
283 }
284 return isCaseSensitive;
285 }
286 }
287
288 /************************************************************************
289 |*
290 |* DirEntry::ToAbs()
291 |*
292 |* Beschreibung FSYS.SDW
293 |* Ersterstellung MI 26.04.91
294 |* Letzte Aenderung MA 02.12.91 13:30
295 |*
296 *************************************************************************/
297
ToAbs()298 sal_Bool DirEntry::ToAbs()
299 {
300 if ( FSYS_FLAG_VOLUME == eFlag )
301 {
302 eFlag = FSYS_FLAG_ABSROOT;
303 return sal_True;
304 }
305
306 if ( IsAbs() )
307 return sal_True;
308
309 char sBuf[MAXPATHLEN + 1];
310 *this = DirEntry( String( getcwd( sBuf, MAXPATHLEN ), osl_getThreadTextEncoding() ) ) + *this;
311 return IsAbs();
312 }
313
314 /*************************************************************************
315 |*
316 |* DirEntry::GetVolume()
317 |*
318 |* Beschreibung FSYS.SDW
319 |* Ersterstellung MI 04.03.92
320 |* Letzte Aenderung
321 |*
322 *************************************************************************/
323
324 namespace { struct mymnt : public rtl::Static< mymnttab, mymnt > {}; }
325
GetVolume() const326 String DirEntry::GetVolume() const
327 {
328 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
329
330 DirEntry aPath( *this );
331 aPath.ToAbs();
332
333 struct stat buf;
334 while (stat (ByteString(aPath.GetFull(), osl_getThreadTextEncoding()).GetBuffer(), &buf))
335 {
336 if (aPath.Level() <= 1)
337 return String();
338 aPath = aPath [1];
339 }
340 mymnttab &rMnt = mymnt::get();
341 return ((buf.st_dev == rMnt.mountdevice ||
342 GetMountEntry(buf.st_dev, &rMnt)) ?
343 String(rMnt.mountspecial, osl_getThreadTextEncoding()) :
344 String());
345 }
346
GetDevice() const347 DirEntry DirEntry::GetDevice() const
348 {
349 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
350
351 DirEntry aPath( *this );
352 aPath.ToAbs();
353
354 struct stat buf;
355 while (stat (ByteString(aPath.GetFull(), osl_getThreadTextEncoding()).GetBuffer(), &buf))
356 {
357 if (aPath.Level() <= 1)
358 return String();
359 aPath = aPath [1];
360 }
361 mymnttab &rMnt = mymnt::get();
362 return ((buf.st_dev == rMnt.mountdevice ||
363 GetMountEntry(buf.st_dev, &rMnt)) ?
364 String( rMnt.mountpoint, osl_getThreadTextEncoding()) :
365 String());
366 }
367
368 /*************************************************************************
369 |*
370 |* DirEntry::SetCWD()
371 |*
372 |* Beschreibung FSYS.SDW
373 |* Ersterstellung MI 26.04.91
374 |* Letzte Aenderung DV 04.11.92
375 |*
376 *************************************************************************/
377
SetCWD(sal_Bool bSloppy) const378 sal_Bool DirEntry::SetCWD( sal_Bool bSloppy ) const
379 {
380 DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
381
382
383 ByteString aPath( GetFull(), osl_getThreadTextEncoding());
384 if ( !chdir( aPath.GetBuffer() ) )
385 {
386 return sal_True;
387 }
388 else
389 {
390 if ( bSloppy && !chdir(aPath.GetBuffer()) )
391 {
392 return sal_True;
393 }
394 else
395 {
396 return sal_False;
397 }
398 }
399 }
400
401 //-------------------------------------------------------------------------
402
Init()403 sal_uInt16 DirReader_Impl::Init()
404 {
405 return 0;
406 }
407
408 //-------------------------------------------------------------------------
409
Read()410 sal_uInt16 DirReader_Impl::Read()
411 {
412 if (!pDosDir)
413 {
414 pDosDir = opendir( (char*) ByteString(aPath, osl_getThreadTextEncoding()).GetBuffer() );
415 }
416
417 if (!pDosDir)
418 {
419 bReady = sal_True;
420 return 0;
421 }
422
423 // Directories und Files auflisten?
424 if ( ( pDir->eAttrMask & FSYS_KIND_DIR || pDir->eAttrMask & FSYS_KIND_FILE ) &&
425 ( ( pDosEntry = readdir( pDosDir ) ) != NULL ) )
426 {
427 String aD_Name(pDosEntry->d_name, osl_getThreadTextEncoding());
428 if ( pDir->aNameMask.Matches( aD_Name ) )
429 {
430 DirEntryFlag eFlag =
431 0 == strcmp( pDosEntry->d_name, "." ) ? FSYS_FLAG_CURRENT
432 : 0 == strcmp( pDosEntry->d_name, ".." ) ? FSYS_FLAG_PARENT
433 : FSYS_FLAG_NORMAL;
434 DirEntry *pTemp = new DirEntry( ByteString(pDosEntry->d_name), eFlag, FSYS_STYLE_UNX );
435 if ( pParent )
436 pTemp->ImpChangeParent( new DirEntry( *pParent ), sal_False);
437 FileStat aStat( *pTemp );
438 if ( ( ( ( pDir->eAttrMask & FSYS_KIND_DIR ) &&
439 ( aStat.IsKind( FSYS_KIND_DIR ) ) ) ||
440 ( ( pDir->eAttrMask & FSYS_KIND_FILE ) &&
441 !( aStat.IsKind( FSYS_KIND_DIR ) ) ) ) &&
442 !( pDir->eAttrMask & FSYS_KIND_VISIBLE &&
443 pDosEntry->d_name[0] == '.' ) )
444 {
445 if ( pDir->pStatLst ) //Status fuer Sort gewuenscht?
446 pDir->ImpSortedInsert( pTemp, new FileStat( aStat ) );
447 else
448 pDir->ImpSortedInsert( pTemp, NULL );;
449 return 1;
450 }
451 else
452 delete pTemp;
453 }
454 }
455 else
456 bReady = sal_True;
457 return 0;
458 }
459
460 /*************************************************************************
461 |*
462 |* FileStat::FileStat()
463 |*
464 |* Beschreibung FSYS.SDW
465 |* Ersterstellung MA 05.11.91
466 |* Letzte Aenderung MA 07.11.91
467 |*
468 *************************************************************************/
469
FileStat(const void *,const void *)470 FileStat::FileStat( const void *, const void * ):
471 aDateCreated(0),
472 aTimeCreated(0),
473 aDateModified(0),
474 aTimeModified(0),
475 aDateAccessed(0),
476 aTimeAccessed(0)
477 {
478 }
479
480 /*************************************************************************
481 |*
482 |* FileStat::Update()
483 |*
484 |* Beschreibung FSYS.SDW
485 |* Ersterstellung MI 11.06.91
486 |* Letzte Aenderung MA 07.11.91
487 |*
488 *************************************************************************/
Update(const DirEntry & rDirEntry,sal_Bool)489 sal_Bool FileStat::Update( const DirEntry& rDirEntry, sal_Bool )
490 {
491
492 nSize = 0;
493 nKindFlags = 0;
494 aCreator.Erase();
495 aType.Erase();
496 aDateCreated = Date(0);
497 aTimeCreated = Time(0);
498 aDateModified = Date(0);
499 aTimeModified = Time(0);
500 aDateAccessed = Date(0);
501 aTimeAccessed = Time(0);
502
503 if ( !rDirEntry.IsValid() )
504 {
505 nError = FSYS_ERR_NOTEXISTS;
506 return sal_False;
507 }
508
509 // Sonderbehandlung falls es sich um eine Root handelt
510 if ( rDirEntry.eFlag == FSYS_FLAG_ABSROOT )
511 {
512 nKindFlags = FSYS_KIND_DIR;
513 nError = FSYS_ERR_OK;
514 return sal_True;
515 }
516
517 struct stat aStat;
518 ByteString aPath( rDirEntry.GetFull(), osl_getThreadTextEncoding() );
519 if ( stat( (char*) aPath.GetBuffer(), &aStat ) )
520 {
521 // pl: #67851#
522 // do this here, because an existing filename containing "wildcards"
523 // should be handled as a file, not a wildcard
524 // note that this is not a solution, since filenames containing special characters
525 // are handled badly across the whole Office
526
527 // Sonderbehandlung falls es sich um eine Wildcard handelt
528 ByteString aTempName( rDirEntry.GetName(), osl_getThreadTextEncoding() );
529 if ( strchr( (char*) aTempName.GetBuffer(), '?' ) ||
530 strchr( (char*) aTempName.GetBuffer(), '*' ) ||
531 strchr( (char*) aTempName.GetBuffer(), ';' ) )
532 {
533 nKindFlags = FSYS_KIND_WILD;
534 nError = FSYS_ERR_OK;
535 return sal_True;
536 }
537
538 nError = FSYS_ERR_NOTEXISTS;
539 return sal_False;
540 }
541
542 nError = FSYS_ERR_OK;
543 nSize = aStat.st_size;
544
545 nKindFlags = FSYS_KIND_UNKNOWN;
546 if ( ( aStat.st_mode & S_IFDIR ) == S_IFDIR )
547 nKindFlags = nKindFlags | FSYS_KIND_DIR;
548 if ( ( aStat.st_mode & S_IFREG ) == S_IFREG )
549 nKindFlags = nKindFlags | FSYS_KIND_FILE;
550 if ( ( aStat.st_mode & S_IFCHR ) == S_IFCHR )
551 nKindFlags = nKindFlags | FSYS_KIND_DEV | FSYS_KIND_CHAR;
552 if ( ( aStat.st_mode & S_IFBLK ) == S_IFBLK )
553 nKindFlags = nKindFlags | FSYS_KIND_DEV | FSYS_KIND_BLOCK;
554 if ( nKindFlags == FSYS_KIND_UNKNOWN )
555 nKindFlags = nKindFlags | FSYS_KIND_FILE;
556
557 Unx2DateAndTime( aStat.st_ctime, aTimeCreated, aDateCreated );
558 Unx2DateAndTime( aStat.st_mtime, aTimeModified, aDateModified );
559 Unx2DateAndTime( aStat.st_atime, aTimeAccessed, aDateAccessed );
560
561 return sal_True;
562 }
563
564 //====================================================================
565
TempDirImpl(char * pBuf)566 const char *TempDirImpl( char *pBuf )
567 {
568 #ifdef MACOSX
569 // P_tmpdir is /var/tmp on Mac OS X, and it is not cleaned up on system
570 // startup
571 strcpy( pBuf, "/tmp" );
572 #else
573 const char *pValue = getenv( "TEMP" );
574 if ( !pValue )
575 pValue = getenv( "TMP" );
576 if ( pValue )
577 strcpy( pBuf, pValue );
578 else
579 // auf Solaris und Linux ist P_tmpdir vorgesehen
580 strcpy( pBuf, P_tmpdir );
581 // hart auf "/tmp" sollte wohl nur im Notfall verwendet werden
582 //strcpy( pBuf, "/tmp" );
583 #endif /* MACOSX */
584
585 return pBuf;
586 }
587
588 /*************************************************************************
589 |*
590 |* DirEntry::GetPathStyle() const
591 |*
592 |* Beschreibung
593 |* Ersterstellung MI 11.05.95
594 |* Letzte Aenderung MI 11.05.95
595 |*
596 *************************************************************************/
597
GetPathStyle(const String &)598 FSysPathStyle DirEntry::GetPathStyle( const String & )
599 {
600 return FSYS_STYLE_UNX;
601 }
602
603 /*************************************************************************
604 |*
605 |* FileStat::SetDateTime
606 |*
607 |* Ersterstellung PB 27.06.97
608 |* Letzte Aenderung
609 |*
610 *************************************************************************/
611
SetDateTime(const String & rFileName,const DateTime & rNewDateTime)612 void FileStat::SetDateTime( const String& rFileName,
613 const DateTime& rNewDateTime )
614 {
615 tm times;
616
617 times.tm_year = rNewDateTime.GetYear() - 1900; // 1997 -> 97
618 times.tm_mon = rNewDateTime.GetMonth() - 1; // 0 == Januar!
619 times.tm_mday = rNewDateTime.GetDay();
620
621 times.tm_hour = rNewDateTime.GetHour();
622 times.tm_min = rNewDateTime.GetMin();
623 times.tm_sec = rNewDateTime.GetSec();
624
625 times.tm_wday = 0;
626 times.tm_yday = 0;
627 #ifdef SOLARIS
628 times.tm_isdst = -1;
629 #else
630 times.tm_isdst = 0;
631 #endif
632
633 time_t time = mktime (×);
634
635 if (time != (time_t) -1)
636 {
637 struct utimbuf u_time;
638 u_time.actime = time;
639 u_time.modtime = time;
640 utime (ByteString(rFileName, osl_getThreadTextEncoding()).GetBuffer(), &u_time);
641 }
642 }
643
644 //=========================================================================
645
QueryDiskSpace(const String &,BigInt &,BigInt &)646 ErrCode FileStat::QueryDiskSpace( const String &, BigInt &, BigInt & )
647 {
648 return ERRCODE_IO_NOTSUPPORTED;
649 }
650
651 //=========================================================================
652
FSysEnableSysErrorBox(sal_Bool)653 void FSysEnableSysErrorBox( sal_Bool )
654 {
655 }
656
657