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; 89 mymnttab() { mountdevice = (dev_t) -1; } 90 }; 91 92 93 #if defined(NETBSD) || defined(FREEBSD) || defined(MACOSX) 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 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 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 218 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 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 326 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 347 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 378 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 403 sal_uInt16 DirReader_Impl::Init() 404 { 405 return 0; 406 } 407 408 //------------------------------------------------------------------------- 409 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 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 *************************************************************************/ 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 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 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 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 646 ErrCode FileStat::QueryDiskSpace( const String &, BigInt &, BigInt & ) 647 { 648 return ERRCODE_IO_NOTSUPPORTED; 649 } 650 651 //========================================================================= 652 653 void FSysEnableSysErrorBox( sal_Bool ) 654 { 655 } 656 657