From fd1af58ef29a5906a09e68eb4b414dd786f9360b Mon Sep 17 00:00:00 2001 From: Dmytro Volovnenko Date: Wed, 11 May 2016 11:34:37 +0300 Subject: [PATCH 1/7] added support for FreeBSD(headers & solving problem in get_fdinfo function) --- progress.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/progress.c b/progress.c index 95463ab..2131981 100644 --- a/progress.c +++ b/progress.c @@ -44,9 +44,13 @@ # include # include # include -#else +#endif // __APPLE__ +#ifdef __linux__ # include -#endif +#endif // __linux__ +#ifdef __FreeBSD__ +# include +#endif // __FreeBSD__ #include "progress.h" #include "sizes.h" @@ -406,7 +410,16 @@ if (S_ISBLK(stat_buf.st_mode)) { } fd_info->size = bc*bs; printf("Size: %lld\n", fd_info->size); -#else +#endif +#ifdef __FreeBSD__ + if (ioctl(fd, DIOCGMEDIASIZE, &fd_info->size) < 0) { + if (flag_debug) + nperror("ioctl (get_fdinfo)"); + close(fd); + return 0; + } +#endif +#ifdef __linux__ if (ioctl(fd, BLKGETSIZE64, &fd_info->size) < 0) { if (flag_debug) nperror("ioctl (get_fdinfo)"); From a9c4760f42b96f3720d9e26b3a011536bb0f126f Mon Sep 17 00:00:00 2001 From: Dmytro Volovnenko Date: Wed, 11 May 2016 11:41:36 +0300 Subject: [PATCH 2/7] update Makefile for FreeBSD --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 07bb059..eda53ac 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,9 @@ endif ifeq ($(UNAME), Darwin) override LDFLAGS += -lncurses endif +ifeq ($(UNAME), FreeBSD) + override LDFLAGS += -lncurses +endif PREFIX ?= /usr/local BINDIR = $(PREFIX)/bin MANDIR = $(PREFIX)/share/man/man1 From c1e2163cf325c8cdaa8628dcb6af1540c97558c7 Mon Sep 17 00:00:00 2001 From: vthriller Date: Sat, 27 Feb 2021 11:38:11 +0300 Subject: [PATCH 3/7] FreeBSD support. Well, quick-and-dirty it keeps being. For simplicity this patch keeps reallocating `procstat` all over the place even though a lot of information can be obtained in way fewer passes. --- Makefile | 2 +- README.md | 6 +- progress.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 225 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 6b37a35..af468ea 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ ifeq ($(UNAME), Darwin) override LDFLAGS += -lncurses endif ifeq ($(UNAME), FreeBSD) - override LDFLAGS += -lncurses + override LDFLAGS += -lncurses -lprocstat endif PREFIX ?= /usr/local BINDIR = $(PREFIX)/bin diff --git a/README.md b/README.md index 0e79023..d4dea27 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ progress - Coreutils Progress Viewer [![Build Status](https://travis-ci.org/Xfen What is it ---------- -This tool can be described as a **Tiny**, Dirty, Linux-and-OSX-Only C command +This tool can be described as a **Tiny**, Dirty C command that looks for coreutils basic commands (cp, mv, dd, tar, gzip/gunzip, cat, etc.) currently running on your system and displays the **percentage** of copied data. It can also show **estimated time** and **throughput**, @@ -14,6 +14,8 @@ and provides a "top-like" mode (monitoring). _(After many requests: the colors in the shell come from [powerline-shell](https://github.com/milkbikis/powerline-shell). Try it, it's cool.)_ +`progress` works on Linux, FreeBSD and macOS. + Formerly known as cv (Coreutils Viewer). How do you install it @@ -40,6 +42,8 @@ How do you build it from source make && make install +On FreeBSD, substitute `make` with `gmake`. + It depends on library ncurses, you may have to install corresponding packages (may be something like 'libncurses5-dev' or 'ncurses-devel'). How do you run it diff --git a/progress.c b/progress.c index fa30cb2..6b0f9af 100644 --- a/progress.c +++ b/progress.c @@ -54,6 +54,15 @@ # include #endif // __FreeBSD__ +#ifdef __FreeBSD__ +# include +# include +# include +# include +# include +# include +#endif + #include "progress.h" #include "sizes.h" #include "hlist.h" @@ -187,7 +196,8 @@ for(i = 0; i < nb_processes; ++i) { free(pids); return pid_count; } -#else +#endif // __APPLE__ +#ifdef __linux__ int find_pid_by_id(pid_t pid, pidinfo_t *pid_list) { char fullpath_exe[MAXPATHLEN + 1]; @@ -263,7 +273,86 @@ while ((direntp = readdir(proc)) != NULL) { closedir(proc); return pid_count; } -#endif +#endif // __linux__ +#ifdef __FreeBSD__ +int find_pid_by_id(pid_t pid, pidinfo_t *pid_list) +{ +struct procstat *procstat; +struct kinfo_proc *procs; +unsigned int proc_count; + +struct kinfo_proc *proc; +char pathname[PATH_MAX]; + +int i, found = 0; + +procstat = procstat_open_sysctl(); +assert(procstat != NULL); + +procs = procstat_getprocs(procstat, KERN_PROC_PID, pid, &proc_count); +// procstat doesn't seem to set errno, so don't nperror() +assert(procs != NULL); + +for (i = 0; i < proc_count; i++) { + proc = &procs[i]; + procstat_getpathname(procstat, proc, pathname, sizeof(pathname)); + if (strlen(pathname) == 0) + // kernel thread I guess? + continue; + + pid_list[0].pid = pid; + strcpy(pid_list[0].name, basename(pathname)); + found = 1; + break; +} + +procstat_freeprocs(procstat, procs); +procstat_close(procstat); + +return found; +} + +int find_pids_by_binary_name(char *bin_name, pidinfo_t *pid_list, int max_pids) +{ +struct procstat *procstat; +struct kinfo_proc *procs; +unsigned int proc_count; + +struct kinfo_proc *proc; +char pathname[PATH_MAX]; + +int pid_count = 0; +int i; + +procstat = procstat_open_sysctl(); +assert(procstat != NULL); + +procs = procstat_getprocs(procstat, KERN_PROC_PROC, 0, &proc_count); +// procstat doesn't seem to set errno, so don't nperror() +assert(procs != NULL); + +for (i = 0; i < proc_count; i++) { + proc = &procs[i]; + procstat_getpathname(procstat, proc, pathname, sizeof(pathname)); + if (strlen(pathname) == 0) + // kernel thread I guess? see proc->ki_comm instead + continue; + + if (!strcmp(basename(pathname), bin_name)) { + pid_list[pid_count].pid = proc->ki_pid; + strcpy(pid_list[pid_count].name, bin_name); + pid_count++; + if (pid_count == max_pids) + break; + } +} + +procstat_freeprocs(procstat, procs); +procstat_close(procstat); + +return pid_count; +} +#endif // __FreeBSD__ #ifdef __APPLE__ int find_fd_for_pid(pid_t pid, int *fd_list, int max_fd) @@ -307,7 +396,8 @@ for(i = 0; i < numberOfProcFDs; i++) { } return count; } -#else +#endif // __APPLE__ +#ifdef __linux__ int find_fd_for_pid(pid_t pid, int *fd_list, int max_fd) { DIR *proc; @@ -370,13 +460,76 @@ while ((direntp = readdir(proc)) != NULL) { closedir(proc); return count; } -#endif +#endif // __linux__ +#ifdef __FreeBSD__ +int find_fd_for_pid(pid_t pid, int *fd_list, int max_fd) +{ +struct procstat *procstat; +struct kinfo_proc *procs; +unsigned int proc_count; + +struct kinfo_proc *proc; +struct filestat *fstat; +struct filestat_list *fstat_list; + +int count = 0; +int i; + +procstat = procstat_open_sysctl(); +assert(procstat != NULL); + +procs = procstat_getprocs(procstat, KERN_PROC_PID, pid, &proc_count); +// procstat doesn't seem to set errno, so don't nperror() +assert(procs != NULL); + +for (i = 0; i < proc_count; i++) { + proc = &procs[i]; + + fstat_list = procstat_getfiles(procstat, proc, 0); + if (fstat_list == NULL) + continue; + STAILQ_FOREACH(fstat, fstat_list, next) { + if (fstat->fs_type != PS_FST_TYPE_VNODE) + continue; + if (fstat->fs_fd < 0) // usually non-zero fs_uflags: PS_FST_UFLAG_{TEXT,CTTY,...} + continue; + + struct vnstat vn; + char errbuf[_POSIX2_LINE_MAX]; + + if (procstat_get_vnode_info(procstat, fstat, &vn, errbuf) != 0) + // see errbuf + continue; + + if (!(vn.vn_type == PS_FST_VTYPE_VREG || vn.vn_type == PS_FST_VTYPE_VBLK)) + continue; + + if (is_ignored_file(fstat->fs_path)) + continue; + + // OK, we've found a potential interesting file. + fd_list[count++] = fstat->fs_fd; + // fstat->fs_offset is looked up once again in get_fdinfo() + + if (count == max_fd) + break; + } + + procstat_freefiles(procstat, fstat_list); +} + +procstat_freeprocs(procstat, procs); +procstat_close(procstat); + +return count; +} +#endif // __FreeBSD__ signed char get_fdinfo(pid_t pid, int fdnum, fdinfo_t *fd_info) { struct stat stat_buf; -#ifndef __APPLE__ +#ifdef __linux__ char fdpath[MAXPATHLEN + 1]; char line[LINE_LEN]; FILE *fp; @@ -392,7 +545,8 @@ struct vnode_fdinfowithpath vnodeInfo; if (proc_pidfdinfo(pid, fdnum, PROC_PIDFDVNODEPATHINFO, &vnodeInfo, PROC_PIDFDVNODEPATHINFO_SIZE) <= 0) return 0; strncpy(fd_info->name, vnodeInfo.pvip.vip_path, MAXPATHLEN); -#else +#endif // __APPLE__ +#ifdef __linux__ ssize_t len; snprintf(fdpath, MAXPATHLEN, "%s/%d/fd/%d", PROC_PATH, pid, fdnum); @@ -404,6 +558,62 @@ else { return 0; } #endif +#ifdef __FreeBSD__ +struct procstat *procstat; +struct kinfo_proc *procs; +unsigned int proc_count; + +struct kinfo_proc *proc; +struct filestat *fstat; +struct filestat_list *fstat_list; + +int i; + +procstat = procstat_open_sysctl(); +assert(procstat != NULL); + +procs = procstat_getprocs(procstat, KERN_PROC_PID, pid, &proc_count); +// procstat doesn't seem to set errno, so don't nperror() +assert(procs != NULL); + +for (i = 0; i < proc_count; i++) { + proc = &procs[i]; + + fstat_list = procstat_getfiles(procstat, proc, 0); + if (fstat_list == NULL) + continue; + + gettimeofday(&fd_info->tv, &tz); + + STAILQ_FOREACH(fstat, fstat_list, next) { + if (fstat->fs_fd != fdnum) + continue; + + strncpy(fd_info->name, fstat->fs_path, MAXPATHLEN); + + struct vnstat vn; + char errbuf[_POSIX2_LINE_MAX]; + + if (procstat_get_vnode_info(procstat, fstat, &vn, errbuf) != 0) + // see errbuf + continue; + + fd_info->pos = fstat->fs_offset; + // XXX PS_FST_FFLAG_APPEND? + fd_info->mode = ( + fstat->fs_fflags & (PS_FST_FFLAG_WRITE | PS_FST_FFLAG_READ) ? PM_READWRITE : + fstat->fs_fflags & PS_FST_FFLAG_WRITE ? PM_WRITE : + fstat->fs_fflags & PS_FST_FFLAG_READ ? PM_READ : + 0 + ); + } + + procstat_freefiles(procstat, fstat_list); +} + +procstat_freeprocs(procstat, procs); +procstat_close(procstat); +#endif // __FreeBSD__ if (stat(fd_info->name, &stat_buf) == -1) { //~ printf("[debug] %i - %s\n",pid,fd_info->name); @@ -467,7 +677,8 @@ if (vnodeInfo.pfi.fi_openflags & FWRITE) fd_info->mode = PM_WRITE; if (vnodeInfo.pfi.fi_openflags & FREAD && vnodeInfo.pfi.fi_openflags & FWRITE) fd_info->mode = PM_READWRITE; -#else +#endif // __APPLE__ +#ifdef __linux__ flags = 0; fd_info->pos = 0; @@ -496,7 +707,7 @@ if ((flags & O_ACCMODE) == O_RDWR) fd_info->mode = PM_READWRITE; fclose(fp); -#endif +#endif // __linux__ return 1; } From f2e1be237e2ccce6883b404462253b7394892a99 Mon Sep 17 00:00:00 2001 From: vthriller Date: Sat, 27 Feb 2021 11:46:51 +0300 Subject: [PATCH 4/7] track checksum tools that come with freebsd by default --- progress.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/progress.c b/progress.c index 6b0f9af..2b0805c 100644 --- a/progress.c +++ b/progress.c @@ -73,7 +73,12 @@ static int proc_names_cnt; static char **proc_names; char *default_proc_names[] = {"cp", "mv", "dd", "tar", "cat", "rsync", "scp", "grep", "fgrep", "egrep", "cut", "sort", "md5sum", "sha1sum", - "sha224sum", "sha256sum", "sha384sum", "sha512sum", "adb", + "sha224sum", "sha256sum", "sha384sum", "sha512sum", +#ifdef __FreeBSD__ + "md5", "sha1", "sha224", "sha256", "sha512", "sha512t256", "rmd160", + "skein256", "skein512", "skein1024", +#endif + "adb", "gzip", "gunzip", "bzip2", "bunzip2", "xz", "unxz", "lzma", "unlzma", "7z", "7za", "zip", "unzip", "zcat", "bzcat", "lzcat", "coreutils", From d142d26a2403b9116a9e127ffd546f3fdccdc1c3 Mon Sep 17 00:00:00 2001 From: vthriller Date: Sat, 27 Feb 2021 15:52:29 +0300 Subject: [PATCH 5/7] procstat_getprocs() seems to return NULL if no procs match the predicate, which breaks progress -m --- progress.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/progress.c b/progress.c index 2b0805c..bf5578e 100644 --- a/progress.c +++ b/progress.c @@ -295,8 +295,8 @@ procstat = procstat_open_sysctl(); assert(procstat != NULL); procs = procstat_getprocs(procstat, KERN_PROC_PID, pid, &proc_count); -// procstat doesn't seem to set errno, so don't nperror() -assert(procs != NULL); +if (procs == NULL) + goto done; for (i = 0; i < proc_count; i++) { proc = &procs[i]; @@ -312,6 +312,7 @@ for (i = 0; i < proc_count; i++) { } procstat_freeprocs(procstat, procs); +done: procstat_close(procstat); return found; @@ -333,8 +334,8 @@ procstat = procstat_open_sysctl(); assert(procstat != NULL); procs = procstat_getprocs(procstat, KERN_PROC_PROC, 0, &proc_count); -// procstat doesn't seem to set errno, so don't nperror() -assert(procs != NULL); +if (procs == NULL) + goto done; for (i = 0; i < proc_count; i++) { proc = &procs[i]; @@ -353,6 +354,7 @@ for (i = 0; i < proc_count; i++) { } procstat_freeprocs(procstat, procs); +done: procstat_close(procstat); return pid_count; @@ -484,8 +486,8 @@ procstat = procstat_open_sysctl(); assert(procstat != NULL); procs = procstat_getprocs(procstat, KERN_PROC_PID, pid, &proc_count); -// procstat doesn't seem to set errno, so don't nperror() -assert(procs != NULL); +if (procs == NULL) + goto done; for (i = 0; i < proc_count; i++) { proc = &procs[i]; @@ -524,6 +526,7 @@ for (i = 0; i < proc_count; i++) { } procstat_freeprocs(procstat, procs); +done: procstat_close(procstat); return count; @@ -578,8 +581,8 @@ procstat = procstat_open_sysctl(); assert(procstat != NULL); procs = procstat_getprocs(procstat, KERN_PROC_PID, pid, &proc_count); -// procstat doesn't seem to set errno, so don't nperror() -assert(procs != NULL); +if (procs == NULL) + goto done; for (i = 0; i < proc_count; i++) { proc = &procs[i]; @@ -617,6 +620,7 @@ for (i = 0; i < proc_count; i++) { } procstat_freeprocs(procstat, procs); +done: procstat_close(procstat); #endif // __FreeBSD__ From 451e826fca693a741287a577c00556d68cbea41e Mon Sep 17 00:00:00 2001 From: vthriller Date: Wed, 3 Mar 2021 11:52:46 +0300 Subject: [PATCH 6/7] bsdtar is used on some systems like Gentoo, and on FreeBSD, tar is actually a symlink to bsdtar --- progress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/progress.c b/progress.c index bf5578e..b3fa550 100644 --- a/progress.c +++ b/progress.c @@ -71,7 +71,7 @@ // list and generate it at runtime. static int proc_names_cnt; static char **proc_names; -char *default_proc_names[] = {"cp", "mv", "dd", "tar", "cat", "rsync", "scp", +char *default_proc_names[] = {"cp", "mv", "dd", "tar", "bsdtar", "cat", "rsync", "scp", "grep", "fgrep", "egrep", "cut", "sort", "md5sum", "sha1sum", "sha224sum", "sha256sum", "sha384sum", "sha512sum", #ifdef __FreeBSD__ From 01cdafa82cbb171d54e2dc8bffb5203bc8f7a7fa Mon Sep 17 00:00:00 2001 From: vthriller Date: Wed, 3 Mar 2021 11:54:04 +0300 Subject: [PATCH 7/7] also watch for gcp/gmv on freebsd --- progress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/progress.c b/progress.c index b3fa550..cb7f6a9 100644 --- a/progress.c +++ b/progress.c @@ -84,7 +84,7 @@ char *default_proc_names[] = {"cp", "mv", "dd", "tar", "bsdtar", "cat", "rsync", "coreutils", "split", "gpg", -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__FreeBSD__) "gcp", "gmv", #endif NULL