123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- #define _GNU_SOURCE
- #include <dirent.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/stat.h>
- #include <signal.h>
- #include <fcntl.h>
- #include <malloc.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <errno.h>
- #include <gui-fatal.h>
- #include <libqubes-rpc-filecopy.h>
- enum {
- PROGRESS_FLAG_NORMAL,
- PROGRESS_FLAG_INIT,
- PROGRESS_FLAG_DONE
- };
- void do_notify_progress(long long total, int flag)
- {
- const char *du_size_env = getenv("FILECOPY_TOTAL_SIZE");
- const char *progress_type_env = getenv("PROGRESS_TYPE");
- const char *saved_stdout_env = getenv("SAVED_FD_1");
- int ignore;
- if (!progress_type_env)
- return;
- if (!strcmp(progress_type_env, "console") && du_size_env) {
- char msg[256];
- snprintf(msg, sizeof(msg), "sent %lld/%lld KB\r",
- total / 1024, strtoull(du_size_env, NULL, 0));
- ignore = write(2, msg, strlen(msg));
- if (flag == PROGRESS_FLAG_DONE)
- ignore = write(2, "\n", 1);
- }
- if (!strcmp(progress_type_env, "gui") && saved_stdout_env) {
- char msg[256];
- snprintf(msg, sizeof(msg), "%lld\n", total);
- ignore = write(strtoul(saved_stdout_env, NULL, 0), msg,
- strlen(msg));
- }
- if (ignore < 0) {
- /* silence gcc warning */
- }
- }
- void notify_progress(int size, int flag)
- {
- static long long total = 0;
- static long long prev_total = 0;
- total += size;
- if (total > prev_total + PROGRESS_NOTIFY_DELTA
- || (flag != PROGRESS_FLAG_NORMAL)) {
- // check for possible error from qfile-unpacker; if error occured,
- // exit() will be called, so don't bother with current state
- // (notify_progress can be called as callback from copy_file())
- if (flag == PROGRESS_FLAG_NORMAL)
- wait_for_result();
- do_notify_progress(total, flag);
- prev_total = total;
- }
- }
- char *get_abs_path(const char *cwd, const char *pathname)
- {
- char *ret;
- if (pathname[0] == '/')
- return strdup(pathname);
- if (asprintf(&ret, "%s/%s", cwd, pathname) < 0)
- return NULL;
- else
- return ret;
- }
- int main(int argc, char **argv)
- {
- int i;
- char *entry;
- char *cwd;
- char *sep;
- int ignore_symlinks = 0;
- qfile_pack_init();
- register_error_handler(qfile_gui_fatal);
- register_notify_progress(¬ify_progress);
- notify_progress(0, PROGRESS_FLAG_INIT);
- cwd = getcwd(NULL, 0);
- for (i = 1; i < argc; i++) {
- if (strcmp(argv[i], "--ignore-symlinks")==0) {
- ignore_symlinks = 1;
- continue;
- }
- entry = get_abs_path(cwd, argv[i]);
- do {
- sep = rindex(entry, '/');
- if (!sep)
- gui_fatal
- ("Internal error: nonabsolute filenames not allowed");
- *sep = 0;
- } while (sep[1] == 0);
- if (entry[0] == 0) {
- if (chdir("/") < 0) {
- gui_fatal("Internal error: chdir(\"/\") failed?!");
- }
- } else if (chdir(entry))
- gui_fatal("chdir to %s", entry);
- do_fs_walk(sep + 1, ignore_symlinks);
- free(entry);
- }
- notify_end_and_wait_for_result();
- notify_progress(0, PROGRESS_FLAG_DONE);
- return 0;
- }
|