1 /*
2   FXiTe - The Free eXtensIble Text Editor
3   Copyright (c) 2009 Jeffrey Pohlmeyer <yetanothergeek@gmail.com>
4 
5   This program is free software; you can redistribute it and/or modify it
6   under the terms of the GNU General Public License version 3 as
7   published by the Free Software Foundation.
8 
9   This software is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13 
14   You should have received a copy of the GNU General Public License
15   along with this program; if not, write to the Free Software
16   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18 
19 
20 #include <unistd.h>
21 #include <cerrno>
22 #include <fx.h>
23 
24 #include "scidoc_util.h"
25 #include "compat.h"
26 
27 #include "intl.h"
28 #include "backup.h"
29 
30 
31 #define ErrorMessage(fmt, fn) \
32 { \
33   if (mainwin->shown()) { \
34     FXMessageBox::error(mainwin, \
35       MBOX_OK, _("Autosave Error"), "%s:\n%s\n(%s)", fmt,fn.text(), lasterror.text()); \
36   } else { \
37     FXMessageBox::error(FXApp::instance(), \
38       MBOX_OK, _("Autosave Error"), "%s:\n%s\n(%s)", fmt, fn.text(), lasterror.text()); \
39   } \
40 }
41 
42 
43 
MakePath(const FXString & path)44 bool BackupMgr::MakePath(const FXString& path)
45 {
46   lasterror="";
47   FXString parts=FXPath::absolute(path);
48   FXString dirs=FXPath::root(parts);
49   parts.append(PATHSEP);
50   FXint nseps=parts.contains(PATHSEP);
51   FXint i;
52   for (i=1;i<nseps;i++) {
53     dirs.append(parts.section(PATHSEP,i));
54     if (!(IsDir(dirs)||FXDir::create(dirs,FXIO::OwnerFull))) {
55       lasterror=SystemErrorStr();
56       ErrorMessage(_("Failed to create backup directory"), dirs);
57       return false;
58     }
59     dirs.append(PATHSEP);
60   }
61   return true;
62 }
63 
64 
65 
BackupMgr(FXMainWindow * w,const FXString & configdir)66 BackupMgr::BackupMgr(FXMainWindow*w, const FXString &configdir)
67 {
68   mainwin=w;
69   backupdir=configdir;
70   backupdir=FXPath::directory(backupdir);
71   backupdir=FXPath::directory(backupdir);
72   backupdir.append(PATHSEP);
73   backupdir.append("backups.d");
74   MakePath(backupdir);
75   backupdir.append(PATHSEP);
76 }
77 
78 #ifdef WIN32
79 # define FN_FMT "%s%d-%p"
80 #else
81 # define FN_FMT "%s%d-%lx"
82 #endif
83 
84 
SaveBackup(SciDoc * sci)85 bool BackupMgr::SaveBackup(SciDoc*sci)
86 {
87   FXString savename;
88   FXString untitled;
89   untitled.format(FN_FMT, backupdir.text(), abs(getpid()), SciDocUtils::ID(sci));
90   if (SciDocUtils::Filename(sci).empty()) {
91     savename=untitled;
92   } else {
93     if (FXStat::isFile(untitled)) {
94       RemoveBackup(untitled);
95     }
96 #ifdef WIN32
97     savename=SciDocUtils::Filename(sci).text();
98     savename.substitute(':', '%', true);
99     savename.prepend(backupdir.text());
100 #else
101     savename.format("%s%s", backupdir.text(), SciDocUtils::Filename(sci).text());
102 #endif
103   }
104   if (MakePath(FXPath::directory(savename))) {
105     if (SciDocUtils::SaveToFile(sci,savename.text(),false)) {
106       SciDocUtils::NeedBackup(sci, false);
107       return true;
108     } else {
109       lasterror=SciDocUtils::GetLastError(sci);
110       ErrorMessage(_("Failed to save backup"), savename);
111       return false;
112     }
113   } else {
114     return false;
115   }
116 }
117 
118 
119 
RemoveBackup(const FXString & filename)120 void BackupMgr::RemoveBackup(const FXString&filename) {
121   if (FXFile::remove(filename)) {
122     FXString dir=filename;
123     while (1) {
124       dir=FXPath::directory(dir);
125       if ( (dir+PATHSEP) == backupdir ) { break; }
126       if (!FXDir::remove(dir)) { break; }
127     }
128   }
129 }
130 
131 
132 
RemoveBackup(SciDoc * sci)133 void BackupMgr::RemoveBackup(SciDoc*sci)
134 {
135   FXString untitled;
136   SciDocUtils::NeedBackup(sci,false);
137   untitled.format(FN_FMT, backupdir.text(), abs(getpid()), SciDocUtils::ID(sci));
138   RemoveBackup(untitled);
139   if (!SciDocUtils::Filename(sci).empty()) {
140     FXString savename;
141 #ifdef WIN32
142     savename=SciDocUtils::Filename(sci).text();
143     savename.substitute(':', '%', true);
144     savename.prepend(backupdir.text());
145 #else
146     savename.format("%s%s", backupdir.text(), SciDocUtils::Filename(sci).text());
147 #endif
148     RemoveBackup(savename);
149   }
150 }
151 
152