/* Diff-applying tool for DSlib 'liveupgrade' command Shadyman@QS, 04-Aug-2008 Based on: // /bin/dev/_diff.c // Finds the difference between two files. // This file is a part of the TMI distribution mudlib. // Please retain this header if you use this code. // Devised & Written by Douglas Reay (Pallando @ TMI, Ephemeral Dale, etc) // Version 1.0 92-11-28 // // Watcher@TMI (93-04-10) changed it so the output is put through the // user's more pager system, and made the headlines stand out a bit better. // Pallando (93-05-28) Added this command to Dead Souls's mudlib. // Changed its name from "compare" to "diff" */ #include #include #define DOWNLOAD_PATH "/secure/upgrades/files/" #define BACKUP_PATH "/secure/upgrades/bak/" inherit LIB_DAEMON; //Prototypes int GimmeIn(string inchar); int DoneDiff(); int CheckNext(); //Variables int j = 0; //Current iteration, modified to start at 0 int started = 0; string * filesInUpdateDir = ({}); //Files we need to check string DIFFLOG = "diff.log"; string KEEPLOG = "diffkeep.log"; string currfile = ""; string currupgrade = ""; int errored = 0; //flag to tell user to check the logs int sort( string mem, mixed arr ) { return -1 == member_array( mem, arr ); } mixed get_lines( string file_name ) { string file; file_name = absolute_path( "cwd", file_name ); switch( file_size( file_name ) ) { case -2: { write( file_name + " is a directory.\n" ); return 0; } case -1: { return ""; } } if( !master()-> valid_read( file_name, previous_object(), "diff" ) ) { write( file_name + " : Permission denied.\n" ); return 0; } file = read_file( file_name ); if( !file ) return ""; return explode( file, "\n" ); } int cmd(string args) { //filesInUpdateDir = ({}); filesInUpdateDir = get_dir(DOWNLOAD_PATH); j = 0; errored = 0; log_file(DIFFLOG,"Starting diff, "+ctime(time())+"\n"); write("****************************************************\n"+ "* DIFFIT *\n"+ "* Warning! BACK UP your entire mud before diffing. *\n"+ "****************************************************\n\n"+ "Press 'S' to start diffing or 'Q' to quit :"); input_to("GimmeIn"); return 1; } int GimmeIn(string inchar) { int succeeded; switch (lower_case(inchar)) { case "k": //keep, and store that we kept it for reference log_file(DIFFLOG,"Keeping file: "+currfile+"\n"); log_file(KEEPLOG,currfile+"\n"); CheckNext(); break; case "r": //replace //Make a backup succeeded = cp(currfile, BACKUP_PATH + currupgrade+"."+time()+".bak"); if (!succeeded) { errored = 1; write("Backing up "+currfile+" failed."); log_file(DIFFLOG,"ERROR: Backup of "+currfile+" failed\n"); return 0; } //Move the new one in succeeded = cp(DOWNLOAD_PATH + currupgrade,currfile); if (!succeeded) { errored = 1; write("Writing new "+currfile+" failed."); log_file(DIFFLOG,"ERROR: Replacement of "+currfile+" failed\n"); return 0; } CheckNext(); break; case "s": CheckNext(); break; case "q": return 1; break; default: //Ask again if (started == 0) { //If we haven't started diffing //Ask S/Q again write("Would you like to 'S'tart diffing, or 'Q'uit? :"); input_to("GimmeIn"); break; } else { //If we're diffing //Ask K/R/Q again write("Would you like to 'K'eep the CURRENT version, or 'R'eplace it with the UPGRADE? (Q for Quit) :"); input_to("GimmeIn"); break; } } } int CheckNext() { int sentrybit = 1; int succeeded; string pathdirs; //Get next diff, and ask again, if needed. //for (int i=j; i=sizeof(filesInUpdateDir)-1; i++) { while (sentrybit == 1) { string output; string *lines1, *lines2; string *ONEnotTWO, *TWOnotONE; if (j >= sizeof(filesInUpdateDir)-1) { //done; DoneDiff(); sentrybit = 0; continue; } //Currfile is the location in the mud filesystem that we are going to put the file currfile = replace_string(filesInUpdateDir[j],"0^0","/"); //store the target path and file //Currupgrade is the location of the new file in the download directory currupgrade = filesInUpdateDir[j]; //Store the upgrade we're working on write ("\n%^BOLD%^RED%^FILE: "+currfile+"%^RESET%^"); j++; //keep track of where we are incase we need to ask another question. //See if there's even a file where we want to write if ( !file_exists(currfile) || lines1 == ({})) { //Clear to copy write (" File does not exit. Applying update!"); //Find the path, and create any directories that were missing sscanf(currfile,"%(.+/)",pathdirs); if ( !directory_exists(pathdirs) ) mkdir_recurse(pathdirs); //Copy the file into the destination directory succeeded = cp(DOWNLOAD_PATH + currupgrade,currfile); //Error handling if (!succeeded) { errored = 1; write("Writing new "+currfile+" failed."); log_file(DIFFLOG,"Copying file: "+currfile+" FAILED\n"); } continue; //Next! } //Start the diffing lines1 = get_lines( currfile ); lines2 = get_lines( DOWNLOAD_PATH + currupgrade ); if( !pointerp( lines1 ) || !pointerp( lines2 ) ) { //No comparison made. errored = 1; write( " ERROR: No comparison made." ); log_file(DIFFLOG,"Error: No comparison made for "+currfile+"\n"); continue; //Next! } if( lines1 == lines2 ) { //They are identical. write (" File is the same as the update. Skipping..."); log_file(DIFFLOG,"Skipping file: "+currfile+" (Same as the update)\n"); continue; //Next! } ONEnotTWO = filter( lines1, "sort", this_object(), lines2 ); TWOnotONE = filter( lines2, "sort", this_object(), lines1 ); if( ONEnotTWO == TWOnotONE ) { //They have the same lines. write (" File has the same lines as the update. Skipping..."); log_file(DIFFLOG,"Skipping file: "+currfile+" (Same as the update)\n"); continue; //Next! } output = "%^BOLD%^WHITE%^[In the CURRENT version but not in the UPDATE:]%^RESET%^\n" + implode( ONEnotTWO, "\n" ) + "\n" + "\n%^BOLD%^WHITE%^[In the UPDATE but not in the CURRENT version:]%^RESET%^\n" + implode( TWOnotONE, "\n" ) + "\n" + "\n%^BOLD%^RED%^"+currfile+"%^RESET%^: Would you like to 'K'eep the CURRENT version, or 'R'eplace it with the UPGRADE? :"; sentrybit = 0; write( output ); input_to("GimmeIn"); return 1; } return 1; } int DoneDiff(){ string tempoutput; if (errored) tempoutput = "Process completed, but with errors. Check the log: "+DIFFLOG+"\n"; else tempoutput = "Done!\n"; tempoutput += "You may have to update files you 'k'ept, if any. See "+KEEPLOG+" for a list of kept files.\n"; write ( tempoutput +"\n"); return 1; } void help() { message("help", "Syntax: \n\n" "A helper tool to update your installation.\n Do a 'liveupgrade all' first before using diffit" "\n\n",this_player()); }