1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_ucb.hxx" 26 #include "gvfs_stream.hxx" 27 #include <rtl/memory.h> 28 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> 29 30 #include <libgnomevfs/gnome-vfs-ops.h> 31 32 using namespace cppu; 33 using namespace rtl; 34 using namespace com::sun::star::io; 35 using namespace com::sun::star::uno; 36 using namespace com::sun::star::ucb; 37 using namespace gvfs; 38 39 Stream::Stream( GnomeVFSHandle *handle, 40 const GnomeVFSFileInfo *aInfo ) : 41 m_eof (sal_False), 42 m_bInputStreamCalled( sal_False ), 43 m_bOutputStreamCalled( sal_False ) 44 { 45 m_handle = handle; 46 gnome_vfs_file_info_copy (&m_info, aInfo); 47 } 48 49 Stream::~Stream( void ) 50 { 51 if (m_handle) { 52 gnome_vfs_close (m_handle); 53 m_handle = NULL; 54 } 55 } 56 57 Any Stream::queryInterface( const Type &type ) 58 throw( RuntimeException ) 59 { 60 Any aRet = ::cppu::queryInterface 61 ( type, 62 static_cast< XStream * >( this ), 63 static_cast< XInputStream * >( this ), 64 static_cast< XOutputStream * >( this ), 65 static_cast< XSeekable * >( this ), 66 static_cast< XTruncate * >( this ) ); 67 68 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( type ); 69 } 70 71 // ------------------------------------------------------------------- 72 // XStream 73 // ------------------------------------------------------------------- 74 75 com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL 76 Stream::getInputStream( ) 77 throw( com::sun::star::uno::RuntimeException ) 78 { 79 { 80 osl::MutexGuard aGuard( m_aMutex ); 81 m_bInputStreamCalled = true; 82 } 83 return Reference< XInputStream >( this ); 84 } 85 86 com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > SAL_CALL 87 Stream::getOutputStream( ) 88 throw( com::sun::star::uno::RuntimeException ) 89 { 90 { 91 osl::MutexGuard aGuard( m_aMutex ); 92 m_bOutputStreamCalled = true; 93 } 94 return Reference< XOutputStream >( this ); 95 } 96 97 // ------------------------------------------------------------------- 98 // XInputStream 99 // ------------------------------------------------------------------- 100 101 sal_Int32 SAL_CALL Stream::readBytes( 102 Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) 103 throw( NotConnectedException, 104 BufferSizeExceededException, 105 IOException, 106 RuntimeException ) 107 { 108 GnomeVFSResult result; 109 GnomeVFSFileSize nBytesRead = 0; 110 111 if( ! m_handle ) 112 throw IOException(); 113 114 if( m_eof ) { 115 aData.realloc( 0 ); 116 return 0; 117 } 118 119 try { 120 aData.realloc( nBytesToRead ); 121 } catch ( const Exception &e ) { 122 throw BufferSizeExceededException(); 123 } 124 125 do { 126 result = gnome_vfs_read( m_handle, aData.getArray(), 127 nBytesToRead, &nBytesRead ); 128 } while( result == GNOME_VFS_ERROR_INTERRUPTED ); 129 130 if (result != GNOME_VFS_OK && 131 result != GNOME_VFS_ERROR_EOF) 132 throwOnError( result ); 133 134 if (result == GNOME_VFS_ERROR_EOF) 135 m_eof = sal_True; 136 137 aData.realloc( sal::static_int_cast<sal_uInt32>(nBytesRead) ); 138 139 return sal::static_int_cast<sal_Int32>(nBytesRead); 140 } 141 142 sal_Int32 SAL_CALL Stream::readSomeBytes( 143 Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) 144 throw( NotConnectedException, 145 BufferSizeExceededException, 146 IOException, 147 RuntimeException ) 148 { 149 // Again - having 2 methods here just sucks; cf. filinpstr.cxx 150 // This can never be an effective non-blocking API - so why bother ? 151 return readBytes( aData, nMaxBytesToRead ); 152 } 153 154 void SAL_CALL Stream::skipBytes( sal_Int32 nBytesToSkip ) 155 throw( NotConnectedException, 156 BufferSizeExceededException, 157 IOException, 158 RuntimeException ) 159 { 160 GnomeVFSResult result; 161 162 if( ! m_handle ) 163 throw IOException(); 164 165 result = gnome_vfs_seek( m_handle, GNOME_VFS_SEEK_CURRENT, nBytesToSkip ); 166 167 if ( result == GNOME_VFS_ERROR_BAD_PARAMETERS || 168 result == GNOME_VFS_ERROR_NOT_SUPPORTED ) 169 g_warning ("FIXME: just read them in ..."); 170 171 throwOnError( result ); 172 } 173 174 sal_Int32 SAL_CALL Stream::available( ) 175 throw( NotConnectedException, 176 IOException, 177 RuntimeException ) 178 { 179 return 0; // cf. filinpstr.cxx 180 } 181 182 void SAL_CALL Stream::closeInput( void ) 183 throw( NotConnectedException, 184 IOException, 185 RuntimeException ) 186 { 187 osl::MutexGuard aGuard( m_aMutex ); 188 m_bInputStreamCalled = false; 189 190 if( ! m_bOutputStreamCalled ) 191 closeStream(); 192 } 193 194 // ------------------------------------------------------------------- 195 // XSeekable 196 // ------------------------------------------------------------------- 197 198 void SAL_CALL Stream::seek( sal_Int64 location ) 199 throw( ::com::sun::star::lang::IllegalArgumentException, 200 IOException, 201 RuntimeException ) 202 { 203 GnomeVFSResult result; 204 205 if( ! m_handle ) 206 throw IOException(); 207 208 if ( location < 0 ) 209 throw ::com::sun::star::lang::IllegalArgumentException(); 210 211 m_eof = sal_False; 212 result = gnome_vfs_seek( m_handle, GNOME_VFS_SEEK_START, location ); 213 214 if (result == GNOME_VFS_ERROR_EOF) 215 throw ::com::sun::star::lang::IllegalArgumentException(); 216 217 throwOnError( result ); 218 } 219 220 sal_Int64 SAL_CALL Stream::getPosition() 221 throw( IOException, 222 RuntimeException ) 223 { 224 GnomeVFSFileSize nBytesIn = 0; 225 226 if( ! m_handle ) 227 throw IOException(); 228 229 throwOnError( gnome_vfs_tell( m_handle, &nBytesIn ) ); 230 231 return nBytesIn; 232 } 233 234 sal_Int64 SAL_CALL Stream::getLength() 235 throw( IOException, RuntimeException ) 236 { 237 // FIXME: so this sucks; it may be stale but ... 238 if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) 239 return m_info.size; 240 else { 241 g_warning ("FIXME: No valid length"); 242 return 0; 243 } 244 } 245 246 // ------------------------------------------------------------------- 247 // XTruncate 248 // ------------------------------------------------------------------- 249 250 void SAL_CALL Stream::truncate( void ) 251 throw( com::sun::star::io::IOException, 252 com::sun::star::uno::RuntimeException ) 253 { 254 if( ! m_handle ) 255 throw IOException(); 256 257 throwOnError( gnome_vfs_truncate_handle( m_handle, 0 ) ); 258 } 259 260 // ------------------------------------------------------------------- 261 // XOutputStream 262 // ------------------------------------------------------------------- 263 264 void SAL_CALL Stream::writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData ) 265 throw( com::sun::star::io::NotConnectedException, 266 com::sun::star::io::BufferSizeExceededException, 267 com::sun::star::io::IOException, 268 com::sun::star::uno::RuntimeException) 269 { 270 GnomeVFSResult result = GNOME_VFS_OK; 271 GnomeVFSFileSize toWrite = aData.getLength(); 272 const sal_Int8 *p = aData.getConstArray(); 273 274 if( ! m_handle ) 275 throw IOException(); 276 277 while( toWrite > 0) { 278 GnomeVFSFileSize bytesWritten = 0; 279 280 result = gnome_vfs_write( m_handle, p, toWrite, &bytesWritten ); 281 if( result == GNOME_VFS_ERROR_INTERRUPTED ) 282 continue; 283 throwOnError( result ); 284 g_assert( bytesWritten <= toWrite ); 285 toWrite -= bytesWritten; 286 p += bytesWritten; 287 } 288 } 289 290 void SAL_CALL Stream::flush( void ) 291 throw( NotConnectedException, BufferSizeExceededException, 292 IOException, RuntimeException ) 293 { 294 } 295 296 void SAL_CALL Stream::closeOutput( void ) 297 throw( com::sun::star::io::NotConnectedException, 298 com::sun::star::io::IOException, 299 com::sun::star::uno::RuntimeException ) 300 { 301 osl::MutexGuard aGuard( m_aMutex ); 302 m_bOutputStreamCalled = false; 303 304 if( ! m_bInputStreamCalled ) 305 closeStream(); 306 } 307 308 // ------------------------------------------------------------------- 309 // Misc. 310 // ------------------------------------------------------------------- 311 312 void Stream::closeStream( void ) 313 throw( ::com::sun::star::io::NotConnectedException, 314 ::com::sun::star::io::IOException, 315 ::com::sun::star::uno::RuntimeException ) 316 { 317 if (m_handle) { 318 gnome_vfs_close (m_handle); 319 m_handle = NULL; 320 } else 321 throw IOException(); 322 } 323 324 void Stream::throwOnError( GnomeVFSResult result ) 325 throw( NotConnectedException, 326 BufferSizeExceededException, 327 IOException, 328 RuntimeException ) 329 { 330 if( result != GNOME_VFS_OK ) { 331 ::rtl::OUString aMsg = ::rtl::OUString::createFromAscii 332 ( gnome_vfs_result_to_string( result ) ); 333 334 g_warning( "Input Stream exceptional result '%s' (%d)", 335 gnome_vfs_result_to_string( result ), result ); 336 337 throw IOException( aMsg, static_cast< cppu::OWeakObject * >( this ) ); 338 } 339 } 340