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