Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <tools/tempfile.hxx>
21 : #include "comdep.hxx"
22 :
23 : #include <rtl/ustring.hxx>
24 : #include <rtl/ustrbuf.hxx>
25 : #include <osl/file.hxx>
26 : #include <rtl/instance.hxx>
27 : #include <tools/time.hxx>
28 : #include <tools/debug.hxx>
29 :
30 : #include <stdio.h>
31 :
32 : #ifdef UNX
33 : #define _MAX_PATH 260
34 : #endif
35 :
36 : using namespace osl;
37 :
38 : namespace { struct TempNameBase_Impl : public rtl::Static< ::rtl::OUString, TempNameBase_Impl > {}; }
39 :
40 0 : struct TempFile_Impl
41 : {
42 : String aName;
43 : sal_Bool bIsDirectory;
44 : };
45 :
46 0 : String GetSystemTempDir_Impl()
47 : {
48 : char sBuf[_MAX_PATH];
49 0 : const char *pDir = TempDirImpl(sBuf);
50 :
51 0 : ::rtl::OString aTmpA( pDir );
52 0 : ::rtl::OUString aTmp = ::rtl::OStringToOUString( aTmpA, osl_getThreadTextEncoding() );
53 0 : rtl::OUString aRet;
54 0 : FileBase::getFileURLFromSystemPath( aTmp, aRet );
55 0 : String aName = aRet;
56 0 : if( aName.GetChar(aName.Len()-1) != '/' )
57 0 : aName += '/';
58 0 : return aName;
59 : }
60 :
61 : #define TMPNAME_SIZE ( 1 + 5 + 5 + 4 + 1 )
62 :
63 0 : String ConstructTempDir_Impl( const String* pParent )
64 : {
65 0 : String aName;
66 0 : if ( pParent && pParent->Len() )
67 : {
68 : // if parent given try to use it
69 0 : rtl::OUString aTmp( *pParent );
70 0 : rtl::OUString aRet;
71 :
72 : // test for valid filename
73 : {
74 0 : ::osl::DirectoryItem aItem;
75 0 : sal_Int32 i = aRet.getLength();
76 0 : if ( aRet[i-1] == '/' )
77 0 : i--;
78 :
79 0 : if ( DirectoryItem::get( aRet.copy(0, i), aItem ) == FileBase::E_None )
80 0 : aName = aRet;
81 0 : }
82 : }
83 :
84 0 : if ( !aName.Len() )
85 : {
86 : // if no parent or invalid parent : use system directory
87 0 : ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get();
88 0 : if ( rTempNameBase_Impl.isEmpty() )
89 0 : rTempNameBase_Impl = GetSystemTempDir_Impl();
90 0 : aName = rTempNameBase_Impl;
91 : }
92 :
93 : // Make sure that directory ends with a separator
94 0 : xub_StrLen i = aName.Len();
95 0 : if( i>0 && aName.GetChar(i-1) != '/' )
96 0 : aName += '/';
97 :
98 0 : return aName;
99 : }
100 :
101 0 : void CreateTempName_Impl( String& rName, sal_Bool bKeep, sal_Bool bDir = sal_True )
102 : {
103 : // add a suitable tempname
104 : // Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576
105 : // ER 13.07.00 why not radix 36 [0-9A-Z] ?!?
106 0 : const unsigned nRadix = 26;
107 0 : String aName( rName );
108 0 : aName += rtl::OUString("sv");
109 :
110 0 : rName.Erase();
111 0 : static unsigned long u = Time::GetSystemTicks();
112 0 : for ( unsigned long nOld = u; ++u != nOld; )
113 : {
114 0 : u %= (nRadix*nRadix*nRadix);
115 : rtl::OUString aTmp = rtl::OUStringBuffer(aName).
116 0 : append((sal_Int32)(unsigned)u, nRadix).
117 0 : append(".tmp").
118 0 : makeStringAndClear();
119 :
120 0 : if ( bDir )
121 : {
122 0 : FileBase::RC err = Directory::create( aTmp );
123 0 : if ( err == FileBase::E_None )
124 : {
125 : // !bKeep: only for creating a name, not a file or directory
126 0 : if ( bKeep || Directory::remove( aTmp ) == FileBase::E_None )
127 0 : rName = aTmp;
128 : break;
129 : }
130 0 : else if ( err != FileBase::E_EXIST )
131 : {
132 : // if f.e. name contains invalid chars stop trying to create dirs
133 : break;
134 : }
135 : }
136 : else
137 : {
138 : DBG_ASSERT( bKeep, "Too expensive, use directory for creating name!" );
139 0 : File aFile( aTmp );
140 0 : FileBase::RC err = aFile.open(osl_File_OpenFlag_Create);
141 0 : if ( err == FileBase::E_None )
142 : {
143 0 : rName = aTmp;
144 0 : aFile.close();
145 : break;
146 : }
147 0 : else if ( err != FileBase::E_EXIST )
148 : {
149 : // if f.e. name contains invalid chars stop trying to create files
150 : break;
151 0 : }
152 : }
153 0 : }
154 0 : }
155 :
156 0 : String TempFile::CreateTempName( const String* pParent )
157 : {
158 : // get correct directory
159 0 : String aName = ConstructTempDir_Impl( pParent );
160 :
161 : // get TempFile name with default naming scheme
162 0 : CreateTempName_Impl( aName, sal_False );
163 :
164 0 : return aName;
165 : }
166 :
167 0 : TempFile::TempFile( const String* pParent, sal_Bool bDirectory )
168 0 : : pImp( new TempFile_Impl )
169 0 : , bKillingFileEnabled( sal_False )
170 : {
171 0 : pImp->bIsDirectory = bDirectory;
172 :
173 : // get correct directory
174 0 : pImp->aName = ConstructTempDir_Impl( pParent );
175 :
176 : // get TempFile with default naming scheme
177 0 : CreateTempName_Impl( pImp->aName, sal_True, bDirectory );
178 0 : }
179 :
180 0 : TempFile::TempFile( const String& rLeadingChars, const String* pExtension,
181 : const String* pParent, sal_Bool bDirectory )
182 0 : : pImp( new TempFile_Impl )
183 0 : , bKillingFileEnabled( sal_False )
184 : {
185 0 : pImp->bIsDirectory = bDirectory;
186 :
187 : // get correct directory
188 0 : String aName = ConstructTempDir_Impl( pParent );
189 :
190 : // now use special naming scheme ( name takes leading chars and an index counting up from zero
191 0 : aName += rLeadingChars;
192 0 : for ( sal_Int32 i=0;; i++ )
193 : {
194 0 : rtl::OUStringBuffer aTmpBuffer(aName);
195 0 : aTmpBuffer.append(i);
196 0 : if ( pExtension )
197 0 : aTmpBuffer.append(*pExtension);
198 : else
199 0 : aTmpBuffer.append(".tmp");
200 0 : rtl::OUString aTmp = aTmpBuffer.makeStringAndClear();
201 :
202 0 : if ( bDirectory )
203 : {
204 0 : FileBase::RC err = Directory::create( aTmp );
205 0 : if ( err == FileBase::E_None )
206 : {
207 0 : pImp->aName = aTmp;
208 : break;
209 : }
210 0 : else if ( err != FileBase::E_EXIST )
211 : // if f.e. name contains invalid chars stop trying to create dirs
212 : break;
213 : }
214 : else
215 : {
216 0 : File aFile( aTmp );
217 0 : FileBase::RC err = aFile.open(osl_File_OpenFlag_Create);
218 0 : if ( err == FileBase::E_None )
219 : {
220 0 : pImp->aName = aTmp;
221 0 : aFile.close();
222 : break;
223 : }
224 0 : else if ( err != FileBase::E_EXIST )
225 : // if f.e. name contains invalid chars stop trying to create dirs
226 0 : break;
227 : }
228 0 : }
229 0 : }
230 :
231 0 : TempFile::~TempFile()
232 : {
233 0 : if ( bKillingFileEnabled )
234 : {
235 0 : if ( pImp->bIsDirectory )
236 : {
237 : // at the moment no recursiv algorithm present
238 0 : Directory::remove( pImp->aName );
239 : }
240 : else
241 : {
242 0 : File::remove( pImp->aName );
243 : }
244 : }
245 :
246 0 : delete pImp;
247 0 : }
248 :
249 0 : String TempFile::GetName() const
250 : {
251 0 : rtl::OUString aTmp;
252 0 : aTmp = pImp->aName;
253 0 : return aTmp;
254 : }
255 :
256 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|