source: other-projects/gs2-export-cdrom-installer/trunk/fileCopier.cpp

Last change on this file was 22919, checked in by ak19, 14 years ago

Dr Bainbridge got gssetup.exe (for the export to cdrom installer) to work again for a later version of Visual Studio: now it works with Visual Studio 9 and does not use STLPort anymore. Changed .rc reference to including afxres.h to windows.h in vcinstall.rc, and there were changes to dereferencing File elements in an STL iterator (in fileCopier.cpp). Also needed to change references to unsigned double to double since the former seems to no longer be supported in later versions of Vis Studio.

  • Property svn:keywords set to Author Date Id Revision
File size: 9.5 KB
Line 
1#include "fileCopier.h"
2
3#include <stdlib.h>
4#include <stdio.h>
5//#include <dir.h>
6#include <direct.h>
7
8#if defined (GSDL_USE_IOS_H)
9#include <fstream.h>
10#else
11#include <fstream>
12#endif
13
14fileCopySet::fileCopySet()
15{
16 // do we need this - they're FilePath's, not pointers
17 // this->sourceDir = NULL;
18 // this->destDir = NULL;
19}
20
21fileCopySet::fileCopySet(string label, FileVector files, FilePath &from, FilePath &to)
22{
23 this->fileList = files;
24 this->sourceDir = from;
25 this->label = label;
26 this->destDir = to;
27 this->dataSize = 0;
28 this->dataFiles = 0;
29
30 FileVector::iterator here = files.begin();
31 FileVector::iterator end = files.end();
32
33 while (here != end)
34 {
35 unsigned long size, files;
36 here->getFileSize(size, files);
37 this->dataSize += size;
38 this->dataFiles += files;
39 here ++;
40 }
41}
42
43/**
44 * Get the destination file name for a given source file; source and destination
45 * directory locations are obtained from the object
46 */
47char *fileCopySet::destination(File *file)
48{
49 const char *oldname = file->cString();
50 char *newname = (char *) malloc(strlen(oldname) - strlen(this->sourceDir.cString()) + strlen(this->destDir.cString()) + 1);
51
52 if (newname != NULL)
53 {
54 strcpy(newname, this->destDir.cString());
55 strcat(newname, &oldname[strlen(this->sourceDir.cString())]);
56 }
57
58 return newname;
59}
60
61bool fileCopySet::ensureParent(FilePath &child, fileCopyMonitor *monitor)
62{ FilePath *parentName = child.parent();
63
64 // check for existence of parent
65 if (parentName->exists() == false)
66 { // ensure the grandparent exists
67 if (!this->ensureParent(*parentName, monitor))
68 { return false;
69 }
70
71 // create parent directory
72 _mkdir(parentName->cString());
73
74 // log the creation - we don't give a source - it's not needed for directories
75 if (monitor != NULL)
76 { monitor->createdDir(parentName->cString());
77 }
78 }
79 delete parentName;
80 return true;
81}
82
83/**
84 * Copy a particular file to its destination
85 */
86bool fileCopySet::copyFile(File *file, fileCopyMonitor *monitor, copyProgressBar *progressBar)
87{
88 unsigned long copied = 0;
89 unsigned long bytes_read, bytes_written;
90 static unsigned char buffer[65536];
91 FILE *read_handle, *write_handle;
92 char *destination;
93
94 // get destination as a char[] block; will free it later
95 destination = this->destination(file);
96
97 // ensure that the parent exists, as some install requirements are for files with
98 // directory paths which may not preexist
99 FilePath destPath(destination);
100 this->ensureParent(destPath, monitor);
101
102 // get read and write file handles
103 read_handle = fopen(file->cString(), "rb");
104 if (read_handle == NULL)
105 {
106 return false;
107 }
108 write_handle = fopen(destination, "wb");
109 if (write_handle == NULL)
110 {
111 fclose(read_handle);
112 return false;
113 }
114
115 while (copied < file->getFileSize())
116 {
117 // TODO: lock
118 // read so many bytes
119 if (file->getFileSize() - copied < 65536)
120 {
121 bytes_read = file->getFileSize() - copied;
122 }
123 else
124 {
125 bytes_read = 65536;
126 }
127 bytes_read = fread((void *) buffer, 1, bytes_read, read_handle);
128
129 // write so many bytes
130 bytes_written = fwrite((void *) buffer, 1, bytes_read, write_handle);
131
132 // TODO: unlock
133
134 // note new bytes copied
135 copied += bytes_written;
136// this->dataSize += bytes_written;
137 }
138 fclose(read_handle);
139 fclose(write_handle);
140
141// this->dataFiles += 1;
142
143 // free destination filename text
144 if (monitor != NULL)
145 {
146 monitor->copiedFile(file->cString(), destination);
147 }
148 delete destination;
149 return true;
150}
151
152/**
153 * Copy a file "object" (may be a directory or a "proper" file) to it's
154 * destination
155 */
156void fileCopySet::copy(File *file, fileCopyMonitor *monitor, copyProgressBar *progressBar)
157{
158 // just skip this file if it doesn't exist
159 if (file->exists() == false)
160 {
161 return;
162 }
163
164 // if a directory, scan it.
165 if (file->isDirectory())
166 {
167 // get destination directory
168 char *thisDestDir = this->destination(file);
169 FilePath destPath(thisDestDir);
170
171 // create a directory if needsbe
172 if (destPath.exists() == false)
173 {
174 _mkdir(thisDestDir);
175
176 // note amount of data copied
177 // this->copied += file->getRawFileSize();
178
179 // note for uninstall the action done
180 if (monitor != NULL)
181 {
182 monitor->copiedDir(destPath.pathString());
183 }
184 }
185
186 // copy children
187 vector<File>::iterator here = file->childBegin();
188 vector<File>::iterator end = file->childEnd();
189 while (here != end)
190 {
191 File& file_here = (*here); // to the best of our understanding, this returns a reference to the object (rather than a local copy)
192 this->copy(&file_here, monitor, progressBar);
193 here ++;
194 }
195
196 // delete constructed destination name
197 delete thisDestDir;
198 }
199
200 // not a directory; just copy the file
201 else
202 {
203 // copy file itself
204 this->copyFile(file, monitor, progressBar);
205 }
206
207 if (progressBar != NULL)
208 { progressBar->done(file->getRawFileSize());
209 }
210}
211
212void fileCopySet::copy(fileCopyMonitor *monitor, copyProgressBar *progressBar)
213{
214 FileVector::iterator here = fileList.begin();
215 FileVector::iterator end = fileList.end();
216 while (here != end)
217 {
218 File& file_here = (*here); // to the best of our understanding, this returns a reference to the object (rather than a local copy)
219 this->copy(&file_here, monitor, progressBar);
220 here ++;
221 }
222}
223
224double fileCopySet::getCopiedSize(DiskSpace &space)
225{
226 // initialise counters for size
227 unsigned long copiedSize = 0;
228
229 // iterate through our list of files to obtain total space requirement
230 FileVector::iterator here = fileList.begin();
231 FileVector::iterator end = fileList.end();
232 while (here != end)
233 {
234 copiedSize += here->getDiskSpace(space);
235 here ++;
236 }
237 return (double) copiedSize / (double) 1024;
238}
239
240unsigned long fileCopySet::getOriginalSize()
241{
242 // initialise counters for size
243 return this->dataSize;
244}
245
246unsigned long fileCopySet::getOriginalFiles()
247{
248 // initialise counters for size
249 return this->dataFiles;
250}
251
252/**
253 * Perform a check on the total space available at the destination; if not
254 * enough then return false to indicate the error state
255 */
256bool fileCopier::checkSpace()
257{
258 fileCopySetList localSet = this->list;
259
260 this->progressBar.message("Checking disk space requirements");
261
262 do
263 {
264 unsigned int i = 0;
265
266 // get destination root and use it to obtain space check information
267 FilePath *destRoot = localSet[0].destDir.root();
268 DiskSpace space(destRoot->cString());
269
270 // check that diskspace checking is functional
271 if (space.initialisedOk() == false)
272 {
273 delete destRoot;
274 return false;
275 }
276
277 // get size of the first set
278 unsigned long copiedSize = localSet[0].getCopiedSize(space);
279
280 // dispose of the first set
281 localSet.erase(localSet.begin());
282
283 // get all remaining sets and in turn if they share the root with
284 // the first root, add their size to the count and remove them from
285 // the local list of sets; otherwise skip
286 while (i < localSet.size())
287 {
288 // get a new root object for this set's destination
289 FilePath *p = localSet[i].destDir.root();
290
291 if (*destRoot == *p)
292 {
293 copiedSize += localSet[i].getCopiedSize(space);
294 localSet.erase(localSet.begin() + i);
295 }
296 else
297 {
298 i ++;
299 }
300
301 // delete the constructed root
302 delete p;
303 }
304
305 // dispose of destination root
306 delete destRoot;
307
308 // return false if not enough space
309 if (space.totalFreeSpace() < copiedSize)
310 {
311 char buffer[100];
312 sprintf(buffer, "Total free space on disk %3.1fMb, but the size of the copied collection is %3.1fMb", (double) space.totalFreeSpace() / (double) (1024), (double) copiedSize / (double) (1024));
313 MessageBox(0, buffer, "Greenstone Installer", MB_OK);
314
315 return false;
316 }
317
318 } while (localSet.size() != 0);
319
320
321 // record size and initialise the progressbar with the same
322 this->dataSize = 0;
323 this->dataFiles = 0;
324 for (unsigned int i = 0; i < this->list.size(); i ++)
325 {
326 this->dataSize += this->list[i].getOriginalSize();
327 this->dataFiles += this->list[i].getOriginalFiles();
328 }
329 this->progressBar.init(this->dataSize, this->dataFiles);
330
331 // return postive check
332 return true;
333}
334
335fileCopier::fileCopier(fileCopyMonitor *monitor, fileCopySetList &_list)
336{
337 this->list = _list;
338 this->dataSize = 0;
339 this->copied = 0;
340 this->dataFiles = 0;
341 this->monitor = monitor;
342
343 this->progressBar.show();
344 this->progressBar.message("Initialising");
345}
346
347fileCopier::fileCopier(fileCopyMonitor *monitor)
348{
349 this->dataSize = 0;
350 this->copied = 0;
351 this->dataFiles = 0;
352 this->monitor = monitor;
353
354 this->progressBar.show();
355 this->progressBar.message("Initialising");
356}
357
358void fileCopier::addSet(fileCopySet &set)
359{ this->list.push_back(set);
360 this->progressBar.message("Gathering files to copy");
361}
362
363// Do the actual file copy
364void fileCopier::copy()
365{
366 fileCopySetList::iterator here = list.begin();
367 fileCopySetList::iterator end = list.end();
368
369 // Tell the user what is happening
370 char buffer[100];
371 sprintf(buffer, "Copying %3.1fMb of files", (double) this->dataSize / (double) (1024 * 1024));
372 this->progressBar.message(buffer);
373 this->progressBar.setStartTime();
374
375 // Copy each file set individually, using the progress bar as a monitor
376 while (here != end)
377 {
378 here->copy(this->monitor, &this->progressBar);
379 here ++;
380 }
381
382 // Close the progress bar, as it is no longer needed
383 this->progressBar.close();
384}
Note: See TracBrowser for help on using the repository browser.