diff options
author | Benny Baumann <BenBE@geshi.org> | 2020-11-11 22:15:35 +0100 |
---|---|---|
committer | Benny Baumann <BenBE@geshi.org> | 2020-11-14 15:51:26 +0100 |
commit | 18763051a2c5a5d3a39bfabc284b3d72b1f6fc9b (patch) | |
tree | 6674c47d7b011aca855ea72a0b94c7567bc28294 /linux/Platform.c | |
parent | 2d6da2e52066067e4c82a2e16f73438319e1db81 (diff) |
Split platform dependent parts for file locks screen
Diffstat (limited to 'linux/Platform.c')
-rw-r--r-- | linux/Platform.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/linux/Platform.c b/linux/Platform.c index f7a768c9..7e51bf61 100644 --- a/linux/Platform.c +++ b/linux/Platform.c @@ -11,11 +11,16 @@ in the source distribution for its full text. #include <assert.h> #include <ctype.h> +#include <dirent.h> +#include <fcntl.h> +#include <inttypes.h> +#include <limits.h> #include <math.h> #include <stdio.h> #include "BatteryMeter.h" #include "ClockMeter.h" +#include "Compat.h" #include "CPUMeter.h" #include "DateMeter.h" #include "DateTimeMeter.h" @@ -304,6 +309,120 @@ char* Platform_getProcessEnv(pid_t pid) { return env; } +/* + * Return the absolute path of a file given its pid&inode number + * + * Based on implementation of lslocks from util-linux: + * https://sources.debian.org/src/util-linux/2.36-3/misc-utils/lslocks.c/#L162 + */ +char* Platform_getInodeFilename(pid_t pid, ino_t inode) { + struct stat sb; + struct dirent *de; + DIR *dirp; + size_t len; + int fd; + + char path[PATH_MAX]; + char sym[PATH_MAX]; + char* ret = NULL; + + memset(path, 0, sizeof(path)); + memset(sym, 0, sizeof(sym)); + + xSnprintf(path, sizeof(path), "%s/%d/fd/", PROCDIR, pid); + if (strlen(path) >= (sizeof(path) - 2)) + return NULL; + + if (!(dirp = opendir(path))) + return NULL; + + if ((fd = dirfd(dirp)) < 0 ) + goto out; + + while ((de = readdir(dirp))) { + if (String_eq(de->d_name, ".") || String_eq(de->d_name, "..")) + continue; + + /* care only for numerical descriptors */ + if (!strtoull(de->d_name, (char **) NULL, 10)) + continue; + + if (!Compat_fstatat(fd, path, de->d_name, &sb, 0) && inode != sb.st_ino) + continue; + + if ((len = Compat_readlinkat(fd, path, de->d_name, sym, sizeof(sym) - 1)) < 1) + goto out; + + sym[len] = '\0'; + + ret = xStrdup(sym); + break; + } + +out: + closedir(dirp); + return ret; +} + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) { + FileLocks_ProcessData* pdata = xCalloc(1, sizeof(FileLocks_ProcessData)); + + FILE* f = fopen(PROCDIR "/locks", "r"); + if (!f) { + pdata->error = true; + return pdata; + } + + char buffer[1024]; + FileLocks_LockData** data_ref = &pdata->locks; + while(fgets(buffer, sizeof(buffer), f)) { + if (!strchr(buffer, '\n')) + continue; + + int lock_id; + char lock_type[16]; + char lock_excl[16]; + char lock_rw[16]; + pid_t lock_pid; + unsigned int lock_dev[2]; + uint64_t lock_inode; + char lock_start[25]; + char lock_end[25]; + + if (10 != sscanf(buffer, "%d: %15s %15s %15s %d %x:%x:%"PRIu64" %24s %24s", + &lock_id, lock_type, lock_excl, lock_rw, &lock_pid, + &lock_dev[0], &lock_dev[1], &lock_inode, + lock_start, lock_end)) + continue; + + if (pid != lock_pid) + continue; + + FileLocks_LockData* ldata = xCalloc(1, sizeof(FileLocks_LockData)); + FileLocks_Data* data = &ldata->data; + data->id = lock_id; + data->data[0] = xStrdup(lock_type); + data->data[1] = xStrdup(lock_excl); + data->data[2] = xStrdup(lock_rw); + data->data[3] = Platform_getInodeFilename(lock_pid, lock_inode); + data->dev[0] = lock_dev[0]; + data->dev[1] = lock_dev[1]; + data->inode = lock_inode; + data->start = strtoull(lock_start, NULL, 10); + if (!String_eq(lock_end, "EOF")) { + data->end = strtoull(lock_end, NULL, 10); + } else { + data->end = ULLONG_MAX; + } + + *data_ref = ldata; + data_ref = &ldata->next; + } + + fclose(f); + return pdata; +} + void Platform_getPressureStall(const char *file, bool some, double* ten, double* sixty, double* threehundred) { *ten = *sixty = *threehundred = 0; char procname[128+1]; |