mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-09 19:30:29 +00:00
RealPath in ape/loader.c
This commit is contained in:
parent
809f0f5019
commit
4673a6f186
1 changed files with 48 additions and 7 deletions
55
ape/loader.c
55
ape/loader.c
|
@ -87,6 +87,8 @@
|
||||||
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
|
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
|
||||||
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
|
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
|
||||||
|
|
||||||
|
#define PATH_MAX 1024 /* XXX verify */
|
||||||
|
|
||||||
#define SupportsLinux() (SUPPORT_VECTOR & LINUX)
|
#define SupportsLinux() (SUPPORT_VECTOR & LINUX)
|
||||||
#define SupportsXnu() (SUPPORT_VECTOR & XNU)
|
#define SupportsXnu() (SUPPORT_VECTOR & XNU)
|
||||||
#define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD)
|
#define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD)
|
||||||
|
@ -212,13 +214,13 @@ struct PathSearcher {
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *syspath;
|
const char *syspath;
|
||||||
unsigned long namelen;
|
unsigned long namelen;
|
||||||
char path[1024];
|
char path[PATH_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ApeLoader {
|
struct ApeLoader {
|
||||||
union ElfPhdrBuf phdr;
|
union ElfPhdrBuf phdr;
|
||||||
struct PathSearcher ps;
|
struct PathSearcher ps;
|
||||||
char path[1024];
|
char path[PATH_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
EXTERN_C long SystemCall(long, long, long, long, long, long, long, int);
|
EXTERN_C long SystemCall(long, long, long, long, long, long, long, int);
|
||||||
|
@ -239,6 +241,8 @@ static int StrCmp(const char *l, const char *r) {
|
||||||
return (l[i] & 255) - (r[i] & 255);
|
return (l[i] & 255) - (r[i] & 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
static const char *StrRChr(const char *s, int c) {
|
static const char *StrRChr(const char *s, int c) {
|
||||||
const char *b = 0;
|
const char *b = 0;
|
||||||
if (s) {
|
if (s) {
|
||||||
|
@ -256,6 +260,8 @@ static const char *BaseName(const char *s) {
|
||||||
return b ? b + 1 : s;
|
return b ? b + 1 : s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static void Bzero(void *a, unsigned long n) {
|
static void Bzero(void *a, unsigned long n) {
|
||||||
long z;
|
long z;
|
||||||
char *p, *e;
|
char *p, *e;
|
||||||
|
@ -347,7 +353,7 @@ static char *Utox(char p[19], unsigned long x) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *Utoa(char p[21], unsigned long x) {
|
static char *Utoa(char p[20], unsigned long x) {
|
||||||
char t;
|
char t;
|
||||||
unsigned long i, a, b;
|
unsigned long i, a, b;
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -538,6 +544,40 @@ __attribute__((__noreturn__)) static void Pexit(int os, const char *c, int rc,
|
||||||
Exit(127, os);
|
Exit(127, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PSFD "/proc/self/fd/"
|
||||||
|
|
||||||
|
static int RealPath(int os, int fd, char *path, char **resolved) {
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
int rc;
|
||||||
|
if (IsLinux()) {
|
||||||
|
char psfd[sizeof(PSFD) + 19];
|
||||||
|
MemMove(psfd, PSFD, sizeof(PSFD) - 1);
|
||||||
|
Utoa(psfd + sizeof(PSFD) - 1, fd);
|
||||||
|
rc = SystemCall(-100, (long)psfd, (long)buf, PATH_MAX, 0, 0, 0,
|
||||||
|
IsAarch64() ? 78 : 267);
|
||||||
|
if (rc >= 0) {
|
||||||
|
if (rc == PATH_MAX) {
|
||||||
|
rc = -36;
|
||||||
|
} else {
|
||||||
|
buf[rc] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (IsXnu()) {
|
||||||
|
rc = SystemCall(fd, 50, (long)buf, 0, 0, 0, 0, 92 | 0x2000000);
|
||||||
|
} else if (IsOpenbsd()) {
|
||||||
|
rc = SystemCall((long)path, (long)buf, 0, 0, 0, 0, 0, 115);
|
||||||
|
} else {
|
||||||
|
*resolved = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (rc >= 0) {
|
||||||
|
MemMove(path, buf, StrLen(buf) + 1);
|
||||||
|
*resolved = path;
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static char AccessCommand(struct PathSearcher *ps, unsigned long pathlen) {
|
static char AccessCommand(struct PathSearcher *ps, unsigned long pathlen) {
|
||||||
if (pathlen + 1 + ps->namelen + 1 > sizeof(ps->path)) return 0;
|
if (pathlen + 1 + ps->namelen + 1 > sizeof(ps->path)) return 0;
|
||||||
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
|
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
|
||||||
|
@ -1039,6 +1079,8 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
||||||
Pexit(os, prog, 0, "not found (maybe chmod +x or ./ needed)");
|
Pexit(os, prog, 0, "not found (maybe chmod +x or ./ needed)");
|
||||||
} else if ((fd = Open(exe, O_RDONLY, 0, os)) < 0) {
|
} else if ((fd = Open(exe, O_RDONLY, 0, os)) < 0) {
|
||||||
Pexit(os, exe, fd, "open");
|
Pexit(os, exe, fd, "open");
|
||||||
|
} else if ((rc = RealPath(os, fd, exe, &prog)) < 0) {
|
||||||
|
Pexit(os, exe, rc, "realpath");
|
||||||
} else if ((rc = Pread(fd, ebuf->buf, sizeof(ebuf->buf), 0, os)) < 0) {
|
} else if ((rc = Pread(fd, ebuf->buf, sizeof(ebuf->buf), 0, os)) < 0) {
|
||||||
Pexit(os, exe, rc, "read");
|
Pexit(os, exe, rc, "read");
|
||||||
} else if ((unsigned long)rc < sizeof(ebuf->ehdr)) {
|
} else if ((unsigned long)rc < sizeof(ebuf->ehdr)) {
|
||||||
|
@ -1046,10 +1088,9 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
||||||
}
|
}
|
||||||
pe = ebuf->buf + rc;
|
pe = ebuf->buf + rc;
|
||||||
|
|
||||||
/* change argv[0] to resolved path if it's ambiguous */
|
/* change argv[0] to resolved path (TODO remove) */
|
||||||
if (argc > 0 && ((*prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) ||
|
if (argc > 0 && prog) {
|
||||||
!StrCmp(BaseName(prog), argv[0]))) {
|
argv[0] = prog;
|
||||||
argv[0] = exe;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ape intended behavior
|
/* ape intended behavior
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue