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 114 : sal_Bool InternalStreamLock::LockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* pStream )
108 : {
109 114 : osl::MutexGuard aGuard( LockMutex::get() );
110 114 : osl::DirectoryItem aItem;
111 114 : if (osl::DirectoryItem::get( pStream->GetFileName(), aItem) != osl::FileBase::E_None )
112 : {
113 : SAL_INFO("tools.stream", "Failed to lookup stream for locking");
114 114 : 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.stream", "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 0 : return sal_True;
162 : }
163 :
164 1526 : void InternalStreamLock::UnlockFile( sal_Size nStart, sal_Size nEnd, SvFileStream* pStream )
165 : {
166 1526 : osl::MutexGuard aGuard( LockMutex::get() );
167 1526 : InternalStreamLock* pLock = NULL;
168 1526 : InternalStreamLockList &rLockList = LockList::get();
169 1526 : if( nStart == 0 && nEnd == 0 )
170 : {
171 : // nStart & nEnd = 0, so delete all locks
172 1526 : 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 1526 : }
194 : }
195 :
196 : // StreamData ------------------------------------------------------------------
197 :
198 : class StreamData
199 : {
200 : public:
201 : oslFileHandle rHandle;
202 :
203 1484 : 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 80 : 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 80 : sal_uInt32 nRetVal = SVSTREAM_GENERALERROR; // default error
284 80 : int i=0;
285 560 : do
286 : {
287 640 : if ( errArr[i].nErr == nErrno )
288 : {
289 80 : nRetVal = errArr[i].sv;
290 80 : break;
291 : }
292 560 : ++i;
293 : }
294 : while( errArr[i].nErr != (oslFileError)0xFFFF );
295 80 : return nRetVal;
296 : }
297 :
298 1262 : SvFileStream::SvFileStream( const String& rFileName, StreamMode nOpenMode )
299 : {
300 1262 : bIsOpen = sal_False;
301 1262 : nLockCounter = 0;
302 1262 : bIsWritable = sal_False;
303 1262 : pInstanceData = new StreamData;
304 :
305 1262 : SetBufferSize( 1024 );
306 : // convert URL to SystemPath, if necessary
307 1262 : ::rtl::OUString aSystemFileName;
308 1262 : if( FileBase::getSystemPathFromFileURL( rFileName , aSystemFileName )
309 : != FileBase::E_None )
310 : {
311 272 : aSystemFileName = rFileName;
312 : }
313 1262 : Open( aSystemFileName, nOpenMode );
314 1262 : }
315 :
316 222 : SvFileStream::SvFileStream()
317 : {
318 222 : bIsOpen = sal_False;
319 222 : nLockCounter = 0;
320 222 : bIsWritable = sal_False;
321 222 : pInstanceData = new StreamData;
322 222 : SetBufferSize( 1024 );
323 222 : }
324 :
325 2308 : SvFileStream::~SvFileStream()
326 : {
327 914 : Close();
328 :
329 914 : InternalStreamLock::UnlockFile( 0, 0, this );
330 :
331 914 : if (pInstanceData)
332 914 : delete pInstanceData;
333 1394 : }
334 :
335 0 : sal_uInt32 SvFileStream::GetFileHandle() const
336 : {
337 : sal_IntPtr handle;
338 0 : if (osl_getFileOSHandle(pInstanceData->rHandle, &handle) == osl_File_E_None)
339 0 : return (sal_uInt32) handle;
340 : else
341 0 : return (sal_uInt32) -1;
342 : }
343 :
344 0 : sal_uInt16 SvFileStream::IsA() const
345 : {
346 0 : return ID_FILESTREAM;
347 : }
348 :
349 166993 : 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 166993 : sal_uInt64 nRead = 0;
362 166993 : if ( IsOpen() )
363 : {
364 166993 : oslFileError rc = osl_readFile(pInstanceData->rHandle,pData,(sal_uInt64)nSize,&nRead);
365 166993 : if ( rc != osl_File_E_None )
366 : {
367 0 : SetError( ::GetSvError( rc ));
368 0 : return -1;
369 : }
370 : }
371 166993 : return (sal_Size)nRead;
372 : }
373 :
374 554 : 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 554 : sal_uInt64 nWrite = 0;
387 554 : if ( IsOpen() )
388 : {
389 554 : oslFileError rc = osl_writeFile(pInstanceData->rHandle,pData,(sal_uInt64)nSize,&nWrite);
390 554 : if ( rc != osl_File_E_None )
391 : {
392 0 : SetError( ::GetSvError( rc ) );
393 0 : return -1;
394 : }
395 554 : else if( !nWrite )
396 0 : SetError( SVSTREAM_DISK_FULL );
397 : }
398 554 : return (sal_Size)nWrite;
399 : }
400 :
401 182649 : sal_Size SvFileStream::SeekPos( sal_Size nPos )
402 : {
403 182649 : if ( IsOpen() )
404 : {
405 : oslFileError rc;
406 : sal_uInt64 nNewPos;
407 182649 : if ( nPos != STREAM_SEEK_TO_END )
408 181445 : rc = osl_setFilePos( pInstanceData->rHandle, osl_Pos_Absolut, nPos );
409 : else
410 1204 : rc = osl_setFilePos( pInstanceData->rHandle, osl_Pos_End, 0 );
411 :
412 182649 : if ( rc != osl_File_E_None )
413 : {
414 0 : SetError( SVSTREAM_SEEK_ERROR );
415 0 : return 0L;
416 : }
417 182649 : rc = osl_getFilePos( pInstanceData->rHandle, &nNewPos );
418 182649 : return (sal_Size) nNewPos;
419 : }
420 0 : SetError( SVSTREAM_GENERALERROR );
421 0 : return 0L;
422 : }
423 :
424 402 : void SvFileStream::FlushData()
425 : {
426 : // does not exist locally
427 402 : }
428 :
429 1182 : sal_Bool SvFileStream::LockRange( sal_Size nByteOffset, sal_Size nBytes )
430 : {
431 1182 : int nLockMode = 0;
432 :
433 1182 : if ( ! IsOpen() )
434 0 : return sal_False;
435 :
436 1182 : if ( eStreamMode & STREAM_SHARE_DENYALL )
437 : {
438 114 : if (bIsWritable)
439 114 : nLockMode = F_WRLCK;
440 : else
441 0 : nLockMode = F_RDLCK;
442 : }
443 :
444 1182 : 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 1182 : if ( eStreamMode & STREAM_SHARE_DENYWRITE )
456 : {
457 842 : if (bIsWritable)
458 0 : nLockMode = F_WRLCK;
459 : else
460 842 : nLockMode = F_RDLCK;
461 : }
462 :
463 1182 : if (!nLockMode)
464 1068 : return sal_True;
465 :
466 114 : 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 114 : return sal_True;
476 : }
477 :
478 2176 : sal_Bool SvFileStream::UnlockRange( sal_Size nByteOffset, sal_Size nBytes )
479 : {
480 2176 : if ( ! IsOpen() )
481 1564 : return sal_False;
482 :
483 612 : InternalStreamLock::UnlockFile( nByteOffset, nByteOffset+nBytes, this );
484 :
485 612 : return sal_True;
486 : }
487 :
488 1182 : sal_Bool SvFileStream::LockFile()
489 : {
490 1182 : return LockRange( 0UL, 0UL );
491 : }
492 :
493 2176 : sal_Bool SvFileStream::UnlockFile()
494 : {
495 2176 : return UnlockRange( 0UL, 0UL );
496 : }
497 :
498 1262 : void SvFileStream::Open( const String& rFilename, StreamMode nOpenMode )
499 : {
500 : sal_uInt32 uFlags;
501 : oslFileHandle nHandleTmp;
502 :
503 1262 : Close();
504 1262 : errno = 0;
505 1262 : eStreamMode = nOpenMode;
506 1262 : eStreamMode &= ~STREAM_TRUNC; // don't truncat on reopen
507 :
508 : // !!! NoOp: use ToAbs()
509 : // !!! DirEntry aDirEntry( rFilename );
510 : // !!! aFilename = aDirEntry.GetFull();
511 1262 : aFilename = rFilename;
512 1262 : 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 1262 : rtl::OUString aFileURL;
522 1262 : osl::DirectoryItem aItem;
523 1262 : 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 1262 : if ( osl::File::getFileURLFromSystemPath( aFilename, aFileURL ) != osl::FileBase::E_None )
527 0 : aFileURL = aFilename;
528 1262 : bool bStatValid = ( osl::DirectoryItem::get( aFileURL, aItem) == osl::FileBase::E_None &&
529 1262 : aItem.getFileStatus( aStatus ) == osl::FileBase::E_None );
530 :
531 : // SvFileStream can't open a directory
532 1262 : if( bStatValid && aStatus.getFileType() == osl::FileStatus::Directory )
533 : {
534 0 : SetError( ::GetSvError( EISDIR ) );
535 1262 : return;
536 : }
537 :
538 1262 : if ( !( nOpenMode & STREAM_WRITE ) )
539 1148 : uFlags = osl_File_OpenFlag_Read;
540 114 : else if ( !( nOpenMode & STREAM_READ ) )
541 0 : uFlags = osl_File_OpenFlag_Write;
542 : else
543 114 : 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 1262 : if ( (!( nOpenMode & STREAM_NOCREATE )) && ( uFlags != osl_File_OpenFlag_Read ) )
548 114 : uFlags |= osl_File_OpenFlag_Create;
549 1262 : if ( nOpenMode & STREAM_TRUNC )
550 0 : uFlags |= osl_File_OpenFlag_Trunc;
551 :
552 1262 : uFlags |= osl_File_OpenFlag_NoExcl | osl_File_OpenFlag_NoLock;
553 :
554 1262 : if ( nOpenMode & STREAM_WRITE)
555 : {
556 114 : 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 1262 : oslFileError rc = osl_openFile( aFileURL.pData, &nHandleTmp, uFlags );
579 1262 : if ( rc != osl_File_E_None )
580 : {
581 80 : 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 1262 : if ( rc == osl_File_E_None )
589 : {
590 1182 : pInstanceData->rHandle = nHandleTmp;
591 1182 : bIsOpen = sal_True;
592 1182 : if ( uFlags & osl_File_OpenFlag_Write )
593 114 : bIsWritable = sal_True;
594 :
595 1182 : 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 80 : SetError( ::GetSvError( rc ) );
605 : }
606 :
607 2176 : void SvFileStream::Close()
608 : {
609 2176 : UnlockFile();
610 :
611 2176 : 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 612 : Flush();
622 612 : osl_closeFile( pInstanceData->rHandle );
623 612 : pInstanceData->rHandle = 0;
624 : }
625 :
626 2176 : bIsOpen = sal_False;
627 2176 : bIsWritable = sal_False;
628 2176 : SvStream::ClearBuffer();
629 2176 : SvStream::ClearError();
630 2176 : }
631 :
632 : /// set filepointer to beginning of file
633 88 : void SvFileStream::ResetError()
634 : {
635 88 : SvStream::ClearError();
636 88 : }
637 :
638 82 : void SvFileStream::SetSize (sal_Size nSize)
639 : {
640 82 : if (IsOpen())
641 : {
642 82 : oslFileError rc = osl_setFileSize( pInstanceData->rHandle, nSize );
643 82 : if (rc != osl_File_E_None )
644 : {
645 0 : SetError ( ::GetSvError( rc ));
646 : }
647 : }
648 82 : }
649 :
650 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|