blob: 963fc1ea82d0a811452322b10b0f82be9028cdfc [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_tools.hxx"
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <utime.h>
#if defined HPUX || defined LINUX
#include <mntent.h>
#define mnttab mntent
#elif defined SCO
#include <mnttab.h>
#elif defined AIX
#include <sys/mntctl.h>
#include <sys/vmount.h>
extern "C" int mntctl( int cmd, size_t size, char* buf );
#elif defined(NETBSD)
#include <sys/mount.h>
#elif defined(FREEBSD) || defined(MACOSX)
#elif defined DECUNIX
struct mnttab
{
char *mnt_dir;
char *mnt_fsname;
};
#else
#include <sys/mnttab.h>
#endif
#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
#include <tools/debug.hxx>
#include <tools/list.hxx>
#include <tools/fsys.hxx>
#include "comdep.hxx"
#include <rtl/instance.hxx>
DECLARE_LIST( DirEntryList, DirEntry* )
DECLARE_LIST( FSysSortList, FSysSort* )
DECLARE_LIST( FileStatList, FileStat* )
#if defined SOLARIS || defined SINIX
#define MOUNTSPECIAL mnt_special
#define MOUNTPOINT mnt_mountp
#define MOUNTOPTS mnt_mntopts
#define MOUNTFS mnt_fstype
#elif defined SCO
#define MNTTAB "/etc/mnttab"
#define MOUNTSPECIAL mt_dev
#define MOUNTPOINT mt_filsys
#else
#define MOUNTSPECIAL mnt_fsname
#define MOUNTPOINT mnt_dir
#define MOUNTFS mnt_type
#endif
struct mymnttab
{
dev_t mountdevice;
ByteString mountspecial;
ByteString mountpoint;
ByteString mymnttab_filesystem;
mymnttab() { mountdevice = (dev_t) -1; }
};
#if defined(NETBSD) || defined(FREEBSD) || defined(MACOSX)
sal_Bool GetMountEntry(dev_t /* dev */, struct mymnttab * /* mytab */ )
{
DBG_WARNING( "Sorry, not implemented: GetMountEntry" );
return sal_False;
}
#elif defined AIX
sal_Bool GetMountEntry(dev_t dev, struct mymnttab *mytab)
{
int bufsize;
if (mntctl (MCTL_QUERY, sizeof bufsize, (char*) &bufsize))
return sal_False;
char* buffer = (char *)malloc( bufsize * sizeof(char) );
if (mntctl (MCTL_QUERY, bufsize, buffer) != -1)
for ( char* vmt = buffer;
vmt < buffer + bufsize;
vmt += ((struct vmount*)vmt)->vmt_length)
{
struct stat buf;
char *mountp = vmt2dataptr((struct vmount*)vmt, VMT_STUB);
if ((stat (mountp, &buf) != -1) && (buf.st_dev == dev))
{
mytab->mountpoint = mountp;
mytab->mountspecial
= vmt2dataptr((struct vmount*)vmt, VMT_HOSTNAME);
if (mytab->mountspecial.Len())
mytab->mountspecial += ':';
mytab->mountspecial
+= vmt2dataptr((struct vmount*)vmt, VMT_OBJECT);
mytab->mountdevice = dev;
free( buffer );
return sal_True;
}
}
free( buffer );
return sal_False;
}
#else
static sal_Bool GetMountEntry(dev_t dev, struct mymnttab *mytab)
{
#if defined SOLARIS || defined SINIX
FILE *fp = fopen (MNTTAB, "r");
if (! fp)
return sal_False;
struct mnttab mnt[1];
while (getmntent (fp, mnt) != -1)
#elif defined SCO
FILE *fp = fopen (MNTTAB, "r");
if (! fp)
return sal_False;
struct mnttab mnt[1];
while (fread (&mnt, sizeof mnt, 1, fp) > 0)
#elif defined DECUNIX || defined AIX
FILE *fp = NULL;
if (! fp)
return sal_False;
struct mnttab mnt[1];
while ( 0 )
#else
FILE *fp = setmntent (MOUNTED, "r");
if (! fp)
return sal_False;
struct mnttab *mnt;
while ((mnt = getmntent (fp)) != NULL)
#endif
{
#ifdef SOLARIS
char *devopt = NULL;
if ( mnt->MOUNTOPTS != NULL )
devopt = strstr (mnt->MOUNTOPTS, "dev=");
if (devopt)
{
if (dev != (dev_t) strtoul (devopt+4, NULL, 16))
continue;
}
else
#endif
{
struct stat buf;
if ((stat (mnt->MOUNTPOINT, &buf) == -1) || (buf.st_dev != dev))
continue;
}
# ifdef LINUX
/* #61624# File mit setmntent oeffnen und mit fclose schliessen stoesst
bei der glibc-2.1 auf wenig Gegenliebe */
endmntent( fp );
# else
fclose (fp);
# endif
mytab->mountspecial = mnt->MOUNTSPECIAL;
mytab->mountpoint = mnt->MOUNTPOINT;
mytab->mountdevice = dev;
#ifndef SCO
mytab->mymnttab_filesystem = mnt->MOUNTFS;
#else
mytab->mymnttab_filesystem = "ext2"; //default ist case sensitiv unter unix
#endif
return sal_True;
}
# ifdef LINUX
/* #61624# dito */
endmntent( fp );
# else
fclose (fp);
# endif
return sal_False;
}
#endif
/************************************************************************
|*
|* DirEntry::IsCaseSensitive()
|*
|* Beschreibung
|* Ersterstellung TPF 25.02.1999
|* Letzte Aenderung TPF 25.02.1999
|*
*************************************************************************/
sal_Bool DirEntry::IsCaseSensitive( FSysPathStyle eFormatter ) const
{
if (eFormatter==FSYS_STYLE_HOST)
{
#ifdef NETBSD
return sal_True;
#else
struct stat buf;
DirEntry aPath(*this);
aPath.ToAbs();
while (stat (ByteString(aPath.GetFull(), osl_getThreadTextEncoding()).GetBuffer(), &buf))
{
if (aPath.Level() == 1)
{
return sal_True; // ich bin unter UNIX, also ist der default im Zweifelsfall case sensitiv
}
aPath = aPath [1];
}
struct mymnttab fsmnt;
GetMountEntry(buf.st_dev, &fsmnt);
if ((fsmnt.mymnttab_filesystem.CompareTo("msdos")==COMPARE_EQUAL) ||
(fsmnt.mymnttab_filesystem.CompareTo("umsdos")==COMPARE_EQUAL) ||
(fsmnt.mymnttab_filesystem.CompareTo("vfat")==COMPARE_EQUAL) ||
(fsmnt.mymnttab_filesystem.CompareTo("hpfs")==COMPARE_EQUAL) ||
(fsmnt.mymnttab_filesystem.CompareTo("smb") ==COMPARE_EQUAL) ||
(fsmnt.mymnttab_filesystem.CompareTo("ncpfs")==COMPARE_EQUAL))
{
return sal_False;
}
else
{
return sal_True;
}
#endif
}
else
{
sal_Bool isCaseSensitive = sal_True; // ich bin unter UNIX, also ist der default im Zweifelsfall case sensitiv
switch ( eFormatter )
{
case FSYS_STYLE_MAC:
case FSYS_STYLE_FAT:
case FSYS_STYLE_VFAT:
case FSYS_STYLE_NTFS:
case FSYS_STYLE_NWFS:
case FSYS_STYLE_HPFS:
{
isCaseSensitive = sal_False;
break;
}
case FSYS_STYLE_SYSV:
case FSYS_STYLE_BSD:
case FSYS_STYLE_DETECT:
{
isCaseSensitive = sal_True;
break;
}
default:
{
isCaseSensitive = sal_True; // ich bin unter UNIX, also ist der default im Zweifelsfall case sensitiv
break;
}
}
return isCaseSensitive;
}
}
/************************************************************************
|*
|* DirEntry::ToAbs()
|*
|* Beschreibung FSYS.SDW
|* Ersterstellung MI 26.04.91
|* Letzte Aenderung MA 02.12.91 13:30
|*
*************************************************************************/
sal_Bool DirEntry::ToAbs()
{
if ( FSYS_FLAG_VOLUME == eFlag )
{
eFlag = FSYS_FLAG_ABSROOT;
return sal_True;
}
if ( IsAbs() )
return sal_True;
char sBuf[MAXPATHLEN + 1];
*this = DirEntry( String( getcwd( sBuf, MAXPATHLEN ), osl_getThreadTextEncoding() ) ) + *this;
return IsAbs();
}
/*************************************************************************
|*
|* DirEntry::GetVolume()
|*
|* Beschreibung FSYS.SDW
|* Ersterstellung MI 04.03.92
|* Letzte Aenderung
|*
*************************************************************************/
namespace { struct mymnt : public rtl::Static< mymnttab, mymnt > {}; }
String DirEntry::GetVolume() const
{
DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
DirEntry aPath( *this );
aPath.ToAbs();
struct stat buf;
while (stat (ByteString(aPath.GetFull(), osl_getThreadTextEncoding()).GetBuffer(), &buf))
{
if (aPath.Level() <= 1)
return String();
aPath = aPath [1];
}
mymnttab &rMnt = mymnt::get();
return ((buf.st_dev == rMnt.mountdevice ||
GetMountEntry(buf.st_dev, &rMnt)) ?
String(rMnt.mountspecial, osl_getThreadTextEncoding()) :
String());
}
DirEntry DirEntry::GetDevice() const
{
DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
DirEntry aPath( *this );
aPath.ToAbs();
struct stat buf;
while (stat (ByteString(aPath.GetFull(), osl_getThreadTextEncoding()).GetBuffer(), &buf))
{
if (aPath.Level() <= 1)
return String();
aPath = aPath [1];
}
mymnttab &rMnt = mymnt::get();
return ((buf.st_dev == rMnt.mountdevice ||
GetMountEntry(buf.st_dev, &rMnt)) ?
String( rMnt.mountpoint, osl_getThreadTextEncoding()) :
String());
}
/*************************************************************************
|*
|* DirEntry::SetCWD()
|*
|* Beschreibung FSYS.SDW
|* Ersterstellung MI 26.04.91
|* Letzte Aenderung DV 04.11.92
|*
*************************************************************************/
sal_Bool DirEntry::SetCWD( sal_Bool bSloppy ) const
{
DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
ByteString aPath( GetFull(), osl_getThreadTextEncoding());
if ( !chdir( aPath.GetBuffer() ) )
{
return sal_True;
}
else
{
if ( bSloppy && !chdir(aPath.GetBuffer()) )
{
return sal_True;
}
else
{
return sal_False;
}
}
}
//-------------------------------------------------------------------------
sal_uInt16 DirReader_Impl::Init()
{
return 0;
}
//-------------------------------------------------------------------------
sal_uInt16 DirReader_Impl::Read()
{
if (!pDosDir)
{
pDosDir = opendir( (char*) ByteString(aPath, osl_getThreadTextEncoding()).GetBuffer() );
}
if (!pDosDir)
{
bReady = sal_True;
return 0;
}
// Directories und Files auflisten?
if ( ( pDir->eAttrMask & FSYS_KIND_DIR || pDir->eAttrMask & FSYS_KIND_FILE ) &&
( ( pDosEntry = readdir( pDosDir ) ) != NULL ) )
{
String aD_Name(pDosEntry->d_name, osl_getThreadTextEncoding());
if ( pDir->aNameMask.Matches( aD_Name ) )
{
DirEntryFlag eFlag =
0 == strcmp( pDosEntry->d_name, "." ) ? FSYS_FLAG_CURRENT
: 0 == strcmp( pDosEntry->d_name, ".." ) ? FSYS_FLAG_PARENT
: FSYS_FLAG_NORMAL;
DirEntry *pTemp = new DirEntry( ByteString(pDosEntry->d_name), eFlag, FSYS_STYLE_UNX );
if ( pParent )
pTemp->ImpChangeParent( new DirEntry( *pParent ), sal_False);
FileStat aStat( *pTemp );
if ( ( ( ( pDir->eAttrMask & FSYS_KIND_DIR ) &&
( aStat.IsKind( FSYS_KIND_DIR ) ) ) ||
( ( pDir->eAttrMask & FSYS_KIND_FILE ) &&
!( aStat.IsKind( FSYS_KIND_DIR ) ) ) ) &&
!( pDir->eAttrMask & FSYS_KIND_VISIBLE &&
pDosEntry->d_name[0] == '.' ) )
{
if ( pDir->pStatLst ) //Status fuer Sort gewuenscht?
pDir->ImpSortedInsert( pTemp, new FileStat( aStat ) );
else
pDir->ImpSortedInsert( pTemp, NULL );;
return 1;
}
else
delete pTemp;
}
}
else
bReady = sal_True;
return 0;
}
/*************************************************************************
|*
|* FileStat::FileStat()
|*
|* Beschreibung FSYS.SDW
|* Ersterstellung MA 05.11.91
|* Letzte Aenderung MA 07.11.91
|*
*************************************************************************/
FileStat::FileStat( const void *, const void * ):
aDateCreated(0),
aTimeCreated(0),
aDateModified(0),
aTimeModified(0),
aDateAccessed(0),
aTimeAccessed(0)
{
}
/*************************************************************************
|*
|* FileStat::Update()
|*
|* Beschreibung FSYS.SDW
|* Ersterstellung MI 11.06.91
|* Letzte Aenderung MA 07.11.91
|*
*************************************************************************/
sal_Bool FileStat::Update( const DirEntry& rDirEntry, sal_Bool )
{
nSize = 0;
nKindFlags = 0;
aCreator.Erase();
aType.Erase();
aDateCreated = Date(0);
aTimeCreated = Time(0);
aDateModified = Date(0);
aTimeModified = Time(0);
aDateAccessed = Date(0);
aTimeAccessed = Time(0);
if ( !rDirEntry.IsValid() )
{
nError = FSYS_ERR_NOTEXISTS;
return sal_False;
}
// Sonderbehandlung falls es sich um eine Root handelt
if ( rDirEntry.eFlag == FSYS_FLAG_ABSROOT )
{
nKindFlags = FSYS_KIND_DIR;
nError = FSYS_ERR_OK;
return sal_True;
}
struct stat aStat;
ByteString aPath( rDirEntry.GetFull(), osl_getThreadTextEncoding() );
if ( stat( (char*) aPath.GetBuffer(), &aStat ) )
{
// pl: #67851#
// do this here, because an existing filename containing "wildcards"
// should be handled as a file, not a wildcard
// note that this is not a solution, since filenames containing special characters
// are handled badly across the whole Office
// Sonderbehandlung falls es sich um eine Wildcard handelt
ByteString aTempName( rDirEntry.GetName(), osl_getThreadTextEncoding() );
if ( strchr( (char*) aTempName.GetBuffer(), '?' ) ||
strchr( (char*) aTempName.GetBuffer(), '*' ) ||
strchr( (char*) aTempName.GetBuffer(), ';' ) )
{
nKindFlags = FSYS_KIND_WILD;
nError = FSYS_ERR_OK;
return sal_True;
}
nError = FSYS_ERR_NOTEXISTS;
return sal_False;
}
nError = FSYS_ERR_OK;
nSize = aStat.st_size;
nKindFlags = FSYS_KIND_UNKNOWN;
if ( ( aStat.st_mode & S_IFDIR ) == S_IFDIR )
nKindFlags = nKindFlags | FSYS_KIND_DIR;
if ( ( aStat.st_mode & S_IFREG ) == S_IFREG )
nKindFlags = nKindFlags | FSYS_KIND_FILE;
if ( ( aStat.st_mode & S_IFCHR ) == S_IFCHR )
nKindFlags = nKindFlags | FSYS_KIND_DEV | FSYS_KIND_CHAR;
if ( ( aStat.st_mode & S_IFBLK ) == S_IFBLK )
nKindFlags = nKindFlags | FSYS_KIND_DEV | FSYS_KIND_BLOCK;
if ( nKindFlags == FSYS_KIND_UNKNOWN )
nKindFlags = nKindFlags | FSYS_KIND_FILE;
Unx2DateAndTime( aStat.st_ctime, aTimeCreated, aDateCreated );
Unx2DateAndTime( aStat.st_mtime, aTimeModified, aDateModified );
Unx2DateAndTime( aStat.st_atime, aTimeAccessed, aDateAccessed );
return sal_True;
}
//====================================================================
const char *TempDirImpl( char *pBuf )
{
#ifdef MACOSX
// P_tmpdir is /var/tmp on Mac OS X, and it is not cleaned up on system
// startup
strcpy( pBuf, "/tmp" );
#else
const char *pValue = getenv( "TEMP" );
if ( !pValue )
pValue = getenv( "TMP" );
if ( pValue )
strcpy( pBuf, pValue );
else
// auf Solaris und Linux ist P_tmpdir vorgesehen
strcpy( pBuf, P_tmpdir );
// hart auf "/tmp" sollte wohl nur im Notfall verwendet werden
//strcpy( pBuf, "/tmp" );
#endif /* MACOSX */
return pBuf;
}
/*************************************************************************
|*
|* DirEntry::GetPathStyle() const
|*
|* Beschreibung
|* Ersterstellung MI 11.05.95
|* Letzte Aenderung MI 11.05.95
|*
*************************************************************************/
FSysPathStyle DirEntry::GetPathStyle( const String & )
{
return FSYS_STYLE_UNX;
}
/*************************************************************************
|*
|* FileStat::SetDateTime
|*
|* Ersterstellung PB 27.06.97
|* Letzte Aenderung
|*
*************************************************************************/
void FileStat::SetDateTime( const String& rFileName,
const DateTime& rNewDateTime )
{
tm times;
times.tm_year = rNewDateTime.GetYear() - 1900; // 1997 -> 97
times.tm_mon = rNewDateTime.GetMonth() - 1; // 0 == Januar!
times.tm_mday = rNewDateTime.GetDay();
times.tm_hour = rNewDateTime.GetHour();
times.tm_min = rNewDateTime.GetMin();
times.tm_sec = rNewDateTime.GetSec();
times.tm_wday = 0;
times.tm_yday = 0;
#ifdef SOLARIS
times.tm_isdst = -1;
#else
times.tm_isdst = 0;
#endif
time_t time = mktime (&times);
if (time != (time_t) -1)
{
struct utimbuf u_time;
u_time.actime = time;
u_time.modtime = time;
utime (ByteString(rFileName, osl_getThreadTextEncoding()).GetBuffer(), &u_time);
}
}
//=========================================================================
ErrCode FileStat::QueryDiskSpace( const String &, BigInt &, BigInt & )
{
return ERRCODE_IO_NOTSUPPORTED;
}
//=========================================================================
void FSysEnableSysErrorBox( sal_Bool )
{
}