524 lines
15 KiB
C++
524 lines
15 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 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 LINUX || defined ANDROID
|
|
#include <mntent.h>
|
|
#define mnttab mntent
|
|
#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) || defined(OPENBSD) || \
|
|
defined(DRAGONFLY) || defined(IOS)
|
|
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/fsys.hxx>
|
|
#include "comdep.hxx"
|
|
#include <rtl/instance.hxx>
|
|
|
|
#if defined SOLARIS
|
|
#define MOUNTSPECIAL mnt_special
|
|
#define MOUNTPOINT mnt_mountp
|
|
#define MOUNTOPTS mnt_mntopts
|
|
#define MOUNTFS mnt_fstype
|
|
#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) || \
|
|
defined(OPENBSD) || defined(DRAGONFLY) || defined(IOS)
|
|
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
|
|
FILE *fp = fopen (MNTTAB, "r");
|
|
if (! fp)
|
|
return sal_False;
|
|
struct mnttab mnt[1];
|
|
while (getmntent (fp, mnt) != -1)
|
|
#elif defined AIX || defined ANDROID
|
|
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;
|
|
mytab->mymnttab_filesystem = mnt->MOUNTFS;
|
|
|
|
return sal_True;
|
|
}
|
|
# ifdef LINUX
|
|
/* #61624# dito */
|
|
endmntent( fp );
|
|
# else
|
|
fclose (fp);
|
|
# endif
|
|
return sal_False;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/************************************************************************
|
|
|*
|
|
|* DirEntry::ToAbs()
|
|
|*
|
|
*************************************************************************/
|
|
|
|
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()
|
|
|*
|
|
*************************************************************************/
|
|
|
|
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()
|
|
|*
|
|
*************************************************************************/
|
|
|
|
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()
|
|
|*
|
|
*************************************************************************/
|
|
|
|
FileStat::FileStat( const void *, const void * ):
|
|
aDateCreated(0),
|
|
aTimeCreated(0),
|
|
aDateModified(0),
|
|
aTimeModified(0),
|
|
aDateAccessed(0),
|
|
aTimeAccessed(0)
|
|
{
|
|
}
|
|
|
|
/*************************************************************************
|
|
|*
|
|
|* FileStat::Update()
|
|
|*
|
|
*************************************************************************/
|
|
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
|
|
|*
|
|
*************************************************************************/
|
|
|
|
FSysPathStyle DirEntry::GetPathStyle()
|
|
{
|
|
return FSYS_STYLE_UNX;
|
|
}
|
|
|
|
/*************************************************************************
|
|
|*
|
|
|* FileStat::SetDateTime
|
|
|*
|
|
*************************************************************************/
|
|
|
|
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 (×);
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|