Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/ucb/source/ucp/file/filstr.cxx
Line
Count
Source
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 <sal/config.h>
21
22
#include <com/sun/star/io/BufferSizeExceededException.hpp>
23
#include <com/sun/star/io/IOException.hpp>
24
#include <com/sun/star/lang/IllegalArgumentException.hpp>
25
#include <com/sun/star/uno/RuntimeException.hpp>
26
#include <osl/diagnose.h>
27
#include "filstr.hxx"
28
#include "filerror.hxx"
29
30
using namespace fileaccess;
31
using namespace com::sun::star;
32
33
#if OSL_DEBUG_LEVEL > 0
34
#define THROW_WHERE SAL_WHERE
35
#else
36
0
#define THROW_WHERE ""
37
#endif
38
39
/******************************************************************************/
40
/*                                                                            */
41
/*               XStream_impl implementation                                  */
42
/*                                                                            */
43
/******************************************************************************/
44
45
XStream_impl::XStream_impl( const OUString& aUncPath, bool bLock )
46
46.4k
    : m_bInputStreamCalled( false ),
47
46.4k
      m_bOutputStreamCalled( false ),
48
46.4k
      m_aFile( aUncPath ),
49
46.4k
      m_nErrorCode( TaskHandlerErr::NO_ERROR ),
50
46.4k
      m_nMinorErrorCode( 0 )
51
46.4k
{
52
46.4k
    sal_uInt32 nFlags = ( osl_File_OpenFlag_Read | osl_File_OpenFlag_Write );
53
46.4k
    if ( !bLock )
54
0
        nFlags |= osl_File_OpenFlag_NoLock;
55
56
46.4k
    osl::FileBase::RC err = m_aFile.open( nFlags );
57
46.4k
    if(  err != osl::FileBase::E_None )
58
0
    {
59
0
        m_nIsOpen = false;
60
0
        m_aFile.close();
61
62
0
        m_nErrorCode = TaskHandlerErr::OPEN_FOR_STREAM;
63
0
        m_nMinorErrorCode = err;
64
0
    }
65
46.4k
    else
66
46.4k
        m_nIsOpen = true;
67
46.4k
}
68
69
70
XStream_impl::~XStream_impl()
71
46.4k
{
72
46.4k
    try
73
46.4k
    {
74
46.4k
        closeStream();
75
46.4k
    }
76
46.4k
    catch (const io::IOException&)
77
46.4k
    {
78
0
        OSL_FAIL("unexpected situation");
79
0
    }
80
46.4k
    catch (const uno::RuntimeException&)
81
46.4k
    {
82
0
        OSL_FAIL("unexpected situation");
83
0
    }
84
46.4k
}
85
86
87
uno::Reference< io::XInputStream > SAL_CALL
88
XStream_impl::getInputStream(  )
89
46.4k
{
90
46.4k
    {
91
46.4k
        std::scoped_lock aGuard( m_aMutex );
92
46.4k
        m_bInputStreamCalled = true;
93
46.4k
    }
94
46.4k
    return uno::Reference< io::XInputStream >( this );
95
46.4k
}
96
97
98
uno::Reference< io::XOutputStream > SAL_CALL
99
XStream_impl::getOutputStream(  )
100
46.4k
{
101
46.4k
    {
102
46.4k
        std::scoped_lock aGuard( m_aMutex );
103
46.4k
        m_bOutputStreamCalled = true;
104
46.4k
    }
105
46.4k
    return uno::Reference< io::XOutputStream >( this );
106
46.4k
}
107
108
109
void SAL_CALL XStream_impl::truncate()
110
0
{
111
0
    if (osl::FileBase::E_None != m_aFile.setSize(0))
112
0
        throw io::IOException( THROW_WHERE );
113
114
0
    if (osl::FileBase::E_None != m_aFile.setPos(osl_Pos_Absolut,sal_uInt64(0)))
115
0
        throw io::IOException( THROW_WHERE );
116
0
}
117
118
119
// XStream_impl private non interface methods
120
121
122
sal_Int32 SAL_CALL
123
XStream_impl::readBytes(
124
    uno::Sequence< sal_Int8 >& aData,
125
    sal_Int32 nBytesToRead )
126
0
{
127
0
    if( ! m_nIsOpen )
128
0
        throw io::IOException( THROW_WHERE );
129
130
0
    try
131
0
    {
132
0
        aData.realloc(nBytesToRead);
133
0
    }
134
0
    catch (const std::bad_alloc&)
135
0
    {
136
0
        if( m_nIsOpen ) m_aFile.close();
137
0
        throw io::BufferSizeExceededException( THROW_WHERE );
138
0
    }
139
140
0
    sal_uInt64 nrc(0);
141
0
    if(m_aFile.read( aData.getArray(), sal_uInt64(nBytesToRead), nrc )
142
0
       != osl::FileBase::E_None)
143
0
    {
144
0
        throw io::IOException( THROW_WHERE );
145
0
    }
146
0
    if (nrc != static_cast<sal_uInt64>(nBytesToRead))
147
0
        aData.realloc(nrc);
148
0
    return static_cast<sal_Int32>(nrc);
149
0
}
150
151
sal_Int32
152
XStream_impl::readSomeBytes(
153
    sal_Int8* pData,
154
    sal_Int32 nBytesToRead )
