Skip to content

Instantly share code, notes, and snippets.

@odkr
Last active November 11, 2022 16:38
Show Gist options
  • Save odkr/d204fa4fbea4f2eaab43d9372039ee59 to your computer and use it in GitHub Desktop.
Save odkr/d204fa4fbea4f2eaab43d9372039ee59 to your computer and use it in GitHub Desktop.
Remove dots (".") and supernumerary slashes ("/"s) from paths
int
path_normalise(size_t n, const char *const fname, const norm[n])
{
char *lim; /* Limit of normalised filename. */
char *end; /* Current end of normalised filename. */
assert(*fname != '\0');
lim = norm + n - 1U;
end = norm;
/*
* Some implementations of stpncpy fail to terminate strings.
* Also permits to use assignments instead of stpncpy in some cases.
*/
(void) memset(norm, '\0', n);
for (const char *cur = fname; *cur != '\0'; cur += strspn(cur, "/")) {
size_t len; /* Length of current filename segment. */
len = strcspn(cur, "/");
if (len > 0) {
if (len > 1 || *cur != '.') {
/*
* `<=` to account for the path seperator.
* Assumes that NAME_MAX < PATH_MAX.
*/
if ((size_t) (lim - end) <= len)
return -1;
if (end > norm || *fname == '/')
*(end++) = '/';
end = stpncpy(end, cur, len);
}
cur += len;
}
}
if (end == norm)
/*
* If this point is reached, fname either
* - starts with '.' and points to the working directory or
* - starts with '/' and points to the root directory.
*/
*end = *fname;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment