diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2022-04-03 14:42:03 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2022-04-09 21:47:49 +0000 |
commit | 039d1496b0790a27cbec18e06b9494bf41254019 (patch) | |
tree | fe51d2abfb5c8b85ba4c39cc2cc4b54fdeb69a65 /lib/libprocstat/libprocstat.c | |
parent | eca39864f702e577eba3bc7e9992d1e5e56eba58 (diff) | |
download | src-039d1496b0790a27cbec18e06b9494bf41254019.tar.gz src-039d1496b0790a27cbec18e06b9494bf41254019.zip |
Diffstat (limited to 'lib/libprocstat/libprocstat.c')
-rw-r--r-- | lib/libprocstat/libprocstat.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c index 850d37598423..5948bf72230d 100644 --- a/lib/libprocstat/libprocstat.c +++ b/lib/libprocstat/libprocstat.c @@ -2644,3 +2644,138 @@ procstat_freekstack(struct procstat *procstat __unused, free(kkstp); } + +static struct advlock_list * +procstat_getadvlock_sysctl(struct procstat *procstat __unused) +{ + struct advlock_list *res; + struct advlock *a; + void *buf; + char *c; + struct kinfo_lockf *kl; + size_t buf_len; + int error; + static const int kl_name[] = { CTL_KERN, KERN_LOCKF }; + + res = malloc(sizeof(*res)); + if (res == NULL) + return (NULL); + STAILQ_INIT(res); + buf = NULL; + + buf_len = 0; + error = sysctl(kl_name, nitems(kl_name), NULL, &buf_len, NULL, 0); + if (error != 0) { + warn("sysctl KERN_LOCKF size"); + goto fail; + } + buf_len *= 2; + buf = malloc(buf_len); + if (buf == NULL) { + warn("malloc"); + goto fail; + } + error = sysctl(kl_name, nitems(kl_name), buf, &buf_len, NULL, 0); + if (error != 0) { + warn("sysctl KERN_LOCKF data"); + goto fail; + } + + for (c = buf; (char *)c < (char *)buf + buf_len; + c += kl->kl_structsize) { + kl = (struct kinfo_lockf *)(void *)c; + if (sizeof(*kl) < (size_t)kl->kl_structsize) { + warn("ABI broken"); + goto fail; + } + a = malloc(sizeof(*a)); + if (a == NULL) { + warn("malloc advlock"); + goto fail; + } + switch (kl->kl_rw) { + case KLOCKF_RW_READ: + a->rw = PS_ADVLOCK_RO; + break; + case KLOCKF_RW_WRITE: + a->rw = PS_ADVLOCK_RW; + break; + default: + warn("ABI broken"); + free(a); + goto fail; + } + switch (kl->kl_type) { + case KLOCKF_TYPE_FLOCK: + a->type = PS_ADVLOCK_TYPE_FLOCK; + break; + case KLOCKF_TYPE_PID: + a->type = PS_ADVLOCK_TYPE_PID; + break; + case KLOCKF_TYPE_REMOTE: + a->type = PS_ADVLOCK_TYPE_REMOTE; + break; + default: + warn("ABI broken"); + free(a); + goto fail; + } + a->pid = kl->kl_pid; + a->sysid = kl->kl_sysid; + a->file_fsid = kl->kl_file_fsid; + a->file_rdev = kl->kl_file_rdev; + a->file_fileid = kl->kl_file_fileid; + a->start = kl->kl_start; + a->len = kl->kl_len; + if (kl->kl_path[0] != '\0') { + a->path = strdup(kl->kl_path); + if (a->path == NULL) { + warn("malloc"); + free(a); + goto fail; + } + } else + a->path = NULL; + STAILQ_INSERT_TAIL(res, a, next); + } + + free(buf); + return (res); + +fail: + free(buf); + procstat_freeadvlock(procstat, res); + return (NULL); +} + +struct advlock_list * +procstat_getadvlock(struct procstat *procstat) +{ + switch(procstat->type) { + case PROCSTAT_KVM: + warnx("kvm method is not supported"); + return (NULL); + case PROCSTAT_SYSCTL: + return (procstat_getadvlock_sysctl(procstat)); + case PROCSTAT_CORE: + warnx("core method is not supported"); + return (NULL); + default: + warnx("unknown access method: %d", procstat->type); + return (NULL); + } +} + +void +procstat_freeadvlock(struct procstat *procstat __unused, + struct advlock_list *lst) +{ + struct advlock *a, *a1; + + STAILQ_FOREACH_SAFE(a, lst, next, a1) { + free(__DECONST(char *, a->path)); + free(a); + } + free(lst); +} + |