1 /* === S Y N F I G ========================================================= */
2 /*! \file autorecover.cpp
3 ** \brief Template File
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** General Public License for more details.
21 /* ========================================================================= */
23 /* === H E A D E R S ======================================================= */
32 #include "autorecover.h"
34 #ifdef HAVE_SYS_ERRNO_H
35 #include <sys/errno.h>
39 #include <synfig/savecanvas.h>
40 #include <synfig/loadcanvas.h>
45 #ifdef HAVE_SYS_STAT_H
49 #ifdef HAVE_SYS_TIME_H
53 #ifdef HAVE_SYS_WAIT_H
57 #ifdef HAVE_SYS_RESOURCE_H
58 #include <sys/resource.h>
69 /* === U S I N G =========================================================== */
73 using namespace synfig;
74 using namespace studio;
76 /* === M A C R O S ========================================================= */
79 #define mkdir(x,y) mkdir(x)
82 /* === G L O B A L S ======================================================= */
84 /* === P R O C E D U R E S ================================================= */
86 /* === M E T H O D S ======================================================= */
88 AutoRecover::AutoRecover()
91 set_timeout(3*60*1000);
93 if(mkdir(get_shadow_directory().c_str(),ACCESSPERMS)<0)
96 synfig::error("UNABLE TO CREATE \"%s\"",get_shadow_directory().c_str());
100 synfig::info("Created directory \"%s\"",get_shadow_directory().c_str());
104 AutoRecover::~AutoRecover()
109 AutoRecover::get_shadow_directory()
111 return Glib::build_filename(App::get_user_app_directory(),"tmp");
122 AutoRecover::set_timeout(int milliseconds)
124 timeout=milliseconds;
125 auto_backup_connect.disconnect();
127 auto_backup_connect=Glib::signal_timeout().connect(sigc::ptr_fun(&AutoRecover::auto_backup),timeout);
128 // auto_backup_connect=App::main.get_context()->signal_timeout().connect(sigc::mem_fun(&AutoRecover::auto_backup),timeout);
132 AutoRecover::get_shadow_file_name(const synfig::String& filename)
134 unsigned int hash1(0xdeadbeef);
135 unsigned int hash2(0x83502529);
136 char* str_hash1(reinterpret_cast<char*>(&hash1));
137 char* str_hash2(reinterpret_cast<char*>(&hash2));
139 // First we need to hash up the directory
141 String pool(dirname(filename));
145 str_hash1[0]^=pool[1];str_hash1[1]^=pool[2];str_hash1[2]^=pool[3];str_hash1[3]^=pool[0];
146 str_hash2[3]+=pool[0];str_hash2[2]+=pool[1];str_hash2[1]+=pool[2];str_hash2[0]+=pool[3];
148 pool=String(pool,4,pool.size());
152 str_hash1[0]^=pool[0];
153 str_hash1[2]^=pool[0];
154 str_hash2[1]^=pool[0];
155 str_hash2[3]^=pool[0];
157 pool=String(pool,1,pool.size());
162 return Glib::build_filename(get_shadow_directory(),strprintf("%08X-%s",hash1,basename(filename).c_str()));
164 // return dirname(filename) + ETL_DIRECTORY_SEPARATOR + ".shadow_" + basename(filename);
168 AutoRecover::cleanup_pid(int pid)
172 if(waitpid(pid,&status,WNOHANG)==-1)
174 synfig::info("PID %d isn't a zombie yet",pid);
177 if(WEXITSTATUS(status)!=0)
179 synfig::error("Autobackup seems to have failed! (PID=%d)",pid);
182 synfig::info("PID=%d has been cleaned up",pid);
188 AutoRecover::auto_backup()
198 #ifdef HAVE_SETPRIORITY
199 // make us low priority so that we don't
200 // cause the machine to slow down too much
201 setpriority(PRIO_PROCESS,0,15);
206 std::list<etl::handle<Instance> >::iterator iter;
208 std::string filename=App::get_config_file("autorecovery");
209 std::ofstream file(filename.c_str());
213 for(iter=App::instance_list.begin();iter!=App::instance_list.end();++iter)
215 // If this file hasn't even been changed
216 // since it was last saved, then don't bother
218 if((*iter)->get_action_count()==0)
221 Canvas::Handle canvas((*iter)->get_canvas());
222 file<<canvas->get_file_name()<<endl;
223 save_canvas(get_shadow_file_name(canvas->get_file_name()),canvas);
228 synfig::info("AutoRecover::auto_backup(): %d Files backed up.",savecount);
232 synfig::error("AutoRecover::auto_backup(): UNKNOWN EXCEPTION THROWN.");
233 synfig::error("AutoRecover::auto_backup(): FILES NOT BACKED UP.");
245 Glib::signal_timeout().connect(
247 sigc::ptr_fun(&AutoRecover::cleanup_pid),
254 // Also go ahead and save the settings
255 App::save_settings();
261 AutoRecover::recovery_needed()const
263 std::string filename=App::get_config_file("autorecovery");
264 std::ifstream file(filename.c_str());
270 std::string filename;
271 getline(file,filename);
272 if(!filename.empty())
280 AutoRecover::recover()
282 std::string filename=App::get_config_file("autorecovery");
283 std::ifstream file(filename.c_str());
290 std::string filename;
291 getline(file,filename);
296 if(App::open_as(get_shadow_file_name(filename),filename))
298 // Correct the file name
299 App::instance_list.back()->set_file_name(filename);
301 // This file isn't saved! mark it as such
302 App::instance_list.back()->inc_action_count();
312 AutoRecover::normal_shutdown()
314 // Turn off the timer
315 auto_backup_connect.disconnect();
317 std::string filename=App::get_config_file("autorecovery");
318 remove(filename.c_str());
322 AutoRecover::clear_backup(synfig::Canvas::Handle canvas)
325 remove(get_shadow_file_name(canvas->get_file_name()).c_str());