aboutsummaryrefslogtreecommitdiff
path: root/lib/libprocstat/libprocstat.c
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2022-04-03 14:42:03 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2022-04-09 21:47:49 +0000
commit039d1496b0790a27cbec18e06b9494bf41254019 (patch)
treefe51d2abfb5c8b85ba4c39cc2cc4b54fdeb69a65 /lib/libprocstat/libprocstat.c
parenteca39864f702e577eba3bc7e9992d1e5e56eba58 (diff)
downloadsrc-039d1496b0790a27cbec18e06b9494bf41254019.tar.gz
src-039d1496b0790a27cbec18e06b9494bf41254019.zip
Diffstat (limited to 'lib/libprocstat/libprocstat.c')
-rw-r--r--lib/libprocstat/libprocstat.c135
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);
+}
+