/* htop - Compat.c (C) 2020 htop dev team Released under the GNU GPLv2+, see the COPYING file in the source distribution for its full text. */ #include "config.h" // IWYU pragma: keep #include "Compat.h" #include #include // IWYU pragma: keep #include #include #include #include // IWYU pragma: keep #include "XUtils.h" // IWYU pragma: keep /* GNU/Hurd does not have PATH_MAX in limits.h */ #ifndef PATH_MAX # define PATH_MAX 4096 #endif int Compat_faccessat(int dirfd, const char* pathname, int mode, int flags) { int ret; #ifdef HAVE_FACCESSAT // Implementation note: AT_SYMLINK_NOFOLLOW unsupported on FreeBSD, fallback to lstat in that case errno = 0; ret = faccessat(dirfd, pathname, mode, flags); if (!ret || errno != EINVAL) return ret; #endif // Error out on unsupported configurations if (dirfd != (int)AT_FDCWD || mode != F_OK) { errno = EINVAL; return -1; } // Fallback to stat(2)/lstat(2) depending on flags struct stat sb; if (flags) { ret = lstat(pathname, &sb); } else { ret = stat(pathname, &sb); } return ret; } int Compat_fstatat(int dirfd, const char* dirpath, const char* pathname, struct stat* statbuf, int flags) { #ifdef HAVE_FSTATAT (void)dirpath; return fstatat(dirfd, pathname, statbuf, flags); #else (void)dirfd; char path[4096]; xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname); if (flags & AT_SYMLINK_NOFOLLOW) return lstat(path, statbuf); return stat(path, statbuf); #endif } #ifndef HAVE_OPENAT int Compat_openat(const char* dirpath, const char* pathname, int flags) { char path[4096]; xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname); return open(path, flags); } #endif /* !HAVE_OPENAT */ ssize_t Compat_readlinkat(int dirfd, const char* dirpath, const char* pathname, char* buf, size_t bufsize) { #ifdef HAVE_READLINKAT (void)dirpath; return readlinkat(dirfd, pathname, buf, bufsize); #else (void)dirfd; char path[4096]; xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname); return readlink(path, buf, bufsize); #endif } ssize_t Compat_readlink(openat_arg_t dirfd, const char* pathname, char* buf, size_t bufsize) { #ifdef HAVE_OPENAT char fdPath[32]; xSnprintf(fdPath, sizeof(fdPath), "/proc/self/fd/%d", dirfd); char dirPath[PATH_MAX + 1]; ssize_t r = readlink(fdPath, dirPath, sizeof(dirPath) - 1); if (r < 0) return r; dirPath[r] = '\0'; char linkPath[PATH_MAX + 1]; xSnprintf(linkPath, sizeof(linkPath), "%s/%s", dirPath, pathname); #else char linkPath[PATH_MAX + 1]; xSnprintf(linkPath, sizeof(linkPath), "%s/%s", dirfd, pathname); #endif /* HAVE_OPENAT */ return readlink(linkPath, buf, bufsize); }