📄 file.cc
字号:
#include "file.h"#include <config.h>#include <kio_manager.h>#include <kio_rename_dlg.h>#include <kio_skip_dlg.h>#include <stdio.h>#include <signal.h>#include <errno.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/stat.h>#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif#include <dirent.h>#include <time.h>#include <unistd.h>#include <string.h>#include <pwd.h>#include <grp.h>#include <assert.h>#include <iostream>#include <k2url.h>string testLogFile( const char *_filename );int check( Connection *_con );void sig_handler( int );void sig_handler2( int );int main( int argc, char **argv ){ signal(SIGCHLD,sig_handler); signal(SIGSEGV,sig_handler2); ProtocolManager manager; debug( "kio_file : Starting"); Connection parent( 0, 1 ); FileProtocol file( &parent ); file.dispatchLoop(); debug( "kio_file : Done" );}void sig_handler2( int ){ debug( "kio_file : ###############SEG FILE#############" ); exit(1);}void sig_handler( int ){ int pid; int status; while( 1 ) { pid = waitpid( -1, &status, WNOHANG ); if ( pid <= 0 ) { // Reinstall signal handler, since Linux resets to default after // the signal occured ( BSD handles it different, but it should do // no harm ). signal( SIGCHLD, sig_handler ); return; } }}FileProtocol::FileProtocol( Connection *_conn ) : IOProtocol( _conn ){ m_cmd = CMD_NONE; m_bIgnoreJobErrors = false;}void FileProtocol::slotMkdir( const char *_url, int _mode ){ string url = _url; K2URL usrc( _url ); if ( usrc.isMalformed() ) { error( ERR_MALFORMED_URL, url.c_str() ); m_cmd = CMD_NONE; return; } if ( !usrc.isLocalFile() ) { error( ERR_INTERNAL, "kio_file got non local name in mkdir command" ); m_cmd = CMD_NONE; return; } struct stat buff; if ( stat( usrc.path(), &buff ) == -1 ) { if ( ::mkdir( usrc.path(), S_IRWXU ) != 0 ) { if ( errno == EACCES ) { error( ERR_ACCESS_DENIED, url.c_str() ); m_cmd = CMD_NONE; return; } else { error( ERR_COULD_NOT_MKDIR, url.c_str() ); m_cmd = CMD_NONE; return; } } else { if ( _mode != -1 ) if ( chmod( usrc.path(), _mode ) == -1 ) { error( ERR_CANNOT_CHMOD, url.c_str() ); m_cmd = CMD_NONE; return; } finished(); return; } } if ( S_ISDIR( buff.st_mode ) ) { error( ERR_DOES_ALREADY_EXIST, url.c_str() ); m_cmd = CMD_NONE; return; } error( ERR_COULD_NOT_MKDIR, url.c_str() ); m_cmd = CMD_NONE; return;}void FileProtocol::slotCopy( list<string>& _source, const char *_dest ){ doCopy( _source, _dest, false );}void FileProtocol::slotCopy( const char* _source, const char *_dest ){ list<string> lst; lst.push_back( _source ); doCopy( lst, _dest, true );}void FileProtocol::slotMove( list<string>& _source, const char *_dest ){ doCopy( _source, _dest, false, true );}void FileProtocol::slotMove( const char* _source, const char *_dest ){ list<string> lst; lst.push_back( _source ); doCopy( lst, _dest, true, true );}void FileProtocol::doCopy( list<string>& _source, const char *_dest, bool _rename, bool _move ) { if ( _rename ) assert( _source.size() == 1 ); debug( "kio_file : Making copy to %s", _dest ); // Check wether the URLs are wellformed list<string>::iterator soit = _source.begin(); for( ; soit != _source.end(); ++soit ) { debug( "kio_file : Checking %s", soit->c_str() ); K2URL usrc( *soit ); if ( usrc.isMalformed() ) { error( ERR_MALFORMED_URL, soit->c_str() ); m_cmd = CMD_NONE; return; } if ( !usrc.isLocalFile() ) { error( ERR_INTERNAL, "kio_file got non local file as source in copy command" ); m_cmd = CMD_NONE; return; } } debug( "kio_file : All URLs ok %s", _dest ); // Make a copy of the parameter. if we do IPC calls from here, then we overwrite // our argument. This is tricky! ( but saves memory and speeds things up ) string dest = _dest; // Check wellformedness of the destination K2URL udest( dest ); if ( udest.isMalformed() ) { error( ERR_MALFORMED_URL, dest.c_str() ); m_cmd = CMD_NONE; return; } debug( "kio_file : Dest ok %s", dest.c_str() ); // Extract destinations right most protocol list<K2URL> lst; if ( !K2URL::split( dest.c_str(), lst ) ) { error( ERR_MALFORMED_URL, dest.c_str() ); m_cmd = CMD_NONE; return; } // Find IO server for destination string exec = ProtocolManager::self()->find( lst.back().protocol() ); if ( exec.empty() ) { error( ERR_UNSUPPORTED_PROTOCOL, lst.back().protocol() ); m_cmd = CMD_NONE; return; } // Is the right most protocol a filesystem protocol ? if ( ProtocolManager::self()->outputType( lst.back().protocol() ) != ProtocolManager::T_FILESYSTEM ) { error( ERR_PROTOCOL_IS_NOT_A_FILESYSTEM, lst.back().protocol() ); m_cmd = CMD_NONE; return; } debug( "kio_file : IO server ok %s", dest.c_str() ); // Get a list of all source files and directories list<Copy> files; list<CopyDir> dirs; int size = 0; debug( "kio_file : Iterating" ); soit = _source.begin(); debug( "kio_file : Looping" ); for( ; soit != _source.end(); ++soit ) { debug( "kio_file : Executing %s", soit->c_str() ); K2URL usrc( *soit ); debug( "kio_file : Parsed URL" ); // Did an error occur ? int s; if ( ( s = listRecursive( usrc.path(), files, dirs, _rename ) ) == -1 ) { // Error message is already sent m_cmd = CMD_NONE; return; } // Sum up the total amount of bytes we have to copy size += s; } debug( "kio_file : Recursive 1 %s", dest.c_str() ); // Check wether we do not copy a directory in itself or one of its subdirectories struct stat buff2; if ( udest.isLocalFile() && stat( udest.path(), &buff2 ) == 0 ) { bool b_error = false; for( soit = _source.begin(); soit != _source.end(); ++soit ) { K2URL usrc( *soit ); struct stat buff1; // Can we stat both the source, too ? ( Should always be the case ) if ( stat( usrc.path(), &buff1 ) == 0 ) { bool b_error = false; // Are source and dest equal ? => error if ( buff1.st_ino == buff2.st_ino ) b_error = true; } } if ( !b_error ) { // Iterate over all subdirectories list<CopyDir>::iterator it = dirs.begin(); for( ; it != dirs.end() && !b_error; it++ ) if ( buff2.st_ino == it->m_ino ) b_error = true; } // Do we have a cyclic copy now ? => error if ( b_error ) { error( ERR_CYCLIC_COPY, soit->c_str() ); m_cmd = CMD_NONE; return; } } debug( "kio_file : Recursive ok %s", dest.c_str() ); m_cmd = CMD_GET; // Start a server for the destination protocol Slave slave( exec.c_str() ); if ( slave.pid() == -1 ) { error( ERR_CANNOT_LAUNCH_PROCESS, exec.c_str() ); m_cmd = CMD_NONE; return; } // Put a protocol on top of the job FileIOJob job( &slave, this ); debug( "kio_file : Job started ok %s", dest.c_str() ); // Tell our client what we 'r' gonna do totalSize( size ); totalFiles( files.size() ); totalDirs( dirs.size() ); int processed_files = 0; int processed_dirs = 0; int processed_size = 0; // Replace the relative destinations with absolut destinations // by prepending the destinations path string tmp1 = lst.back().path( 1 ); // Strip '/' string tmp1_stripped = lst.back().path( -1 ); list<CopyDir>::iterator dit = dirs.begin(); for( ; dit != dirs.end(); dit++ ) { string tmp2 = dit->m_strRelDest; if ( _rename ) dit->m_strRelDest = tmp1_stripped; else dit->m_strRelDest = tmp1; dit->m_strRelDest += tmp2; } list<Copy>::iterator fit = files.begin(); for( ; fit != files.end(); fit++ ) { string tmp2 = fit->m_strRelDest; if ( _rename ) // !!! && fit->m_strRelDest == "" ) fit->m_strRelDest = tmp1_stripped; else fit->m_strRelDest = tmp1; fit->m_strRelDest += tmp2; } debug( "kio_file : Destinations ok %s", dest.c_str() ); /***** * Make directories *****/ m_bIgnoreJobErrors = true; bool overwrite_all = false; bool auto_skip = false; list<string> skip_list; list<string> overwrite_list; // Create all directories dit = dirs.begin(); for( ; dit != dirs.end(); dit++ ) { // Repeat until we got no error do { job.clearError(); list<K2URL> l( lst ); l.back().setPath( dit->m_strRelDest.c_str() ); string d; list<K2URL>::iterator it = l.begin(); for( ; it != l.end(); it++ ) d += it->url(); // Is this URL on the skip list ? bool skip = false; list<string>::iterator sit = skip_list.begin(); for( ; sit != skip_list.end() && !skip; sit++ ) // Is d a subdirectory of *sit ? if ( strncmp( sit->c_str(), d.c_str(), sit->size() ) == 0 ) skip = true; if ( skip ) continue; // Is this URL on the overwrite list ? bool overwrite = false; list<string>::iterator oit = overwrite_list.begin(); for( ; oit != overwrite_list.end() && !overwrite; oit++ ) if ( strncmp( oit->c_str(), d.c_str(), oit->size() ) == 0 ) overwrite = true; if ( overwrite ) continue; // Tell what we are doing makingDir( d.c_str() ); // debug( "kio_file : Making remote dir %s", d ); // Create the directory job.mkdir( d.c_str(), dit->m_mode ); while( !job.hasFinished() ) job.dispatch(); // Did we have an error ? if ( job.hasError() ) { // Can we prompt the user and ask for a solution ? if ( /* m_bGUI && */ job.errorId() == ERR_DOES_ALREADY_EXIST ) { string old_path = l.back().path( 1 ); string old_url = l.back().url( 1 ); // Should we skip automatically ? if ( auto_skip ) { job.clearError(); // We dont want to copy files in this directory, so we put it on the skip list. skip_list.push_back( old_url ); continue; } else if ( overwrite_all ) { job.clearError(); continue; } string n; /* RenameDlg_Mode m = (RenameDlg_Mode)( M_SINGLE | M_OVERWRITE ); if ( dirs.size() > 1 ) m = (RenameDlg_Mode)(M_MULTI | M_SKIP | M_OVERWRITE ); */ RenameDlg_Mode m = (RenameDlg_Mode)( M_MULTI | M_SKIP | M_OVERWRITE ); string tmp2 = l.back().url(); RenameDlg_Result r = open_RenameDlg( dit->m_strAbsSource.c_str(), tmp2.c_str(), m, n ); if ( r == R_CANCEL ) { error( ERR_USER_CANCELED, "" ); m_cmd = CMD_NONE; return; } else if ( r == R_RENAME ) { K2URL u( n.c_str() ); // The Dialog should have checked this. if ( u.isMalformed() ) assert( 0 ); // The new path with trailing '/' string tmp3 = u.path( 1 ); renamed( tmp3.c_str() ); /////// // Replace old path with tmp3 /////// list<CopyDir>::iterator dit2 = dit; // Change the current one and strip the trailing '/' dit2->m_strRelDest = u.path( -1 ); // Change the name of all subdirectories dit2++; for( ; dit2 != dirs.end(); dit2++ ) if ( strncmp( dit2->m_strRelDest.c_str(), old_path.c_str(), old_path.size() ) == 0 ) dit2->m_strRelDest.replace( 0, old_path.size(), tmp3 ); // Change all filenames list<Copy>::iterator fit2 = files.begin(); for( ; fit2 != files.end(); fit2++ ) if ( strncmp( fit2->m_strRelDest.c_str(), old_path.c_str(), old_path.size() ) == 0 ) fit2->m_strRelDest.replace( 0, old_path.size(), tmp3 ); // Dont clear error => we will repeat the current command } else if ( r == R_SKIP ) { // Skip all files and directories that start with 'old_url' skip_list.push_back( old_url ); // Clear the error => The current command is not repeated => skipped job.clearError(); } else if ( r == R_AUTO_SKIP ) { // Skip all files and directories that start with 'old_url' skip_list.push_back( old_url ); // Clear the error => The current command is not repeated => skipped job.clearError(); auto_skip = true; } else if ( r == R_OVERWRITE ) { // Dont bother for subdirectories overwrite_list.push_back( old_url ); // Clear the error => The current command is not repeated => we will // overwrite every file in this directory or any of its subdirectories job.clearError(); } else if ( r == R_OVERWRITE_ALL ) { job.clearError(); overwrite_all = true; } else assert( 0 ); } // No need to ask the user, so raise an error else { error( job.errorId(), job.errorText() ); m_cmd = CMD_NONE; return; } } } while( job.hasError() ); processedDirs( ++processed_dirs ); } debug( "kio_file : Created directories %s", dest.c_str() ); /***** * Copy files *****/ time_t t_start = time( 0L ); time_t t_last = t_start; fit = files.begin(); for( ; fit != files.end(); fit++ ) { bool overwrite = false; bool skip_copying = false; // Repeat until we got no error do { job.clearError(); list<K2URL> l( lst ); l.back().setPath( fit->m_strRelDest.c_str() ); // debug( "kio_file : ########### SET Path to '%s'", fit->m_strRelDest.c_str() ); string d; list<K2URL>::iterator it = l.begin(); for( ; it != l.end(); it++ ) d += it->url(); // Is this URL on the skip list ?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -