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