Mercurial > minori
diff dep/animone/src/fd/bsd.cc @ 270:0718f538c5f9
dep/animone: filter open files by access mode
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Fri, 12 Apr 2024 19:13:50 -0400 |
parents | 1a6a5d3a94cd |
children | 65df2813d0de |
line wrap: on
line diff
--- a/dep/animone/src/fd/bsd.cc Fri Apr 12 05:23:45 2024 -0400 +++ b/dep/animone/src/fd/bsd.cc Fri Apr 12 19:13:50 2024 -0400 @@ -13,6 +13,7 @@ #ifdef HAVE_KVM_GETFILES # include <kvm.h> +# include <fts.h> #elif defined(LIBUTIL) # include <libutil.h> #endif @@ -110,10 +111,8 @@ return false; /* actually get our results */ - if (sysctl((const int*)mib, (sizeof(mib) / sizeof(*mib)) - 1, result.get(), &length, NULL, 0) == ENOMEM) { - result.reset(); - throw std::bad_alloc(); - } + if (sysctl((const int*)mib, (sizeof(mib) / sizeof(*mib)) - 1, result.get(), &length, NULL, 0) == ENOMEM) + return false; if (length < sizeof(struct kinfo_proc)) return false; @@ -126,10 +125,47 @@ #endif } +#ifdef HAVE_KVM_GETFILES +static bool GetOpenFileName(const struct kinfo_file& file, std::string& name) { + /* OpenBSD doesn't provide a native API for this, so we have + * to do it ourselves */ + static constexpr std::string_view root = "/"; + + FTS* file_system = fts_open(root.data(), FTS_COMFOLLOW | FTS_NOCHDIR, nullptr); + if (!file_system) + return false; + + /* Search through the filesystem for a file that matches our + * kinfo_file structure */ + FTSENT* parent = nullptr; + while ((parent = fts_read(file_system))) { + FTSENT* child = fts_children(file_system, 0); + while (child && child->fts_link) { + child = child->fts_link; + if (!S_ISREG(child->fts_statp->st_mode) || !S_ISLNK(child->fts_statp->st_mode)) + continue; + + if (child->fts_statp->st_dev != file->va_fsid) + continue; + + if (child->fts_statp->st_ino != file->va_fileid) + continue; + + name = std::string(child->fts_path) + child->fts_name; + fts_close(file_system); + return true; + } + } + + fts_close(filesystem); + return false; +} +#endif /* HAVE_KVM_GETFILES */ + bool EnumerateOpenFiles(const std::set<pid_t>& pids, open_file_proc_t open_file_proc) { #ifdef HAVE_KVM_GETFILES char errbuf[_POSIX2_LINE_MAX]; - kvm_t* kernel = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); + kvm_t* kernel = kvm_openfiles(nullptr, nullptr, nullptr, O_RDONLY, errbuf); if (!kernel) return false; @@ -142,7 +178,15 @@ } for (int i = 0; i < cnt; i++) { - if (!open_file_proc({pid, kfile[i].kf_path})) { + uint32_t oflags = kfile[i].kf_flags & O_ACCMODE; + if (oflags == O_WRONLY || oflags == O_RDWR) + continue; + + std::string name; + if (!GetOpenFileName(kfile[i], name)) + continue; + + if (!open_file_proc({pid, name})) { kvm_close(kernel); return false; } @@ -150,10 +194,8 @@ } kvm_close(kernel); - return true; #elif defined(LIBUTIL) - /* does this code even work? */ for (const auto& pid : pids) { int cnt; std::unique_ptr<struct kinfo_file[]> files(kinfo_getfile(pid, &cnt)); @@ -162,7 +204,11 @@ for (int i = 0; i < cnt; i++) { const struct kinfo_file& current = files[i]; - if (current.kf_vnode_type != KF_VTYPE_VREG) + if (current.kf_vnode_type != KF_VTYPE_VREG || current.kf_vnode_type != KF_VTYPE_VLNK) + continue; + + const int oflags = current.kf_flags & O_ACCMODE; + if (oflags == O_WRONLY || oflags == O_RDWR) continue; if (!open_file_proc({pid, current.kf_path})) @@ -172,29 +218,8 @@ return true; #else - for (const auto& pid : pids) { - int mib[6] = {CTL_KERN, KERN_FILE2, KERN_FILE_BYPID, pid, sizeof(struct kinfo_file), 0}; - - size_t len = 0; - if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &len, NULL, 0) == -1) - return false; - - mib[5] = len / sizeof(struct kinfo_file); - - std::unique_ptr<struct kinfo_file[]> buf(new struct kinfo_file[mib[5]]); - if (!buf) - return false; - - if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf.get(), &len, NULL, 0) == -1) - return false; - - /* TODO: check kfile[i].ki_ofileflags */ - for (size_t i = 0; i < mib[5]; i++) - if (!open_file_proc({pid, kfile[i].kf_path})) - return false; - } - - return true; + /* NetBSD doesn't even provide a real API for this */ + return false; #endif }