source: trunk/gsinstaller/fileCopier.cpp@ 1541

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

Fixes for WindowsNT. Also made File class subclass of FilePath class.

  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 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
50/**
51 * Copy a particular file to its destination
52 */
53bool fileCopySet::copyFile(File *file, fileCopyMonitor *monitor, copyProgressBar &progressBar)
54{
55 unsigned long copied = 0;
56 unsigned long bytes_read, bytes_written;
57 unsigned char buffer[65536];
58 FILE *read_handle, *write_handle;
59 char *destination;
60
61 // get destination as a char[] block; will free it later
62 destination = this->destination(file);
63
64 FilePath destPath(destination);
65 FilePath *destDir = destPath.parent();
66 if (!destDir->ensureWriteablePath())
67 { delete destDir;
68 return false;
69 }
70 delete destDir;
71
72 // get read and write file handles
73 read_handle = fopen(file->cString(), "rb");
74 if (read_handle == NULL)
75 {
76 return false;
77 }
78 write_handle = fopen(destination, "wb");
79 if (write_handle == NULL)
80 {
81 fclose(read_handle);
82 return false;
83 }
84
85 while (copied < file->getFileSize())
86 {
87 // TODO: lock
88 // read so many bytes
89 if (file->getFileSize() - copied < 65536)
90 {
91 bytes_read = file->getFileSize() - copied;
92 }
93 else
94 {
95 bytes_read = 65536;
96 }
97 bytes_read = fread((void *) buffer, 1, bytes_read, read_handle);
98
99 // write so many bytes
100 bytes_written = fwrite((void *) buffer, 1, bytes_read, write_handle);
101
102 // TODO: unlock
103
104 // note new bytes copied
105 copied += bytes_written;
106 this->dataSize += bytes_written;
107 }
108 fclose(read_handle);
109 fclose(write_handle);
110
111 // free destination filename text
112 if (monitor != NULL)
113 {
114 monitor->copied(file->cString(), destination, false);
115 }
116 delete destination;
117 return true;
118}
119
120/**
121 * Copy a file "object" (may be a directory or a "proper" file) to it's
122 * destination
123 */
124void fileCopySet::copy(File *file, fileCopyMonitor *monitor, copyProgressBar &progressBar)
125{
126 // just skip this file if it doesn't exist
127 if (file->exists() == false)
128 {
129 return;
130 }
131
132 // if a directory, scan it.
133 if (file->isDirectory())
134 {
135 // create directory
136 char *thisDestDir = this->destination(file);
137 _mkdir(thisDestDir);
138
139 // note amount of data copied
140 // this->copied += file->getRawFileSize();
141
142 // note for uninstall the action done
143 if (monitor != NULL)
144 {
145 monitor->copied(file->cString(), thisDestDir, true);
146 }
147
148 // copy children
149 vector<File>::iterator here = file->childBegin();
150 vector<File>::iterator end = file->childEnd();
151 while (here != end)
152 {
153 this->copy(here, monitor, progressBar);
154 here ++;
155 }
156
157 // delete constructed destination name
158 delete thisDestDir;
159 }
160
161 // not a directory; just copy the file
162 else
163 {
164 // copy file itself
165 this->copyFile(file, monitor, progressBar);
166 }
167
168 progressBar.done(file->getRawFileSize());
169}
170
171void fileCopySet::copy(fileCopyMonitor *monitor, copyProgressBar &progressBar)
172{
173 FileVector::iterator here = fileList.begin();
174 FileVector::iterator end = fileList.end();
175 while (here != end)
176 {
177 this->copy(here, monitor, progressBar);
178 here ++;
179 }
180}
181
182unsigned long fileCopySet::getCopiedSize(DiskSpace &space)
183{
184 // initialise counters for size
185 unsigned long copiedSize = 0;
186
187 // iterate through our list of files to obtain total space requirement
188 FileVector::iterator here = fileList.begin();
189 FileVector::iterator end = fileList.end();
190 while (here != end)
191 {
192 copiedSize += here->getDiskSpace(space);
193 here ++;
194 }
195 return copiedSize;
196}
197
198unsigned long fileCopySet::getOriginalSize()
199{
200 // initialise counters for size
201 return this->dataSize;
202}
203
204/**
205 * Perform a check on the total space available at the destination; if not
206 * enough then return false to indicate the error state
207 */
208bool fileCopier::checkSpace()
209{
210 fileCopySetList localSet = this->list;
211
212 do
213 {
214 unsigned int i = 0;
215
216 // get destination root and use it to obtain space check information
217 FilePath *destRoot = localSet[0].destDir.root();
218 DiskSpace space(destRoot->cString());
219
220 // check that diskspace checking is functional
221 if (space.initialisedOk() == false)
222 {
223 delete destRoot;
224 return false;
225 }
226
227 // get size of the first set
228 unsigned long copiedSize = localSet[0].getCopiedSize(space);
229
230 // dispose of the first set
231 localSet.erase(localSet.begin());
232
233 // get all remaining sets and in turn if they share the root with
234 // the first root, add their size to the count and remove them from
235 // the local list of sets; otherwise skip
236 while (i < localSet.size())
237 {
238 // get a new root object for this set's destination
239 FilePath *p = localSet[i].destDir.root();
240
241 if (*destRoot == *p)
242 {
243 copiedSize += localSet[i].getCopiedSize(space);
244 localSet.erase(localSet.begin() + i);
245 }
246 else
247 {
248 i ++;
249 }
250
251 // delete the constructed root
252 delete p;
253 }
254
255 // dispose of destination root
256 delete destRoot;
257
258 // return false if not enough space
259 if (space.totalFreeSpace() < copiedSize)
260 {
261 return false;
262 }
263
264 } while (localSet.size() != 0);
265
266
267 // record size and initialise the progressbar with the same
268 this->dataSize = 0;
269 for (unsigned int i = 0; i < this->list.size(); i ++)
270 {
271 this->dataSize += this->list[i].getOriginalSize();
272 }
273 this->progressBar.init(this->dataSize);
274
275 // return postive check
276 return true;
277}
278
279fileCopier::fileCopier(fileCopyMonitor *monitor, fileCopySetList &_list)
280{
281 this->list = _list;
282 this->dataSize = 0;
283 this->copied = 0;
284 this->monitor = monitor;
285}
286
287fileCopier::fileCopier(fileCopyMonitor *monitor)
288{
289 this->dataSize = 0;
290 this->copied = 0;
291 this->monitor = monitor;
292}
293
294void fileCopier::copy()
295{
296 fileCopySetList::iterator here = list.begin();
297 fileCopySetList::iterator end = list.end();
298
299 this->progressBar.show();
300 while (here != end)
301 {
302 here->copy(this->monitor, this->progressBar);
303 here ++;
304 }
305
306 this->progressBar.close();
307}
Note: See TracBrowser for help on using the repository browser.