155
240k
{
156
240k
    if( ! m_nIsOpen )
157
0
        throw io::IOException( THROW_WHERE );
158
159
240k
    sal_uInt64 nrc(0);
160
240k
    if(m_aFile.read( pData, sal_uInt64(nBytesToRead), nrc )
161
240k
       != osl::FileBase::E_None)
162
0
    {
163
0
        throw io::IOException( THROW_WHERE );
164
0
    }
165
240k
    return static_cast<sal_Int32>(nrc);
166
240k
}
167
168
sal_Int32 SAL_CALL
169
XStream_impl::readSomeBytes(
170
    uno::Sequence< sal_Int8 >& aData,
171
    sal_Int32 nMaxBytesToRead )
172
0
{
173
0
    return readBytes( aData,nMaxBytesToRead );
174
0
}
175
176
177
void SAL_CALL
178
XStream_impl::skipBytes( sal_Int32 nBytesToSkip )
179
0
{
180
0
    m_aFile.setPos( osl_Pos_Current, sal_uInt64( nBytesToSkip ) );
181
0
}
182
183
184
sal_Int32 SAL_CALL
185
XStream_impl::available()
186
0
{
187
0
    sal_Int64 avail = getLength() - getPosition();
188
0
    return std::min<sal_Int64>(avail, SAL_MAX_INT32);
189
0
}
190
191
192
void SAL_CALL
193
XStream_impl::writeBytes( const uno::Sequence< sal_Int8 >& aData )
194
18
{
195
18
    sal_uInt32 length = aData.getLength();
196
18
    if(length)
197
18
    {
198
18
        sal_uInt64 nWrittenBytes(0);
199
18
        const sal_Int8* p = aData.getConstArray();
200
18
        if(osl::FileBase::E_None != m_aFile.write(static_cast<void const *>(p),sal_uInt64(length),nWrittenBytes) ||
201
18
           nWrittenBytes != length )
202
0
            throw io::IOException( THROW_WHERE );
203
18
    }
204
18
}
205
206
207
void
208
XStream_impl::closeStream()
209
46.4k
{
210
46.4k
    if( m_nIsOpen )
211
46.4k
    {
212
46.4k
        osl::FileBase::RC err = m_aFile.close();
213
214
46.4k
        if( err != osl::FileBase::E_None ) {
215
0
            throw io::IOException(u"could not close file"_ustr);
216
0
        }
217
218
46.4k
        m_nIsOpen = false;
219
46.4k
    }
220
46.4k
}
221
222
void SAL_CALL
223
XStream_impl::closeInput()
224
0
{
225
0
    std::scoped_lock aGuard( m_aMutex );
226
0
    m_bInputStreamCalled = false;
227
228
0
    if( ! m_bOutputStreamCalled )
229
0
        closeStream();
230
0
}
231
232
233
void SAL_CALL
234
XStream_impl::closeOutput()
235
0
{
236
0
    std::scoped_lock aGuard( m_aMutex );
237
0
    m_bOutputStreamCalled = false;
238
239
0
    if( ! m_bInputStreamCalled )
240
0
        closeStream();
241
0
}
242
243
244
void SAL_CALL
245
XStream_impl::seek( sal_Int64 location )
246
240k
{
247
240k
    if( location < 0 )
248
0
        throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 );
249
240k
    if( osl::FileBase::E_None != m_aFile.setPos( osl_Pos_Absolut, sal_uInt64( location ) ) )
250
0
        throw io::IOException( THROW_WHERE );
251
240k
}
252
253
254
sal_Int64 SAL_CALL
255
XStream_impl::getPosition()
256
0
{
257
0
    sal_uInt64 uPos;
258
0
    if( osl::FileBase::E_None != m_aFile.getPos( uPos ) )
259
0
        throw io::IOException( THROW_WHERE );
260
0
    return sal_Int64( uPos );
261
0
}
262
263
sal_Int64 SAL_CALL
264
XStream_impl::getLength()
265
138k
{
266
138k
    sal_uInt64 uEndPos;
267
138k
    if ( m_aFile.getSize(uEndPos) != osl::FileBase::E_None )
268
0
            throw io::IOException( THROW_WHERE );
269
138k
    return sal_Int64( uEndPos );
270
138k
}
271
272
void SAL_CALL
273
XStream_impl::flush()
274
46.4k
{}
275
276
void XStream_impl::waitForCompletion()
277
0
{
278
    // At least on UNIX, to reliably learn about any errors encountered by
279
    // asynchronous NFS write operations, without closing the file directly
280
    // afterwards, there appears to be no cheaper way than to call fsync:
281
0
    if (m_nIsOpen && m_aFile.sync() != osl::FileBase::E_None) {
282
0
        throw io::IOException(
283
0
            u"could not synchronize file to disc"_ustr,
284
0
            getXWeak());
285
0
    }
286
0
}
287
288
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */