source: trunk/gsinstaller/fileCopier.cpp@ 2216

Last change on this file since 2216 was 1766, checked in by cs025, 23 years ago

No true alterations; any differences should be merely whitespace from
debugging.

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