summaryrefslogtreecommitdiffstats
path: root/linux/Platform.c
diff options
context:
space:
mode:
authorнаб <nabijaczleweli@nabijaczleweli.xyz>2022-11-26 00:34:59 +0100
committerBenBE <BenBE@geshi.org>2023-01-08 18:22:10 +0100
commitaa48120a160b1eadf7d87e46385767cec5392c8f (patch)
treef45d82f44dba1506a3c3a36f2eb3c09fd09a1b56 /linux/Platform.c
parentf320171578ba37d085e5daabfea8b809c3c62633 (diff)
Fix Linux Platform_getProcessLocks() for file-description locks
Instead of filtering the global /proc/locks by PID-that-locked (which is different than the process that holds it for inherited flock(2)s and always literal -1 for fcntl(F_OFD_SETLK)s), just look at the locks on open files For a process with: $ head /proc/$$/fdinfo/{9,10,11} ==> /proc/797393/fdinfo/9 <== pos: 0 flags: 0100000 mnt_id: 2775 lock: 1: FLOCK ADVISORY WRITE 818754 00:69:7 0 EOF ==> /proc/797393/fdinfo/10 <== pos: 0 flags: 0100000 mnt_id: 127 lock: 1: FLOCK ADVISORY WRITE 828244 00:30:509028 0 EOF lock: 2: OFDLCK ADVISORY READ -1 00:30:509028 0 199 ==> /proc/797393/fdinfo/11 <== pos: 0 flags: 0100000 mnt_id: 2775 lock: 1: FLOCK ADVISORY WRITE 935925 00:69:1187 0 EOF Instead of: No locks have been found for the selected process. I now observe: 1 FLOCK ADVISORY WRITE 00:30:00000000000000509028 0 <END OF FILE> /home/nabijaczleweli/.feeds 1 FLOCK ADVISORY WRITE 00:69:00000000000000000007 0 <END OF FILE> /home/nabijaczleweli/uwu/mart.html 1 FLOCK ADVISORY WRITE 00:69:00000000000000001187 0 <END OF FILE> /home/nabijaczleweli/uwu/removedfile (deleted) 2 OFDLCK ADVISORY READ 00:30:00000000000000509028 0 199 /home/nabijaczleweli/.feeds This also fixes an obvious issue where the filename for fd 0 would never be resolved
Diffstat (limited to 'linux/Platform.c')
-rw-r--r--linux/Platform.c107
1 files changed, 67 insertions, 40 deletions
diff --git a/linux/Platform.c b/linux/Platform.c
index 8c608d6d..38f9854d 100644
--- a/linux/Platform.c
+++ b/linux/Platform.c
@@ -12,6 +12,7 @@ in the source distribution for its full text.
#include <assert.h>
#include <ctype.h>
#include <dirent.h>
+#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <math.h>
@@ -487,60 +488,86 @@ out:
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
FileLocks_ProcessData* pdata = xCalloc(1, sizeof(FileLocks_ProcessData));
+ DIR* dirp;
+ int dfd;
+
+ char path[PATH_MAX];
+ xSnprintf(path, sizeof(path), PROCDIR "/%d/fdinfo/", pid);
+ if (strlen(path) >= (sizeof(path) - 2))
+ goto err;
+
+ if (!(dirp = opendir(path)))
+ goto err;
- FILE* f = fopen(PROCDIR "/locks", "r");
- if (!f) {
- pdata->error = true;
- return pdata;
+ if ((dfd = dirfd(dirp)) == -1) {
+ closedir(dirp);
+ goto err;
}
- char buffer[1024];
FileLocks_LockData** data_ref = &pdata->locks;
- while (fgets(buffer, sizeof(buffer), f)) {
- if (!strchr(buffer, '\n'))
+ for (struct dirent* de; (de = readdir(dirp)); ) {
+ if (String_eq(de->d_name, ".") || String_eq(de->d_name, ".."))
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))
+ errno = 0;
+ char *end = de->d_name;
+ strtoull(de->d_name, &end, 10);
+ if (errno || *end)
continue;
- if (pid != lock_pid)
+ int fd = openat(dfd, de->d_name, O_RDONLY | O_CLOEXEC);
+ if(fd == -1)
continue;
+ FILE *f = fdopen(fd, "r");
+ if(!f) {
+ close(fd);
+ continue;
+ }
- FileLocks_LockData* ldata = xCalloc(1, sizeof(FileLocks_LockData));
- FileLocks_Data* data = &ldata->data;
- data->id = lock_id;
- data->locktype = xStrdup(lock_type);
- data->exclusive = xStrdup(lock_excl);
- data->readwrite = xStrdup(lock_rw);
- data->filename = 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;
+ for (char buffer[1024]; fgets(buffer, sizeof(buffer), f); ) {
+ if (!strchr(buffer, '\n'))
+ continue;
+
+ if (strncmp(buffer, "lock:\t", strlen("lock:\t")))
+ continue;
+
+ FileLocks_Data data = {0};
+ int _;
+ char lock_end[25], locktype[32], exclusive[32], readwrite[32];
+ if (10 != sscanf(buffer + strlen("lock:\t"), "%d: %31s %31s %31s %d %x:%x:%"PRIu64" %"PRIu64" %24s",
+ &data.id, locktype, exclusive, readwrite, &_,
+ &data.dev[0], &data.dev[1], &data.inode,
+ &data.start, lock_end))
+ continue;
+
+ data.locktype = xStrdup(locktype);
+ data.exclusive = xStrdup(exclusive);
+ data.readwrite = xStrdup(readwrite);
+
+ if (String_eq(lock_end, "EOF"))
+ data.end = ULLONG_MAX;
+ else
+ data.end = strtoull(lock_end, NULL, 10);
+
+ xSnprintf(path, sizeof(path), PROCDIR "/%d/fd/%s", pid, de->d_name);
+ char link[PATH_MAX];
+ ssize_t link_len;
+ if (strlen(path) < (sizeof(path) - 2) && (link_len = readlink(path, link, sizeof(link))) != -1)
+ data.filename = xStrndup(link, link_len);
+
+ *data_ref = xCalloc(1, sizeof(FileLocks_LockData));
+ (*data_ref)->data = data;
+ data_ref = &(*data_ref)->next;
}
- *data_ref = ldata;
- data_ref = &ldata->next;
+ fclose(f);
}
- fclose(f);
+ closedir(dirp);
+ return pdata;
+
+err:
+ pdata->error = true;
return pdata;
}

© 2014-2024 Faster IT GmbH | imprint | privacy policy