1*89b56da7SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*89b56da7SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*89b56da7SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*89b56da7SAndrew Rist * distributed with this work for additional information 6*89b56da7SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*89b56da7SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*89b56da7SAndrew Rist * "License"); you may not use this file except in compliance 9*89b56da7SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*89b56da7SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*89b56da7SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*89b56da7SAndrew Rist * software distributed under the License is distributed on an 15*89b56da7SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*89b56da7SAndrew Rist * KIND, either express or implied. See the License for the 17*89b56da7SAndrew Rist * specific language governing permissions and limitations 18*89b56da7SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*89b56da7SAndrew Rist *************************************************************/ 21*89b56da7SAndrew Rist 22*89b56da7SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_tools.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <tools/tempfile.hxx> 28cdf0e10cSrcweir #include "comdep.hxx" 29cdf0e10cSrcweir 30cdf0e10cSrcweir #include <rtl/ustring.hxx> 31cdf0e10cSrcweir #include <osl/file.hxx> 32cdf0e10cSrcweir #include <rtl/instance.hxx> 33cdf0e10cSrcweir #include <tools/time.hxx> 34cdf0e10cSrcweir #include <tools/debug.hxx> 35cdf0e10cSrcweir #include <stdio.h> 36cdf0e10cSrcweir 37cdf0e10cSrcweir #ifdef UNX 38cdf0e10cSrcweir #define _MAX_PATH 260 39cdf0e10cSrcweir #endif 40cdf0e10cSrcweir 41cdf0e10cSrcweir using namespace osl; 42cdf0e10cSrcweir 43cdf0e10cSrcweir namespace { struct TempNameBase_Impl : public rtl::Static< ::rtl::OUString, TempNameBase_Impl > {}; } 44cdf0e10cSrcweir 45cdf0e10cSrcweir struct TempFile_Impl 46cdf0e10cSrcweir { 47cdf0e10cSrcweir String aName; 48cdf0e10cSrcweir sal_Bool bIsDirectory; 49cdf0e10cSrcweir }; 50cdf0e10cSrcweir 51cdf0e10cSrcweir String GetSystemTempDir_Impl() 52cdf0e10cSrcweir { 53cdf0e10cSrcweir char sBuf[_MAX_PATH]; 54cdf0e10cSrcweir const char *pDir = TempDirImpl(sBuf); 55cdf0e10cSrcweir 56cdf0e10cSrcweir ::rtl::OString aTmpA( pDir ); 57cdf0e10cSrcweir ::rtl::OUString aTmp = ::rtl::OStringToOUString( aTmpA, osl_getThreadTextEncoding() ); 58cdf0e10cSrcweir rtl::OUString aRet; 59cdf0e10cSrcweir FileBase::getFileURLFromSystemPath( aTmp, aRet ); 60cdf0e10cSrcweir String aName = aRet; 61cdf0e10cSrcweir if( aName.GetChar(aName.Len()-1) != '/' ) 62cdf0e10cSrcweir aName += '/'; 63cdf0e10cSrcweir return aName; 64cdf0e10cSrcweir } 65cdf0e10cSrcweir 66cdf0e10cSrcweir #define TMPNAME_SIZE ( 1 + 5 + 5 + 4 + 1 ) 67cdf0e10cSrcweir String ConstructTempDir_Impl( const String* pParent ) 68cdf0e10cSrcweir { 69cdf0e10cSrcweir String aName; 70cdf0e10cSrcweir if ( pParent && pParent->Len() ) 71cdf0e10cSrcweir { 72cdf0e10cSrcweir // if parent given try to use it 73cdf0e10cSrcweir rtl::OUString aTmp( *pParent ); 74cdf0e10cSrcweir rtl::OUString aRet; 75cdf0e10cSrcweir 76cdf0e10cSrcweir // test for valid filename 77cdf0e10cSrcweir { 78cdf0e10cSrcweir ::osl::DirectoryItem aItem; 79cdf0e10cSrcweir sal_Int32 i = aRet.getLength(); 80cdf0e10cSrcweir if ( aRet[i-1] == '/' ) 81cdf0e10cSrcweir i--; 82cdf0e10cSrcweir 83cdf0e10cSrcweir if ( DirectoryItem::get( ::rtl::OUString( aRet, i ), aItem ) == FileBase::E_None ) 84cdf0e10cSrcweir aName = aRet; 85cdf0e10cSrcweir } 86cdf0e10cSrcweir } 87cdf0e10cSrcweir 88cdf0e10cSrcweir if ( !aName.Len() ) 89cdf0e10cSrcweir { 90cdf0e10cSrcweir // if no parent or invalid parent : use system directory 91cdf0e10cSrcweir ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get(); 92cdf0e10cSrcweir if ( !rTempNameBase_Impl.getLength() ) 93cdf0e10cSrcweir rTempNameBase_Impl = GetSystemTempDir_Impl(); 94cdf0e10cSrcweir aName = rTempNameBase_Impl; 95cdf0e10cSrcweir } 96cdf0e10cSrcweir 97cdf0e10cSrcweir // Make sure that directory ends with a separator 98cdf0e10cSrcweir xub_StrLen i = aName.Len(); 99cdf0e10cSrcweir if( i>0 && aName.GetChar(i-1) != '/' ) 100cdf0e10cSrcweir aName += '/'; 101cdf0e10cSrcweir 102cdf0e10cSrcweir return aName; 103cdf0e10cSrcweir } 104cdf0e10cSrcweir 105cdf0e10cSrcweir void CreateTempName_Impl( String& rName, sal_Bool bKeep, sal_Bool bDir = sal_True ) 106cdf0e10cSrcweir { 107cdf0e10cSrcweir // add a suitable tempname 108cdf0e10cSrcweir // Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576 109cdf0e10cSrcweir // ER 13.07.00 why not radix 36 [0-9A-Z] ?!? 110cdf0e10cSrcweir const unsigned nRadix = 26; 111cdf0e10cSrcweir String aName( rName ); 112cdf0e10cSrcweir aName += String::CreateFromAscii( "sv" ); 113cdf0e10cSrcweir 114cdf0e10cSrcweir rName.Erase(); 115cdf0e10cSrcweir static unsigned long u = Time::GetSystemTicks(); 116cdf0e10cSrcweir for ( unsigned long nOld = u; ++u != nOld; ) 117cdf0e10cSrcweir { 118cdf0e10cSrcweir u %= (nRadix*nRadix*nRadix); 119cdf0e10cSrcweir String aTmp( aName ); 120cdf0e10cSrcweir aTmp += String::CreateFromInt32( (sal_Int32) (unsigned) u, nRadix ); 121cdf0e10cSrcweir aTmp += String::CreateFromAscii( ".tmp" ); 122cdf0e10cSrcweir 123cdf0e10cSrcweir if ( bDir ) 124cdf0e10cSrcweir { 125cdf0e10cSrcweir FileBase::RC err = Directory::create( aTmp ); 126cdf0e10cSrcweir if ( err == FileBase::E_None ) 127cdf0e10cSrcweir { 128cdf0e10cSrcweir // !bKeep: only for creating a name, not a file or directory 129cdf0e10cSrcweir if ( bKeep || Directory::remove( aTmp ) == FileBase::E_None ) 130cdf0e10cSrcweir rName = aTmp; 131cdf0e10cSrcweir break; 132cdf0e10cSrcweir } 133cdf0e10cSrcweir else if ( err != FileBase::E_EXIST ) 134cdf0e10cSrcweir { 135cdf0e10cSrcweir // if f.e. name contains invalid chars stop trying to create dirs 136cdf0e10cSrcweir break; 137cdf0e10cSrcweir } 138cdf0e10cSrcweir } 139cdf0e10cSrcweir else 140cdf0e10cSrcweir { 141cdf0e10cSrcweir DBG_ASSERT( bKeep, "Too expensive, use directory for creating name!" ); 142cdf0e10cSrcweir File aFile( aTmp ); 143cdf0e10cSrcweir FileBase::RC err = aFile.open(osl_File_OpenFlag_Create); 144cdf0e10cSrcweir if ( err == FileBase::E_None ) 145cdf0e10cSrcweir { 146cdf0e10cSrcweir rName = aTmp; 147cdf0e10cSrcweir aFile.close(); 148cdf0e10cSrcweir break; 149cdf0e10cSrcweir } 150cdf0e10cSrcweir else if ( err != FileBase::E_EXIST ) 151cdf0e10cSrcweir { 152cdf0e10cSrcweir // if f.e. name contains invalid chars stop trying to create files 153cdf0e10cSrcweir break; 154cdf0e10cSrcweir } 155cdf0e10cSrcweir } 156cdf0e10cSrcweir } 157cdf0e10cSrcweir } 158cdf0e10cSrcweir 159cdf0e10cSrcweir String TempFile::CreateTempName( const String* pParent ) 160cdf0e10cSrcweir { 161cdf0e10cSrcweir // get correct directory 162cdf0e10cSrcweir String aName = ConstructTempDir_Impl( pParent ); 163cdf0e10cSrcweir 164cdf0e10cSrcweir // get TempFile name with default naming scheme 165cdf0e10cSrcweir CreateTempName_Impl( aName, sal_False ); 166cdf0e10cSrcweir 167cdf0e10cSrcweir // convert to file URL 168cdf0e10cSrcweir rtl::OUString aTmp; 169cdf0e10cSrcweir if ( aName.Len() ) 170cdf0e10cSrcweir aTmp = aName; 171cdf0e10cSrcweir return aTmp; 172cdf0e10cSrcweir } 173cdf0e10cSrcweir 174cdf0e10cSrcweir TempFile::TempFile( const String* pParent, sal_Bool bDirectory ) 175cdf0e10cSrcweir : pImp( new TempFile_Impl ) 176cdf0e10cSrcweir , bKillingFileEnabled( sal_False ) 177cdf0e10cSrcweir { 178cdf0e10cSrcweir pImp->bIsDirectory = bDirectory; 179cdf0e10cSrcweir 180cdf0e10cSrcweir // get correct directory 181cdf0e10cSrcweir pImp->aName = ConstructTempDir_Impl( pParent ); 182cdf0e10cSrcweir 183cdf0e10cSrcweir // get TempFile with default naming scheme 184cdf0e10cSrcweir CreateTempName_Impl( pImp->aName, sal_True, bDirectory ); 185cdf0e10cSrcweir } 186cdf0e10cSrcweir 187cdf0e10cSrcweir TempFile::TempFile( const String& rLeadingChars, const String* pExtension, const String* pParent, sal_Bool bDirectory ) 188cdf0e10cSrcweir : pImp( new TempFile_Impl ) 189cdf0e10cSrcweir , bKillingFileEnabled( sal_False ) 190cdf0e10cSrcweir { 191cdf0e10cSrcweir pImp->bIsDirectory = bDirectory; 192cdf0e10cSrcweir 193cdf0e10cSrcweir // get correct directory 194cdf0e10cSrcweir String aName = ConstructTempDir_Impl( pParent ); 195cdf0e10cSrcweir 196cdf0e10cSrcweir // now use special naming scheme ( name takes leading chars and an index counting up from zero 197cdf0e10cSrcweir aName += rLeadingChars; 198cdf0e10cSrcweir for ( sal_Int32 i=0;; i++ ) 199cdf0e10cSrcweir { 200cdf0e10cSrcweir String aTmp( aName ); 201cdf0e10cSrcweir aTmp += String::CreateFromInt32( i ); 202cdf0e10cSrcweir if ( pExtension ) 203cdf0e10cSrcweir aTmp += *pExtension; 204cdf0e10cSrcweir else 205cdf0e10cSrcweir aTmp += String::CreateFromAscii( ".tmp" ); 206cdf0e10cSrcweir if ( bDirectory ) 207cdf0e10cSrcweir { 208cdf0e10cSrcweir FileBase::RC err = Directory::create( aTmp ); 209cdf0e10cSrcweir if ( err == FileBase::E_None ) 210cdf0e10cSrcweir { 211cdf0e10cSrcweir pImp->aName = aTmp; 212cdf0e10cSrcweir break; 213cdf0e10cSrcweir } 214cdf0e10cSrcweir else if ( err != FileBase::E_EXIST ) 215cdf0e10cSrcweir // if f.e. name contains invalid chars stop trying to create dirs 216cdf0e10cSrcweir break; 217cdf0e10cSrcweir } 218cdf0e10cSrcweir else 219cdf0e10cSrcweir { 220cdf0e10cSrcweir File aFile( aTmp ); 221cdf0e10cSrcweir FileBase::RC err = aFile.open(osl_File_OpenFlag_Create); 222cdf0e10cSrcweir if ( err == FileBase::E_None ) 223cdf0e10cSrcweir { 224cdf0e10cSrcweir pImp->aName = aTmp; 225cdf0e10cSrcweir aFile.close(); 226cdf0e10cSrcweir break; 227cdf0e10cSrcweir } 228cdf0e10cSrcweir else if ( err != FileBase::E_EXIST ) 229cdf0e10cSrcweir // if f.e. name contains invalid chars stop trying to create dirs 230cdf0e10cSrcweir break; 231cdf0e10cSrcweir } 232cdf0e10cSrcweir } 233cdf0e10cSrcweir } 234cdf0e10cSrcweir 235cdf0e10cSrcweir TempFile::~TempFile() 236cdf0e10cSrcweir { 237cdf0e10cSrcweir if ( bKillingFileEnabled ) 238cdf0e10cSrcweir { 239cdf0e10cSrcweir if ( pImp->bIsDirectory ) 240cdf0e10cSrcweir { 241cdf0e10cSrcweir // at the moment no recursiv algorithm present 242cdf0e10cSrcweir Directory::remove( pImp->aName ); 243cdf0e10cSrcweir } 244cdf0e10cSrcweir else 245cdf0e10cSrcweir { 246cdf0e10cSrcweir File::remove( pImp->aName ); 247cdf0e10cSrcweir } 248cdf0e10cSrcweir } 249cdf0e10cSrcweir 250cdf0e10cSrcweir delete pImp; 251cdf0e10cSrcweir } 252cdf0e10cSrcweir 253cdf0e10cSrcweir sal_Bool TempFile::IsValid() const 254cdf0e10cSrcweir { 255cdf0e10cSrcweir return pImp->aName.Len() != 0; 256cdf0e10cSrcweir } 257cdf0e10cSrcweir 258cdf0e10cSrcweir String TempFile::GetName() const 259cdf0e10cSrcweir { 260cdf0e10cSrcweir rtl::OUString aTmp; 261cdf0e10cSrcweir aTmp = pImp->aName; 262cdf0e10cSrcweir return aTmp; 263cdf0e10cSrcweir } 264cdf0e10cSrcweir 265cdf0e10cSrcweir String TempFile::SetTempNameBaseDirectory( const String &rBaseName ) 266cdf0e10cSrcweir { 267cdf0e10cSrcweir String aName( rBaseName ); 268cdf0e10cSrcweir 269cdf0e10cSrcweir ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get(); 270cdf0e10cSrcweir 271cdf0e10cSrcweir FileBase::RC err= Directory::create( aName ); 272cdf0e10cSrcweir if ( err == FileBase::E_None || err == FileBase::E_EXIST ) 273cdf0e10cSrcweir { 274cdf0e10cSrcweir rTempNameBase_Impl = aName; 275cdf0e10cSrcweir rTempNameBase_Impl += String( '/' ); 276cdf0e10cSrcweir 277cdf0e10cSrcweir TempFile aBase( NULL, sal_True ); 278cdf0e10cSrcweir if ( aBase.IsValid() ) 279cdf0e10cSrcweir rTempNameBase_Impl = aBase.pImp->aName; 280cdf0e10cSrcweir } 281cdf0e10cSrcweir 282cdf0e10cSrcweir rtl::OUString aTmp; 283cdf0e10cSrcweir aTmp = rTempNameBase_Impl; 284cdf0e10cSrcweir return aTmp; 285cdf0e10cSrcweir } 286cdf0e10cSrcweir 287cdf0e10cSrcweir String TempFile::GetTempNameBaseDirectory() 288cdf0e10cSrcweir { 289cdf0e10cSrcweir ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get(); 290cdf0e10cSrcweir if ( !rTempNameBase_Impl.getLength() ) 291cdf0e10cSrcweir rTempNameBase_Impl = GetSystemTempDir_Impl(); 292cdf0e10cSrcweir 293cdf0e10cSrcweir rtl::OUString aTmp; 294cdf0e10cSrcweir aTmp = rTempNameBase_Impl; 295cdf0e10cSrcweir return aTmp; 296cdf0e10cSrcweir } 297cdf0e10cSrcweir 298