mirror of https://github.com/htop-dev/htop.git
157 lines
3.1 KiB
C
157 lines
3.1 KiB
C
/*
|
|
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 <errno.h>
|
|
#include <fcntl.h> // IWYU pragma: keep
|
|
#include <limits.h>
|
|
#include <unistd.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h> // 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);
|
|
}
|