/
linux-proc.h
100 lines (90 loc) · 3.67 KB
/
linux-proc.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include "realpath.h"
#include "fcntl.h" // for AT_FDCWD
static inline char *interpret_path_at(pid_t pid, int fd, const char *path) {
if (!path) return NULL;
/* printf("path: %s\n", path); */
const char *procself = "/proc/self/";
const int procselflen = strlen(procself);
if (strlen(path) > procselflen &&
!memcmp(path, procself, procselflen)) {
char *out = malloc(PATH_MAX);
snprintf(out, PATH_MAX, "/proc/%d/%s", pid, path + procselflen);
/* printf("rawpath: %s\n", out); */
return out;
}
/* printf("path '%s' does not match '%s'\n", path, procself); */
if (path[0] == '/') {
/* printf("rawpath: %s\n", path); */
return strdup(path);
}
char *proc_fd = malloc(PATH_MAX);
if (fd >= 0 && fd != AT_FDCWD) snprintf(proc_fd, PATH_MAX, "/proc/%d/fd/%d", pid, fd);
else snprintf(proc_fd, PATH_MAX, "/proc/%d/cwd", pid);
char *cwd = malloc(PATH_MAX);
int linklen = readlink(proc_fd, cwd, PATH_MAX);
if (linklen < 0) {
fprintf(stderr, "unable to determine cwd from %s i.e. fd %d!!! (%s)\n",
proc_fd, fd, strerror(errno));
return NULL;
}
cwd[linklen] = 0;
/* printf("cwd(%d): %s (from %s)\n", fd, cwd, proc_fd); */
int total_len = strlen(cwd) + strlen(path) + 4;
if (total_len > PATH_MAX) cwd = realloc(cwd, total_len);
strcat(cwd, "/");
strcat(cwd, path);
free(proc_fd);
/* printf("rawpath: (%d) %s\n", fd, cwd); */
return cwd;
}
static inline void read_dir_fd(pid_t pid, int dirfd, rw_status *h) {
char *rawpath = interpret_path_at(pid, dirfd, ".");
char *abspath = flexible_realpath(rawpath, h, look_for_file_or_directory, false);
if (!lookup_in_hash(&h->mkdir, abspath)) {
insert_hashset(&h->readdir, abspath);
}
free(rawpath);
free(abspath);
}
static inline void read_something_at(pid_t pid, int dirfd, const char *path,
rw_status *h, enum last_symlink_handling lh,
bool failure_is_okay) {
char *rawpath = interpret_path_at(pid, dirfd, path);
char *abspath = flexible_realpath(rawpath, h, lh, failure_is_okay);
struct stat st;
if (!lookup_in_hash(&h->written, abspath) && !stat(abspath, &st) && S_ISREG(st.st_mode)) {
insert_hashset(&h->read, abspath);
}
free(rawpath);
free(abspath);
}
static inline void write_something_at(pid_t pid, int dirfd, const char *path,
rw_status *h, enum last_symlink_handling lh,
bool failure_is_okay) {
char *rawpath = interpret_path_at(pid, dirfd, path);
char *abspath = flexible_realpath(rawpath, h, lh, failure_is_okay);
insert_hashset(&h->written, abspath);
delete_from_hashset(&h->read, abspath);
free(rawpath);
free(abspath);
}
static inline void read_file_at(pid_t pid, int dirfd, const char *path,
rw_status *h) {
read_something_at(pid, dirfd, path, h, look_for_file_or_directory, false);
}
static inline void maybe_read_file_at(pid_t pid, int dirfd, const char *path,
rw_status *h) {
read_something_at(pid, dirfd, path, h, look_for_file_or_directory, true);
}
static inline void write_file_at(pid_t pid, int dirfd, const char *path,
rw_status *h) {
write_something_at(pid, dirfd, path, h, look_for_file_or_directory, false);
}
static inline void read_link_at(pid_t pid, int dirfd, const char *path,
rw_status *h) {
read_something_at(pid, dirfd, path, h, look_for_symlink, false);
}
static inline void write_link_at(pid_t pid, int dirfd, const char *path,
rw_status *h) {
write_something_at(pid, dirfd, path, h, look_for_symlink, false);
}