[c5c522c] | 1 | From: Ben Hutchings <ben@decadent.org.uk> |
---|
| 2 | Date: Sat, 27 Sep 2014 15:04:15 +0100 |
---|
| 3 | Subject: [klibc] Implement realpath() |
---|
| 4 | Bug-Debian: https://bugs.debian.org/763049 |
---|
| 5 | Forwarded: http://www.zytor.com/pipermail/klibc/2016-January/003885.html |
---|
| 6 | |
---|
| 7 | This is needed as the basis for the readlink -f option. |
---|
| 8 | |
---|
| 9 | Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
---|
| 10 | --- |
---|
| 11 | --- a/usr/include/stdlib.h |
---|
| 12 | +++ b/usr/include/stdlib.h |
---|
| 13 | @@ -92,4 +92,6 @@ static __inline__ int grantpt(int __fd) |
---|
| 14 | return 0; /* devpts does this all for us! */ |
---|
| 15 | } |
---|
| 16 | |
---|
| 17 | +__extern char *realpath(const char *, char *); |
---|
| 18 | + |
---|
| 19 | #endif /* _STDLIB_H */ |
---|
| 20 | --- a/usr/klibc/Kbuild |
---|
| 21 | +++ b/usr/klibc/Kbuild |
---|
| 22 | @@ -60,7 +60,7 @@ klib-y += vsnprintf.o snprintf.o vsprint |
---|
| 23 | send.o recv.o \ |
---|
| 24 | access.o chmod.o chown.o dup2.o mknod.o poll.o rename.o stat.o \ |
---|
| 25 | lchown.o link.o rmdir.o unlink.o utimes.o lstat.o mkdir.o \ |
---|
| 26 | - readlink.o select.o symlink.o pipe.o \ |
---|
| 27 | + readlink.o realpath.o select.o symlink.o pipe.o \ |
---|
| 28 | ctype/isalnum.o ctype/isalpha.o ctype/isascii.o \ |
---|
| 29 | ctype/isblank.o ctype/iscntrl.o ctype/isdigit.o \ |
---|
| 30 | ctype/isgraph.o ctype/islower.o ctype/isprint.o \ |
---|
| 31 | --- /dev/null |
---|
| 32 | +++ b/usr/klibc/realpath.c |
---|
| 33 | @@ -0,0 +1,49 @@ |
---|
| 34 | +#include <fcntl.h> |
---|
| 35 | +#include <limits.h> |
---|
| 36 | +#include <stdio.h> |
---|
| 37 | +#include <stdlib.h> |
---|
| 38 | +#include <sys/types.h> |
---|
| 39 | +#include <unistd.h> |
---|
| 40 | + |
---|
| 41 | +/* |
---|
| 42 | + * Note that this requires name to refer to an existing file. This is |
---|
| 43 | + * correct according to POSIX. However, BSD and GNU implementations |
---|
| 44 | + * also allow name to refer to a non-existing file in an existing |
---|
| 45 | + * directory. |
---|
| 46 | + */ |
---|
| 47 | + |
---|
| 48 | +char *realpath(const char *name, char *resolved_name) |
---|
| 49 | +{ |
---|
| 50 | + static const char proc_fd_prefix[] = "/proc/self/fd/"; |
---|
| 51 | + char proc_fd_name[sizeof(proc_fd_prefix) + sizeof(int) * 3]; |
---|
| 52 | + int allocated = 0; |
---|
| 53 | + int fd; |
---|
| 54 | + ssize_t len; |
---|
| 55 | + |
---|
| 56 | + /* Open for path lookup only */ |
---|
| 57 | + fd = open(name, O_PATH); |
---|
| 58 | + if (fd < 0) |
---|
| 59 | + return NULL; |
---|
| 60 | + |
---|
| 61 | + if (!resolved_name) { |
---|
| 62 | + resolved_name = malloc(PATH_MAX); |
---|
| 63 | + if (!resolved_name) |
---|
| 64 | + goto out_close; |
---|
| 65 | + allocated = 1; |
---|
| 66 | + } |
---|
| 67 | + |
---|
| 68 | + /* Use procfs to read back the resolved name */ |
---|
| 69 | + sprintf(proc_fd_name, "%s%d", proc_fd_prefix, fd); |
---|
| 70 | + len = readlink(proc_fd_name, resolved_name, PATH_MAX - 1); |
---|
| 71 | + if (len < 0) { |
---|
| 72 | + if (allocated) |
---|
| 73 | + free(resolved_name); |
---|
| 74 | + resolved_name = NULL; |
---|
| 75 | + } else { |
---|
| 76 | + resolved_name[len] = 0; |
---|
| 77 | + } |
---|
| 78 | + |
---|
| 79 | +out_close: |
---|
| 80 | + close(fd); |
---|
| 81 | + return resolved_name; |
---|
| 82 | +} |
---|