X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-studio%2Ftags%2Fsynfigstudio_%40VERSION_MAJ%40_%40VERSION_MIN%40_%40VERSION_REV%40%2Fsrc%2Fgtkmm%2Fautorecover.cpp;fp=synfig-studio%2Ftags%2Fsynfigstudio_%40VERSION_MAJ%40_%40VERSION_MIN%40_%40VERSION_REV%40%2Fsrc%2Fgtkmm%2Fautorecover.cpp;h=1b55eb4a23edd6e38648f0cfdc6128ea6eaa8b1a;hb=d98a5bdd45e2c836aa7996f22516008f1ce29947;hp=0000000000000000000000000000000000000000;hpb=c33037508a9f5a0607b14f3feed692a0d364d68a;p=synfig.git diff --git a/synfig-studio/tags/synfigstudio_@VERSION_MAJ@_@VERSION_MIN@_@VERSION_REV@/src/gtkmm/autorecover.cpp b/synfig-studio/tags/synfigstudio_@VERSION_MAJ@_@VERSION_MIN@_@VERSION_REV@/src/gtkmm/autorecover.cpp new file mode 100644 index 0000000..1b55eb4 --- /dev/null +++ b/synfig-studio/tags/synfigstudio_@VERSION_MAJ@_@VERSION_MIN@_@VERSION_REV@/src/gtkmm/autorecover.cpp @@ -0,0 +1,330 @@ +/* === S Y N F I G ========================================================= */ +/*! \file autorecover.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "autorecover.h" + +#ifdef HAVE_SYS_ERRNO_H +#include +#endif +//#include +#include "app.h" +#include +#include +#include +#include +#include "instance.h" + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +#ifdef _WIN32 +#define mkdir(x,y) mkdir(x) +#endif + +/* === G L O B A L S ======================================================= */ + +/* === P R O C E D U R E S ================================================= */ + +/* === M E T H O D S ======================================================= */ + +AutoRecover::AutoRecover() +{ + // Three Minutes + set_timeout(3*60*1000); + + if(mkdir(get_shadow_directory().c_str(),ACCESSPERMS)<0) + { + if(errno!=EEXIST) + synfig::error("UNABLE TO CREATE \"%s\"",get_shadow_directory().c_str()); + } + else + { + synfig::info("Created directory \"%s\"",get_shadow_directory().c_str()); + } +} + +AutoRecover::~AutoRecover() +{ +} + +synfig::String +AutoRecover::get_shadow_directory() +{ + return Glib::build_filename(App::get_user_app_directory(),"tmp"); +} + +int +AutoRecover::pid() +{ +// return getpid(); + return 0; +} + +void +AutoRecover::set_timeout(int milliseconds) +{ + timeout=milliseconds; + auto_backup_connect.disconnect(); + if(timeout) + auto_backup_connect=Glib::signal_timeout().connect(sigc::ptr_fun(&AutoRecover::auto_backup),timeout); +// auto_backup_connect=App::main.get_context()->signal_timeout().connect(sigc::mem_fun(&AutoRecover::auto_backup),timeout); +} + +synfig::String +AutoRecover::get_shadow_file_name(const synfig::String& filename) +{ + unsigned int hash1(0xdeadbeef); + unsigned int hash2(0x83502529); + char* str_hash1(reinterpret_cast(&hash1)); + char* str_hash2(reinterpret_cast(&hash2)); + + // First we need to hash up the directory + { + String pool(dirname(filename)); + + while(pool.size()>4) + { + str_hash1[0]^=pool[1];str_hash1[1]^=pool[2];str_hash1[2]^=pool[3];str_hash1[3]^=pool[0]; + str_hash2[3]+=pool[0];str_hash2[2]+=pool[1];str_hash2[1]+=pool[2];str_hash2[0]+=pool[3]; + swap(hash1,hash2); + pool=String(pool,4,pool.size()); + } + while(pool.size()) + { + str_hash1[0]^=pool[0]; + str_hash1[2]^=pool[0]; + str_hash2[1]^=pool[0]; + str_hash2[3]^=pool[0]; + swap(hash1,hash2); + pool=String(pool,1,pool.size()); + } + } + hash1^=hash2; + + return Glib::build_filename(get_shadow_directory(),strprintf("%08X-%s",hash1,basename(filename).c_str())); + +// return dirname(filename) + ETL_DIRECTORY_SEPARATOR + ".shadow_" + basename(filename); +} + +bool +AutoRecover::cleanup_pid(int pid) +{ +#ifdef HAVE_FORK + int status=0; + if(waitpid(pid,&status,WNOHANG)==-1) + { + synfig::info("PID %d isn't a zombie yet",pid); + return true; + } + if(WEXITSTATUS(status)!=0) + { + synfig::error("Autobackup seems to have failed! (PID=%d)",pid); + } +// else +// synfig::info("PID=%d has been cleaned up",pid); +#endif + return false; +} + +bool +AutoRecover::auto_backup() +{ + int pid(0); + +#ifdef HAVE_FORK + pid=fork(); +#endif + + if(pid<=0) + { +#ifdef HAVE_SETPRIORITY + // make us low priority so that we don't + // cause the machine to slow down too much + setpriority(PRIO_PROCESS,0,15); +#endif + + try + { + std::list >::iterator iter; + + std::string filename=App::get_config_file("autorecovery"); + std::ofstream file(filename.c_str()); + + int savecount(0); + + for(iter=App::instance_list.begin();iter!=App::instance_list.end();++iter) + { + // If this file hasn't even been changed + // since it was last saved, then don't bother + // backing it up. + if((*iter)->get_action_count()==0) + continue; + + Canvas::Handle canvas((*iter)->get_canvas()); + file<get_file_name()<get_file_name()),canvas); + savecount++; + } + +// if(savecount) +// synfig::info("AutoRecover::auto_backup(): %d Files backed up.",savecount); + } + catch(...) + { + synfig::error("AutoRecover::auto_backup(): UNKNOWN EXCEPTION THROWN."); + synfig::error("AutoRecover::auto_backup(): FILES NOT BACKED UP."); + } + +#ifdef HAVE_FORK + if(pid==0) + { + _exit(0); + } +#endif + } + +#ifdef HAVE_FORK + Glib::signal_timeout().connect( + sigc::bind( + sigc::ptr_fun(&AutoRecover::cleanup_pid), + pid + ), + 60*1000 + ); +#endif + + // Also go ahead and save the settings + App::save_settings(); + + return true; +} + +bool +AutoRecover::recovery_needed()const +{ + std::string filename=App::get_config_file("autorecovery"); + std::ifstream file(filename.c_str()); + if(!file) + return false; + + while(file) + { + std::string filename; + getline(file,filename); + if(!filename.empty()) + return true; + } + + return false; +} + +bool +AutoRecover::recover(int& number_recovered) +{ + std::string filename=App::get_config_file("autorecovery"); + std::ifstream file(filename.c_str()); + number_recovered = 0; + if(!file) + return false; + bool success=true; + + while(file) + { + std::string filename; + getline(file,filename); + if(filename.empty()) + continue; + + // Open the file + if(App::open_as(get_shadow_file_name(filename),filename)) + { + // Correct the file name + App::instance_list.back()->set_file_name(filename); + + // This file isn't saved! mark it as such + App::instance_list.back()->inc_action_count(); + + number_recovered++; + } + else + success=false; + } + + return success; +} + +void +AutoRecover::normal_shutdown() +{ + // Turn off the timer + auto_backup_connect.disconnect(); + + std::string filename=App::get_config_file("autorecovery"); + remove(filename.c_str()); +} + +void +AutoRecover::clear_backup(synfig::Canvas::Handle canvas) +{ + if(canvas) + remove(get_shadow_file_name(canvas->get_file_name()).c_str()); +}