#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include void display_error(const char *fmt, va_list args) { char *dialog_cmd; char buf[1024]; struct stat st_buf; int ret; (void) vsnprintf(buf, sizeof(buf), fmt, args); ret = stat("/usr/bin/kdialog", &st_buf); #define KDIALOG_CMD "kdialog --title 'File copy/move error' --sorry " #define ZENITY_CMD "zenity --title 'File copy/move error' --warning --text " if (asprintf(&dialog_cmd, "%s '%s: %s (error type: %s)'", ret==0 ? KDIALOG_CMD : ZENITY_CMD, program_invocation_short_name, buf, strerror(errno)) < 0) { fprintf(stderr, "Failed to allocate memory for error message :(\n"); return; } #undef KDIALOG_CMD #undef ZENITY_CMD fprintf(stderr, "%s\n", buf); system(dialog_cmd); } _Noreturn void gui_fatal(const char *fmt, ...) { va_list args; va_start(args, fmt); display_error(fmt, args); va_end(args); exit(1); } 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(display_error); 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(); return 0; }