|
|
d4b2a5 |
/*******************************************************************/
|
|
|
d4b2a5 |
/* slibtool: a skinny libtool implementation, written in C */
|
|
|
d4b2a5 |
/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
|
|
|
d4b2a5 |
/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
|
|
|
d4b2a5 |
/*******************************************************************/
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
#include <fcntl.h>
|
|
|
d4b2a5 |
#include <stdlib.h>
|
|
|
d4b2a5 |
#include <limits.h>
|
|
|
d4b2a5 |
#include <errno.h>
|
|
|
d4b2a5 |
#include <sys/stat.h>
|
|
|
d4b2a5 |
#include <slibtool/slibtool.h>
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
#include "slibtool_driver_impl.h"
|
|
|
d4b2a5 |
#include "slibtool_readlink_impl.h"
|
|
|
d4b2a5 |
#include "slibtool_realpath_impl.h"
|
|
|
d4b2a5 |
#include "slibtool_visibility_impl.h"
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
#ifdef HAVE_SYS_SYSCALL_H
|
|
|
d4b2a5 |
#include <sys/syscall.h>
|
|
|
d4b2a5 |
#endif
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
#ifdef _MIDIPIX_ABI
|
|
|
d4b2a5 |
#include <sys/fs.h>
|
|
|
d4b2a5 |
#endif
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
#ifndef ENOTSUP
|
|
|
d4b2a5 |
#define ENOTSUP EOPNOTSUPP
|
|
|
d4b2a5 |
#endif
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
#ifdef SYS___realpathat
|
|
|
d4b2a5 |
extern long syscall(int, ...);
|
|
|
d4b2a5 |
#endif
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
slbt_hidden int slbt_realpath(
|
|
|
d4b2a5 |
int fdat,
|
|
|
d4b2a5 |
const char * path,
|
|
|
d4b2a5 |
int options,
|
|
|
d4b2a5 |
char * buf,
|
|
|
d4b2a5 |
size_t buflen)
|
|
|
d4b2a5 |
{
|
|
|
d4b2a5 |
int ret;
|
|
|
d4b2a5 |
int fd;
|
|
|
d4b2a5 |
int fdproc;
|
|
|
d4b2a5 |
struct stat st;
|
|
|
d4b2a5 |
struct stat stproc;
|
|
|
d4b2a5 |
char procfspath[36];
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
/* common validation */
|
|
|
d4b2a5 |
if (!buf || (options & O_CREAT)) {
|
|
|
d4b2a5 |
errno = EINVAL;
|
|
|
d4b2a5 |
return -1;
|
|
|
d4b2a5 |
}
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
/* framework-based wrapper */
|
|
|
d4b2a5 |
#ifdef _MIDIPIX_ABI
|
|
|
d4b2a5 |
return __fs_rpath(fdat,path,options,buf,buflen);
|
|
|
d4b2a5 |
#endif
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
#ifdef SYS___realpathat
|
|
|
d4b2a5 |
return syscall(SYS___realpathat,fdat,path,buf,buflen,0);
|
|
|
d4b2a5 |
#endif
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
/* buflen */
|
|
|
d4b2a5 |
if (buflen < PATH_MAX) {
|
|
|
d4b2a5 |
errno = ENOBUFS;
|
|
|
d4b2a5 |
return -1;
|
|
|
d4b2a5 |
}
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
/* AT_FDCWD */
|
|
|
d4b2a5 |
if (fdat == AT_FDCWD) {
|
|
|
d4b2a5 |
return realpath(path,buf) ? 0 : -1;
|
|
|
d4b2a5 |
}
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
/* /proc/self/fd */
|
|
|
d4b2a5 |
if ((fd = openat(fdat,path,options,0)) < 0)
|
|
|
d4b2a5 |
return -1;
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
sprintf(procfspath,"/proc/self/fd/%d",fd);
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
if (slbt_readlinkat(fdat,procfspath,buf,buflen)) {
|
|
|
d4b2a5 |
close(fd);
|
|
|
d4b2a5 |
return -1;
|
|
|
d4b2a5 |
}
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
if ((fdproc = openat(AT_FDCWD,buf,options|O_NOFOLLOW,0)) < 0) {
|
|
|
d4b2a5 |
close(fd);
|
|
|
d4b2a5 |
errno = ELOOP;
|
|
|
d4b2a5 |
return -1;
|
|
|
d4b2a5 |
}
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
ret = fstat(fd,&st) || fstat(fdproc,&stproc);
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
close(fd);
|
|
|
d4b2a5 |
close(fdproc);
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
if (ret || (st.st_dev != stproc.st_dev) || (st.st_ino != stproc.st_ino)) {
|
|
|
d4b2a5 |
errno = ENOTSUP;
|
|
|
d4b2a5 |
return -1;
|
|
|
d4b2a5 |
}
|
|
|
d4b2a5 |
|
|
|
d4b2a5 |
return 0;
|
|
|
d4b2a5 |
}
|