Subversion Repositories spk

Rev

Rev 105 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
93 cycrow 1
 
2
#include "OriginalFiles.h"
3
#include "File.h"
4
#include "Logging/Log.h"
5
#include "BaseFile.h"
6
#include "spk.h"
7
//#include "ProgressInfo.h"
8
 
9
namespace SPK {
10
 
11
void AddLogEntry(int type, CyString args, CyStringList *errors)
12
{
13
	if ( errors ) errors->PushBack(args, ERRORLOG(type));
14
}
15
 
16
 
17
COriginalFiles::COriginalFiles(const Utils::String &dir) : _sDir(dir)
18
{
19
}
20
 
21
COriginalFiles::~COriginalFiles(void)
22
{
23
	reset();
24
}
25
 
26
int COriginalFiles::count() const
27
{
28
	return _lFiles.size();
29
}
30
 
31
/**
32
 * Check for original file
33
 *
34
 * Checks if the file is an original file or not
35
 */
36
bool COriginalFiles::isOriginal(C_File *f) const
37
{
38
	if ( _getFile(f) )
39
		return true;
40
	return false;
41
}
42
 
43
void COriginalFiles::backup(CBaseFile *package, CyStringList *errors)
44
{
45
	// backup any original files before installing
46
	CLog::log(CLog::Log_Install, 3, "Checking for any original files to backup");
47
	CDirIO oDir(_sDir + "/PluginManager/Original");
48
	for ( CListNode<C_File> *oNode = _lFiles.Front(); oNode; oNode = oNode->next() )
49
	{
50
		C_File *of = oNode->Data();
51
		for ( CListNode<C_File> *checkNode = package->GetFileList()->Front(); checkNode; checkNode = checkNode->next() )
52
		{
53
			C_File *f = checkNode->Data();
54
 
55
			// match the same filetype
56
			if ( of->GetFileType() != f->GetFileType() )
57
				continue;
58
 
59
			// same file
60
			if ( of->GetFilename().Compare(f->GetFilename()) )
61
			{
62
				// check if original file already exists (assume already backed up)
63
				if ( !backupFile(of, errors) )
64
					continue;
65
				break;
66
			}
67
		}
68
	}
69
}
70
 
71
bool COriginalFiles::backupFile(C_File *f, CyStringList *errors)
72
{
73
	Utils::String newDir = "PluginManager/Original/" + f->GetDirectory(NULL).ToString();
74
	CDirIO oDir(_sDir);
75
	if ( oDir.Exists(newDir + "/" + f->GetFilename().ToString()) )
76
		return true;
77
 
78
	// make sure the directory exissts
79
	if ( !oDir.Exists(newDir) )
80
	{
81
		if ( !oDir.Create(newDir) )
82
		{
83
			CLog::logf(CLog::Log_Install, 2, "Unable to create directory to backup original files, %s", newDir.c_str());
84
			AddLogEntry(SPKINSTALL_CREATEDIRECTORY_FAIL, newDir, errors);
85
			return false;
86
		}
87
 
88
		CLog::logf(CLog::Log_Install, 2, "Created new directory, %s", newDir.c_str());
89
		AddLogEntry(SPKINSTALL_CREATEDIRECTORY, newDir, errors);
90
	}
91
 
92
	// now lets copy the file
93
	CFileIO CopyFile(f->GetFilePointer());
94
	if ( CopyFile.copy(oDir.File(newDir + "/" + f->GetFilename().ToString()).ToString()) )
95
	{
96
		CLog::logf(CLog::Log_Install, 2, "Original file: %s has been backed up", f->GetNameDirectory(NULL).c_str());
97
		AddLogEntry(SPKINSTALL_ORIGINAL_BACKUP, f->GetNameDirectory(NULL), errors);
98
		return true;
99
	}
100
	else
101
	{
102
		CLog::logf(CLog::Log_Install, 2, "Failed to backup the original file: %s", f->GetNameDirectory(NULL).c_str());
103
		AddLogEntry(SPKINSTALL_ORIGINAL_BACKUP_FAIL, f->GetNameDirectory(NULL), errors);
104
		return false;
105
	}
106
}
107
 
108
bool COriginalFiles::doBackup(C_File *f, CyStringList *errors)
109
{
110
	bool backed = false;
111
 
112
	C_File *of = this->_getFile(f);
113
	if ( of ) {
114
		// check if the orignal file is already backed up
115
		if ( !CFileIO::Exists(_sDir + "/PluginManager/Original/" + f->GetNameDirectory(NULL).ToString()) )
116
		{
117
			// lets back up the file now
118
			backed = this->backupFile(of, errors);
119
		}
120
	}
121
 
122
	return backed;
123
}
124
 
125
 
126
int COriginalFiles::restoreAll(CProgressInfo *info, int files, int max)
127
{
128
	for ( CListNode<C_File> *oNode = _lFiles.Front(); oNode; oNode = oNode->next() )
129
	{
130
		// update the progress
131
		if ( info ) info->UpdateProgress(files, max);
132
		++files;
133
 
134
		C_File *f = oNode->Data();
135
		CFileIO of(_sDir + "/PluginManager/Original/" + f->GetNameDirectory(NULL).ToString());
136
 
137
		if ( of.exists() )
138
			of.Rename(_sDir + "/" + f->GetNameDirectory(NULL).ToString());
139
 
140
		delete oNode->Data();
141
	}
142
 
143
	_lFiles.clear();
144
 
145
	return files;
146
}
147
 
148
bool COriginalFiles::restoreFile(C_File *f, CyStringList *errors)
149
{
150
	bool original = false;
151
 
152
	// check if its an original file and restore
153
	if ( this->isOriginal(f) )
154
	{
155
		CFileIO of(_sDir + "/PluginManager/Original/" + f->GetNameDirectory(NULL).ToString());
156
		if ( of.exists() )
157
		{
158
			original = true;
159
			if ( of.Rename(_sDir + "/" + f->GetNameDirectory(NULL).ToString()) )
160
				AddLogEntry(SPKINSTALL_ORIGINAL_RESTORE, f->GetNameDirectory(NULL), errors);
161
			else
162
				AddLogEntry(SPKINSTALL_ORIGINAL_RESTORE_FAIL, f->GetNameDirectory(NULL), errors);
163
		}
164
	}
165
 
166
	return original;
167
}
168
 
169
 
170
void COriginalFiles::parse(const Utils::String &data)
171
{
172
	C_File *uf = new C_File();
173
 
174
	uf->SetFileType(data.token(" ", 1).toLong());
175
 
176
	// Extra files also contain a directory, so make sure we split that up
177
	if ( uf->GetFileType() == FILETYPE_EXTRA )
178
	{
179
		uf->SetDir(data.tokens(" ", 2).tokens(":", 2));
180
		uf->SetFilename(data.tokens(" ", 2).token(":", 1));
181
	}
182
	else
183
		uf->SetFilename(data.tokens(" ", 2));
184
 
185
	// set the complete filename, GetNameDirectory returns the directory based on the file type
186
	uf->SetFilename(_sDir + "/" + uf->GetNameDirectory(NULL).ToString());
187
 
188
	_lFiles.push_back(uf);
189
}
190
 
191
void COriginalFiles::update(bool bForce, const CLinkList<C_File> *pFiles)
192
{
193
	if ( _lFiles.empty() || bForce )
194
	{
195
		_storeFiles(FILETYPE_SCRIPT, "scripts", pFiles);
196
		_storeFiles(FILETYPE_TEXT, "t", pFiles);
197
		_storeFiles(FILETYPE_SOUND, "soundtrack", pFiles);
198
		_storeFiles(FILETYPE_EXTRA, "mov", pFiles);
199
	}
200
}
201
 
202
bool COriginalFiles::writeData(CyStringList *lines)
203
{
204
	bool addAny = false;
205
 
206
	if ( !_lFiles.empty() )
207
	{
208
		for ( CListNode<C_File> *node = _lFiles.Front(); node; node = node->next() )
209
		{
210
			C_File *uf = node->Data();
211
			Utils::String uString = "Original: ";
212
			uString += Utils::String::Number((long)uf->GetFileType()) + " ";
213
			uString += uf->GetFilename().ToString();
214
 
215
			// add the directory for Extra files
216
			if ( uf->GetFileType() == FILETYPE_EXTRA && !uf->GetDir().Empty())
217
			{
218
				uString += ":";
219
				uString += uf->GetDir().ToString();
220
			}
221
 
222
			lines->PushBack(CyString(uString));
223
			addAny = true;
224
		}
225
	}
226
 
227
	return addAny;
228
}
229
 
230
 
231
void COriginalFiles::reset()
232
{
233
	_lFiles.MemoryClear();
234
}
235
 
236
 
237
/**
238
 * Update original files list
239
 *
240
 * Scan the current directory for any fiels that are already there, ie ones that have not been installed
241
 * Original files should be all the scripts/sounds, etc that are in an unmodified game directory
242
 *
243
 * Save list of files and check if any packages overright these files
244
 * Any file that gets overrighten from this list will automatically be backed up, and restored once the packages are removed
245
 */
246
void COriginalFiles::_storeFiles(int filetype, const Utils::String &searchPath, const CLinkList<C_File> *pFiles)
247
{
248
	Utils::String ext = "pck";
249
	switch ( filetype )
250
	{
251
		case FILETYPE_SOUND:
252
			ext = "mp3";
253
			break;
254
	}
255
 
256
	CDirIO Dir(_sDir + "/" + searchPath);
257
 
258
	CyStringList *files = Dir.DirList();
259
	if ( !files )
260
		return;
261
 
262
	for ( SStringList *node = files->Head(); node; node = node->next )
263
	{
264
		CFileIO File(Dir.File(node->str));
265
 
266
 
267
		if ( File.extension().Compare(ext) )
268
			_add(filetype, File.filename(), searchPath, pFiles);
269
	}
270
 
271
	delete files;
272
}
273
 
274
/**
275
 * Get original file
276
 *
277
 * Finds a matching original file entry and returns it
278
 */
279
C_File *COriginalFiles::_getFile(C_File *file) const
280
{
281
	if ( !file ) return NULL;
282
 
283
	for ( CListNode<C_File> *node = _lFiles.Front(); node; node = node->next() )
284
	{
285
		C_File *of = node->Data();
286
 
287
		// not of the same file type
288
		if ( of->GetFileType() != file->GetFileType() )
289
			continue;
290
 
291
		// same file name, must be the same file
292
		if ( of->GetFilename().Compare(file->GetFilename()) )
293
			return of;
294
	}
295
 
296
	return NULL;
297
}
298
 
299
 
300
/**
301
 * Adds a file onto the original files list
302
 *
303
 * Checks if it already exists so we dont create multiples
304
 */
305
void COriginalFiles::_add(int filetype, const Utils::String &filename, const Utils::String &searchPath, const CLinkList<C_File> *pFiles)
306
{
307
	// dont add plugin manager as original files
308
	if ( filetype == FILETYPE_SCRIPT && filename.isin("!init.pmanager") )
309
		return;
310
 
311
	// first check if a matching one exists
312
	for ( CListNode<C_File> *node = _lFiles.Front(); node; node = node->next() )
313
	{
314
		C_File *file = node->Data();
315
		if ( file->GetFileType() != filetype )
316
			continue;
317
 
318
		if ( file->GetFilename().Compare(CyString(filename)) )
319
			return;
320
	}
321
 
322
	// check that no packages are currently using them either, not original if being used already
323
	for ( CListNode<C_File> *node = pFiles->Front(); node; node = node->next() )
324
	{
325
		C_File *file = node->Data();
326
		if ( file->GetFileType() != filetype )
327
			continue;
328
 
329
		if ( file->GetFilename().Compare(CyString(filename)) )
330
			return;
331
	}
332
 
333
	// add the file entry to the list
334
	C_File *of = new C_File(CyString(filename));
335
	of->SetFileType(filetype);
336
	if ( filetype == FILETYPE_EXTRA )
337
		of->SetDir(searchPath);
338
	of->SetFilename(_sDir + "/" + of->GetNameDirectory(NULL).ToString());
339
 
340
	_lFiles.push_back(of);
341
}
342
 
343
}