commit - 87095cb80e54eb834a52a0b292b8e252094a836b
commit + 720da91ac04474144004566b0ff0afca9facccb6
blob - 98a5510821f8a7e2ec32aadb20fb62e10559988d
blob + 04bd9aa95cf0232e76fabdaf4bcf6f6d366797b8
--- rover.c
+++ rover.c
char cwd[PATH_MAX];
} Tab;
+typedef struct Prog {
+ off_t partial;
+ off_t total;
+ const char *msg;
+} Prog;
+
/* Global state. */
static struct Rover {
int tab;
Edit edit;
int edit_scroll;
volatile sig_atomic_t pending_winch;
+ Prog prog;
Tab tabs[10];
} rover;
update_view();
} else
cd(1);
+}
+
+static off_t
+count_dir(const char *path)
+{
+ DIR *dp;
+ struct dirent *ep;
+ struct stat statbuf;
+ char subpath[PATH_MAX];
+ off_t total;
+
+ if(!(dp = opendir(path))) return 0;
+ total = 0;
+ while ((ep = readdir(dp))) {
+ if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, ".."))
+ continue;
+ snprintf(subpath, PATH_MAX, "%s%s", path, ep->d_name);
+ lstat(subpath, &statbuf);
+ if (S_ISDIR(statbuf.st_mode)) {
+ strcat(subpath, "/");
+ total += count_dir(subpath);
+ } else
+ total += statbuf.st_size;
+ }
+ closedir(dp);
+ return total;
+}
+
+static off_t
+count_marked()
+{
+ int i;
+ char *entry;
+ off_t total;
+ struct stat statbuf;
+
+ total = 0;
+ chdir(rover.marks.dirpath);
+ for (i = 0; i < rover.marks.bulk; i++) {
+ entry = rover.marks.entries[i];
+ if (entry) {
+ if (ISDIR(entry)) {
+ total += count_dir(entry);
+ } else {
+ lstat(entry, &statbuf);
+ total += statbuf.st_size;
+ }
+ }
+ }
+ chdir(CWD);
+ return total;
}
/* Recursively process a source directory using CWD as destination root.
clear_message();
message(CYAN, "%s...", msg_doing);
refresh();
+ rover.prog = (Prog) {count_marked(), 0, msg_doing};
for (i = 0; i < rover.marks.bulk; i++)
if (rover.marks.entries[i]) {
ret = 0;
else
message(RED, "Some errors occured while %s.", msg_doing);
RV_ALERT();
+}
+
+static void
+update_progress(off_t delta)
+{
+ int percent;
+
+ rover.prog.partial += delta;
+ percent = (int) (rover.prog.partial * 100 / rover.prog.total);
+ message(CYAN, "%s...%d%%", rover.prog.msg, percent);
+ refresh();
}
/* Wrappers for file operations. */
-static PROCESS delfile = unlink;
+static int delfile(const char *path) {
+ int ret;
+ struct stat st;
+
+ ret = lstat(path, &st);
+ if (ret < 0) return ret;
+ update_progress(st.st_size);
+ return unlink(path);
+}
static PROCESS deldir = rmdir;
static int addfile(const char *path) {
/* Using creat(2) because mknod(2) doesn't seem to be portable. */
if (ret < 0) return ret;
while ((size = read(src, buf, BUFSIZ)) > 0) {
write(dst, buf, size);
+ update_progress(size);
sync_signals();
}
close(src);
}
static int movfile(const char *srcpath) {
int ret;
+ struct stat st;
char dstpath[PATH_MAX];
strcpy(dstpath, CWD);
strcat(dstpath, srcpath + strlen(rover.marks.dirpath));
ret = rename(srcpath, dstpath);
- if (ret < 0 && errno == EXDEV) {
+ if (ret == 0) {
+ ret = lstat(srcpath, &st);
+ if (ret < 0) return ret;
+ update_progress(st.st_size);
+ } else if (errno == EXDEV) {
ret = cpyfile(srcpath);
if (ret < 0) return ret;
- ret = delfile(srcpath);
+ ret = unlink(srcpath);
}
return ret;
}