X-Git-Url: https://develop.uap-core.de/gitweb/mizunara.git/blobdiff_plain/2f4baaacb05f4d69dac8d2888b8b8eb07606e67c..HEAD:/mizucp/main.c diff --git a/mizucp/main.c b/mizucp/main.c index 18aaf5a..f590dc7 100644 --- a/mizucp/main.c +++ b/mizucp/main.c @@ -23,9 +23,11 @@ #include "main.h" #include "srvctrl.h" +#include "atomic.h" #include #include +#include #include #include #include @@ -61,6 +63,13 @@ static MZQueue *queue_end; static int scan_complete; + +static uint64_t stat_num_files; +static uint64_t stat_copied_files; +static uint64_t stat_error_files; +static uint64_t stat_total_size; +static uint64_t stat_copied_size; + int main(int argc, char** argv) { int ret = 1; @@ -215,13 +224,12 @@ int mzcp_copy(CPSettings *settings) { int mzcp_start_scan(CPSettings *settings) { - struct stat s; - if(stat(settings->from, &s)) { + if(stat(settings->from, &settings->root_stat)) { // TODO: error return 1; } - if(!S_ISDIR(s.st_mode)) { + if(!S_ISDIR(settings->root_stat.st_mode)) { // queue single file queue_begin = queue_root_elm_new(); if(!queue_begin) { @@ -259,6 +267,7 @@ void* scan_run(void *data) { } file->path = root; file->isdir = 1; + file->mode = settings->root_stat.st_mode; if(enqueue_file(file)) { scan_complete = 1; // TODO: error @@ -298,12 +307,18 @@ void* scan_run(void *data) { SrcFile *f = calloc(1, sizeof(SrcFile)); f->path = util_concat_path(elm->path, name); f->isdir = S_ISDIR(s.st_mode); + f->size = s.st_size; + f->mode = s.st_mode; f->depends_on = elm; if(enqueue_file(f)) { // TODO: error? fprintf(stderr, "enqueue failed\n"); break; + } else { + mz_atomic_inc64(&stat_num_files); + int64_t sz = s.st_size; + mz_atomic_add64(&stat_total_size, sz); } // put dir on stack @@ -399,17 +414,60 @@ static SrcFile* queue_get_file(void) { void* copy_run(void *data) { CPSettings *settings = data; + + char *buffer = malloc(MZ_COPY_BUFSIZE); + size_t bufsize = MZ_COPY_BUFSIZE; + for(;;) { SrcFile *file = queue_get_file(); if(!file) { break; } - char *from = file->path ? util_concat_path(settings->from, file->path) : settings->from; - printf("src: %s\n", from); - + char *from = file->path ? util_concat_path(settings->from, file->path) : settings->from; char *to = util_concat_path(settings->to, file->path ? file->path : util_resource_name(settings->from)); - printf("dst: %s\n", to); + + size_t from_len = strlen(from); + size_t to_len = strlen(to); + + if(from[from_len-1] == '/') { + from[from_len-1] = 0; + } + if(to[to_len-1] == '/') { + to[to_len-1] = 0; + } + + if(file->depends_on) { + SrcFile *dep = file->depends_on; + // check first without lock + if(dep->status == 0) { + if(dep->lock) { + pthread_mutex_lock(&dep->lock->mutex); + if(file->depends_on->status == 0) { + pthread_cond_wait(&dep->lock->cond, &dep->lock->mutex); + } + pthread_mutex_unlock(&dep->lock->mutex); + } else { + // locking disabled (because we have only one thread) + // but in that case the file status can't be 0 + // therefore this case here should not happen + file->status = -1; + } + } + // check again + if(dep->status == -1) { + file->status = -1; + } + } + + int ret; + if(file->status == 0) { + if(file->isdir) { + ret = mz_copy_dir(settings, file, from, to); + } else { + ret = mz_copy_file(settings, file, from, to, buffer, bufsize); + } + } free(to); if(from != settings->from) { @@ -420,3 +478,86 @@ void* copy_run(void *data) { return NULL; } +static void file_set_status(SrcFile *file, int status) { + if(file->lock) { + pthread_mutex_lock(&file->lock->mutex); + file->status = status; + pthread_cond_broadcast(&file->lock->cond); + pthread_mutex_unlock(&file->lock->mutex); + } else { + file->status = status; + } +} + +int mz_copy_dir(CPSettings *settings, SrcFile *file, const char *from, const char *to) { + printf("mkdir %s\n", to); + int ret = mkdir(to, file->mode); + if(ret) { + if(errno == EEXIST) { + struct stat s; + if(!stat(to, &s)) { + if(S_ISDIR(s.st_mode)) { + ret = 0; + } + } + } + } + file_set_status(file, !ret ? 1 : -1); + return ret; +} + +int mz_copy_file(CPSettings *settings, SrcFile *file, const char *from, const char *to, char *buffer, size_t bufsize) { + printf("cp %s %s\n", from, to); + int fin = open(from, O_RDONLY); + if(fin < 0) { + file_set_status(file, -1); + return 1; + } + + int ret = 0; + + int fout = open(to, O_WRONLY|O_CREAT, file->mode); + if(fout < 0) { + perror("open"); + close(fin); + file_set_status(file, -1); + return 1; + } + + int64_t copied = 0; + ssize_t r; + while((r = read(fin, buffer, bufsize)) > 0) { + ssize_t w = write(fout, buffer, r); + if(w > 0) { + mz_atomic_add64(&stat_copied_size, w); + copied += w; + } + if(w != r) { + ret = 1; + break; + } + } + + close(fin); + close(fout); + + if(!ret) { + file_set_status(file, 1); + mz_atomic_inc64(&stat_copied_files); + if(copied != file->size) { + // size changed after scan -> readjust total size + int64_t filesz_diff = copied - file->size; + mz_atomic_add64(&stat_total_size, filesz_diff); + } + } else { + file_set_status(file, -1); + mz_atomic_inc64(&stat_error_files); + if(copied != file->size) { + // count the full file size as copied, although we had an error + int64_t filesz_diff = file->size - copied; + mz_atomic_add64(&stat_copied_size, filesz_diff); + } + } + + return ret; +}