Compat.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. htop - Compat.c
  3. (C) 2020 htop dev team
  4. Released under the GNU GPLv2+, see the COPYING file
  5. in the source distribution for its full text.
  6. */
  7. #include "config.h" // IWYU pragma: keep
  8. #include "Compat.h"
  9. #include <errno.h>
  10. #include <fcntl.h> // IWYU pragma: keep
  11. #include <limits.h>
  12. #include <unistd.h>
  13. #include <sys/stat.h>
  14. #include <sys/types.h> // IWYU pragma: keep
  15. #include "XUtils.h" // IWYU pragma: keep
  16. /* GNU/Hurd does not have PATH_MAX in limits.h */
  17. #ifndef PATH_MAX
  18. # define PATH_MAX 4096
  19. #endif
  20. int Compat_faccessat(int dirfd,
  21. const char* pathname,
  22. int mode,
  23. int flags) {
  24. int ret;
  25. #ifdef HAVE_FACCESSAT
  26. // Implementation note: AT_SYMLINK_NOFOLLOW unsupported on FreeBSD, fallback to lstat in that case
  27. errno = 0;
  28. ret = faccessat(dirfd, pathname, mode, flags);
  29. if (!ret || errno != EINVAL)
  30. return ret;
  31. #endif
  32. // Error out on unsupported configurations
  33. if (dirfd != (int)AT_FDCWD || mode != F_OK) {
  34. errno = EINVAL;
  35. return -1;
  36. }
  37. // Fallback to stat(2)/lstat(2) depending on flags
  38. struct stat sb;
  39. if (flags) {
  40. ret = lstat(pathname, &sb);
  41. } else {
  42. ret = stat(pathname, &sb);
  43. }
  44. return ret;
  45. }
  46. int Compat_fstatat(int dirfd,
  47. const char* dirpath,
  48. const char* pathname,
  49. struct stat* statbuf,
  50. int flags) {
  51. #ifdef HAVE_FSTATAT
  52. (void)dirpath;
  53. return fstatat(dirfd, pathname, statbuf, flags);
  54. #else
  55. (void)dirfd;
  56. char path[4096];
  57. xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname);
  58. if (flags & AT_SYMLINK_NOFOLLOW)
  59. return lstat(path, statbuf);
  60. return stat(path, statbuf);
  61. #endif
  62. }
  63. #ifndef HAVE_OPENAT
  64. int Compat_openat(const char* dirpath,
  65. const char* pathname,
  66. int flags) {
  67. char path[4096];
  68. xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname);
  69. return open(path, flags);
  70. }
  71. #endif /* !HAVE_OPENAT */
  72. ssize_t Compat_readlinkat(int dirfd,
  73. const char* dirpath,
  74. const char* pathname,
  75. char* buf,
  76. size_t bufsize) {
  77. #ifdef HAVE_READLINKAT
  78. (void)dirpath;
  79. return readlinkat(dirfd, pathname, buf, bufsize);
  80. #else
  81. (void)dirfd;
  82. char path[4096];
  83. xSnprintf(path, sizeof(path), "%s/%s", dirpath, pathname);
  84. return readlink(path, buf, bufsize);
  85. #endif
  86. }
  87. ssize_t Compat_readlink(openat_arg_t dirfd,
  88. const char* pathname,
  89. char* buf,
  90. size_t bufsize) {
  91. #ifdef HAVE_OPENAT
  92. char fdPath[32];
  93. xSnprintf(fdPath, sizeof(fdPath), "/proc/self/fd/%d", dirfd);
  94. char dirPath[PATH_MAX + 1];
  95. ssize_t r = readlink(fdPath, dirPath, sizeof(dirPath) - 1);
  96. if (r < 0)
  97. return r;
  98. dirPath[r] = '\0';
  99. char linkPath[PATH_MAX + 1];
  100. xSnprintf(linkPath, sizeof(linkPath), "%s/%s", dirPath, pathname);
  101. #else
  102. char linkPath[PATH_MAX + 1];
  103. xSnprintf(linkPath, sizeof(linkPath), "%s/%s", dirfd, pathname);
  104. #endif /* HAVE_OPENAT */
  105. return readlink(linkPath, buf, bufsize);
  106. }