source: trunk/gsinstaller/fileCopier.cpp@ 1545

Last change on this file since 1545 was 1545, checked in by cs025, 24 years ago

Improved logging of manifest items, tidied the handling of items with extended
paths in the manifest (logging creation of directories on the path); finally
removed some old garbage from gsinstall.cpp.

  • 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 // get destination directory
155 char *thisDestDir = this->destination(file);
156 FilePath destPath(thisDestDir);
157
158 // create a directory if needsbe
159 if (destPath.exists() == false)
160 {
161 _mkdir(thisDestDir);
162
163 // note amount of data copied
164 // this->copied += file->getRawFileSize();
165
166 // note for uninstall the action done
167 if (monitor != NULL)
168 {
169 monitor->copiedDir(thisDestDir);
170 }
171 }
172
173 // copy children
174 vector<File>::iterator here = file->childBegin();
175 vector<File>::iterator end = file->childEnd();
176 while (here != end)
177 {
178 this->copy(here, monitor, progressBar);
179 here ++;
180 }
181
182 // delete constructed destination name
183 delete thisDestDir;
184 }
185
186 // not a directory; just copy the file
187 else
188 {
189 // copy file itself
190 this->copyFile(file, monitor, progressBar);
191 }
192
193 progressBar.done(file->getRawFileSize());
194}
195
196void fileCopySet::copy(fileCopyMonitor *monitor, copyProgressBar &progressBar)
197{
198 FileVector::iterator here = fileList.begin();
199 FileVector::iterator end = fileList.end();
200 while (here != end)
201 {
202 this->copy(here, monitor, progressBar);
203 here ++;
204 }
205}
206
207unsigned long fileCopySet::getCopiedSize(DiskSpace &space)
208{
209 // initialise counters for size
210 unsigned long copiedSize = 0;
211
212 // iterate through our list of files to obtain total space requirement
213 FileVector::iterator here = fileList.begin();
214 FileVector::iterator end = fileList.end();
215 while (here != end)
216 {
217 copiedSize += here->getDiskSpace(space);
218 here ++;
219 }
220 return copiedSize;
221}
222
223unsigned long fileCopySet::getOriginalSize()
224{
225 // initialise counters for size
226 return this->dataSize;
227}
228
229/**
230 * Perform a check on the total space available at the destination; if not
231 * enough then return false to indicate the error state
232 */
233bool fileCopier::checkSpace()
234{
235 fileCopySetList localSet = this->list;
236
237 do
238 {
239 unsigned int i = 0;
240
241 // get destination root and use it to obtain space check information
242 FilePath *destRoot = localSet[0].destDir.root();
243 DiskSpace space(destRoot->cString());
244
245 // check that diskspace checking is functional
246 if (space.initialisedOk() == false)
247 {
248 delete destRoot;
249 return false;
250 }
251
252 // get size of the first set
253 unsigned long copiedSize = localSet[0].getCopiedSize(space);
254
255 // dispose of the first set
256 localSet.erase(localSet.begin());
257
258 // get all remaining sets and in turn if they share the root with
259 // the first root, add their size to the count and remove them from
260 // the local list of sets; otherwise skip
261 while (i < localSet.size())
262 {
263 // get a new root object for this set's destination
264 FilePath *p = localSet[i].destDir.root();
265
266 if (*destRoot == *p)
267 {
268 copiedSize += localSet[i].getCopiedSize(space);
269 localSet.erase(localSet.begin() + i);
270 }
271 else
272 {
273 i ++;
274 }
275
276 // delete the constructed root
277 delete p;
278 }
279
280 // dispose of destination root
281 delete destRoot;
282
283 // return false if not enough space
284 if (space.totalFreeSpace() < copiedSize)
285 {
286 return false;
287 }
288
289 } while (localSet.size() != 0);
290
291
292 // record size and initialise the progressbar with the same
293 this->dataSize = 0;
294 for (unsigned int i = 0; i < this->list.size(); i ++)
295 {
296 this->dataSize += this->list[i].getOriginalSize();
297 }
298 this->progressBar.init(this->dataSize);
299
300 // return postive check
301 return true;
302}
303
304fileCopier::fileCopier(fileCopyMonitor *monitor, fileCopySetList &_list)
305{
306 this->list = _list;
307 this->dataSize = 0;
308 this->copied = 0;
309 this->monitor = monitor;
310}
311
312fileCopier::fileCopier(fileCopyMonitor *monitor)
313{
314 this->dataSize = 0;
315 this->copied = 0;
316 this->monitor = monitor;
317}
318
319void fileCopier::copy()
320{
321 fileCopySetList::iterator here = list.begin();
322 fileCopySetList::iterator end = list.end();
323
324 this->progressBar.show();
325 while (here != end)
326 {
327 here->copy(this->monitor, this->progressBar);
328 here ++;
329 }
330
331 this->progressBar.close();
332}
Note: See TracBrowser for help on using the repository browser.