commit e6eac3b8ebc595e916b1133437b204ca21ebee29 from: Stefan Sperling date: Sun Jun 17 09:47:23 2018 UTC introduce got_canonpath() commit - ec7988073791f4ddb1c17661eb379ff607fa636b commit + e6eac3b8ebc595e916b1133437b204ca21ebee29 blob - eabdbf935d8610815257c95226a9987a6e95b775 blob + 435ee1d97e2cbf7f07b5608aec1e115279fc7850 --- lib/got_lib_path.h +++ 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) blob - 99967297bba6bcde7d6126012e0a62fb85809082 blob + fa26c7a7e5b5421a2282d81af15d789f189d004b --- lib/path.c +++ lib/path.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Stefan Sperling + * Copyright (c) 2015 Theo de Raadt * * 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; +}