diff options
Diffstat (limited to 'src/util.c')
-rw-r--r-- | src/util.c | 153 |
1 files changed, 151 insertions, 2 deletions
@@ -30,12 +30,17 @@ #include <unistd.h> #include <sys/mman.h> #include <fcntl.h> +#include <ctype.h> +#include <dirent.h> #ifdef USE_SENDFILE #include <sys/sendfile.h> #endif #include "util.h" +#include "syrep.h" + +static int stderr_tty = -1; void statistics(DB *db) { DB_BTREE_STAT *statp; @@ -90,7 +95,10 @@ void rotdash(void) { static const char dashes[] = /* ".oOo"; */ "|/-\\"; const static char *d = dashes; - if (isatty(fileno(stderr))) { + if (stderr_tty < 0) + stderr_tty = isatty(fileno(stderr)); + + if (stderr_tty) { fprintf(stderr, "%c\b", *d); d++; @@ -99,7 +107,15 @@ void rotdash(void) { } } -const char* get_attached_filename(const char *path, const char *fn) { +void rotdash_hide(void) { + if (stderr_tty < 0) + stderr_tty = isatty(fileno(stderr)); + + if (stderr_tty) + fputs(" \b", stderr); +} + +const char* get_snapshot_filename(const char *path, const char *fn) { static char npath[PATH_MAX]; struct stat st; @@ -213,6 +229,11 @@ int copy_fd(int sfd, int dfd, uint32_t l) { munmap(src_p, m); munmap(dst_p, m); + + if (interrupted) { + fprintf(stderr, "Canceled.\n"); + goto finish; + } src_o += m; dst_o += m; @@ -243,6 +264,11 @@ int copy_fd(int sfd, int dfd, uint32_t l) { for (;;) { ssize_t m; + if (interrupted) { + fprintf(stderr, "Canceled.\n"); + goto finish; + } + if ((m = read(sfd, buf, BUFSIZE)) < 0) { fprintf(stderr, "read(): %s\n", strerror(errno)); goto finish; @@ -421,3 +447,126 @@ int makeprefixpath(const char *path, mode_t m) { return mkdir_p(tmp, m); } + +int question(const char *text, const char *replies) { + int r = 0; + FILE *f; + + assert(text && replies && *replies); + + if (!(f = fopen("/dev/tty", "r"))) + f = stdin; + + for (;;) { + const char *q; + char reply[256]; + + if (interrupted) { + fprintf(stderr, "Canceled.\n"); + goto finish; + } + + fprintf(stderr, "\r%s [", text); + + for (q = replies; *q; q++) { + fputc(q == replies ? toupper(*q) : tolower(*q), stderr); + + if (*(q+1)) + fputc('|', stderr); + } + + fprintf(stderr, "] "); + + if (!fgets(reply, sizeof(reply), f)) + goto finish; + + if (reply[0] == '\r' || reply[0] == '\n') + reply[0] = *replies; + + reply[0] = tolower(reply[0]); + + for (q = replies; *q; q++) + + if (tolower(*q) == reply[0]) { + r = *q; + goto finish; + } + } + + +finish: + + fputc('\r', stderr); + + if (f != stdin) + fclose(f); + + return r; + +} + + +int rm_rf(const char *root, int rec) { + DIR *dir = NULL; + int r = -1; + struct dirent *de; + + if (!(dir = opendir(root))) { + + if (errno == ENOENT) { + r = 0; + goto finish; + } + + fprintf(stderr, "opendir(\"%s\"): %s", root, strerror(errno)); + goto finish; + } + + while ((de = readdir(dir))) { + char path[PATH_MAX]; + + if (!strcmp(de->d_name, ".")) + continue; + + if (!strcmp(de->d_name, "..")) + continue; + + snprintf(path, sizeof(path), "%s/%s", root, de->d_name); + + if (rec) { + struct stat st; + + if (stat(path, &st) < 0) { + fprintf(stderr, "stat(\"%s\"): %s\n", path, strerror(errno)); + goto finish; + } + + if (S_ISDIR(st.st_mode)) { + + if (rm_rf(path, rec) < 0) + return -1; + + continue; + } + } + + if (unlink(path) < 0) { + fprintf(stderr, "unlink(\"%s\"): %s\n", path, strerror(errno)); + goto finish; + } + } + + if (rmdir(root) < 0) { + fprintf(stderr, "rmdir(\"%s\"): %s\n", root, strerror(errno)); + goto finish; + } + + r = 0; + +finish: + if (dir) + closedir(dir); + + return r; +} + |