global.cpp
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2000 David Faure <faure@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License version 2 as published by the Free Software Foundation. 00007 00008 This library is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 Library General Public License for more details. 00012 00013 You should have received a copy of the GNU Library General Public License 00014 along with this library; see the file COPYING.LIB. If not, write to 00015 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00016 Boston, MA 02110-1301, USA. 00017 */ 00018 00019 #include <config.h> 00020 00021 #include <sys/types.h> 00022 #include <sys/wait.h> 00023 #include <sys/uio.h> 00024 00025 #include <assert.h> 00026 #include <signal.h> 00027 #include <stdlib.h> 00028 #include <string.h> 00029 #include <unistd.h> 00030 #include <stdio.h> 00031 00032 #include "tdeio/global.h" 00033 #include "tdeio/job.h" 00034 00035 #include <kdebug.h> 00036 #include <tdelocale.h> 00037 #include <tdeglobal.h> 00038 #include <tdeprotocolmanager.h> 00039 #include <kde_file.h> 00040 00041 #ifdef HAVE_VOLMGT 00042 #include <volmgt.h> 00043 #endif 00044 00045 TDEIO_EXPORT TQString TDEIO::convertSizeWithBytes( TDEIO::filesize_t size ) 00046 { 00047 if ( size >= 1024 ) 00048 return convertSize( size ) + " (" + i18n( "%1 B" ).arg( TDEGlobal::locale()->formatNumber(size, 0) ) + ")"; 00049 else 00050 return convertSize( size ); 00051 } 00052 00053 TDEIO_EXPORT TQString TDEIO::convertSize( TDEIO::filesize_t size ) 00054 { 00055 double fsize = size; 00056 TQString s; 00057 // Giga-byte 00058 if ( size >= 1073741824 ) 00059 { 00060 fsize /= 1073741824.0; 00061 if ( fsize > 1024 ) // Tera-byte 00062 s = i18n( "%1 TB" ).arg( TDEGlobal::locale()->formatNumber(fsize / 1024.0, 1)); 00063 else 00064 s = i18n( "%1 GB" ).arg( TDEGlobal::locale()->formatNumber(fsize, 1)); 00065 } 00066 // Mega-byte 00067 else if ( size >= 1048576 ) 00068 { 00069 fsize /= 1048576.0; 00070 s = i18n( "%1 MB" ).arg( TDEGlobal::locale()->formatNumber(fsize, 1)); 00071 } 00072 // Kilo-byte 00073 else if ( size >= 1024 ) 00074 { 00075 fsize /= 1024.0; 00076 s = i18n( "%1 KB" ).arg( TDEGlobal::locale()->formatNumber(fsize, 1)); 00077 } 00078 // Just byte 00079 else if ( size > 0 ) 00080 { 00081 s = i18n( "%1 B" ).arg( TDEGlobal::locale()->formatNumber(fsize, 0)); 00082 } 00083 // Nothing 00084 else 00085 { 00086 s = i18n( "0 B" ); 00087 } 00088 return s; 00089 } 00090 00091 TDEIO_EXPORT TQString TDEIO::convertSizeFromKB( TDEIO::filesize_t kbSize ) 00092 { 00093 return convertSize(kbSize * 1024); 00094 } 00095 00096 TDEIO_EXPORT TQString TDEIO::number( TDEIO::filesize_t size ) 00097 { 00098 char charbuf[256]; 00099 sprintf(charbuf, "%lld", size); 00100 return TQString::fromLatin1(charbuf); 00101 } 00102 00103 TDEIO_EXPORT unsigned int TDEIO::calculateRemainingSeconds( TDEIO::filesize_t totalSize, 00104 TDEIO::filesize_t processedSize, TDEIO::filesize_t speed ) 00105 { 00106 if ( (speed != 0) && (totalSize != 0) ) 00107 return ( totalSize - processedSize ) / speed; 00108 else 00109 return 0; 00110 } 00111 00112 TDEIO_EXPORT TQString TDEIO::convertSeconds( unsigned int seconds ) 00113 { 00114 unsigned int days = seconds / 86400; 00115 unsigned int hours = (seconds - (days * 86400)) / 3600; 00116 unsigned int mins = (seconds - (days * 86400) - (hours * 3600)) / 60; 00117 seconds = (seconds - (days * 86400) - (hours * 3600) - (mins * 60)); 00118 00119 const TQTime time(hours, mins, seconds); 00120 const TQString timeStr( TDEGlobal::locale()->formatTime(time, true /*with seconds*/, true /*duration*/) ); 00121 if ( days > 0 ) 00122 return i18n("1 day %1", "%n days %1", days).arg(timeStr); 00123 else 00124 return timeStr; 00125 } 00126 00127 TDEIO_EXPORT TQTime TDEIO::calculateRemaining( TDEIO::filesize_t totalSize, TDEIO::filesize_t processedSize, TDEIO::filesize_t speed ) 00128 { 00129 TQTime remainingTime; 00130 00131 if ( speed != 0 ) { 00132 TDEIO::filesize_t secs; 00133 if ( totalSize == 0 ) { 00134 secs = 0; 00135 } else { 00136 secs = ( totalSize - processedSize ) / speed; 00137 } 00138 if (secs >= (24*60*60)) // Limit to 23:59:59 00139 secs = (24*60*60)-1; 00140 int hr = secs / ( 60 * 60 ); 00141 int mn = ( secs - hr * 60 * 60 ) / 60; 00142 int sc = ( secs - hr * 60 * 60 - mn * 60 ); 00143 00144 remainingTime.setHMS( hr, mn, sc ); 00145 } 00146 00147 return remainingTime; 00148 } 00149 00150 TDEIO_EXPORT TQString TDEIO::itemsSummaryString(uint items, uint files, uint dirs, TDEIO::filesize_t size, bool showSize) 00151 { 00152 TQString text = items == 0 ? i18n( "No Items" ) : i18n( "One Item", "%n Items", items ); 00153 text += " - "; 00154 text += files == 0 ? i18n( "No Files" ) : i18n( "One File", "%n Files", files ); 00155 if ( showSize && files > 0 ) 00156 { 00157 text += " "; 00158 text += i18n("(%1 Total)").arg(TDEIO::convertSize( size ) ); 00159 } 00160 text += " - "; 00161 text += dirs == 0 ? i18n( "No Folders" ) : i18n("One Folder", "%n Folders", dirs); 00162 return text; 00163 } 00164 00165 TDEIO_EXPORT TQString TDEIO::encodeFileName( const TQString & _str ) 00166 { 00167 TQString str( _str ); 00168 bool unicode_supported = (TQString::fromLocal8Bit(TQString(TQChar((uint)0x2215)).local8Bit())[0].unicode() != 0x3f); 00169 00170 int i = 0; 00171 while ( ( i = str.find( "%", i ) ) != -1 ) { 00172 str.replace( i, 1, "%%"); 00173 i += 2; 00174 } 00175 while ( ( i = str.find( "/" ) ) != -1 ) { 00176 if (unicode_supported) { 00177 // Use U+2215 (DIVISION SLASH) to represent the forward slash 00178 // While U+2044 (FRACTION SLASH) is a tempting replacement, it can indicate to 00179 // rendering engines that a combined fraction character should be displayed 00180 str.replace( i, 1, TQChar((uint)0x2215)); 00181 } 00182 else { 00183 // Unicode does not appear to be supported on this system! 00184 // Fall back to older encoding method... 00185 str.replace( i, 1, "%2f"); 00186 } 00187 } 00188 return str; 00189 } 00190 00191 TDEIO_EXPORT TQString TDEIO::decodeFileName( const TQString & _str ) 00192 { 00193 TQString str; 00194 bool unicode_supported = (TQString::fromLocal8Bit(TQString(TQChar((uint)0x2215)).local8Bit())[0].unicode() != 0x3f); 00195 00196 unsigned int i = 0; 00197 for ( ; i < _str.length() ; ++i ) { 00198 if ( _str[i]=='%' ) { 00199 if ( _str[i+1]=='%' ) // %% -> % 00200 { 00201 str.append('%'); 00202 ++i; 00203 } 00204 else if ((!unicode_supported) && ( _str[i+1]=='2' && (i+2<_str.length()) && _str[i+2].lower()=='f' )) // %2f -> / 00205 { 00206 str.append('/'); 00207 i += 2; 00208 } 00209 else 00210 { 00211 str.append('%'); 00212 } 00213 } 00214 else if ( _str[i] == TQChar((uint)0x2215) ) { 00215 str.append('/'); 00216 } 00217 else { 00218 str.append(_str[i]); 00219 } 00220 } 00221 00222 return str; 00223 } 00224 00225 TDEIO_EXPORT TQString TDEIO::Job::errorString() const 00226 { 00227 return TDEIO::buildErrorString(m_error, m_errorText); 00228 } 00229 00230 TDEIO_EXPORT TQString TDEIO::buildErrorString(int errorCode, const TQString &errorText) 00231 { 00232 TQString result; 00233 00234 switch( errorCode ) 00235 { 00236 case TDEIO::ERR_CANNOT_OPEN_FOR_READING: 00237 result = i18n( "Could not read %1." ).arg( errorText ); 00238 break; 00239 case TDEIO::ERR_CANNOT_OPEN_FOR_WRITING: 00240 result = i18n( "Could not write to %1." ).arg( errorText ); 00241 break; 00242 case TDEIO::ERR_CANNOT_LAUNCH_PROCESS: 00243 result = i18n( "Could not start process %1." ).arg( errorText ); 00244 break; 00245 case TDEIO::ERR_INTERNAL: 00246 result = i18n( "Internal Error\nPlease send a full bug report at http://bugs.trinitydesktop.org\n%1" ).arg( errorText ); 00247 break; 00248 case TDEIO::ERR_MALFORMED_URL: 00249 result = i18n( "Malformed URL %1." ).arg( errorText ); 00250 break; 00251 case TDEIO::ERR_UNSUPPORTED_PROTOCOL: 00252 result = i18n( "The protocol %1 is not supported." ).arg( errorText ); 00253 break; 00254 case TDEIO::ERR_NO_SOURCE_PROTOCOL: 00255 result = i18n( "The protocol %1 is only a filter protocol.").arg( errorText ); 00256 break; 00257 case TDEIO::ERR_UNSUPPORTED_ACTION: 00258 result = errorText; 00259 // result = i18n( "Unsupported action %1" ).arg( errorText ); 00260 break; 00261 case TDEIO::ERR_IS_DIRECTORY: 00262 result = i18n( "%1 is a folder, but a file was expected." ).arg( errorText ); 00263 break; 00264 case TDEIO::ERR_IS_FILE: 00265 result = i18n( "%1 is a file, but a folder was expected." ).arg( errorText ); 00266 break; 00267 case TDEIO::ERR_DOES_NOT_EXIST: 00268 result = i18n( "The file or folder %1 does not exist." ).arg( errorText ); 00269 break; 00270 case TDEIO::ERR_FILE_ALREADY_EXIST: 00271 result = i18n( "A file named %1 already exists." ).arg( errorText ); 00272 break; 00273 case TDEIO::ERR_DIR_ALREADY_EXIST: 00274 result = i18n( "A folder named %1 already exists." ).arg( errorText ); 00275 break; 00276 case TDEIO::ERR_UNKNOWN_HOST: 00277 result = errorText.isEmpty() ? i18n( "No hostname specified." ) : i18n( "Unknown host %1" ).arg( errorText ); 00278 break; 00279 case TDEIO::ERR_ACCESS_DENIED: 00280 result = i18n( "Access denied to %1." ).arg( errorText ); 00281 break; 00282 case TDEIO::ERR_WRITE_ACCESS_DENIED: 00283 result = i18n( "Access denied.\nCould not write to %1." ).arg( errorText ); 00284 break; 00285 case TDEIO::ERR_CANNOT_ENTER_DIRECTORY: 00286 result = i18n( "Could not enter folder %1." ).arg( errorText ); 00287 break; 00288 case TDEIO::ERR_PROTOCOL_IS_NOT_A_FILESYSTEM: 00289 result = i18n( "The protocol %1 does not implement a folder service." ).arg( errorText ); 00290 break; 00291 case TDEIO::ERR_CYCLIC_LINK: 00292 result = i18n( "Found a cyclic link in %1." ).arg( errorText ); 00293 break; 00294 case TDEIO::ERR_USER_CANCELED: 00295 // Do nothing in this case. The user doesn't need to be told what he just did. 00296 break; 00297 case TDEIO::ERR_CYCLIC_COPY: 00298 result = i18n( "Found a cyclic link while copying %1." ).arg( errorText ); 00299 break; 00300 case TDEIO::ERR_COULD_NOT_CREATE_SOCKET: 00301 result = i18n( "Could not create socket for accessing %1." ).arg( errorText ); 00302 break; 00303 case TDEIO::ERR_COULD_NOT_CONNECT: 00304 result = i18n( "Could not connect to host %1." ).arg( errorText.isEmpty() ? TQString::fromLatin1("localhost") : errorText ); 00305 break; 00306 case TDEIO::ERR_CONNECTION_BROKEN: 00307 result = i18n( "Connection to host %1 is broken." ).arg( errorText ); 00308 break; 00309 case TDEIO::ERR_NOT_FILTER_PROTOCOL: 00310 result = i18n( "The protocol %1 is not a filter protocol." ).arg( errorText ); 00311 break; 00312 case TDEIO::ERR_COULD_NOT_MOUNT: 00313 result = i18n( "Could not mount device.\nThe reported error was:\n%1" ).arg( errorText ); 00314 break; 00315 case TDEIO::ERR_COULD_NOT_UNMOUNT: 00316 result = i18n( "Could not unmount device.\nThe reported error was:\n%1" ).arg( errorText ); 00317 break; 00318 case TDEIO::ERR_COULD_NOT_READ: 00319 result = i18n( "Could not read file %1." ).arg( errorText ); 00320 break; 00321 case TDEIO::ERR_COULD_NOT_WRITE: 00322 result = i18n( "Could not write to file %1." ).arg( errorText ); 00323 break; 00324 case TDEIO::ERR_COULD_NOT_BIND: 00325 result = i18n( "Could not bind %1." ).arg( errorText ); 00326 break; 00327 case TDEIO::ERR_COULD_NOT_LISTEN: 00328 result = i18n( "Could not listen %1." ).arg( errorText ); 00329 break; 00330 case TDEIO::ERR_COULD_NOT_ACCEPT: 00331 result = i18n( "Could not accept %1." ).arg( errorText ); 00332 break; 00333 case TDEIO::ERR_COULD_NOT_LOGIN: 00334 result = errorText; 00335 break; 00336 case TDEIO::ERR_COULD_NOT_STAT: 00337 result = i18n( "Could not access %1." ).arg( errorText ); 00338 break; 00339 case TDEIO::ERR_COULD_NOT_CLOSEDIR: 00340 result = i18n( "Could not terminate listing %1." ).arg( errorText ); 00341 break; 00342 case TDEIO::ERR_COULD_NOT_MKDIR: 00343 result = i18n( "Could not make folder %1." ).arg( errorText ); 00344 break; 00345 case TDEIO::ERR_COULD_NOT_RMDIR: 00346 result = i18n( "Could not remove folder %1." ).arg( errorText ); 00347 break; 00348 case TDEIO::ERR_CANNOT_RESUME: 00349 result = i18n( "Could not resume file %1." ).arg( errorText ); 00350 break; 00351 case TDEIO::ERR_CANNOT_RENAME: 00352 result = i18n( "Could not rename file %1." ).arg( errorText ); 00353 break; 00354 case TDEIO::ERR_CANNOT_CHMOD: 00355 result = i18n( "Could not change permissions for %1." ).arg( errorText ); 00356 break; 00357 case TDEIO::ERR_CANNOT_DELETE: 00358 result = i18n( "Could not delete file %1." ).arg( errorText ); 00359 break; 00360 case TDEIO::ERR_SLAVE_DIED: 00361 result = i18n( "The process for the %1 protocol died unexpectedly." ).arg( errorText ); 00362 break; 00363 case TDEIO::ERR_OUT_OF_MEMORY: 00364 result = i18n( "Error. Out of memory.\n%1" ).arg( errorText ); 00365 break; 00366 case TDEIO::ERR_UNKNOWN_PROXY_HOST: 00367 result = i18n( "Unknown proxy host\n%1" ).arg( errorText ); 00368 break; 00369 case TDEIO::ERR_COULD_NOT_AUTHENTICATE: 00370 result = i18n( "Authorization failed, %1 authentication not supported" ).arg( errorText ); 00371 break; 00372 case TDEIO::ERR_ABORTED: 00373 result = i18n( "User canceled action\n%1" ).arg( errorText ); 00374 break; 00375 case TDEIO::ERR_INTERNAL_SERVER: 00376 result = i18n( "Internal error in server\n%1" ).arg( errorText ); 00377 break; 00378 case TDEIO::ERR_SERVER_TIMEOUT: 00379 result = i18n( "Timeout on server\n%1" ).arg( errorText ); 00380 break; 00381 case TDEIO::ERR_UNKNOWN: 00382 result = i18n( "Unknown error\n%1" ).arg( errorText ); 00383 break; 00384 case TDEIO::ERR_UNKNOWN_INTERRUPT: 00385 result = i18n( "Unknown interrupt\n%1" ).arg( errorText ); 00386 break; 00387 /* 00388 case TDEIO::ERR_CHECKSUM_MISMATCH: 00389 if (errorText) 00390 result = i18n( "Warning: MD5 Checksum for %1 does not match checksum returned from server" ).arg(errorText); 00391 else 00392 result = i18n( "Warning: MD5 Checksum for %1 does not match checksum returned from server" ).arg("document"); 00393 break; 00394 */ 00395 case TDEIO::ERR_CANNOT_DELETE_ORIGINAL: 00396 result = i18n( "Could not delete original file %1.\nPlease check permissions." ).arg( errorText ); 00397 break; 00398 case TDEIO::ERR_CANNOT_DELETE_PARTIAL: 00399 result = i18n( "Could not delete partial file %1.\nPlease check permissions." ).arg( errorText ); 00400 break; 00401 case TDEIO::ERR_CANNOT_RENAME_ORIGINAL: 00402 result = i18n( "Could not rename original file %1.\nPlease check permissions." ).arg( errorText ); 00403 break; 00404 case TDEIO::ERR_CANNOT_RENAME_PARTIAL: 00405 result = i18n( "Could not rename partial file %1.\nPlease check permissions." ).arg( errorText ); 00406 break; 00407 case TDEIO::ERR_CANNOT_SYMLINK: 00408 result = i18n( "Could not create symlink %1.\nPlease check permissions." ).arg( errorText ); 00409 break; 00410 case TDEIO::ERR_NO_CONTENT: 00411 result = errorText; 00412 break; 00413 case TDEIO::ERR_DISK_FULL: 00414 result = i18n( "Could not write file %1.\nDisk full." ).arg( errorText ); 00415 break; 00416 case TDEIO::ERR_IDENTICAL_FILES: 00417 result = i18n( "The source and destination are the same file.\n%1" ).arg( errorText ); 00418 break; 00419 case TDEIO::ERR_SLAVE_DEFINED: 00420 result = errorText; 00421 break; 00422 case TDEIO::ERR_UPGRADE_REQUIRED: 00423 result = i18n( "%1 is required by the server, but is not available." ).arg(errorText); 00424 break; 00425 case TDEIO::ERR_POST_DENIED: 00426 result = i18n( "Access to restricted port in POST denied."); 00427 break; 00428 case TDEIO::ERR_OFFLINE_MODE: 00429 result = i18n( "Could not access %1.\nOffline mode active.").arg( errorText ); 00430 break; 00431 default: 00432 result = i18n( "Unknown error code %1\n%2\nPlease send a full bug report at http://bugs.trinitydesktop.org." ).arg( errorCode ).arg( errorText ); 00433 break; 00434 } 00435 00436 return result; 00437 } 00438 00439 TDEIO_EXPORT TQString TDEIO::unsupportedActionErrorString(const TQString &protocol, int cmd) { 00440 switch (cmd) { 00441 case CMD_CONNECT: 00442 return i18n("Opening connections is not supported with the protocol %1." ).arg(protocol); 00443 case CMD_DISCONNECT: 00444 return i18n("Closing connections is not supported with the protocol %1." ).arg(protocol); 00445 case CMD_STAT: 00446 return i18n("Accessing files is not supported with the protocol %1.").arg(protocol); 00447 case CMD_PUT: 00448 return i18n("Writing to %1 is not supported.").arg(protocol); 00449 case CMD_SPECIAL: 00450 return i18n("There are no special actions available for protocol %1.").arg(protocol); 00451 case CMD_LISTDIR: 00452 return i18n("Listing folders is not supported for protocol %1.").arg(protocol); 00453 case CMD_GET: 00454 return i18n("Retrieving data from %1 is not supported.").arg(protocol); 00455 case CMD_MIMETYPE: 00456 return i18n("Retrieving mime type information from %1 is not supported.").arg(protocol); 00457 case CMD_RENAME: 00458 return i18n("Renaming or moving files within %1 is not supported.").arg(protocol); 00459 case CMD_SYMLINK: 00460 return i18n("Creating symlinks is not supported with protocol %1.").arg(protocol); 00461 case CMD_COPY: 00462 return i18n("Copying files within %1 is not supported.").arg(protocol); 00463 case CMD_DEL: 00464 return i18n("Deleting files from %1 is not supported.").arg(protocol); 00465 case CMD_MKDIR: 00466 return i18n("Creating folders is not supported with protocol %1.").arg(protocol); 00467 case CMD_CHMOD: 00468 return i18n("Changing the attributes of files is not supported with protocol %1.").arg(protocol); 00469 case CMD_SUBURL: 00470 return i18n("Using sub-URLs with %1 is not supported.").arg(protocol); 00471 case CMD_MULTI_GET: 00472 return i18n("Multiple get is not supported with protocol %1.").arg(protocol); 00473 default: 00474 return i18n("Protocol %1 does not support action %2.").arg(protocol).arg(cmd); 00475 }/*end switch*/ 00476 } 00477 00478 TDEIO_EXPORT TQStringList TDEIO::Job::detailedErrorStrings( const KURL *reqUrl /*= 0L*/, 00479 int method /*= -1*/ ) const 00480 { 00481 TQString errorName, techName, description, ret2; 00482 TQStringList causes, solutions, ret; 00483 00484 TQByteArray raw = rawErrorDetail( m_error, m_errorText, reqUrl, method ); 00485 TQDataStream stream(raw, IO_ReadOnly); 00486 00487 stream >> errorName >> techName >> description >> causes >> solutions; 00488 00489 TQString url, protocol, datetime; 00490 if ( reqUrl ) { 00491 url = reqUrl->htmlURL(); 00492 protocol = reqUrl->protocol(); 00493 } else { 00494 url = i18n( "(unknown)" ); 00495 } 00496 00497 datetime = TDEGlobal::locale()->formatDateTime( TQDateTime::currentDateTime(), 00498 false ); 00499 00500 ret << errorName; 00501 ret << TQString::fromLatin1( "<qt><p><b>" ) + errorName + 00502 TQString::fromLatin1( "</b></p><p>" ) + description + 00503 TQString::fromLatin1( "</p>" ); 00504 ret2 = TQString::fromLatin1( "<qt><p>" ); 00505 if ( !techName.isEmpty() ) 00506 ret2 += i18n( "<b>Technical reason</b>: " ) + techName + TQString::fromLatin1( "</p>" ); 00507 ret2 += i18n( "</p><p><b>Details of the request</b>:" ); 00508 ret2 += i18n( "</p><ul><li>URL: %1</li>" ).arg( url ); 00509 if ( !protocol.isEmpty() ) { 00510 ret2 += i18n( "<li>Protocol: %1</li>" ).arg( protocol ); 00511 } 00512 ret2 += i18n( "<li>Date and time: %1</li>" ).arg( datetime ); 00513 ret2 += i18n( "<li>Additional information: %1</li></ul>" ).arg( m_errorText ); 00514 if ( !causes.isEmpty() ) { 00515 ret2 += i18n( "<p><b>Possible causes</b>:</p><ul><li>" ); 00516 ret2 += causes.join( "</li><li>" ); 00517 ret2 += TQString::fromLatin1( "</li></ul>" ); 00518 } 00519 if ( !solutions.isEmpty() ) { 00520 ret2 += i18n( "<p><b>Possible solutions</b>:</p><ul><li>" ); 00521 ret2 += solutions.join( "</li><li>" ); 00522 ret2 += TQString::fromLatin1( "</li></ul>" ); 00523 } 00524 ret << ret2; 00525 return ret; 00526 } 00527 00528 TDEIO_EXPORT TQByteArray TDEIO::rawErrorDetail(int errorCode, const TQString &errorText, 00529 const KURL *reqUrl /*= 0L*/, int /*method = -1*/ ) 00530 { 00531 TQString url, host, protocol, datetime, domain, path, dir, filename; 00532 bool isSlaveNetwork = false; 00533 if ( reqUrl ) { 00534 url = reqUrl->prettyURL(); 00535 host = reqUrl->host(); 00536 protocol = reqUrl->protocol(); 00537 00538 if ( host.left(4) == "www." ) 00539 domain = host.mid(4); 00540 else 00541 domain = host; 00542 00543 path = reqUrl->path(1); 00544 filename = reqUrl->fileName(); 00545 dir = path + filename; 00546 00547 // detect if protocol is a network protocol... 00548 // add your hacks here... 00549 if ( protocol == "http" || 00550 protocol == "https" || 00551 protocol == "ftp" || 00552 protocol == "sftp" || 00553 protocol == "webdav" || 00554 protocol == "webdavs" || 00555 protocol == "finger" || 00556 protocol == "fish" || 00557 protocol == "gopher" || 00558 protocol == "imap" || 00559 protocol == "imaps" || 00560 protocol == "lan" || 00561 protocol == "ldap" || 00562 protocol == "mailto" || 00563 protocol == "news" || 00564 protocol == "nntp" || 00565 protocol == "pop3" || 00566 protocol == "pop3s" || 00567 protocol == "smtp" || 00568 protocol == "smtps" || 00569 protocol == "telnet" 00570 ) { 00571 isSlaveNetwork = false; 00572 } 00573 } else { 00574 // assume that the errorText has the location we are interested in 00575 url = host = domain = path = filename = dir = errorText; 00576 protocol = i18n( "(unknown)" ); 00577 } 00578 00579 datetime = TDEGlobal::locale()->formatDateTime( TQDateTime::currentDateTime(), 00580 false ); 00581 00582 TQString errorName, techName, description; 00583 TQStringList causes, solutions; 00584 00585 // c == cause, s == solution 00586 TQString sSysadmin = i18n( "Contact your appropriate computer support system, " 00587 "whether the system administrator, or technical support group for further " 00588 "assistance." ); 00589 TQString sServeradmin = i18n( "Contact the administrator of the server " 00590 "for further assistance." ); 00591 // FIXME active link to permissions dialog 00592 TQString sAccess = i18n( "Check your access permissions on this resource." ); 00593 TQString cAccess = i18n( "Your access permissions may be inadequate to " 00594 "perform the requested operation on this resource." ); 00595 TQString cLocked = i18n( "The file may be in use (and thus locked) by " 00596 "another user or application." ); 00597 TQString sQuerylock = i18n( "Check to make sure that no other " 00598 "application or user is using the file or has locked the file." ); 00599 TQString cHardware = i18n( "Although unlikely, a hardware error may have " 00600 "occurred." ); 00601 TQString cBug = i18n( "You may have encountered a bug in the program." ); 00602 TQString cBuglikely = i18n( "This is most likely to be caused by a bug in the " 00603 "program. Please consider submitting a full bug report as detailed below." ); 00604 TQString sUpdate = i18n( "Update your software to the latest version. " 00605 "Your distribution should provide tools to update your software." ); 00606 TQString sBugreport = i18n( "When all else fails, please consider helping the " 00607 "TDE team or the third party maintainer of this software by submitting a " 00608 "high quality bug report. If the software is provided by a third party, " 00609 "please contact them directly. Otherwise, first look to see if " 00610 "the same bug has been submitted by someone else by searching at the " 00611 "<a href=\"http://bugs.trinitydesktop.org/\">TDE bug reporting website</a>. If not, take " 00612 "note of the details given above, and include them in your bug report, along " 00613 "with as many other details as you think might help." ); 00614 TQString cNetwork = i18n( "There may have been a problem with your network " 00615 "connection." ); 00616 // FIXME netconf kcontrol link 00617 TQString cNetconf = i18n( "There may have been a problem with your network " 00618 "configuration. If you have been accessing the Internet with no problems " 00619 "recently, this is unlikely." ); 00620 TQString cNetpath = i18n( "There may have been a problem at some point along " 00621 "the network path between the server and this computer." ); 00622 TQString sTryagain = i18n( "Try again, either now or at a later time." ); 00623 TQString cProtocol = i18n( "A protocol error or incompatibility may have occurred." ); 00624 TQString sExists = i18n( "Ensure that the resource exists, and try again." ); 00625 TQString cExists = i18n( "The specified resource may not exist." ); 00626 TQString cTypo = i18n( "You may have incorrectly typed the location." ); 00627 TQString sTypo = i18n( "Double-check that you have entered the correct location " 00628 "and try again." ); 00629 TQString sNetwork = i18n( "Check your network connection status." ); 00630 00631 switch( errorCode ) { 00632 case TDEIO::ERR_CANNOT_OPEN_FOR_READING: 00633 errorName = i18n( "Cannot Open Resource For Reading" ); 00634 description = i18n( "This means that the contents of the requested file " 00635 "or folder <strong>%1</strong> could not be retrieved, as read " 00636 "access could not be obtained." ).arg( dir ); 00637 causes << i18n( "You may not have permissions to read the file or open " 00638 "the folder.") << cLocked << cHardware; 00639 solutions << sAccess << sQuerylock << sSysadmin; 00640 break; 00641 00642 case TDEIO::ERR_CANNOT_OPEN_FOR_WRITING: 00643 errorName = i18n( "Cannot Open Resource For Writing" ); 00644 description = i18n( "This means that the file, <strong>%1</strong>, could " 00645 "not be written to as requested, because access with permission to " 00646 "write could not be obtained." ).arg( filename ); 00647 causes << cAccess << cLocked << cHardware; 00648 solutions << sAccess << sQuerylock << sSysadmin; 00649 break; 00650 00651 case TDEIO::ERR_CANNOT_LAUNCH_PROCESS: 00652 errorName = i18n( "Cannot Initiate the %1 Protocol" ).arg( protocol ); 00653 techName = i18n( "Unable to Launch Process" ); 00654 description = i18n( "The program on your computer which provides access " 00655 "to the <strong>%1</strong> protocol could not be started. This is " 00656 "usually due to technical reasons." ).arg( protocol ); 00657 causes << i18n( "The program which provides compatibility with this " 00658 "protocol may not have been updated with your last update of TDE. " 00659 "This can cause the program to be incompatible with the current version " 00660 "and thus not start." ) << cBug; 00661 solutions << sUpdate << sSysadmin; 00662 break; 00663 00664 case TDEIO::ERR_INTERNAL: 00665 errorName = i18n( "Internal Error" ); 00666 description = i18n( "The program on your computer which provides access " 00667 "to the <strong>%1</strong> protocol has reported an internal error." ) 00668 .arg( protocol ); 00669 causes << cBuglikely; 00670 solutions << sUpdate << sBugreport; 00671 break; 00672 00673 case TDEIO::ERR_MALFORMED_URL: 00674 errorName = i18n( "Improperly Formatted URL" ); 00675 description = i18n( "The <strong>U</strong>niform <strong>R</strong>esource " 00676 "<strong>L</strong>ocator (URL) that you entered was not properly " 00677 "formatted. The format of a URL is generally as follows:" 00678 "<blockquote><strong>protocol://user:password@www.example.org:port/folder/" 00679 "filename.extension?query=value</strong></blockquote>" ); 00680 solutions << sTypo; 00681 break; 00682 00683 case TDEIO::ERR_UNSUPPORTED_PROTOCOL: 00684 errorName = i18n( "Unsupported Protocol %1" ).arg( protocol ); 00685 description = i18n( "The protocol <strong>%1</strong> is not supported " 00686 "by the TDE programs currently installed on this computer." ) 00687 .arg( protocol ); 00688 causes << i18n( "The requested protocol may not be supported." ) 00689 << i18n( "The versions of the %1 protocol supported by this computer and " 00690 "the server may be incompatible." ).arg( protocol ); 00691 solutions << i18n( "You may perform a search on the Trinity website for a TDE " 00692 "program (called a tdeioslave, ioslave or tdeio) which supports this protocol. " 00693 "Places to search include <a href=\"https://mirror.git.trinitydesktop.org/cgit/\">" 00694 "https://mirror.git.trinitydesktop.org/cgit/</a> or the repos for your distribution." ) 00695 << sUpdate << sSysadmin; 00696 break; 00697 00698 case TDEIO::ERR_NO_SOURCE_PROTOCOL: 00699 errorName = i18n( "URL Does Not Refer to a Resource." ); 00700 techName = i18n( "Protocol is a Filter Protocol" ); 00701 description = i18n( "The <strong>U</strong>niform <strong>R</strong>esource " 00702 "<strong>L</strong>ocator (URL) that you entered did not refer to a " 00703 "specific resource." ); 00704 causes << i18n( "TDE is able to communicate through a protocol within a " 00705 "protocol; the protocol specified is only for use in such situations, " 00706 "however this is not one of these situations. This is a rare event, and " 00707 "is likely to indicate a programming error." ); 00708 solutions << sTypo; 00709 break; 00710 00711 case TDEIO::ERR_UNSUPPORTED_ACTION: 00712 errorName = i18n( "Unsupported Action: %1" ).arg( errorText ); 00713 description = i18n( "The requested action is not supported by the TDE " 00714 "program which is implementing the <strong>%1</strong> protocol." ) 00715 .arg( protocol ); 00716 causes << i18n( "This error is very much dependent on the TDE program. The " 00717 "additional information should give you more information than is available " 00718 "to the TDE input/output architecture." ); 00719 solutions << i18n( "Attempt to find another way to accomplish the same " 00720 "outcome." ); 00721 break; 00722 00723 case TDEIO::ERR_IS_DIRECTORY: 00724 errorName = i18n( "File Expected" ); 00725 description = i18n( "The request expected a file, however the " 00726 "folder <strong>%1</strong> was found instead." ).arg( dir ); 00727 causes << i18n( "This may be an error on the server side." ) << cBug; 00728 solutions << sUpdate << sSysadmin; 00729 break; 00730 00731 case TDEIO::ERR_IS_FILE: 00732 errorName = i18n( "Folder Expected" ); 00733 description = i18n( "The request expected a folder, however " 00734 "the file <strong>%1</strong> was found instead." ).arg( filename ); 00735 causes << cBug; 00736 solutions << sUpdate << sSysadmin; 00737 break; 00738 00739 case TDEIO::ERR_DOES_NOT_EXIST: 00740 errorName = i18n( "File or Folder Does Not Exist" ); 00741 description = i18n( "The specified file or folder <strong>%1</strong> " 00742 "does not exist." ).arg( dir ); 00743 causes << cBug; 00744 solutions << sUpdate << sSysadmin; 00745 break; 00746 00747 case TDEIO::ERR_FILE_ALREADY_EXIST: 00748 errorName = i18n( "File Already Exists" ); 00749 description = i18n( "The requested file could not be created because a " 00750 "file with the same name already exists." ); 00751 solutions << i18n ( "Try moving the current file out of the way first, " 00752 "and then try again." ) 00753 << i18n ( "Delete the current file and try again." ) 00754 << i18n( "Choose an alternate filename for the new file." ); 00755 break; 00756 00757 case TDEIO::ERR_DIR_ALREADY_EXIST: 00758 errorName = i18n( "Folder Already Exists" ); 00759 description = i18n( "The requested folder could not be created because " 00760 "a folder with the same name already exists." ); 00761 solutions << i18n( "Try moving the current folder out of the way first, " 00762 "and then try again." ) 00763 << i18n( "Delete the current folder and try again." ) 00764 << i18n( "Choose an alternate name for the new folder." ); 00765 break; 00766 00767 case TDEIO::ERR_UNKNOWN_HOST: 00768 errorName = i18n( "Unknown Host" ); 00769 description = i18n( "An unknown host error indicates that the server with " 00770 "the requested name, <strong>%1</strong>, could not be " 00771 "located on the Internet." ).arg( host ); 00772 causes << i18n( "The name that you typed, %1, may not exist: it may be " 00773 "incorrectly typed." ).arg( host ) 00774 << cNetwork << cNetconf; 00775 solutions << sNetwork << sSysadmin; 00776 break; 00777 00778 case TDEIO::ERR_ACCESS_DENIED: 00779 errorName = i18n( "Access Denied" ); 00780 description = i18n( "Access was denied to the specified resource, " 00781 "<strong>%1</strong>." ).arg( url ); 00782 causes << i18n( "You may have supplied incorrect authentication details or " 00783 "none at all." ) 00784 << i18n( "Your account may not have permission to access the " 00785 "specified resource." ); 00786 solutions << i18n( "Retry the request and ensure your authentication details " 00787 "are entered correctly." ) << sSysadmin; 00788 if ( !isSlaveNetwork ) solutions << sServeradmin; 00789 break; 00790 00791 case TDEIO::ERR_WRITE_ACCESS_DENIED: 00792 errorName = i18n( "Write Access Denied" ); 00793 description = i18n( "This means that an attempt to write to the file " 00794 "<strong>%1</strong> was rejected." ).arg( filename ); 00795 causes << cAccess << cLocked << cHardware; 00796 solutions << sAccess << sQuerylock << sSysadmin; 00797 break; 00798 00799 case TDEIO::ERR_CANNOT_ENTER_DIRECTORY: 00800 errorName = i18n( "Unable to Enter Folder" ); 00801 description = i18n( "This means that an attempt to enter (in other words, " 00802 "to open) the requested folder <strong>%1</strong> was rejected." ) 00803 .arg( dir ); 00804 causes << cAccess << cLocked; 00805 solutions << sAccess << sQuerylock << sSysadmin; 00806 break; 00807 00808 case TDEIO::ERR_PROTOCOL_IS_NOT_A_FILESYSTEM: 00809 errorName = i18n( "Folder Listing Unavailable" ); 00810 techName = i18n( "Protocol %1 is not a Filesystem" ).arg( protocol ); 00811 description = i18n( "This means that a request was made which requires " 00812 "determining the contents of the folder, and the TDE program supporting " 00813 "this protocol is unable to do so." ); 00814 causes << cBug; 00815 solutions << sUpdate << sBugreport; 00816 break; 00817 00818 case TDEIO::ERR_CYCLIC_LINK: 00819 errorName = i18n( "Cyclic Link Detected" ); 00820 description = i18n( "UNIX environments are commonly able to link a file or " 00821 "folder to a separate name and/or location. TDE detected a link or " 00822 "series of links that results in an infinite loop - i.e. the file was " 00823 "(perhaps in a roundabout way) linked to itself." ); 00824 solutions << i18n( "Delete one part of the loop in order that it does not " 00825 "cause an infinite loop, and try again." ) << sSysadmin; 00826 break; 00827 00828 case TDEIO::ERR_USER_CANCELED: 00829 // Do nothing in this case. The user doesn't need to be told what he just did. 00830 // rodda: However, if we have been called, an application is about to display 00831 // this information anyway. If we don't return sensible information, the 00832 // user sees a blank dialog (I have seen this myself) 00833 errorName = i18n( "Request Aborted By User" ); 00834 description = i18n( "The request was not completed because it was " 00835 "aborted." ); 00836 solutions << i18n( "Retry the request." ); 00837 break; 00838 00839 case TDEIO::ERR_CYCLIC_COPY: 00840 errorName = i18n( "Cyclic Link Detected During Copy" ); 00841 description = i18n( "UNIX environments are commonly able to link a file or " 00842 "folder to a separate name and/or location. During the requested copy " 00843 "operation, TDE detected a link or series of links that results in an " 00844 "infinite loop - i.e. the file was (perhaps in a roundabout way) linked " 00845 "to itself." ); 00846 solutions << i18n( "Delete one part of the loop in order that it does not " 00847 "cause an infinite loop, and try again." ) << sSysadmin; 00848 break; 00849 00850 case TDEIO::ERR_COULD_NOT_CREATE_SOCKET: 00851 errorName = i18n( "Could Not Create Network Connection" ); 00852 techName = i18n( "Could Not Create Socket" ); 00853 description = i18n( "This is a fairly technical error in which a required " 00854 "device for network communications (a socket) could not be created." ); 00855 causes << i18n( "The network connection may be incorrectly configured, or " 00856 "the network interface may not be enabled." ); 00857 solutions << sNetwork << sSysadmin; 00858 break; 00859 00860 case TDEIO::ERR_COULD_NOT_CONNECT: 00861 errorName = i18n( "Connection to Server Refused" ); 00862 description = i18n( "The server <strong>%1</strong> refused to allow this " 00863 "computer to make a connection." ).arg( host ); 00864 causes << i18n( "The server, while currently connected to the Internet, " 00865 "may not be configured to allow requests." ) 00866 << i18n( "The server, while currently connected to the Internet, " 00867 "may not be running the requested service (%1)." ).arg( protocol ) 00868 << i18n( "A network firewall (a device which restricts Internet " 00869 "requests), either protecting your network or the network of the server, " 00870 "may have intervened, preventing this request." ); 00871 solutions << sTryagain << sServeradmin << sSysadmin; 00872 break; 00873 00874 case TDEIO::ERR_CONNECTION_BROKEN: 00875 errorName = i18n( "Connection to Server Closed Unexpectedly" ); 00876 description = i18n( "Although a connection was established to " 00877 "<strong>%1</strong>, the connection was closed at an unexpected point " 00878 "in the communication." ).arg( host ); 00879 causes << cNetwork << cNetpath << i18n( "A protocol error may have occurred, " 00880 "causing the server to close the connection as a response to the error." ); 00881 solutions << sTryagain << sServeradmin << sSysadmin; 00882 break; 00883 00884 case TDEIO::ERR_NOT_FILTER_PROTOCOL: 00885 errorName = i18n( "URL Resource Invalid" ); 00886 techName = i18n( "Protocol %1 is not a Filter Protocol" ).arg( protocol ); 00887 description = i18n( "The <strong>U</strong>niform <strong>R</strong>esource " 00888 "<strong>L</strong>ocator (URL) that you entered did not refer to " 00889 "a valid mechanism of accessing the specific resource, " 00890 "<strong>%1%2</strong>." ) 00891 .arg( !host.isNull() ? host + '/' : TQString::null ).arg( dir ); 00892 causes << i18n( "TDE is able to communicate through a protocol within a " 00893 "protocol. This request specified a protocol be used as such, however " 00894 "this protocol is not capable of such an action. This is a rare event, " 00895 "and is likely to indicate a programming error." ); 00896 solutions << sTypo << sSysadmin; 00897 break; 00898 00899 case TDEIO::ERR_COULD_NOT_MOUNT: 00900 errorName = i18n( "Unable to Initialize Input/Output Device" ); 00901 techName = i18n( "Could Not Mount Device" ); 00902 description = i18n( "The requested device could not be initialized " 00903 "(\"mounted\"). The reported error was: <strong>%1</strong>" ) 00904 .arg( errorText ); 00905 causes << i18n( "The device may not be ready, for example there may be " 00906 "no media in a removable media device (i.e. no CD-ROM in a CD drive), " 00907 "or in the case of a peripheral/portable device, the device may not " 00908 "be correctly connected." ) 00909 << i18n( "You may not have permissions to initialize (\"mount\") the " 00910 "device. On UNIX systems, often system administrator privileges are " 00911 "required to initialize a device." ) 00912 << cHardware; 00913 solutions << i18n( "Check that the device is ready; removable drives " 00914 "must contain media, and portable devices must be connected and powered " 00915 "on.; and try again." ) << sAccess << sSysadmin; 00916 break; 00917 00918 case TDEIO::ERR_COULD_NOT_UNMOUNT: 00919 errorName = i18n( "Unable to Uninitialize Input/Output Device" ); 00920 techName = i18n( "Could Not Unmount Device" ); 00921 description = i18n( "The requested device could not be uninitialized " 00922 "(\"unmounted\"). The reported error was: <strong>%1</strong>" ) 00923 .arg( errorText ); 00924 causes << i18n( "The device may be busy, that is, still in use by " 00925 "another application or user. Even such things as having an open " 00926 "browser window on a location on this device may cause the device to " 00927 "remain in use." ) 00928 << i18n( "You may not have permissions to uninitialize (\"unmount\") " 00929 "the device. On UNIX systems, system administrator privileges are " 00930 "often required to uninitialize a device." ) 00931 << cHardware; 00932 solutions << i18n( "Check that no applications are accessing the device, " 00933 "and try again." ) << sAccess << sSysadmin; 00934 break; 00935 00936 case TDEIO::ERR_COULD_NOT_READ: 00937 errorName = i18n( "Cannot Read From Resource" ); 00938 description = i18n( "This means that although the resource, " 00939 "<strong>%1</strong>, was able to be opened, an error occurred while " 00940 "reading the contents of the resource." ).arg( url ); 00941 causes << i18n( "You may not have permissions to read from the resource." ); 00942 if ( !isSlaveNetwork ) causes << cNetwork; 00943 causes << cHardware; 00944 solutions << sAccess; 00945 if ( !isSlaveNetwork ) solutions << sNetwork; 00946 solutions << sSysadmin; 00947 break; 00948 00949 case TDEIO::ERR_COULD_NOT_WRITE: 00950 errorName = i18n( "Cannot Write to Resource" ); 00951 description = i18n( "This means that although the resource, <strong>%1</strong>" 00952 ", was able to be opened, an error occurred while writing to the resource." ) 00953 .arg( url ); 00954 causes << i18n( "You may not have permissions to write to the resource." ); 00955 if ( !isSlaveNetwork ) causes << cNetwork; 00956 causes << cHardware; 00957 solutions << sAccess; 00958 if ( !isSlaveNetwork ) solutions << sNetwork; 00959 solutions << sSysadmin; 00960 break; 00961 00962 case TDEIO::ERR_COULD_NOT_BIND: 00963 errorName = i18n( "Could Not Listen for Network Connections" ); 00964 techName = i18n( "Could Not Bind" ); 00965 description = i18n( "This is a fairly technical error in which a required " 00966 "device for network communications (a socket) could not be established " 00967 "to listen for incoming network connections." ); 00968 causes << i18n( "The network connection may be incorrectly configured, or " 00969 "the network interface may not be enabled." ); 00970 solutions << sNetwork << sSysadmin; 00971 break; 00972 00973 case TDEIO::ERR_COULD_NOT_LISTEN: 00974 errorName = i18n( "Could Not Listen for Network Connections" ); 00975 techName = i18n( "Could Not Listen" ); 00976 description = i18n( "This is a fairly technical error in which a required " 00977 "device for network communications (a socket) could not be established " 00978 "to listen for incoming network connections." ); 00979 causes << i18n( "The network connection may be incorrectly configured, or " 00980 "the network interface may not be enabled." ); 00981 solutions << sNetwork << sSysadmin; 00982 break; 00983 00984 case TDEIO::ERR_COULD_NOT_ACCEPT: 00985 errorName = i18n( "Could Not Accept Network Connection" ); 00986 description = i18n( "This is a fairly technical error in which an error " 00987 "occurred while attempting to accept an incoming network connection." ); 00988 causes << i18n( "The network connection may be incorrectly configured, or " 00989 "the network interface may not be enabled." ) 00990 << i18n( "You may not have permissions to accept the connection." ); 00991 solutions << sNetwork << sSysadmin; 00992 break; 00993 00994 case TDEIO::ERR_COULD_NOT_LOGIN: 00995 errorName = i18n( "Could Not Login: %1" ).arg( errorText ); 00996 description = i18n( "An attempt to login to perform the requested " 00997 "operation was unsuccessful." ); 00998 causes << i18n( "You may have supplied incorrect authentication details or " 00999 "none at all." ) 01000 << i18n( "Your account may not have permission to access the " 01001 "specified resource." ) << cProtocol; 01002 solutions << i18n( "Retry the request and ensure your authentication details " 01003 "are entered correctly." ) << sServeradmin << sSysadmin; 01004 break; 01005 01006 case TDEIO::ERR_COULD_NOT_STAT: 01007 errorName = i18n( "Could Not Determine Resource Status" ); 01008 techName = i18n( "Could Not Stat Resource" ); 01009 description = i18n( "An attempt to determine information about the status " 01010 "of the resource <strong>%1</strong>, such as the resource name, type, " 01011 "size, etc., was unsuccessful." ).arg( url ); 01012 causes << i18n( "The specified resource may not have existed or may " 01013 "not be accessible." ) << cProtocol << cHardware; 01014 solutions << i18n( "Retry the request and ensure your authentication details " 01015 "are entered correctly." ) << sSysadmin; 01016 break; 01017 01018 case TDEIO::ERR_COULD_NOT_CLOSEDIR: 01019 //result = i18n( "Could not terminate listing %1" ).arg( errorText ); 01020 errorName = i18n( "Could Not Cancel Listing" ); 01021 techName = i18n( "FIXME: Document this" ); 01022 break; 01023 01024 case TDEIO::ERR_COULD_NOT_MKDIR: 01025 errorName = i18n( "Could Not Create Folder" ); 01026 description = i18n( "An attempt to create the requested folder failed." ); 01027 causes << cAccess << i18n( "The location where the folder was to be created " 01028 "may not exist." ); 01029 if ( !isSlaveNetwork ) causes << cProtocol; 01030 solutions << i18n( "Retry the request." ) << sAccess; 01031 break; 01032 01033 case TDEIO::ERR_COULD_NOT_RMDIR: 01034 errorName = i18n( "Could Not Remove Folder" ); 01035 description = i18n( "An attempt to remove the specified folder, " 01036 "<strong>%1</strong>, failed." ).arg( dir ); 01037 causes << i18n( "The specified folder may not exist." ) 01038 << i18n( "The specified folder may not be empty." ) 01039 << cAccess; 01040 if ( !isSlaveNetwork ) causes << cProtocol; 01041 solutions << i18n( "Ensure that the folder exists and is empty, and try " 01042 "again." ) << sAccess; 01043 break; 01044 01045 case TDEIO::ERR_CANNOT_RESUME: 01046 errorName = i18n( "Could Not Resume File Transfer" ); 01047 description = i18n( "The specified request asked that the transfer of " 01048 "file <strong>%1</strong> be resumed at a certain point of the " 01049 "transfer. This was not possible." ).arg( filename ); 01050 causes << i18n( "The protocol, or the server, may not support file " 01051 "resuming." ); 01052 solutions << i18n( "Retry the request without attempting to resume " 01053 "transfer." ); 01054 break; 01055 01056 case TDEIO::ERR_CANNOT_RENAME: 01057 errorName = i18n( "Could Not Rename Resource" ); 01058 description = i18n( "An attempt to rename the specified resource " 01059 "<strong>%1</strong> failed." ).arg( url ); 01060 causes << cAccess << cExists; 01061 if ( !isSlaveNetwork ) causes << cProtocol; 01062 solutions << sAccess << sExists; 01063 break; 01064 01065 case TDEIO::ERR_CANNOT_CHMOD: 01066 errorName = i18n( "Could Not Alter Permissions of Resource" ); 01067 description = i18n( "An attempt to alter the permissions on the specified " 01068 "resource <strong>%1</strong> failed." ).arg( url ); 01069 causes << cAccess << cExists; 01070 solutions << sAccess << sExists; 01071 break; 01072 01073 case TDEIO::ERR_CANNOT_DELETE: 01074 errorName = i18n( "Could Not Delete Resource" ); 01075 description = i18n( "An attempt to delete the specified resource " 01076 "<strong>%1</strong> failed." ).arg( url ); 01077 causes << cAccess << cExists; 01078 solutions << sAccess << sExists; 01079 break; 01080 01081 case TDEIO::ERR_SLAVE_DIED: 01082 errorName = i18n( "Unexpected Program Termination" ); 01083 description = i18n( "The program on your computer which provides access " 01084 "to the <strong>%1</strong> protocol has unexpectedly terminated." ) 01085 .arg( url ); 01086 causes << cBuglikely; 01087 solutions << sUpdate << sBugreport; 01088 break; 01089 01090 case TDEIO::ERR_OUT_OF_MEMORY: 01091 errorName = i18n( "Out of Memory" ); 01092 description = i18n( "The program on your computer which provides access " 01093 "to the <strong>%1</strong> protocol could not obtain the memory " 01094 "required to continue." ).arg( protocol ); 01095 causes << cBuglikely; 01096 solutions << sUpdate << sBugreport; 01097 break; 01098 01099 case TDEIO::ERR_UNKNOWN_PROXY_HOST: 01100 errorName = i18n( "Unknown Proxy Host" ); 01101 description = i18n( "While retrieving information about the specified " 01102 "proxy host, <strong>%1</strong>, an Unknown Host error was encountered. " 01103 "An unknown host error indicates that the requested name could not be " 01104 "located on the Internet." ).arg( errorText ); 01105 causes << i18n( "There may have been a problem with your network " 01106 "configuration, specifically your proxy's hostname. If you have been " 01107 "accessing the Internet with no problems recently, this is unlikely." ) 01108 << cNetwork; 01109 solutions << i18n( "Double-check your proxy settings and try again." ) 01110 << sSysadmin; 01111 break; 01112 01113 case TDEIO::ERR_COULD_NOT_AUTHENTICATE: 01114 errorName = i18n( "Authentication Failed: Method %1 Not Supported" ) 01115 .arg( errorText ); 01116 description = i18n( "Although you may have supplied the correct " 01117 "authentication details, the authentication failed because the " 01118 "method that the server is using is not supported by the TDE " 01119 "program implementing the protocol %1." ).arg( protocol ); 01120 solutions << i18n( "Please file a bug at <a href=\"http://bugs.trinitydesktop.org/\">" 01121 "http://bugs.trinitydesktop.org/</a> to inform the TDE team of the unsupported " 01122 "authentication method." ) << sSysadmin; 01123 break; 01124 01125 case TDEIO::ERR_ABORTED: 01126 errorName = i18n( "Request Aborted" ); 01127 description = i18n( "The request was not completed because it was " 01128 "aborted." ); 01129 solutions << i18n( "Retry the request." ); 01130 break; 01131 01132 case TDEIO::ERR_INTERNAL_SERVER: 01133 errorName = i18n( "Internal Error in Server" ); 01134 description = i18n( "The program on the server which provides access " 01135 "to the <strong>%1</strong> protocol has reported an internal error: " 01136 "%0." ).arg( protocol ); 01137 causes << i18n( "This is most likely to be caused by a bug in the " 01138 "server program. Please consider submitting a full bug report as " 01139 "detailed below." ); 01140 solutions << i18n( "Contact the administrator of the server " 01141 "to advise them of the problem." ) 01142 << i18n( "If you know who the authors of the server software are, " 01143 "submit the bug report directly to them." ); 01144 break; 01145 01146 case TDEIO::ERR_SERVER_TIMEOUT: 01147 errorName = i18n( "Timeout Error" ); 01148 description = i18n( "Although contact was made with the server, a " 01149 "response was not received within the amount of time allocated for " 01150 "the request as follows:<ul>" 01151 "<li>Timeout for establishing a connection: %1 seconds</li>" 01152 "<li>Timeout for receiving a response: %2 seconds</li>" 01153 "<li>Timeout for accessing proxy servers: %3 seconds</li></ul>" 01154 "Please note that you can alter these timeout settings in the TDE " 01155 "Control Center, by selecting Network -> Preferences." ) 01156 .arg( KProtocolManager::connectTimeout() ) 01157 .arg( KProtocolManager::responseTimeout() ) 01158 .arg( KProtocolManager::proxyConnectTimeout() ); 01159 causes << cNetpath << i18n( "The server was too busy responding to other " 01160 "requests to respond." ); 01161 solutions << sTryagain << sServeradmin; 01162 break; 01163 01164 case TDEIO::ERR_UNKNOWN: 01165 errorName = i18n( "Unknown Error" ); 01166 description = i18n( "The program on your computer which provides access " 01167 "to the <strong>%1</strong> protocol has reported an unknown error: " 01168 "%2." ).arg( protocol ).arg( errorText ); 01169 causes << cBug; 01170 solutions << sUpdate << sBugreport; 01171 break; 01172 01173 case TDEIO::ERR_UNKNOWN_INTERRUPT: 01174 errorName = i18n( "Unknown Interruption" ); 01175 description = i18n( "The program on your computer which provides access " 01176 "to the <strong>%1</strong> protocol has reported an interruption of " 01177 "an unknown type: %2." ).arg( protocol ).arg( errorText ); 01178 causes << cBug; 01179 solutions << sUpdate << sBugreport; 01180 break; 01181 01182 case TDEIO::ERR_CANNOT_DELETE_ORIGINAL: 01183 errorName = i18n( "Could Not Delete Original File" ); 01184 description = i18n( "The requested operation required the deleting of " 01185 "the original file, most likely at the end of a file move operation. " 01186 "The original file <strong>%1</strong> could not be deleted." ) 01187 .arg( errorText ); 01188 causes << cAccess; 01189 solutions << sAccess; 01190 break; 01191 01192 case TDEIO::ERR_CANNOT_DELETE_PARTIAL: 01193 errorName = i18n( "Could Not Delete Temporary File" ); 01194 description = i18n( "The requested operation required the creation of " 01195 "a temporary file in which to save the new file while being " 01196 "downloaded. This temporary file <strong>%1</strong> could not be " 01197 "deleted." ).arg( errorText ); 01198 causes << cAccess; 01199 solutions << sAccess; 01200 break; 01201 01202 case TDEIO::ERR_CANNOT_RENAME_ORIGINAL: 01203 errorName = i18n( "Could Not Rename Original File" ); 01204 description = i18n( "The requested operation required the renaming of " 01205 "the original file <strong>%1</strong>, however it could not be " 01206 "renamed." ).arg( errorText ); 01207 causes << cAccess; 01208 solutions << sAccess; 01209 break; 01210 01211 case TDEIO::ERR_CANNOT_RENAME_PARTIAL: 01212 errorName = i18n( "Could Not Rename Temporary File" ); 01213 description = i18n( "The requested operation required the creation of " 01214 "a temporary file <strong>%1</strong>, however it could not be " 01215 "created." ).arg( errorText ); 01216 causes << cAccess; 01217 solutions << sAccess; 01218 break; 01219 01220 case TDEIO::ERR_CANNOT_SYMLINK: 01221 errorName = i18n( "Could Not Create Link" ); 01222 techName = i18n( "Could Not Create Symbolic Link" ); 01223 description = i18n( "The requested symbolic link %1 could not be created." ) 01224 .arg( errorText ); 01225 causes << cAccess; 01226 solutions << sAccess; 01227 break; 01228 01229 case TDEIO::ERR_NO_CONTENT: 01230 errorName = i18n( "No Content" ); 01231 description = errorText; 01232 break; 01233 01234 case TDEIO::ERR_DISK_FULL: 01235 errorName = i18n( "Disk Full" ); 01236 description = i18n( "The requested file <strong>%1</strong> could not be " 01237 "written to as there is inadequate disk space." ).arg( errorText ); 01238 solutions << i18n( "Free up enough disk space by 1) deleting unwanted and " 01239 "temporary files; 2) archiving files to removable media storage such as " 01240 "CD-Recordable discs; or 3) obtain more storage capacity." ) 01241 << sSysadmin; 01242 break; 01243 01244 case TDEIO::ERR_IDENTICAL_FILES: 01245 errorName = i18n( "Source and Destination Files Identical" ); 01246 description = i18n( "The operation could not be completed because the " 01247 "source and destination files are the same file." ); 01248 solutions << i18n( "Choose a different filename for the destination file." ); 01249 break; 01250 01251 // We assume that the slave has all the details 01252 case TDEIO::ERR_SLAVE_DEFINED: 01253 errorName = TQString::null; 01254 description = errorText; 01255 break; 01256 01257 default: 01258 // fall back to the plain error... 01259 errorName = i18n( "Undocumented Error" ); 01260 description = buildErrorString( errorCode, errorText ); 01261 } 01262 01263 TQByteArray ret; 01264 TQDataStream stream(ret, IO_WriteOnly); 01265 stream << errorName << techName << description << causes << solutions; 01266 return ret; 01267 } 01268 01269 #ifdef Q_OS_UNIX 01270 01271 #include <limits.h> 01272 #include <stdlib.h> 01273 #include <stdio.h> 01274 #include <tqfile.h> 01275 01276 #include <config.h> 01277 01278 #ifdef HAVE_PATHS_H 01279 #include <paths.h> 01280 #endif 01281 #ifdef HAVE_SYS_STAT_H 01282 #include <sys/stat.h> 01283 #endif 01284 #include <sys/param.h> 01285 #ifdef HAVE_LIMITS_H 01286 #include <limits.h> 01287 #endif 01288 #ifdef HAVE_SYS_MNTTAB_H 01289 #include <sys/mnttab.h> 01290 #endif 01291 #ifdef HAVE_MNTENT_H 01292 #include <mntent.h> 01293 #elif defined(HAVE_SYS_MNTENT_H) 01294 #include <sys/mntent.h> 01295 #endif 01296 #ifdef HAVE_SYS_UCRED_H 01297 #include <sys/ucred.h> 01298 #endif 01299 #ifdef HAVE_SYS_MOUNT_H 01300 #include <sys/mount.h> 01301 #endif 01302 #ifdef HAVE_FSTAB_H 01303 #include <fstab.h> 01304 #endif 01305 #if defined(_AIX) 01306 #include <sys/mntctl.h> 01307 #include <sys/vmount.h> 01308 #include <sys/vfs.h> 01309 01310 /* AIX does not prototype mntctl anywhere that I can find */ 01311 #ifndef mntctl 01312 extern "C" { 01313 int mntctl(int command, int size, void* buffer); 01314 } 01315 #endif 01316 extern "C" struct vfs_ent *getvfsbytype(int vfsType); 01317 extern "C" void endvfsent( ); 01318 #endif 01319 01320 /*************************************************************** 01321 * 01322 * Utility functions 01323 * 01324 ***************************************************************/ 01325 01326 #ifndef HAVE_GETMNTINFO 01327 01328 #ifdef _PATH_MOUNTED 01329 // On some Linux, MNTTAB points to /etc/fstab ! 01330 # undef MNTTAB 01331 # define MNTTAB _PATH_MOUNTED 01332 #else 01333 # ifndef MNTTAB 01334 # ifdef MTAB_FILE 01335 # define MNTTAB MTAB_FILE 01336 # else 01337 # define MNTTAB "/etc/mnttab" 01338 # endif 01339 # endif 01340 #endif 01341 01342 #ifndef FSTAB 01343 # ifdef _PATH_FSTAB 01344 # define FSTAB _PATH_FSTAB 01345 # else 01346 # define FSTAB "/etc/fstab" 01347 # endif 01348 #endif 01349 01350 #ifdef __CYGWIN__ 01351 #define hasmntopt(var,opt) (0) 01352 #endif 01353 01354 // There are (at least) four kind of APIs: 01355 // setmntent + getmntent + struct mntent (linux...) 01356 // getmntent + struct mnttab 01357 // mntctl + struct vmount (AIX) 01358 // getmntinfo + struct statfs&flags (BSD 4.4 and friends) 01359 // getfsent + char* (BSD 4.3 and friends) 01360 01361 #ifdef HAVE_SETMNTENT 01362 #define SETMNTENT setmntent 01363 #define ENDMNTENT endmntent 01364 #define STRUCT_MNTENT struct mntent * 01365 #define STRUCT_SETMNTENT FILE * 01366 #define GETMNTENT(file, var) ((var = getmntent(file)) != 0) 01367 #define MOUNTPOINT(var) var->mnt_dir 01368 #define MOUNTTYPE(var) var->mnt_type 01369 #define HASMNTOPT(var, opt) hasmntopt(var, opt) 01370 #define FSNAME(var) var->mnt_fsname 01371 #elif defined(_AIX) 01372 /* we don't need this stuff */ 01373 #else 01374 #define SETMNTENT fopen 01375 #define ENDMNTENT fclose 01376 #define STRUCT_MNTENT struct mnttab 01377 #define STRUCT_SETMNTENT FILE * 01378 #define GETMNTENT(file, var) (getmntent(file, &var) == 0) 01379 #define MOUNTPOINT(var) var.mnt_mountp 01380 #define MOUNTTYPE(var) var.mnt_fstype 01381 #define HASMNTOPT(var, opt) hasmntopt(&var, opt) 01382 #define FSNAME(var) var.mnt_special 01383 #endif 01384 01385 #endif /* HAVE_GETMNTINFO */ 01386 01387 TQString TDEIO::findDeviceMountPoint( const TQString& filename ) 01388 { 01389 TQString result; 01390 01391 #ifdef HAVE_VOLMGT 01392 /* 01393 * support for Solaris volume management 01394 */ 01395 const char *volpath; 01396 FILE *mnttab; 01397 struct mnttab mnt; 01398 int len; 01399 TQCString devname; 01400 01401 if( (volpath = volmgt_root()) == NULL ) { 01402 kdDebug( 7007 ) << "findDeviceMountPoint: " 01403 << "VOLMGT: can't find volmgt root dir" << endl; 01404 return TQString::null; 01405 } 01406 01407 if( (mnttab = fopen( MNTTAB, "r" )) == NULL ) { 01408 kdDebug( 7007 ) << "findDeviceMountPoint: " 01409 << "VOLMGT: can't open mnttab" << endl; 01410 return TQString::null; 01411 } 01412 01413 devname = volpath; 01414 devname += TQFile::encodeName( filename ); 01415 devname += '/'; 01416 len = devname.length(); 01417 // kdDebug( 7007 ) << "findDeviceMountPoint: " 01418 // << "VOLMGT: searching mountpoint for \"" << devname << "\"" 01419 // << endl; 01420 01421 /* 01422 * find the mountpoint 01423 * floppies: 01424 * /dev/disketteN => <volpath>/dev/disketteN 01425 * CDROM, ZIP, and other media: 01426 * /dev/dsk/cXtYdZs2 => <volpath>/dev/dsk/cXtYdZ (without slice#) 01427 */ 01428 rewind( mnttab ); 01429 result = TQString::null; 01430 while( getmntent( mnttab, &mnt ) == 0 ) { 01431 /* 01432 * either match the exact device name (floppies), 01433 * or the device name without the slice# 01434 */ 01435 if( strncmp( devname.data(), mnt.mnt_special, len ) == 0 01436 || (strncmp( devname.data(), mnt.mnt_special, len - 3 ) == 0 01437 && mnt.mnt_special[len - 3] == '/' ) 01438 || (strcmp(TQFile::encodeName(filename).data() 01439 , mnt.mnt_special)==0)) { 01440 result = mnt.mnt_mountp; 01441 break; 01442 } 01443 } 01444 fclose( mnttab ); 01445 #else 01446 01447 char realpath_buffer[MAXPATHLEN]; 01448 TQCString realname; 01449 01450 realname = TQFile::encodeName(filename); 01451 /* If the path contains symlinks, get the real name */ 01452 if (realpath(realname, realpath_buffer) != 0) 01453 // succes, use result from realpath 01454 realname = realpath_buffer; 01455 01456 //kdDebug(7007) << "findDeviceMountPoint realname=" << realname << endl; 01457 01458 #ifdef HAVE_GETMNTINFO 01459 01460 #ifdef GETMNTINFO_USES_STATVFS 01461 struct statvfs *mounted; 01462 #else 01463 struct statfs *mounted; 01464 #endif 01465 01466 int num_fs = getmntinfo(&mounted, MNT_NOWAIT); 01467 01468 for (int i=0;i<num_fs;i++) { 01469 01470 TQCString device_name = mounted[i].f_mntfromname; 01471 01472 // If the path contains symlinks, get 01473 // the real name 01474 if (realpath(device_name, realpath_buffer) != 0) 01475 // succes, use result from realpath 01476 device_name = realpath_buffer; 01477 01478 if (realname == device_name) { 01479 result = mounted[i].f_mntonname; 01480 break; 01481 } 01482 } 01483 01484 #elif defined(_AIX) 01485 01486 struct vmount *mntctl_buffer; 01487 struct vmount *vm; 01488 char *mountedfrom; 01489 char *mountedto; 01490 int fsname_len, num; 01491 int buf_sz = 4096; 01492 01493 /* mntctl can be used to query mounted file systems. 01494 * mntctl takes only the command MCTL_QUERY so far. 01495 * The buffer is filled with an array of vmount structures, but these 01496 * vmount structures have variable size. 01497 * mntctl return values: 01498 * -1 error 01499 * 0 look in first word of buffer for required bytes, 4096 may be 01500 * a good starting size, but if tables grow too large, look here. 01501 * >0 number of vmount structures 01502 */ 01503 mntctl_buffer = (struct vmount*)malloc(buf_sz); 01504 num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer); 01505 if (num == 0) 01506 { 01507 buf_sz = *(int*)mntctl_buffer; 01508 free(mntctl_buffer); 01509 mntctl_buffer = (struct vmount*)malloc(buf_sz); 01510 num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer); 01511 } 01512 01513 if (num > 0) 01514 { 01515 /* iterate through items in the vmount structure: */ 01516 vm = mntctl_buffer; 01517 for ( ; num > 0; num-- ) 01518 { 01519 /* get the name of the mounted file systems: */ 01520 fsname_len = vmt2datasize(vm, VMT_STUB); 01521 mountedto = (char*)malloc(fsname_len + 1); 01522 mountedto[fsname_len] = '\0'; 01523 strncpy(mountedto, (char *)vmt2dataptr(vm, VMT_STUB), fsname_len); 01524 01525 /* get the mount-from information: */ 01526 fsname_len = vmt2datasize(vm, VMT_OBJECT); 01527 mountedfrom = (char*)malloc(fsname_len + 1); 01528 mountedfrom[fsname_len] = '\0'; 01529 strncpy(mountedfrom, (char *)vmt2dataptr(vm, VMT_OBJECT), fsname_len); 01530 01531 TQCString device_name = mountedfrom; 01532 01533 if (realpath(device_name, realpath_buffer) != 0) 01534 // success, use result from realpath 01535 device_name = realpath_buffer; 01536 01537 free(mountedfrom); 01538 01539 if (realname == device_name) { 01540 result = mountedto; 01541 free(mountedto); 01542 break; 01543 } 01544 01545 free(mountedto); 01546 01547 /* goto the next vmount structure: */ 01548 vm = (struct vmount *)((char *)vm + vm->vmt_length); 01549 } 01550 } 01551 01552 free( mntctl_buffer ); 01553 01554 #else 01555 01556 STRUCT_SETMNTENT mtab; 01557 01558 /* Get the list of mounted file systems */ 01559 01560 if ((mtab = SETMNTENT(MNTTAB, "r")) == 0) { 01561 perror("setmntent"); 01562 return TQString::null; 01563 } 01564 01565 /* Loop over all file systems and see if we can find our 01566 * mount point. 01567 * Note that this is the mount point with the longest match. 01568 * XXX: Fails if me->mnt_dir is not a realpath but goes 01569 * through a symlink, e.g. /foo/bar where /foo is a symlink 01570 * pointing to /local/foo. 01571 * 01572 * How kinky can you get with a filesystem? 01573 */ 01574 01575 STRUCT_MNTENT me; 01576 01577 while (GETMNTENT(mtab, me)) 01578 { 01579 // There may be symbolic links into the /etc/mnttab 01580 // So we have to find the real device name here as well! 01581 TQCString device_name = FSNAME(me); 01582 if (device_name.isEmpty() || (device_name == "none")) 01583 continue; 01584 01585 //kdDebug( 7007 ) << "device_name=" << device_name << endl; 01586 01587 // If the path contains symlinks, get 01588 // the real name 01589 if (realpath(device_name, realpath_buffer) != 0) 01590 // succes, use result from realpath 01591 device_name = realpath_buffer; 01592 01593 //kdDebug( 7007 ) << "device_name after realpath =" << device_name << endl; 01594 01595 if (realname == device_name) 01596 { 01597 result = MOUNTPOINT(me); 01598 break; 01599 } 01600 } 01601 01602 ENDMNTENT(mtab); 01603 01604 #endif /* GET_MNTINFO */ 01605 #endif /* HAVE_VOLMGT */ 01606 01607 //kdDebug( 7007 ) << "Returning result " << result << endl; 01608 return result; 01609 } 01610 01611 // Don't just trust the return value, keep iterating to check for a better match (bigger max) 01612 static bool is_my_mountpoint( const char *mountpoint, const char *realname, int &max ) 01613 { 01614 int length = strlen(mountpoint); 01615 01616 if (!strncmp(mountpoint, realname, length) 01617 && length > max) { 01618 max = length; 01619 if (length == 1 || realname[length] == '/' || realname[length] == '\0') 01620 return true; 01621 } 01622 return false; 01623 } 01624 01625 typedef enum { Unseen, Right, Wrong } MountState; 01626 01630 static void check_mount_point(const char *mounttype, 01631 const char *fsname, 01632 MountState &isslow, MountState &isautofs) 01633 { 01634 bool nfs = !strcmp(mounttype, "nfs"); 01635 bool autofs = !strcmp(mounttype, "autofs") || !strcmp(mounttype,"subfs"); 01636 bool pid = (strstr(fsname, ":(pid") != 0); 01637 01638 if (nfs && !pid) 01639 isslow = Right; 01640 else if (isslow == Right) 01641 isslow = Wrong; 01642 01643 /* Does this look like automounted? */ 01644 if (autofs || (nfs && pid)) { 01645 isautofs = Right; 01646 isslow = Right; 01647 } 01648 } 01649 01650 // returns the mount point, checks the mount state. 01651 // if ismanual == Wrong this function does not check the manual mount state 01652 static TQString get_mount_info(const TQString& filename, 01653 MountState& isautofs, MountState& isslow, MountState& ismanual, 01654 TQString& fstype) 01655 { 01656 static bool gotRoot = false; 01657 static dev_t rootDevice; 01658 01659 struct cachedDevice_t 01660 { 01661 dev_t device; 01662 TQString mountPoint; 01663 MountState isautofs; 01664 MountState isslow; 01665 MountState ismanual; 01666 TQString fstype; 01667 }; 01668 static struct cachedDevice_t *cachedDevice = 0; 01669 01670 if (!gotRoot) 01671 { 01672 KDE_struct_stat stat_buf; 01673 KDE_stat("/", &stat_buf); 01674 gotRoot = true; 01675 rootDevice = stat_buf.st_dev; 01676 } 01677 01678 bool gotDevice = false; 01679 KDE_struct_stat stat_buf; 01680 if (KDE_stat(TQFile::encodeName(filename), &stat_buf) == 0) 01681 { 01682 gotDevice = true; 01683 if (stat_buf.st_dev == rootDevice) 01684 { 01685 static const TQString &root = TDEGlobal::staticQString("/"); 01686 isautofs = Wrong; 01687 isslow = Wrong; 01688 ismanual = Wrong; 01689 fstype = TQString::null; // ### do we need it? 01690 return root; 01691 } 01692 if (cachedDevice && (stat_buf.st_dev == cachedDevice->device)) 01693 { 01694 bool interestedInIsManual = ismanual != Wrong; 01695 isautofs = cachedDevice->isautofs; 01696 isslow = cachedDevice->isslow; 01697 ismanual = cachedDevice->ismanual; 01698 fstype = cachedDevice->fstype; 01699 // Don't use the cache if it doesn't have the information we're looking for 01700 if ( !interestedInIsManual || ismanual != Unseen ) 01701 return cachedDevice->mountPoint; 01702 } 01703 } 01704 01705 char realname[MAXPATHLEN]; 01706 01707 memset(realname, 0, MAXPATHLEN); 01708 01709 /* If the path contains symlinks, get the real name */ 01710 if (realpath(TQFile::encodeName(filename), realname) == 0) { 01711 if( strlcpy(realname, TQFile::encodeName(filename), MAXPATHLEN)>=MAXPATHLEN) 01712 return TQString::null; 01713 } 01714 01715 int max = 0; 01716 TQString mountPoint; 01717 01718 /* Loop over all file systems and see if we can find our 01719 * mount point. 01720 * Note that this is the mount point with the longest match. 01721 * XXX: Fails if me->mnt_dir is not a realpath but goes 01722 * through a symlink, e.g. /foo/bar where /foo is a symlink 01723 * pointing to /local/foo. 01724 * 01725 * How kinky can you get with a filesystem? 01726 */ 01727 01728 #ifdef HAVE_GETMNTINFO 01729 01730 #ifdef GETMNTINFO_USES_STATVFS 01731 struct statvfs *mounted; 01732 #else 01733 struct statfs *mounted; 01734 #endif 01735 01736 char realpath_buffer[MAXPATHLEN]; 01737 01738 int num_fs = getmntinfo(&mounted, MNT_NOWAIT); 01739 01740 for (int i=0;i<num_fs;i++) { 01741 01742 TQCString device_name = mounted[i].f_mntfromname; 01743 01744 // If the path contains symlinks, get 01745 // the real name 01746 if (realpath(device_name, realpath_buffer) != 0) 01747 // succes, use result from realpath 01748 device_name = realpath_buffer; 01749 #ifdef __osf__ 01750 char * mounttype = mnt_names[mounted[i].f_type]; 01751 #else 01752 char * mounttype = mounted[i].f_fstypename; 01753 #endif 01754 if ( is_my_mountpoint( mounted[i].f_mntonname, realname, max ) ) 01755 { 01756 mountPoint = TQFile::decodeName(mounted[i].f_mntonname); 01757 fstype = TQString::fromLatin1(mounttype); 01758 check_mount_point( mounttype, mounted[i].f_mntfromname, 01759 isautofs, isslow ); 01760 // keep going, looking for a potentially better one 01761 01762 if (ismanual == Unseen) 01763 { 01764 struct fstab *ft = getfsfile(mounted[i].f_mntonname); 01765 if (!ft || strstr(ft->fs_mntops, "noauto")) 01766 ismanual = Right; 01767 } 01768 } 01769 } 01770 01771 #elif defined(_AIX) 01772 01773 struct vmount *mntctl_buffer; 01774 struct vmount *vm; 01775 char *mountedfrom; 01776 char *mountedto; 01777 int fsname_len, num; 01778 char realpath_buffer[MAXPATHLEN]; 01779 int buf_sz = 4096; 01780 01781 mntctl_buffer = (struct vmount*)malloc(buf_sz); 01782 num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer); 01783 if (num == 0) 01784 { 01785 buf_sz = *(int*)mntctl_buffer; 01786 free(mntctl_buffer); 01787 mntctl_buffer = (struct vmount*)malloc(buf_sz); 01788 num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer); 01789 } 01790 01791 if (num > 0) 01792 { 01793 /* iterate through items in the vmount structure: */ 01794 vm = (struct vmount *)mntctl_buffer; 01795 for ( ; num > 0; num-- ) 01796 { 01797 /* get the name of the mounted file systems: */ 01798 fsname_len = vmt2datasize(vm, VMT_STUB); 01799 mountedto = (char*)malloc(fsname_len + 1); 01800 mountedto[fsname_len] = '\0'; 01801 strncpy(mountedto, (char *)vmt2dataptr(vm, VMT_STUB), fsname_len); 01802 01803 fsname_len = vmt2datasize(vm, VMT_OBJECT); 01804 mountedfrom = (char*)malloc(fsname_len + 1); 01805 mountedfrom[fsname_len] = '\0'; 01806 strncpy(mountedfrom, (char *)vmt2dataptr(vm, VMT_OBJECT), fsname_len); 01807 01808 /* get the mount-from information: */ 01809 TQCString device_name = mountedfrom; 01810 01811 if (realpath(device_name, realpath_buffer) != 0) 01812 // success, use result from realpath 01813 device_name = realpath_buffer; 01814 01815 /* Look up the string for the file system type, 01816 * as listed in /etc/vfs. 01817 * ex.: nfs,jfs,afs,cdrfs,sfs,cachefs,nfs3,autofs 01818 */ 01819 struct vfs_ent* ent = getvfsbytype(vm->vmt_gfstype); 01820 01821 if ( is_my_mountpoint( mountedto, realname, max ) ) 01822 { 01823 mountPoint = TQFile::decodeName(mountedto); 01824 fstype = TQString::fromLatin1(ent->vfsent_name); 01825 check_mount_point(ent->vfsent_name, device_name, isautofs, isslow); 01826 01827 if (ismanual == Unseen) 01828 { 01829 // TODO: add check for ismanual, I couldn't find any way 01830 // how to get the mount attribute from /etc/filesystems 01831 ismanual == Wrong; 01832 } 01833 } 01834 01835 free(mountedfrom); 01836 free(mountedto); 01837 01838 /* goto the next vmount structure: */ 01839 vm = (struct vmount *)((char *)vm + vm->vmt_length); 01840 } 01841 01842 endvfsent( ); 01843 } 01844 01845 free( mntctl_buffer ); 01846 01847 #else 01848 01849 STRUCT_SETMNTENT mtab; 01850 /* Get the list of mounted file systems */ 01851 01852 if ((mtab = SETMNTENT(MNTTAB, "r")) == 0) { 01853 perror("setmntent"); 01854 return TQString::null; 01855 } 01856 01857 STRUCT_MNTENT me; 01858 01859 while (true) { 01860 if (!GETMNTENT(mtab, me)) 01861 break; 01862 01863 if ( is_my_mountpoint( MOUNTPOINT(me), realname, max ) ) 01864 { 01865 mountPoint = TQFile::decodeName( MOUNTPOINT(me) ); 01866 fstype = MOUNTTYPE(me); 01867 check_mount_point(MOUNTTYPE(me), FSNAME(me), isautofs, isslow); 01868 // we don't check if ismanual is Right, if /a/b is manually 01869 // mounted /a/b/c can't be automounted. At least IMO. 01870 if (ismanual == Unseen) 01871 { 01872 // The next GETMNTENT call may destroy 'me' 01873 // Copy out the info that we need 01874 TQCString fsname_me = FSNAME(me); 01875 TQCString mounttype_me = MOUNTTYPE(me); 01876 01877 STRUCT_SETMNTENT fstab; 01878 if ((fstab = SETMNTENT(FSTAB, "r")) == 0) { 01879 continue; 01880 } 01881 01882 bool found = false; 01883 STRUCT_MNTENT fe; 01884 while (GETMNTENT(fstab, fe)) 01885 { 01886 if (fsname_me == FSNAME(fe)) 01887 { 01888 found = true; 01889 if (HASMNTOPT(fe, "noauto") || 01890 !strcmp(MOUNTTYPE(fe), "supermount")) 01891 ismanual = Right; 01892 break; 01893 } 01894 } 01895 if (!found || (mounttype_me == "supermount")) 01896 ismanual = Right; 01897 01898 ENDMNTENT(fstab); 01899 } 01900 } 01901 } 01902 01903 ENDMNTENT(mtab); 01904 01905 #endif 01906 01907 if (isautofs == Right && isslow == Unseen) 01908 isslow = Right; 01909 01910 if (gotDevice) 01911 { 01912 if (!cachedDevice) 01913 cachedDevice = new cachedDevice_t; 01914 01915 cachedDevice->device = stat_buf.st_dev; 01916 cachedDevice->mountPoint = mountPoint; 01917 cachedDevice->isautofs = isautofs; 01918 cachedDevice->isslow = isslow; 01919 cachedDevice->ismanual = ismanual; 01920 cachedDevice->fstype = fstype; 01921 } 01922 01923 return mountPoint; 01924 } 01925 01926 #else //!Q_OS_UNIX 01927 //dummy 01928 TQString TDEIO::findDeviceMountPoint( const TQString& filename ) 01929 { 01930 return TQString::null; 01931 } 01932 #endif 01933 01934 TQString TDEIO::findPathMountPoint(const TQString& filename) 01935 { 01936 #ifdef Q_OS_UNIX 01937 MountState isautofs = Unseen, isslow = Unseen, ismanual = Wrong; 01938 TQString fstype; 01939 return get_mount_info(filename, isautofs, isslow, ismanual, fstype); 01940 #else //!Q_OS_UNIX 01941 return TQString::null; 01942 #endif 01943 } 01944 01945 bool TDEIO::manually_mounted(const TQString& filename) 01946 { 01947 #ifdef Q_OS_UNIX 01948 MountState isautofs = Unseen, isslow = Unseen, ismanual = Unseen; 01949 TQString fstype; 01950 TQString mountPoint = get_mount_info(filename, isautofs, isslow, ismanual, fstype); 01951 return !mountPoint.isNull() && (ismanual == Right); 01952 #else //!Q_OS_UNIX 01953 return false; 01954 #endif 01955 } 01956 01957 bool TDEIO::probably_slow_mounted(const TQString& filename) 01958 { 01959 #ifdef Q_OS_UNIX 01960 MountState isautofs = Unseen, isslow = Unseen, ismanual = Wrong; 01961 TQString fstype; 01962 TQString mountPoint = get_mount_info(filename, isautofs, isslow, ismanual, fstype); 01963 return !mountPoint.isNull() && (isslow == Right); 01964 #else //!Q_OS_UNIX 01965 return false; 01966 #endif 01967 } 01968 01969 bool TDEIO::testFileSystemFlag(const TQString& filename, FileSystemFlag flag) 01970 { 01971 #ifdef Q_OS_UNIX 01972 MountState isautofs = Unseen, isslow = Unseen, ismanual = Wrong; 01973 TQString fstype; 01974 TQString mountPoint = get_mount_info(filename, isautofs, isslow, ismanual, fstype); 01975 kdDebug() << "testFileSystemFlag: fstype=" << fstype << endl; 01976 if (mountPoint.isNull()) 01977 return false; 01978 bool isMsDos = ( fstype == "msdos" || fstype == "fat" || fstype == "vfat" ); 01979 switch (flag) { 01980 case SupportsChmod: 01981 case SupportsChown: 01982 case SupportsUTime: 01983 case SupportsSymlinks: 01984 return !isMsDos; // it's amazing the number of things FAT doesn't support :) 01985 case CaseInsensitive: 01986 return isMsDos; 01987 } 01988 #endif 01989 return false; 01990 } 01991 01992 TDEIO::CacheControl TDEIO::parseCacheControl(const TQString &cacheControl) 01993 { 01994 TQString tmp = cacheControl.lower(); 01995 01996 if (tmp == "cacheonly") 01997 return TDEIO::CC_CacheOnly; 01998 if (tmp == "cache") 01999 return TDEIO::CC_Cache; 02000 if (tmp == "verify") 02001 return TDEIO::CC_Verify; 02002 if (tmp == "refresh") 02003 return TDEIO::CC_Refresh; 02004 if (tmp == "reload") 02005 return TDEIO::CC_Reload; 02006 02007 kdDebug() << "unrecognized Cache control option:"<<cacheControl<<endl; 02008 return TDEIO::CC_Verify; 02009 } 02010 02011 TQString TDEIO::getCacheControlString(TDEIO::CacheControl cacheControl) 02012 { 02013 if (cacheControl == TDEIO::CC_CacheOnly) 02014 return "CacheOnly"; 02015 if (cacheControl == TDEIO::CC_Cache) 02016 return "Cache"; 02017 if (cacheControl == TDEIO::CC_Verify) 02018 return "Verify"; 02019 if (cacheControl == TDEIO::CC_Refresh) 02020 return "Refresh"; 02021 if (cacheControl == TDEIO::CC_Reload) 02022 return "Reload"; 02023 kdDebug() << "unrecognized Cache control enum value:"<<cacheControl<<endl; 02024 return TQString::null; 02025 }