1 /* ISC license. */
2 
3 #include <skalibs/sysdeps.h>
4 
5 #ifdef SKALIBS_HASOPENAT
6 
7 #ifndef _ATFILE_SOURCE
8 #define _ATFILE_SOURCE
9 #endif
10 
11 #include <skalibs/nonposix.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <skalibs/unix-transactional.h>
15 
stat_at(int dirfd,char const * file,struct stat * st)16 int stat_at (int dirfd, char const *file, struct stat *st)
17 {
18   return fstatat(dirfd, file, st, 0) ;
19 }
20 
lstat_at(int dirfd,char const * file,struct stat * st)21 int lstat_at (int dirfd, char const *file, struct stat *st)
22 {
23   return fstatat(dirfd, file, st, AT_SYMLINK_NOFOLLOW) ;
24 }
25 
26 #else
27 
28  /* OpenBSD plz. lstat() is POSIX. */
29 #include <skalibs/nonposix.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <skalibs/djbunix.h>
34 #include <skalibs/unix-transactional.h>
35 
fstat_at(int dirfd,char const * file,struct stat * st,int (* dostat)(char const *,struct stat *))36 static int fstat_at (int dirfd, char const *file, struct stat *st, int (*dostat)(char const *, struct stat *))
37 {
38   int r ;
39   int fdhere = open_read(".") ;
40   if (fdhere < 0) return -1 ;
41   if (fd_chdir(dirfd) < 0)
42   {
43     fd_close(fdhere) ;
44     return -1 ;
45   }
46   r = (*dostat)(file, st) ;
47   if (r < 0)
48   {
49     int e = errno ;
50     fd_chdir(fdhere) ;
51     fd_close(fdhere) ;
52     errno = e ;
53     return -1 ;
54   }
55   if (fd_chdir(fdhere) < 0)
56   {
57     fd_close(fdhere) ;
58     return -1 ;
59   }
60   fd_close(fdhere) ;
61   return r ;
62 }
63 
stat_at(int dirfd,char const * file,struct stat * st)64 int stat_at (int dirfd, char const *file, struct stat *st)
65 {
66   return fstat_at(dirfd, file, st, &stat) ;
67 }
68 
lstat_at(int dirfd,char const * file,struct stat * st)69 int lstat_at (int dirfd, char const *file, struct stat *st)
70 {
71   return fstat_at(dirfd, file, st, &lstat) ;
72 }
73 
74 #endif
75