From 9ca35be2ab917dc88bcf5716ccf6cde20e709191 Mon Sep 17 00:00:00 2001 From: midipix Date: Sat, 26 Dec 2020 00:45:51 +0000 Subject: helper api: added slbt_realpath(). --- src/helper/slbt_realpath.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/helper/slbt_realpath.c (limited to 'src/helper') diff --git a/src/helper/slbt_realpath.c b/src/helper/slbt_realpath.c new file mode 100644 index 0000000..4c7446e --- /dev/null +++ b/src/helper/slbt_realpath.c @@ -0,0 +1,89 @@ + +/*******************************************************************/ +/* slibtool: a skinny libtool implementation, written in C */ +/* Copyright (C) 2016--2020 Z. Gilboa */ +/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ +/*******************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "slibtool_readlink_impl.h" + +#ifdef _MIDIPIX_ABI +#include +#endif + +#ifndef ENOTSUP +#define ENOTSUP EOPNOTSUPP +#endif + +int slbt_realpath( + int fdat, + const char * path, + int options, + char * buf, + size_t buflen) +{ + int ret; + int fd; + int fdproc; + struct stat st; + struct stat stproc; + char procfspath[36]; + + /* common validation */ + if (!buf || (options & O_CREAT)) { + errno = EINVAL; + return -1; + } + + /* framework-based wrapper */ +#ifdef _MIDIPIX_ABI + return __fs_rpath(fdat,path,options,buf,buflen); +#endif + + /* buflen */ + if (buflen < PATH_MAX) { + errno = ENOBUFS; + return -1; + } + + /* AT_FDCWD */ + if (fdat == AT_FDCWD) { + return realpath(path,buf) ? 0 : -1; + } + + /* /proc/self/fd */ + if ((fd = openat(fdat,path,options,0)) < 0) + return -1; + + sprintf(procfspath,"/proc/self/fd/%d",fd); + + if (slbt_readlink(procfspath,buf,buflen)) { + close(fd); + return -1; + } + + if ((fdproc = openat(AT_FDCWD,buf,options|O_NOFOLLOW,0)) < 0) { + close(fd); + errno = ELOOP; + return -1; + } + + ret = fstat(fd,&st) || fstat(fdproc,&stproc); + + close(fd); + close(fdproc); + + if (ret || (st.st_dev != stproc.st_dev) || (st.st_ino != stproc.st_ino)) { + errno = ENOTSUP; + return -1; + } + + return 0; +} -- cgit v1.2.3