#include "fileCopier.h" #include #include //#include #include fileCopySet::fileCopySet() { // do we need this - they're FilePath's, not pointers // this->sourceDir = NULL; // this->destDir = NULL; } fileCopySet::fileCopySet(FileVector files, FilePath &from, FilePath &to) { this->fileList = files; this->sourceDir = from; this->destDir = to; this->dataSize = 0; FileVector::iterator here = files.begin(); FileVector::iterator end = files.end(); while (here != end) { this->dataSize += here->getFileSize(); here ++; } } /** * Get the destination file name for a given source file; source and destination * directory locations are obtained from the object */ char *fileCopySet::destination(File *file) { const char *oldname = file->getFileName(); char *newname = (char *) malloc(strlen(oldname) - strlen(this->sourceDir.cString()) + strlen(this->destDir.cString()) + 1); if (newname != NULL) { strcpy(newname, this->destDir.cString()); strcat(newname, &oldname[strlen(this->sourceDir.cString())]); } return newname; } /** * Copy a particular file to its destination */ bool fileCopySet::copyFile(File *file, fileCopyMonitor *monitor, copyProgressBar &progressBar) { unsigned long copied = 0; unsigned long bytes_read, bytes_written; unsigned char buffer[65536]; FILE *read_handle, *write_handle; char *destination; // get destination as a char[] block; will free it later destination = this->destination(file); // get read and write file handles read_handle = fopen(file->getFileName(), "rb"); if (read_handle == NULL) { return false; } write_handle = fopen(destination, "wb"); if (write_handle == NULL) { fclose(read_handle); return false; } while (copied < file->getFileSize()) { // TODO: lock // read so many bytes if (file->getFileSize() - copied < 65536) { bytes_read = file->getFileSize() - copied; } else { bytes_read = 65536; } bytes_read = fread((void *) buffer, 1, bytes_read, read_handle); // write so many bytes bytes_written = fwrite((void *) buffer, 1, bytes_read, write_handle); // TODO: unlock // note new bytes copied copied += bytes_written; this->dataSize += bytes_written; } fclose(read_handle); fclose(write_handle); // free destination filename text if (monitor != NULL) { monitor->copied(file->getFileName(), destination, false); } delete destination; return true; } /** * Copy a file "object" (may be a directory or a "proper" file) to it's * destination */ void fileCopySet::copy(File *file, fileCopyMonitor *monitor, copyProgressBar &progressBar) { // just skip this file if it doesn't exist if (file->exists() == false) { return; } // if a directory, scan it. if (file->isDirectory()) { // create directory char *thisDestDir = this->destination(file); _mkdir(thisDestDir); // note amount of data copied // this->copied += file->getRawFileSize(); // note for uninstall the action done if (monitor != NULL) { monitor->copied(file->getFileName(), thisDestDir, true); } // copy children vector::iterator here = file->childBegin(); vector::iterator end = file->childEnd(); while (here != end) { this->copy(here, monitor, progressBar); here ++; } // delete constructed destination name delete thisDestDir; } // not a directory; just copy the file else { // copy file itself this->copyFile(file, monitor, progressBar); } progressBar.done(file->getRawFileSize()); } void fileCopySet::copy(fileCopyMonitor *monitor, copyProgressBar &progressBar) { FileVector::iterator here = fileList.begin(); FileVector::iterator end = fileList.end(); while (here != end) { this->copy(here, monitor, progressBar); here ++; } } unsigned long fileCopySet::getCopiedSize(DiskSpace &space) { // initialise counters for size unsigned long copiedSize = 0; // iterate through our list of files to obtain total space requirement FileVector::iterator here = fileList.begin(); FileVector::iterator end = fileList.end(); while (here != end) { copiedSize += here->getDiskSpace(space); here ++; } return copiedSize; } unsigned long fileCopySet::getOriginalSize() { // initialise counters for size return this->dataSize; } /** * Perform a check on the total space available at the destination; if not * enough then return false to indicate the error state */ bool fileCopier::checkSpace() { fileCopySetList localSet = this->list; do { unsigned int i = 0; // get destination root and use it to obtain space check information FilePath *destRoot = localSet[0].destDir.root(); DiskSpace space(destRoot->cString()); // check that diskspace checking is functional if (space.initialisedOk() == false) { delete destRoot; return false; } // get size of the first set unsigned long copiedSize = localSet[0].getCopiedSize(space); // dispose of the first set localSet.erase(localSet.begin()); // get all remaining sets and in turn if they share the root with // the first root, add their size to the count and remove them from // the local list of sets; otherwise skip while (i < localSet.size()) { // get a new root object for this set's destination FilePath *p = localSet[i].destDir.root(); if (*destRoot == *p) { copiedSize += localSet[i].getCopiedSize(space); localSet.erase(localSet.begin() + i); } else { i ++; } // delete the constructed root delete p; } // dispose of destination root delete destRoot; // return false if not enough space if (space.totalFreeSpace() < copiedSize) { return false; } } while (localSet.size() != 0); // record size and initialise the progressbar with the same this->dataSize = 0; for (unsigned int i = 0; i < this->list.size(); i ++) { this->dataSize += this->list[i].getOriginalSize(); } this->progressBar.init(this->dataSize); // return postive check return true; } fileCopier::fileCopier(fileCopyMonitor *monitor, fileCopySetList &_list) { this->list = _list; this->dataSize = 0; this->copied = 0; this->monitor = monitor; } fileCopier::fileCopier(fileCopyMonitor *monitor) { this->dataSize = 0; this->copied = 0; this->monitor = monitor; } void fileCopier::copy() { fileCopySetList::iterator here = list.begin(); fileCopySetList::iterator end = list.end(); this->progressBar.show(); while (here != end) { here->copy(this->monitor, this->progressBar); here ++; } this->progressBar.close(); }