#include #include #include #include #include #include #include NETWORK_H #define WEB_SOURCE_PORT 80 string array allnames = ({}); string array tmpnames; string reverts_dir, revert_name; static string upgrade_prefix = "/code/upgrades/"+mudlib_version(); static string reverts_prefix = "/secure/upgrades/reverts/"+mudlib_version(); static string upgrades_txt = "/secure/upgrades/txt"; static string upgrades_files = "/secure/upgrades/files"; static int i = 0; static int oob = 0; static object player = 0; int patched, transver = 0; static mapping NewFiles = ([]); static string SaveFile; void create(){ #ifdef ENABLE_INSTANCES SaveFile = save_file(SAVE_LIVEUPGRADE); if( unguarded( (: file_exists(SaveFile) :) ) ){ unguarded( (: restore_object(SaveFile) :) ); } #endif if(false()){ object uu = find_object("/secure/daemon/update"); if(uu) uu->eventDestruct(); if(uu) destruct(uu); patched = 1; unguarded( (: cp("/secure/daemon/update.patch", "/secure/daemon/update.c") :) ); unguarded( (: reload("/secure/daemon/update.c") :) ); } } int eventDestruct(){ #ifdef ENABLE_INSTANCES if(directory_exists(path_prefix(SaveFile))){ unguarded( (: save_object(SaveFile) :) ); } #endif destruct(); return 1; } int eventBackup(string file){ string tmp, time_str,short_name,filename; if(!file) return 0; if(!file_exists(file)) return -1; if( !(tmp = read_file(file)) ) return -2; time_str = time()+"."+random_numbers(5); short_name = last_string_element(file,"/"); if(!revert_name){ revert_name = itoa(time()); } if(!reverts_prefix){ reverts_prefix = "/secure/upgrades/reverts/"+mudlib_version(); } if(!directory_exists("/secure/upgrades/reverts/")){ mkdir("/secure/upgrades/reverts"); } if(!directory_exists(reverts_prefix)){ mkdir(reverts_prefix); } if(!directory_exists(reverts_prefix+"/"+revert_name)){ mkdir(reverts_prefix+"/"+revert_name); } filename = reverts_prefix+"/"+revert_name+ "/"+short_name+"."+time_str; write_file(reverts_prefix+"/"+revert_name+"/"+ "/bk.db",short_name+"."+time_str+" : "+file+"\n"); cp(file,filename); return 1; } int eventRevert(string revert_path){ string *files; if(!revert_path){ return 0; } if(!directory_exists(revert_path)){ return -1; } if(!file_exists(revert_path+"/bk.db")){ return -2; } files = explode(read_file(revert_path+"/bk.db"),"\n"); if(!files || !sizeof(files)){ return -3; } foreach(string line in files){ string backup, target; if(sscanf(line,"%s : %s", backup, target) != 2) continue; if(!directory_exists(path_prefix(target))){ mkdir_recurse(path_prefix(target)); } cp(revert_path+"/"+backup, target); } return 1; } void eventReloads(){ cp("/secure/daemon/update.patch","/secure/daemon/update.c"); reload(UPDATE_D); reload(LUGET_D); } int eventCopy(string element){ string path; if(!NewFiles[element]) return 0; path = path_prefix(NewFiles[element]); if(!directory_exists(path)) mkdir_recurse(path); rename(element, NewFiles[element]); return 1; } mixed cmd(string str) { string mud = "Dead Souls"; string file; string orig_str = str; int foo, tmpint = 0; object inet = find_object(INET_D); string *preload_file = explode(read_file(CFG_PRELOAD),"\n"); mixed *socks = socket_status(); NewFiles = ([]); if(!revert_name){ revert_name = itoa(time()); } if(!str || str == ""){ write("Try: help liveupgrade."); return 1; } if(str == "alpha"){ if(transver){ transver = 0; write("Alpha/Stable upgrades disabled."); return 1; } if(!transver){ transver = 1; write("Alpha/Stable upgrades enabled."); return 1; } } if(str == "revert"){ string *vers = get_dir("/secure/upgrades/reverts/"); string ver, subver; if(!vers || !sizeof(vers)){ write("There is no previous backup to revert to."); return 1; } else ver = vers[0]; vers = get_dir("/secure/upgrades/reverts/"+ver+"/"); if(!vers || !sizeof(vers)){ write("There is no backup instance to revert to."); return 1; } else subver = "/secure/upgrades/reverts/"+ver+"/"+vers[0]; eventRevert(subver); rename(subver,"/secure/upgrades/bak/"+last_string_element(subver,"/")); rmdir(path_prefix(subver)); write("Reversion complete."); return 1; } foreach(mixed element in socks){ if(element[1] == "DATA_XFER" && element[4] == WEB_SOURCE_IP+"."+WEB_SOURCE_PORT && str != "cancel"){ player->eventPrint("A download is still in progress. Please wait until it is complete."); return 1; } } if(!player && this_player()) player = this_player(); allnames = ({}); if(!player) return 0; if( !(master()->valid_apply(({ "SECURE" }))) ) error("Illegal attempt to access liveupgrade: "+get_stack()+" "+identify(previous_object(-1))); if(!directory_exists("/secure/upgrades/bak")){ mkdir("/secure/upgrades/bak"); } if(!directory_exists(reverts_prefix)){ mkdir(reverts_prefix); } i = sscanf(mudlib_version(),"2.3a%d",tmpint); if(i && tmpint < 12) oob = 1; else { if(!strsrch(str,"-o ")){ oob = 1; str = replace_string(str,"-o ",""); } else oob = 0; } i = 0; foo = sscanf(str,"%s %s",file, mud); if(!foo || foo < 2) file = str; if(str == "apply" || str == "deferred"){ string *files = ({}); string nlu, secs = upgrades_files+"/0^0secure0^0include0^0secrets.h"; object nlob; if(file_exists(SECRETS_H)){ catch( cp(SECRETS_H, "/secure/save/backup/secrets_" + imc2_mud_name() + "." + time() + ".bak") ); } if(file_exists(secs)) catch( rm(secs) ); nlu = upgrades_files+"/0^0secure0^0cmds0^0admins0^0liveupgrade.c"; if(file_exists(nlu)){ catch( nlob = load_object(nlu) ); if(nlob && nlob->GetDeferment() && str != "deferred"){ nlob->eventDestruct(); return 1; } if(nlob) nlob->eventDestruct(); if(!rename(nlu, CMD_LIVEUPGRADE)){ write("The liveupgrade command has been updated."); write("Please wait five seconds, then again type:\n"); write("liveupgrade apply"); if(!(this_object()->eventDestruct())){ RELOAD_D->eventReload(this_object(), 0); } return 1; } } player->eventPrint("I hope you backed up...\n"); foreach(string element in get_dir(upgrades_files+"/")){ if(element == "0^0secure0^0sefun0^0mud_info.c"){ object thingy = load_object(upgrades_files+"/"+element); string vers; if(thingy){ string current_ver = mudlib_version(); vers = thingy->mudlib_version(); if(((grepp(vers,"a") && !grepp(current_ver, "a")) || (!grepp(vers,"a") && grepp(current_ver, "a"))) && !transver){ write("This upgrade would cross stable/alpha " "boundaries, but that has not been enabled " "with \"liveupgrade alpha\" yet."); return 1; } } } files += ({ upgrades_files+"/"+element }); } foreach(string element in files){ string contents = ""; NewFiles[element] = replace_string(replace_string(element,"0^0","/"), upgrades_files+"/",""); contents = read_file(element); if(!contents) contents = ""; if(last(contents,1) != "\n") contents += "\n"; write_file(element, contents, 1); reset_eval_cost(); call_out( (: eventBackup :), 0, NewFiles[element]); if(directory_exists(NewFiles[element])) true(); else { call_out( (: eventCopy :), 0, element); } } if(member_array(INET_D,preload_file) == -1 && inet) inet->eventDestruct(); call_out( (: eventReloads :), 10); patched = 0; RELOAD_D->eventReload(this_object(), 15); rm("/secure/upgrades/txt/list.txt"); player->eventPrint("\nAlmost done..."); player = 0; return 1; } if(str == "cancel"){ string *files = ({}); foreach(string element in get_dir(upgrades_files+"/")){ files += ({ upgrades_files+"/"+element }); } foreach(string element in files){ rm(element); } rm("/secure/upgrades/txt/list.txt"); player->eventPrint("Cancelled."); player = 0; RELOAD_D->eventReload(this_object(), 2); reload(LUGET_D); return 1; } if(oob){ if(!inet){ inet = load_object(INET_D); player->eventPrint("Starting INET_D."); if(member_array(INET_D,preload_file) == -1) player->eventPrint("When you complete the upgrade by using the \"apply\" keyword, the " "inet daemon will be shut down, since you do not have it enabled by " "default. Please remember to either apply the upgrades when the downloading " "is complete, or manually shut down INET_D with the command: mudconfig inet stop\n"); } if(!inet){ player->eventPrint("There is a problem with INET_D. The upgrade will not proceed."); return 1; } if(!INET_D->GetService("oob")){ player->eventPrint("The OOB service is not enabled. Enabling it now."); INET_D->AddService("oob",OFFSET_OOB,LIB_OOB,0); } if(!INET_D->GetService("oob")){ player->eventPrint("There was a problem enabling the OOB service. The upgrade will not proceed."); return 1; } if(!INET_D->GetServer("oob")){ player->eventPrint("The OOB service is not started. Starting it now."); INET_D->eventStartServer("oob"); } if(!INET_D->GetServer("oob")){ player->eventPrint("There was a problem starting the OOB service. The upgrade will not proceed."); return 1; } if(foo < 2) { mud = LIVEUPGRADE_SERVER; file = str; } if(!file){ return this_object()->GetHelp(); } mud = INTERMUD_D->GetMudName(mud); if(!mud){ player->eventPrint("That liveupgrade server appears unavailable."); return 1; } } if(file == "all"){ string tmp = replace_string(upgrades_txt+"/upgrades.txt","/","0^0"); if(player && this_player() && player != this_player()){ this_player()->eventPrint("This command is currently locked and in use by "+capitalize(player->GetKeyName())+"."); return 1; } else if(this_player()) player = this_player(); else player = this_object(); if(LUGET_D->GetUpgrading()){ player->eventPrint("An upgrade in already occurring. Please wait for it to complete."); return 1; } if(!file_exists(upgrades_txt+"/list.txt")){ player->eventPrint("Downloading updates table. Please wait..."); rename("/secure/upgrades/files","/secure/upgrades/bak/"+time()); mkdir("/secure/upgrades/files"); if(oob){ OOB_D->GetFile(mud,upgrades_txt+"/upgrades.txt"); } else { LUGET_D->GetFile(WEB_SOURCE_IP, upgrade_prefix+"/upgrades.txt",WEB_SOURCE_NAME, "/secure/upgrades/txt/list.txt",WEB_SOURCE_PORT); } call_out( (: cmd :), 5, orig_str); return 1; } tmpnames = explode(read_file(upgrades_txt+"/list.txt"),"\n"); foreach(string element in tmpnames){ if(!oob) allnames += ({ "/code/upgrades/"+mudlib_version()+element }); else allnames += ({ element }); } if(oob){ OOB_D->eventMajorUpgrade(mud, allnames); } else { LUGET_D->eventMajorUpgrade(WEB_SOURCE_IP, allnames,WEB_SOURCE_NAME); } rm(upgrades_txt+"/list.txt"); player->eventPrint("Full upgrade begun."); player->eventPrint("Please wait until you receive a completion message, "+ "then issue the command: liveupgrade apply\n\n"); player->eventPrint("%^FLASH%^RED%^WARNING! %^BLACK%^WARNING! %^YELLOW%^WARNING! %^RESET%^WARNING!"); player->eventPrint("You must *always* do a full backup before applying the liveupgrade. "+ "If the liveupgrade screwed up, and you get garbage files because of connection "+ "problems, it may be necessary for you to restore from backup to be able to "+ "start the mud again. You've been warned."); return 1; } if(oob){ OOB_D->GetFile(mud,file); player->eventPrint("Requesting the file \""+file+"\" from "+INTERMUD_D->GetMudName(mud)+"."); } else { player->eventPrint("Requesting the file \""+file+"\" from "+WEB_SOURCE_IP); LUGET_D->GetFile(WEB_SOURCE_IP, upgrade_prefix+file); } return 1; } void eventReceiveReport(string str){ if(player) player->eventPrint(str); } int GetDeferment(){ string *defers = ({ "secrets.h", "network.h", "mssp.h" }); string secs = upgrades_files+"/0^0secure0^0include0^0"; foreach(string deferment in defers){ if(file_exists(secs+deferment) && file_exists("/secure/include/"+deferment)){ rm(secs+deferment); } } return 0; } string GetHelp() { return ("Syntax: liveupgrade all\n" " liveupgrade apply\n" " liveupgrade cancel\n" " liveupgrade revert\n" " liveupgrade alpha\n\n" "To upgrade all files to the next appropriate level for your lib version:\n" "liveupgrade all\n" "Wait until you receive the completion message before finalizing the upgrade. " "You can finalize the upgrade by typing:\n" "liveupgrade apply\n" "This will delete your old copies of files and copy the newly downloaded " "ones in their place.\n" "NEVER EVER do a liveupgrade without a full backup first.\n" "To cancel the liveupgrade process:\n" "liveupgrade cancel\n" "To restore your mud to the condition it was in prior to the last liveupgrade.\n" "liveupgrade revert\n" "To enable liveupgrading between alpha and stable versions:\n" "liveupgrade alpha\n\n" "Web proxies are *NOT* supported. OOB is no longer supported."); }