Added a path normalization function, minor doc fixes.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15239 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2021-12-13 13:01:56 +00:00
parent 2063cec94d
commit d28faca5e1
4 changed files with 84 additions and 10 deletions

View File

@ -56,6 +56,7 @@
extern "C" { extern "C" {
#endif #endif
msg_t vfs_path_append(char *dst, const char *src); msg_t vfs_path_append(char *dst, const char *src);
msg_t vfs_path_normalize(char *dst, const char *src);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -67,7 +67,7 @@ static struct {
/*===========================================================================*/ /*===========================================================================*/
/** /**
* @brief VFS initialization. * @brief VFS path buffers initialization.
* *
* @init * @init
*/ */

View File

@ -91,7 +91,8 @@ msg_t vfs_parse_match_end(const char **pathp) {
/** /**
* @brief Fetches the next path element. * @brief Fetches the next path element.
* @note Consumes the next path separator, if any. * @note Does not consume the next separator, if any.
* @note It can return an empty element, it has to be detected outside.
* *
* @param[in, out] pathp pointer to the path under parsing * @param[in, out] pathp pointer to the path under parsing
* @param[out] fname extracted file name * @param[out] fname extracted file name
@ -108,26 +109,21 @@ msg_t vfs_parse_get_fname(const char **pathp, char *fname) {
/* Path elements must be terminated by a separator or an end-of-string.*/ /* Path elements must be terminated by a separator or an end-of-string.*/
if (vfs_parse_is_separator(c) || vfs_parse_is_terminator(c)) { if (vfs_parse_is_separator(c) || vfs_parse_is_terminator(c)) {
/* Consecutive separators are not valid.*/
if (size == 0U) {
return VFS_RET_ENOENT;
}
/* Advancing the path pointer past the file name in the path and /* Advancing the path pointer past the file name in the path and
closing the file name string.*/ closing the file name string.*/
*pathp = p; *pathp = p;
*fname = '\0'; *fname = '\0';
return VFS_RET_SUCCESS; return (msg_t)size;
} }
/* Valid characters for path names.*/ /* Valid characters for path names.*/
if (!vfs_parse_is_filechar(c)) { if (!vfs_parse_is_filechar(c)) {
return VFS_RET_ENOENT; return VFS_RET_EINVAL;
} }
/* Exceeding the path element length.*/ /* Exceeding the path element length.*/
if (size > VFS_CFG_NAMELEN_MAX) { if (size > VFS_CFG_NAMELEN_MAX) {
return VFS_RET_ENOENT; return VFS_RET_ENAMETOOLONG;
} }
*fname++ = c; *fname++ = c;

View File

@ -101,4 +101,81 @@ msg_t vfs_path_append(char *dst, const char *src) {
return VFS_RET_SUCCESS; return VFS_RET_SUCCESS;
} }
/**
* @brief Normalizes an absolute path.
*
* @param[out] dst The destination buffer.
* @param[in] src The source path.
* @return The operation status.
* @retval VFS_RET_ENAMETOOLONG If the path size exceeded @p VFS_CFG_PATHLEN_MAX.
*/
msg_t vfs_path_normalize(char *dst, const char *src) {
size_t size;
VFS_RETURN_ON_ERROR(vfs_parse_match_separator(&src));
*dst++ = '/';
size = 1U;
while (true) {
/* Consecutive input separators are consumed.*/
while (vfs_parse_is_separator(*src)) {
src++;
}
msg_t ret;
size_t n;
/* Getting next element from the input path and copying it to
the output path.*/
ret = vfs_parse_get_fname(&src, dst);
VFS_RETURN_ON_ERROR(ret);
n = (size_t)ret;
if (n == 0U) {
/* If the path contains something after the root separator.*/
if (size > 1U) {
/* No next path element, replacing the last separator with a zero.*/
size--;
*(dst - 1) = '\0';
}
return (msg_t)size;
}
/* Handling special cases of "." and "..".*/
if (strcmp(dst, ".") == 0) {
/* Single dot elements are discarded.*/
/* Consecutive input separators are consumed.*/
continue;
}
else if (strcmp(dst, "..") == 0) {
/* Double dot elements require to remove the last element from
the output path.*/
if (size > 1) {
/* Back on the separator.*/
dst--;
size--;
/* Scanning back to just after the previous separator.*/
do {
dst--;
size--;
} while(!vfs_parse_is_separator(*(dst - 1)));
}
continue;
}
dst += n;
size += n;
/* Adding a single separator to the output.*/
*dst++ = '/';
size++;
do {
} while (false);
}
}
/** @} */ /** @} */