summaryrefslogtreecommitdiffstats
path: root/Compat.c
blob: 43d02ec70ce9fbb6b9666328f090205096826b57 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
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 <unistd.h>
#include <sys/stat.h>
#include <sys/types.h> // IWYU pragma: keep

#include "XUtils.h" // IWYU pragma: keep


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 != AT_FDCWD || mode != F_OK) {
      errno = EINVAL;
      return -1;
   }

   // Fallback to stat(2)/lstat(2) depending on flags
   struct stat statinfo;
   if(flags) {
      ret = lstat(pathname, &statinfo);
   } else {
      ret = stat(pathname, &statinfo);
   }

   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
}

© 2014-2024 Faster IT GmbH | imprint | privacy policy