Branch data 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: */
|