Implement realpath()
authorBen Hutchings <ben@decadent.org.uk>
Sat, 27 Sep 2014 14:04:15 +0000 (15:04 +0100)
committerBen Hutchings <ben@decadent.org.uk>
Sun, 5 Oct 2014 00:13:31 +0000 (00:13 +0000)
This is needed as the basis for the readlink -f option.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Gbp-Pq: Name implement-realpath.patch

usr/include/stdlib.h
usr/klibc/Kbuild
usr/klibc/realpath.c [new file with mode: 0644]

index 406f44600f28dd10d61329a950f1c904ac17626c..856c64721976e0e93c5f03084667390f4ecb85ae 100644 (file)
@@ -92,4 +92,6 @@ static __inline__ int grantpt(int __fd)
        return 0;               /* devpts does this all for us! */
 }
 
+__extern char *realpath(const char *, char *);
+
 #endif                         /* _STDLIB_H */
index 40d43c7889e55c8fdd3251be30f3f667de494c41..1e678ad856c4b18e100ce83c9935ca642d9a284a 100644 (file)
@@ -60,7 +60,7 @@ klib-y += vsnprintf.o snprintf.o vsprintf.o sprintf.o \
          send.o recv.o \
          access.o chmod.o chown.o dup2.o mknod.o poll.o rename.o stat.o \
          lchown.o link.o rmdir.o unlink.o utimes.o lstat.o mkdir.o \
-         readlink.o select.o symlink.o pipe.o \
+         readlink.o realpath.o select.o symlink.o pipe.o \
          ctype/isalnum.o ctype/isalpha.o ctype/isascii.o \
          ctype/isblank.o ctype/iscntrl.o ctype/isdigit.o \
          ctype/isgraph.o ctype/islower.o ctype/isprint.o \
diff --git a/usr/klibc/realpath.c b/usr/klibc/realpath.c
new file mode 100644 (file)
index 0000000..1474b1e
--- /dev/null
@@ -0,0 +1,49 @@
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/*
+ * Note that this requires name to refer to an existing file.  This is
+ * correct according to POSIX.  However, BSD and GNU implementations
+ * also allow name to refer to a non-existing file in an existing
+ * directory.
+ */
+
+char *realpath(const char *name, char *resolved_name)
+{
+       static const char proc_fd_prefix[] = "/proc/self/fd/";
+       char proc_fd_name[sizeof(proc_fd_prefix) + sizeof(int) * 3];
+       int allocated = 0;
+       int fd;
+       ssize_t len;
+
+       /* Open for path lookup only */
+       fd = open(name, O_PATH);
+       if (fd < 0)
+               return NULL;
+
+       if (!resolved_name) {
+               resolved_name = malloc(PATH_MAX);
+               if (!resolved_name)
+                       goto out_close;
+               allocated = 1;
+       }
+
+       /* Use procfs to read back the resolved name */
+       sprintf(proc_fd_name, "%s%d", proc_fd_prefix, fd);
+       len = readlink(proc_fd_name, resolved_name, PATH_MAX - 1);
+       if (len < 0) {
+               if (allocated)
+                       free(resolved_name);
+               resolved_name = NULL;
+       } else {
+               resolved_name[len] = 0;
+       }
+
+out_close:
+       close(fd);
+       return resolved_name;
+}