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 <stdio.h>
21 : : #include <string.h>
22 : : #include <sys/stat.h>
23 : : #include <fcntl.h>
24 : : #include <errno.h>
25 : : #include <unistd.h>
26 : : #include <limits.h>
27 : :
28 : : #include <tools/debug.hxx>
29 : : #include <tools/fsys.hxx>
30 : : #include <tools/stream.hxx>
31 : : #include <vector>
32 : :
33 : : #include <osl/mutex.hxx>
34 : : #include <osl/thread.h> // osl_getThreadTextEncoding
35 : :
36 : : // class FileBase
37 : : #include <osl/file.hxx>
38 : : #include <osl/detail/file.h>
39 : : #include <rtl/instance.hxx>
40 : : #include <rtl/strbuf.hxx>
41 : :
42 : : using namespace osl;
43 : :
44 : : // InternalLock ----------------------------------------------------------------
45 : :
46 : : namespace { struct LockMutex : public rtl::Static< osl::Mutex, LockMutex > {}; }
47 : :
48 : : class InternalStreamLock
49 : : {
50 : : sal_Size m_nStartPos;
51 : : sal_Size m_nEndPos;
52 : : SvFileStream* m_pStream;
53 : : osl::DirectoryItem m_aItem;
54 : :
55 : : InternalStreamLock( sal_Size, sal_Size, SvFileStream* );
56 : : ~InternalStreamLock();
57 : : public:
58 : : static sal_Bool LockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* );
59 : : static void UnlockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* );
60 : : };
61 : :
62 : : typedef ::std::vector< InternalStreamLock* > InternalStreamLockList;
63 : :
64 : : namespace { struct LockList : public rtl::Static< InternalStreamLockList, LockList > {}; }
65 : :
66 : 0 : InternalStreamLock::InternalStreamLock(
67 : : sal_Size nStart,
68 : : sal_Size nEnd,
69 : : SvFileStream* pStream ) :
70 : : m_nStartPos( nStart ),
71 : : m_nEndPos( nEnd ),
72 : 0 : m_pStream( pStream )
73 : : {
74 [ # # ][ # # ]: 0 : osl::DirectoryItem::get( m_pStream->GetFileName(), m_aItem );
75 [ # # ][ # # ]: 0 : LockList::get().push_back( this );
76 : : #if OSL_DEBUG_LEVEL > 1
77 : : rtl::OString aFileName(rtl::OUStringToOString(m_pStream->GetFileName(),
78 : : osl_getThreadTextEncoding()));
79 : : fprintf( stderr, "locked %s", aFileName.getStr() );
80 : : if( m_nStartPos || m_nEndPos )
81 : : fprintf(stderr, " [ %ld ... %ld ]", m_nStartPos, m_nEndPos );
82 : : fprintf( stderr, "\n" );
83 : : #endif
84 : 0 : }
85 : :
86 : 0 : InternalStreamLock::~InternalStreamLock()
87 : : {
88 [ # # ][ # # ]: 0 : for ( InternalStreamLockList::iterator it = LockList::get().begin();
[ # # ]
89 [ # # ]: 0 : it != LockList::get().end();
90 : : ++it
91 : : ) {
92 [ # # ]: 0 : if ( this == *it ) {
93 [ # # ][ # # ]: 0 : LockList::get().erase( it );
94 : 0 : break;
95 : : }
96 : : }
97 : : #if OSL_DEBUG_LEVEL > 1
98 : : rtl::OString aFileName(rtl::OUStringToOString(m_pStream->GetFileName(),
99 : : osl_getThreadTextEncoding()));
100 : : fprintf( stderr, "unlocked %s", aFileName.getStr() );
101 : : if( m_nStartPos || m_nEndPos )
102 : : fprintf(stderr, " [ %ld ... %ld ]", m_nStartPos, m_nEndPos );
103 : : fprintf( stderr, "\n" );
104 : : #endif
105 : 0 : }
106 : :
107 : 1626 : sal_Bool InternalStreamLock::LockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* pStream )
108 : : {
109 [ + - ][ + - ]: 1626 : osl::MutexGuard aGuard( LockMutex::get() );
110 : 1626 : osl::DirectoryItem aItem;
111 [ + - ][ + - ]: 1626 : if (osl::DirectoryItem::get( pStream->GetFileName(), aItem) != osl::FileBase::E_None )
[ + - ]
112 : : {
113 : : SAL_INFO("tools", "Failed to lookup stream for locking");
114 : 1626 : return sal_True;
115 : : }
116 : :
117 : 0 : osl::FileStatus aStatus( osl_FileStatus_Mask_Type );
118 [ # # ][ # # ]: 0 : if ( aItem.getFileStatus( aStatus ) != osl::FileBase::E_None )
119 : : {
120 : : SAL_INFO("tools", "Failed to stat stream for locking");
121 : 0 : return sal_True;
122 : : }
123 [ # # ][ # # ]: 0 : if( aStatus.getFileType() == osl::FileStatus::Directory )
124 : 0 : return sal_True;
125 : :
126 : 0 : InternalStreamLock* pLock = NULL;
127 [ # # ]: 0 : InternalStreamLockList &rLockList = LockList::get();
128 [ # # ]: 0 : for( size_t i = 0; i < rLockList.size(); ++i )
129 : : {
130 : 0 : pLock = rLockList[ i ];
131 [ # # ][ # # ]: 0 : if( aItem.isIdenticalTo( pLock->m_aItem ) )
132 : : {
133 : 0 : sal_Bool bDenyByOptions = sal_False;
134 : 0 : StreamMode nLockMode = pLock->m_pStream->GetStreamMode();
135 : 0 : StreamMode nNewMode = pStream->GetStreamMode();
136 : :
137 [ # # ]: 0 : if( nLockMode & STREAM_SHARE_DENYALL )
138 : 0 : bDenyByOptions = sal_True;
139 [ # # ][ # # ]: 0 : else if( ( nLockMode & STREAM_SHARE_DENYWRITE ) &&
140 : : ( nNewMode & STREAM_WRITE ) )
141 : 0 : bDenyByOptions = sal_True;
142 [ # # ][ # # ]: 0 : else if( ( nLockMode & STREAM_SHARE_DENYREAD ) &&
143 : : ( nNewMode & STREAM_READ ) )
144 : 0 : bDenyByOptions = sal_True;
145 : :
146 [ # # ]: 0 : if( bDenyByOptions )
147 : : {
148 [ # # ][ # # ]: 0 : if( pLock->m_nStartPos == 0 && pLock->m_nEndPos == 0 ) // whole file is already locked
149 : 0 : return sal_False;
150 [ # # ][ # # ]: 0 : if( nStart == 0 && nEnd == 0) // cannot lock whole file
151 : 0 : return sal_False;
152 : :
153 [ # # ][ # # ]: 0 : if( ( nStart < pLock->m_nStartPos && nEnd > pLock->m_nStartPos ) ||
[ # # ][ # # ]
154 : : ( nStart < pLock->m_nEndPos && nEnd > pLock->m_nEndPos ) )
155 : 0 : return sal_False;
156 : : }
157 : : }
158 : : }
159 : : // hint: new InternalStreamLock() adds the entry to the global list
160 [ # # ][ # # ]: 0 : pLock = new InternalStreamLock( nStart, nEnd, pStream );
161 [ + - ][ + - ]: 1626 : return sal_True;
162 : : }
163 : :
164 : 14687 : void InternalStreamLock::UnlockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* pStream )
165 : : {
166 [ + - ][ + - ]: 14687 : osl::MutexGuard aGuard( LockMutex::get() );
167 : 14687 : InternalStreamLock* pLock = NULL;
168 [ + - ]: 14687 : InternalStreamLockList &rLockList = LockList::get();
169 [ + - ][ + - ]: 14687 : if( nStart == 0 && nEnd == 0 )
170 : : {
171 : : // nStart & nEnd = 0, so delete all locks
172 [ - + ]: 14687 : for( size_t i = 0; i < rLockList.size(); ++i )
173 : : {
174 [ # # ]: 0 : if( ( pLock = rLockList[ i ] )->m_pStream == pStream )
175 : : {
176 : : // hint: delete will remove pLock from the global list
177 [ # # ][ # # ]: 0 : delete pLock;
178 : 0 : i--;
179 : : }
180 : : }
181 : : return;
182 : : }
183 [ # # ]: 0 : for( size_t i = 0; i < rLockList.size(); ++i )
184 : : {
185 [ # # ][ # # ]: 0 : if ( ( pLock = rLockList[ i ] )->m_pStream == pStream
[ # # ][ # # ]
186 : : && nStart == pLock->m_nStartPos
187 : : && nEnd == pLock->m_nEndPos
188 : : ) {
189 : : // hint: delete will remove pLock from the global list
190 [ # # ][ # # ]: 0 : delete pLock;
191 : : return;
192 : : }
193 [ + - ][ - + ]: 14687 : }
194 : : }
195 : :
196 : : // StreamData ------------------------------------------------------------------
197 : :
198 : : class StreamData
199 : : {
200 : : public:
201 : : oslFileHandle rHandle;
202 : :
203 : 8801 : StreamData() : rHandle( 0 ) { }
204 : : };
205 : :
206 : 0 : static sal_uInt32 GetSvError( int nErrno )
207 : : {
208 : : static struct { int nErr; sal_uInt32 sv; } errArr[] =
209 : : {
210 : : { 0, SVSTREAM_OK },
211 : : { EACCES, SVSTREAM_ACCESS_DENIED },
212 : : { EBADF, SVSTREAM_INVALID_HANDLE },
213 : : #if defined(RS6000) || defined(NETBSD) || \
214 : : defined(FREEBSD) || defined(MACOSX) || defined(OPENBSD) || \
215 : : defined(__FreeBSD_kernel__) || defined (AIX) || defined(DRAGONFLY) || \
216 : : defined(IOS)
217 : : { EDEADLK, SVSTREAM_LOCKING_VIOLATION },
218 : : #else
219 : : { EDEADLOCK, SVSTREAM_LOCKING_VIOLATION },
220 : : #endif
221 : : { EINVAL, SVSTREAM_INVALID_PARAMETER },
222 : : { EMFILE, SVSTREAM_TOO_MANY_OPEN_FILES },
223 : : { ENFILE, SVSTREAM_TOO_MANY_OPEN_FILES },
224 : : { ENOENT, SVSTREAM_FILE_NOT_FOUND },
225 : : { EPERM, SVSTREAM_ACCESS_DENIED },
226 : : { EROFS, SVSTREAM_ACCESS_DENIED },
227 : : { EAGAIN, SVSTREAM_LOCKING_VIOLATION },
228 : : { EISDIR, SVSTREAM_PATH_NOT_FOUND },
229 : : { ELOOP, SVSTREAM_PATH_NOT_FOUND },
230 : : #if !defined(RS6000) && !defined(NETBSD) && !defined (FREEBSD) && \
231 : : !defined(MACOSX) && !defined(OPENBSD) && !defined(__FreeBSD_kernel__) && \
232 : : !defined(DRAGONFLY)
233 : : { EMULTIHOP, SVSTREAM_PATH_NOT_FOUND },
234 : : { ENOLINK, SVSTREAM_PATH_NOT_FOUND },
235 : : #endif
236 : : { ENOTDIR, SVSTREAM_PATH_NOT_FOUND },
237 : : { ETXTBSY, SVSTREAM_ACCESS_DENIED },
238 : : { EEXIST, SVSTREAM_CANNOT_MAKE },
239 : : { ENOSPC, SVSTREAM_DISK_FULL },
240 : : { (int)0xFFFF, SVSTREAM_GENERALERROR }
241 : : };
242 : :
243 : 0 : sal_uInt32 nRetVal = SVSTREAM_GENERALERROR; // default error
244 : 0 : int i=0;
245 [ # # ]: 0 : do
246 : : {
247 [ # # ]: 0 : if ( errArr[i].nErr == nErrno )
248 : : {
249 : 0 : nRetVal = errArr[i].sv;
250 : 0 : break;
251 : : }
252 : 0 : ++i;
253 : : }
254 : : while( errArr[i].nErr != 0xFFFF );
255 : 0 : return nRetVal;
256 : : }
257 : :
258 : 443 : static sal_uInt32 GetSvError( oslFileError nErrno )
259 : : {
260 : : static struct { oslFileError nErr; sal_uInt32 sv; } errArr[] =
261 : : {
262 : : { osl_File_E_None, SVSTREAM_OK },
263 : : { osl_File_E_ACCES, SVSTREAM_ACCESS_DENIED },
264 : : { osl_File_E_BADF, SVSTREAM_INVALID_HANDLE },
265 : : { osl_File_E_DEADLK, SVSTREAM_LOCKING_VIOLATION },
266 : : { osl_File_E_INVAL, SVSTREAM_INVALID_PARAMETER },
267 : : { osl_File_E_MFILE, SVSTREAM_TOO_MANY_OPEN_FILES },
268 : : { osl_File_E_NFILE, SVSTREAM_TOO_MANY_OPEN_FILES },
269 : : { osl_File_E_NOENT, SVSTREAM_FILE_NOT_FOUND },
270 : : { osl_File_E_PERM, SVSTREAM_ACCESS_DENIED },
271 : : { osl_File_E_ROFS, SVSTREAM_ACCESS_DENIED },
272 : : { osl_File_E_AGAIN, SVSTREAM_LOCKING_VIOLATION },
273 : : { osl_File_E_ISDIR, SVSTREAM_PATH_NOT_FOUND },
274 : : { osl_File_E_LOOP, SVSTREAM_PATH_NOT_FOUND },
275 : : { osl_File_E_MULTIHOP, SVSTREAM_PATH_NOT_FOUND },
276 : : { osl_File_E_NOLINK, SVSTREAM_PATH_NOT_FOUND },
277 : : { osl_File_E_NOTDIR, SVSTREAM_PATH_NOT_FOUND },
278 : : { osl_File_E_EXIST, SVSTREAM_CANNOT_MAKE },
279 : : { osl_File_E_NOSPC, SVSTREAM_DISK_FULL },
280 : : { (oslFileError)0xFFFF, SVSTREAM_GENERALERROR }
281 : : };
282 : :
283 : 443 : sal_uInt32 nRetVal = SVSTREAM_GENERALERROR; // default error
284 : 443 : int i=0;
285 [ + - ]: 3086 : do
286 : : {
287 [ + + ]: 3529 : if ( errArr[i].nErr == nErrno )
288 : : {
289 : 443 : nRetVal = errArr[i].sv;
290 : 443 : break;
291 : : }
292 : 3086 : ++i;
293 : : }
294 : : while( errArr[i].nErr != (oslFileError)0xFFFF );
295 : 443 : return nRetVal;
296 : : }
297 : :
298 [ + - ]: 8228 : SvFileStream::SvFileStream( const String& rFileName, StreamMode nOpenMode )
299 : : {
300 : 8228 : bIsOpen = sal_False;
301 : 8228 : nLockCounter = 0;
302 : 8228 : bIsWritable = sal_False;
303 [ + - ]: 8228 : pInstanceData = new StreamData;
304 : :
305 [ + - ]: 8228 : SetBufferSize( 1024 );
306 : : // convert URL to SystemPath, if necessary
307 : 8228 : ::rtl::OUString aSystemFileName;
308 [ + - ][ + + ]: 8228 : if( FileBase::getSystemPathFromFileURL( rFileName , aSystemFileName )
[ + - ]
309 : : != FileBase::E_None )
310 : : {
311 [ + - ]: 2147 : aSystemFileName = rFileName;
312 : : }
313 [ + - ][ + - ]: 8228 : Open( aSystemFileName, nOpenMode );
[ + - ]
314 : 8228 : }
315 : :
316 [ + - ]: 573 : SvFileStream::SvFileStream()
317 : : {
318 : 573 : bIsOpen = sal_False;
319 : 573 : nLockCounter = 0;
320 : 573 : bIsWritable = sal_False;
321 [ + - ]: 573 : pInstanceData = new StreamData;
322 [ + - ]: 573 : SetBufferSize( 1024 );
323 : 573 : }
324 : :
325 [ + - ]: 7820 : SvFileStream::~SvFileStream()
326 : : {
327 [ + - ]: 7820 : Close();
328 : :
329 [ + - ]: 7820 : InternalStreamLock::UnlockFile( 0, 0, this );
330 : :
331 [ + - ]: 7820 : if (pInstanceData)
332 : 7820 : delete pInstanceData;
333 [ - + ]: 11318 : }
334 : :
335 : 2640 : sal_uInt32 SvFileStream::GetFileHandle() const
336 : : {
337 : : sal_IntPtr handle;
338 [ + - ][ + - ]: 2640 : if (osl_getFileOSHandle(pInstanceData->rHandle, &handle) == osl_File_E_None)
339 : 2640 : return (sal_uInt32) handle;
340 : : else
341 : 2640 : return (sal_uInt32) -1;
342 : : }
343 : :
344 : 0 : sal_uInt16 SvFileStream::IsA() const
345 : : {
346 : 0 : return ID_FILESTREAM;
347 : : }
348 : :
349 : 474656 : sal_Size SvFileStream::GetData( void* pData, sal_Size nSize )
350 : : {
351 : : #ifdef DBG_UTIL
352 : : rtl::OStringBuffer aTraceStr(
353 : : RTL_CONSTASCII_STRINGPARAM("SvFileStream::GetData(): "));
354 : : aTraceStr.append(static_cast<sal_Int64>(nSize));
355 : : aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" Bytes from "));
356 : : aTraceStr.append(rtl::OUStringToOString(aFilename,
357 : : osl_getThreadTextEncoding()));
358 : : OSL_TRACE("%s", aTraceStr.getStr());
359 : : #endif
360 : :
361 : 474656 : sal_uInt64 nRead = 0;
362 [ + - ]: 474656 : if ( IsOpen() )
363 : : {
364 [ + - ]: 474656 : oslFileError rc = osl_readFile(pInstanceData->rHandle,pData,(sal_uInt64)nSize,&nRead);
365 [ - + ]: 474656 : if ( rc != osl_File_E_None )
366 : : {
367 [ # # ]: 0 : SetError( ::GetSvError( rc ));
368 : 0 : return -1;
369 : : }
370 : : }
371 : 474656 : return (sal_Size)nRead;
372 : : }
373 : :
374 : 36820 : sal_Size SvFileStream::PutData( const void* pData, sal_Size nSize )
375 : : {
376 : : #ifdef DBG_UTIL
377 : : rtl::OStringBuffer aTraceStr(
378 : : RTL_CONSTASCII_STRINGPARAM("SvFileStream::PutData(): "));
379 : : aTraceStr.append(static_cast<sal_Int64>(nSize));
380 : : aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" Bytes to "));
381 : : aTraceStr.append(rtl::OUStringToOString(aFilename,
382 : : osl_getThreadTextEncoding()));
383 : : OSL_TRACE("%s", aTraceStr.getStr());
384 : : #endif
385 : :
386 : 36820 : sal_uInt64 nWrite = 0;
387 [ + - ]: 36820 : if ( IsOpen() )
388 : : {
389 [ + - ]: 36820 : oslFileError rc = osl_writeFile(pInstanceData->rHandle,pData,(sal_uInt64)nSize,&nWrite);
390 [ - + ]: 36820 : if ( rc != osl_File_E_None )
391 : : {
392 [ # # ]: 0 : SetError( ::GetSvError( rc ) );
393 : 0 : return -1;
394 : : }
395 [ - + ]: 36820 : else if( !nWrite )
396 [ # # ]: 0 : SetError( SVSTREAM_DISK_FULL );
397 : : }
398 : 36820 : return (sal_Size)nWrite;
399 : : }
400 : :
401 : 582338 : sal_Size SvFileStream::SeekPos( sal_Size nPos )
402 : : {
403 [ + - ]: 582338 : if ( IsOpen() )
404 : : {
405 : : oslFileError rc;
406 : : sal_uInt64 nNewPos;
407 [ + + ]: 582338 : if ( nPos != STREAM_SEEK_TO_END )
408 [ + - ]: 578604 : rc = osl_setFilePos( pInstanceData->rHandle, osl_Pos_Absolut, nPos );
409 : : else
410 [ + - ]: 3734 : rc = osl_setFilePos( pInstanceData->rHandle, osl_Pos_End, 0 );
411 : :
412 [ - + ]: 582338 : if ( rc != osl_File_E_None )
413 : : {
414 [ # # ]: 0 : SetError( SVSTREAM_SEEK_ERROR );
415 : 0 : return 0L;
416 : : }
417 [ + - ]: 582338 : rc = osl_getFilePos( pInstanceData->rHandle, &nNewPos );
418 : 582338 : return (sal_Size) nNewPos;
419 : : }
420 : 0 : SetError( SVSTREAM_GENERALERROR );
421 : 582338 : return 0L;
422 : : }
423 : :
424 : 2432 : void SvFileStream::FlushData()
425 : : {
426 : : // does not exist locally
427 : 2432 : }
428 : :
429 : 7848 : sal_Bool SvFileStream::LockRange( sal_Size nByteOffset, sal_Size nBytes )
430 : : {
431 : 7848 : int nLockMode = 0;
432 : :
433 [ - + ]: 7848 : if ( ! IsOpen() )
434 : 0 : return sal_False;
435 : :
436 [ + + ]: 7848 : if ( eStreamMode & STREAM_SHARE_DENYALL )
437 : : {
438 [ + - ]: 221 : if (bIsWritable)
439 : 221 : nLockMode = F_WRLCK;
440 : : else
441 : 0 : nLockMode = F_RDLCK;
442 : : }
443 : :
444 [ - + ]: 7848 : if ( eStreamMode & STREAM_SHARE_DENYREAD )
445 : : {
446 [ # # ]: 0 : if (bIsWritable)
447 : 0 : nLockMode = F_WRLCK;
448 : : else
449 : : {
450 : 0 : SetError(SVSTREAM_LOCKING_VIOLATION);
451 : 0 : return sal_False;
452 : : }
453 : : }
454 : :
455 [ + + ]: 7848 : if ( eStreamMode & STREAM_SHARE_DENYWRITE )
456 : : {
457 [ + + ]: 4444 : if (bIsWritable)
458 : 1405 : nLockMode = F_WRLCK;
459 : : else
460 : 3039 : nLockMode = F_RDLCK;
461 : : }
462 : :
463 [ + + ]: 7848 : if (!nLockMode)
464 : 6222 : return sal_True;
465 : :
466 [ - + ]: 1626 : if( ! InternalStreamLock::LockFile( nByteOffset, nByteOffset+nBytes, this ) )
467 : : {
468 : : #if OSL_DEBUG_LEVEL > 1
469 : : fprintf( stderr, "InternalLock on %s [ %ld ... %ld ] failed\n",
470 : : rtl::OUStringToOString(aFilename, osl_getThreadTextEncoding()).getStr(), nByteOffset, nByteOffset+nBytes );
471 : : #endif
472 : 0 : return sal_False;
473 : : }
474 : :
475 : 7848 : return sal_True;
476 : : }
477 : :
478 : 17431 : sal_Bool SvFileStream::UnlockRange( sal_Size nByteOffset, sal_Size nBytes )
479 : : {
480 [ + + ]: 17431 : if ( ! IsOpen() )
481 : 10564 : return sal_False;
482 : :
483 : 6867 : InternalStreamLock::UnlockFile( nByteOffset, nByteOffset+nBytes, this );
484 : :
485 : 17431 : return sal_True;
486 : : }
487 : :
488 : 7848 : sal_Bool SvFileStream::LockFile()
489 : : {
490 : 7848 : return LockRange( 0UL, 0UL );
491 : : }
492 : :
493 : 17431 : sal_Bool SvFileStream::UnlockFile()
494 : : {
495 : 17431 : return UnlockRange( 0UL, 0UL );
496 : : }
497 : :
498 : 8291 : void SvFileStream::Open( const String& rFilename, StreamMode nOpenMode )
499 : : {
500 : : sal_uInt32 uFlags;
501 : : oslFileHandle nHandleTmp;
502 : :
503 [ + - ]: 8291 : Close();
504 : 8291 : errno = 0;
505 : 8291 : eStreamMode = nOpenMode;
506 : 8291 : eStreamMode &= ~STREAM_TRUNC; // don't truncat on reopen
507 : :
508 : : // !!! NoOp: use ToAbs()
509 : : // !!! DirEntry aDirEntry( rFilename );
510 : : // !!! aFilename = aDirEntry.GetFull();
511 [ + - ]: 8291 : aFilename = rFilename;
512 [ + - ][ + - ]: 8291 : rtl::OString aLocalFilename(rtl::OUStringToOString(aFilename, osl_getThreadTextEncoding()));
[ + - ]
513 : :
514 : : #ifdef DBG_UTIL
515 : : rtl::OStringBuffer aTraceStr(RTL_CONSTASCII_STRINGPARAM(
516 : : "SvFileStream::Open(): "));
517 : : aTraceStr.append(aLocalFilename);
518 : : OSL_TRACE( "%s", aTraceStr.getStr() );
519 : : #endif
520 : :
521 : 8291 : rtl::OUString aFileURL;
522 : 8291 : osl::DirectoryItem aItem;
523 : 8291 : osl::FileStatus aStatus( osl_FileStatus_Mask_Type | osl_FileStatus_Mask_LinkTargetURL );
524 : :
525 : : // FIXME: we really need to switch to a pure URL model ...
526 [ + - ][ + + ]: 8291 : if ( osl::File::getFileURLFromSystemPath( aFilename, aFileURL ) != osl::FileBase::E_None )
[ + - ]
527 [ + - ]: 5 : aFileURL = aFilename;
528 [ + - ]: 8291 : bool bStatValid = ( osl::DirectoryItem::get( aFileURL, aItem) == osl::FileBase::E_None &&
529 [ + + ][ + - ]: 8291 : aItem.getFileStatus( aStatus ) == osl::FileBase::E_None );
[ + - ]
530 : :
531 : : // SvFileStream can't open a directory
532 [ + + ][ + - ]: 8291 : if( bStatValid && aStatus.getFileType() == osl::FileStatus::Directory )
[ - + ][ - + ]
533 : : {
534 [ # # ]: 0 : SetError( ::GetSvError( EISDIR ) );
535 : 8291 : return;
536 : : }
537 : :
538 [ + + ]: 8291 : if ( !( nOpenMode & STREAM_WRITE ) )
539 : 6384 : uFlags = osl_File_OpenFlag_Read;
540 [ + + ]: 1907 : else if ( !( nOpenMode & STREAM_READ ) )
541 : 1505 : uFlags = osl_File_OpenFlag_Write;
542 : : else
543 : 402 : uFlags = osl_File_OpenFlag_Read | osl_File_OpenFlag_Write;
544 : :
545 : : // Fix (MDA, 18.01.95): Don't open with O_CREAT upon RD_ONLY
546 : : // Important for Read-Only-Filesystems (e.g, CDROM)
547 [ + + ][ + + ]: 8291 : if ( (!( nOpenMode & STREAM_NOCREATE )) && ( uFlags != osl_File_OpenFlag_Read ) )
548 : 1907 : uFlags |= osl_File_OpenFlag_Create;
549 [ + + ]: 8291 : if ( nOpenMode & STREAM_TRUNC )
550 : 1601 : uFlags |= osl_File_OpenFlag_Trunc;
551 : :
552 : 8291 : uFlags |= osl_File_OpenFlag_NoExcl | osl_File_OpenFlag_NoLock;
553 : :
554 [ + + ]: 8291 : if ( nOpenMode & STREAM_WRITE)
555 : : {
556 [ - + ]: 1907 : if ( nOpenMode & STREAM_COPY_ON_SYMLINK )
557 : : {
558 [ # # ][ # # ]: 0 : if ( bStatValid && aStatus.getFileType() == osl::FileStatus::Link &&
[ # # # # ]
[ # # ]
559 [ # # ][ # # ]: 0 : aStatus.getLinkTargetURL().getLength() > 0 )
[ # # ]
560 : : {
561 : : // delete the symbolic link, and replace it with the contents of the link
562 [ # # ][ # # ]: 0 : if (osl::File::remove( aFileURL ) == osl::FileBase::E_None )
563 : : {
564 [ # # ][ # # ]: 0 : File::copy( aStatus.getLinkTargetURL(), aFileURL );
565 : : #if OSL_DEBUG_LEVEL > 0
566 : : fprintf( stderr,
567 : : "Removing link and replacing with file contents (%s) -> (%s).\n",
568 : : rtl::OUStringToOString( aStatus.getLinkTargetURL(),
569 : : RTL_TEXTENCODING_UTF8).getStr(),
570 : : rtl::OUStringToOString( aFileURL,
571 : : RTL_TEXTENCODING_UTF8).getStr() );
572 : : #endif
573 : : }
574 : : }
575 : : }
576 : : }
577 : :
578 [ + - ]: 8291 : oslFileError rc = osl_openFile( aFileURL.pData, &nHandleTmp, uFlags );
579 [ + + ]: 8291 : if ( rc != osl_File_E_None )
580 : : {
581 [ - + ]: 443 : if ( uFlags & osl_File_OpenFlag_Write )
582 : : {
583 : : // Change to read-only
584 : 0 : uFlags &= ~osl_File_OpenFlag_Write;
585 [ # # ]: 0 : rc = osl_openFile( aFileURL.pData, &nHandleTmp, uFlags );
586 : : }
587 : : }
588 [ + + ]: 8291 : if ( rc == osl_File_E_None )
589 : : {
590 : 7848 : pInstanceData->rHandle = nHandleTmp;
591 : 7848 : bIsOpen = sal_True;
592 [ + + ]: 7848 : if ( uFlags & osl_File_OpenFlag_Write )
593 : 1907 : bIsWritable = sal_True;
594 : :
595 [ + - ][ - + ]: 7848 : if ( !LockFile() ) // whole file
596 : : {
597 [ # # ]: 0 : rc = osl_closeFile( nHandleTmp );
598 : 0 : bIsOpen = sal_False;
599 : 0 : bIsWritable = sal_False;
600 : 0 : pInstanceData->rHandle = 0;
601 : : }
602 : : }
603 : : else
604 [ + - ][ - + ]: 8291 : SetError( ::GetSvError( rc ) );
[ + - ][ - + ]
[ - + ][ + - ]
605 : : }
606 : :
607 : 17431 : void SvFileStream::Close()
608 : : {
609 : 17431 : UnlockFile();
610 : :
611 [ + + ]: 17431 : if ( IsOpen() )
612 : : {
613 : : #ifdef DBG_UTIL
614 : : rtl::OStringBuffer aTraceStr(
615 : : RTL_CONSTASCII_STRINGPARAM("SvFileStream::Close(): "));
616 : : aTraceStr.append(rtl::OUStringToOString(aFilename,
617 : : osl_getThreadTextEncoding()));
618 : : OSL_TRACE("%s", aTraceStr.getStr());
619 : : #endif
620 : :
621 : 6867 : Flush();
622 : 6867 : osl_closeFile( pInstanceData->rHandle );
623 : 6867 : pInstanceData->rHandle = 0;
624 : : }
625 : :
626 : 17431 : bIsOpen = sal_False;
627 : 17431 : bIsWritable = sal_False;
628 : 17431 : SvStream::ClearBuffer();
629 : 17431 : SvStream::ClearError();
630 : 17431 : }
631 : :
632 : : /// set filepointer to beginning of file
633 : 135 : void SvFileStream::ResetError()
634 : : {
635 : 135 : SvStream::ClearError();
636 : 135 : }
637 : :
638 : 160 : void SvFileStream::SetSize (sal_Size nSize)
639 : : {
640 [ + - ]: 160 : if (IsOpen())
641 : : {
642 : 160 : oslFileError rc = osl_setFileSize( pInstanceData->rHandle, nSize );
643 [ - + ]: 160 : if (rc != osl_File_E_None )
644 : : {
645 : 0 : SetError ( ::GetSvError( rc ));
646 : : }
647 : : }
648 : 160 : }
649 : :
650 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|