introduce got_canonpath()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
diff --git a/lib/got_lib_path.h b/lib/got_lib_path.h
index eabdbf9..435ee1d 100644
--- a/lib/got_lib_path.h
+++ b/lib/got_lib_path.h
@@ -33,3 +33,10 @@ char *got_path_get_absolute(const char *);
* The result is allocated with malloc(3).
*/
char *got_path_normalize(const char *);
+
+/*
+ * Canonicalize absolute paths by removing redundant path separators
+ * and resolving references to parent directories ("/../").
+ * Relative paths are copied from input to buf as-is.
+ */
+int got_canonpath(const char *input, char *buf, size_t bufsize)
diff --git a/lib/path.c b/lib/path.c
index 9996729..fa26c7a 100644
--- a/lib/path.c
+++ b/lib/path.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
+ * Copyright (c) 2015 Theo de Raadt <deraadt@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -62,3 +63,45 @@ got_path_normalize(const char *path)
return resolved;
}
+
+/* canonpath() from kern_pledge.c */
+int
+got_canonpath(const char *input, char *buf, size_t bufsize)
+{
+ const char *p;
+ char *q;
+
+ /* can't canon relative paths, don't bother */
+ if (!got_path_is_absolute(input)) {
+ if (strlcpy(buf, input, bufsize) >= bufsize)
+ return ENAMETOOLONG;
+ return 0;
+ }
+
+ p = input;
+ q = buf;
+ while (*p && (q - buf < bufsize)) {
+ if (p[0] == '/' && (p[1] == '/' || p[1] == '\0')) {
+ p += 1;
+
+ } else if (p[0] == '/' && p[1] == '.' &&
+ (p[2] == '/' || p[2] == '\0')) {
+ p += 2;
+
+ } else if (p[0] == '/' && p[1] == '.' && p[2] == '.' &&
+ (p[3] == '/' || p[3] == '\0')) {
+ p += 3;
+ if (q != buf) /* "/../" at start of buf */
+ while (*--q != '/')
+ continue;
+
+ } else {
+ *q++ = *p++;
+ }
+ }
+ if ((*p == '\0') && (q - buf < bufsize)) {
+ *q = 0;
+ return 0;
+ } else
+ return ENAMETOOLONG;
+}