Index: fusl/src/misc/realpath.c |
diff --git a/fusl/src/misc/realpath.c b/fusl/src/misc/realpath.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..88c849cda33de1e285a5b1eec7dfe9c222d013e5 |
--- /dev/null |
+++ b/fusl/src/misc/realpath.c |
@@ -0,0 +1,45 @@ |
+#include <stdlib.h> |
+#include <limits.h> |
+#include <sys/stat.h> |
+#include <fcntl.h> |
+#include <errno.h> |
+#include <unistd.h> |
+#include <string.h> |
+#include "syscall.h" |
+ |
+void __procfdname(char *, unsigned); |
+ |
+char *realpath(const char *restrict filename, char *restrict resolved) |
+{ |
+ int fd; |
+ ssize_t r; |
+ struct stat st1, st2; |
+ char buf[15+3*sizeof(int)]; |
+ char tmp[PATH_MAX]; |
+ |
+ if (!filename) { |
+ errno = EINVAL; |
+ return 0; |
+ } |
+ |
+ fd = sys_open(filename, O_PATH|O_NONBLOCK|O_CLOEXEC); |
+ if (fd < 0) return 0; |
+ __procfdname(buf, fd); |
+ |
+ r = readlink(buf, tmp, sizeof tmp - 1); |
+ if (r < 0) goto err; |
+ tmp[r] = 0; |
+ |
+ fstat(fd, &st1); |
+ r = stat(tmp, &st2); |
+ if (r<0 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) { |
+ if (!r) errno = ELOOP; |
+ goto err; |
+ } |
+ |
+ __syscall(SYS_close, fd); |
+ return resolved ? strcpy(resolved, tmp) : strdup(tmp); |
+err: |
+ __syscall(SYS_close, fd); |
+ return 0; |
+} |