summaryrefslogtreecommitdiffstats
path: root/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c153
1 files changed, 151 insertions, 2 deletions
diff --git a/src/util.c b/src/util.c
index 2a4eb59..f0d66d1 100644
--- a/src/util.c
+++ b/src/util.c
@@ -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;
+}
+