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