summaryrefslogtreecommitdiff
path: root/src/stat/fstatat.c
blob: f5bc3685e77476b4d0fd69a1dfb726a00e6b6892 (plain)
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
#define _BSD_SOURCE
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include "syscall.h"

int fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag)
{
	int ret;

	if (flag==AT_EMPTY_PATH && fd>=0 && !*path) {
		ret = __syscall(SYS_fstat, fd, st);
		if (ret==-EBADF && __syscall(SYS_fcntl, fd, F_GETFD)>=0) {
			ret = __syscall(SYS_fstatat, fd, path, st, flag);
			if (ret==-EINVAL) {
				char buf[15+3*sizeof(int)];
				__procfdname(buf, fd);
#ifdef SYS_stat
				ret = __syscall(SYS_stat, buf, st);
#else
				ret = __syscall(SYS_fstatat, AT_FDCWD, buf, st, 0);
#endif
			}
		}
	}
#ifdef SYS_lstat
	else if ((fd == AT_FDCWD || *path=='/') && flag==AT_SYMLINK_NOFOLLOW)
		ret = __syscall(SYS_lstat, path, st);
#endif
#ifdef SYS_stat
	else if ((fd == AT_FDCWD || *path=='/') && !flag)
		ret = __syscall(SYS_stat, path, st);
#endif
	else ret = __syscall(SYS_fstatat, fd, path, st, flag);

	return __syscall_ret(ret);
}

weak_alias(fstatat, fstatat64);