mirror of https://github.com/rusefi/ChibiOS.git
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15427 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
parent
524e171965
commit
8ed8c6122e
|
@ -68,6 +68,7 @@
|
|||
#define CH_RET_ENOSYS CH_ENCODE_ERROR(ENOSYS) /* Syscall not implemented */
|
||||
#define CH_RET_EOVERFLOW CH_ENCODE_ERROR(EOVERFLOW) /* File offset overflow */
|
||||
#define CH_RET_ENOEXEC CH_ENCODE_ERROR(ENOEXEC) /* Invalid executable */
|
||||
#define CH_RET_EXDEV CH_ENCODE_ERROR(EXDEV) /* Not same volume */
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
|
|
|
@ -61,6 +61,7 @@ extern "C" {
|
|||
size_t path_add_extension(char *dst, const char *ext, size_t size);
|
||||
size_t path_copy_element(const char **pathp, char *dst, size_t size);
|
||||
size_t path_get_element(const char **pathp, char *dst, size_t size);
|
||||
size_t path_match_element(const char *path, const char *match, size_t size);
|
||||
size_t path_normalize(char *dst, const char *src, size_t size);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -211,7 +211,7 @@ size_t path_add_extension(char *dst, const char *ext, size_t size) {
|
|||
* @note It can return an empty element, it has to be detected outside.
|
||||
*
|
||||
* @param[in, out] pathp Pointer to the path under parsing.
|
||||
* @param[out] dst Buffer for the extracted path element
|
||||
* @param[out] dst Buffer for the extracted path element.
|
||||
* @param[in] size Destination buffer size.
|
||||
* @return The size of the fetched path element, it does
|
||||
* not fetch beyond @p size.
|
||||
|
@ -254,7 +254,7 @@ size_t path_copy_element(const char **pathp, char *dst, size_t size) {
|
|||
* @note It can return an empty element, it has to be detected outside.
|
||||
*
|
||||
* @param[in, out] pathp Pointer to the path under parsing.
|
||||
* @param[out] dst Buffer for the extracted path element
|
||||
* @param[out] dst Buffer for the extracted path element.
|
||||
* @param[in] size Destination buffer size.
|
||||
* @return The size of the fetched path element, it does
|
||||
* not fetch beyond @p size.
|
||||
|
@ -272,6 +272,45 @@ size_t path_get_element(const char **pathp, char *dst, size_t size) {
|
|||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Verifies that the next path element is equal to the match string.
|
||||
*
|
||||
* @param[in] path The source path.
|
||||
* @param[in] match String to be matched.
|
||||
* @param[in] size Destination buffer size.
|
||||
* @return The size of the matched path element, it does
|
||||
* not match beyond @p size.
|
||||
* @retval 0 Null element.
|
||||
* @retval size Buffer overflow or no match.
|
||||
*/
|
||||
size_t path_match_element(const char *path, const char *match, size_t size) {
|
||||
size_t n;
|
||||
|
||||
n = (size_t)0;
|
||||
while (true) {
|
||||
char c1 = *path;
|
||||
char c2 = *match;
|
||||
|
||||
/* Path elements must be terminated by a separator or an end-of-string.*/
|
||||
if ((c1 == '/') || (c1 == '\0')) {
|
||||
return c2 == '\0' ? n : size;
|
||||
}
|
||||
|
||||
if (c1 != c2) {
|
||||
return size;
|
||||
}
|
||||
|
||||
path++;
|
||||
match++;
|
||||
n++;
|
||||
|
||||
/* Exceeding the maximum length considering the space for the final zero.*/
|
||||
if (n >= size) {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Normalizes an absolute path.
|
||||
* @note The destination buffer can be the same of the source buffer.
|
||||
|
|
|
@ -100,35 +100,23 @@ static struct {
|
|||
static msg_t match_driver(vfs_overlay_driver_c *odp,
|
||||
const char **pathp,
|
||||
vfs_driver_c **vdpp) {
|
||||
char fname[VFS_CFG_NAMELEN_MAX + 1];
|
||||
size_t n;
|
||||
msg_t ret;
|
||||
unsigned i;
|
||||
|
||||
do {
|
||||
unsigned i;
|
||||
i = 0U;
|
||||
while (i < odp->next_driver) {
|
||||
size_t n;
|
||||
|
||||
n = path_get_element(pathp, fname, VFS_CFG_NAMELEN_MAX + 1);
|
||||
if (n >= VFS_CFG_NAMELEN_MAX + 1) {
|
||||
ret = CH_RET_ENAMETOOLONG;
|
||||
break;
|
||||
n = path_match_element(*pathp, odp->names[i], VFS_CFG_NAMELEN_MAX + 1);
|
||||
if (n < VFS_CFG_NAMELEN_MAX + 1) {
|
||||
*pathp += n;
|
||||
*vdpp = odp->drivers[i];
|
||||
return CH_RET_SUCCESS;
|
||||
}
|
||||
|
||||
/* Searching among registered drivers.*/
|
||||
i = 0U;
|
||||
while (i < odp->next_driver) {
|
||||
if (memcmp(fname, odp->names[i], n) == 0) {
|
||||
*vdpp = odp->drivers[i];
|
||||
return CH_RET_SUCCESS;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
ret = CH_RET_ENOENT;
|
||||
i++;
|
||||
}
|
||||
while (false);
|
||||
|
||||
return ret;
|
||||
return CH_RET_ENOENT;
|
||||
}
|
||||
|
||||
static const char *get_current_directory(vfs_overlay_driver_c *drvp) {
|
||||
|
@ -526,7 +514,10 @@ msg_t drv_rename(void *instance, const char *oldpath, const char *newpath) {
|
|||
}
|
||||
|
||||
do {
|
||||
msg_t oldret, newret;
|
||||
vfs_overlay_driver_c *drvp = (vfs_overlay_driver_c *)instance;
|
||||
vfs_driver_c *olddp, *newdp;
|
||||
const char *op, *np;
|
||||
|
||||
/* Building the absolute paths based on current directory.*/
|
||||
ret = build_absolute_path(drvp, oldbuf, oldpath);
|
||||
|
@ -534,7 +525,57 @@ msg_t drv_rename(void *instance, const char *oldpath, const char *newpath) {
|
|||
ret = build_absolute_path(drvp, newbuf, newpath);
|
||||
CH_BREAK_ON_ERROR(ret);
|
||||
|
||||
/* Skipping root separators.*/
|
||||
op = oldbuf + 1;
|
||||
np = newbuf + 1;
|
||||
|
||||
/* Searching for a match among registered drivers.*/
|
||||
oldret = match_driver(drvp, &op, &olddp);
|
||||
newret = match_driver(drvp, &np, &newdp);
|
||||
|
||||
/* There are various combinations to consider.*/
|
||||
if (!CH_RET_IS_ERROR(oldret) && !CH_RET_IS_ERROR(newret)) {
|
||||
/* If paths both refer to registered drivers then must refer to
|
||||
the same driver, we cannot do a rename across drivers.*/
|
||||
if (olddp == newdp) {
|
||||
/* Delegating node renaming to the registered driver.*/
|
||||
ret = olddp->vmt->rename((void *)olddp, op, np);
|
||||
}
|
||||
else {
|
||||
/* Mixed, not allowing it.*/
|
||||
ret = CH_RET_EXDEV;
|
||||
}
|
||||
}
|
||||
else if (CH_RET_IS_ERROR(oldret) && CH_RET_IS_ERROR(newret)) {
|
||||
/* If both paths refer to the overlaid driver then passing down the
|
||||
request.*/
|
||||
if (drvp->overlaid_drv != NULL) {
|
||||
|
||||
/* Processing the prefix, if defined.*/
|
||||
if (drvp->path_prefix != NULL) {
|
||||
if (path_prepend(oldbuf,
|
||||
drvp->path_prefix,
|
||||
VFS_CFG_PATHLEN_MAX + 1) == (size_t)0) {
|
||||
ret = CH_RET_ENAMETOOLONG;
|
||||
break;
|
||||
}
|
||||
if (path_prepend(newbuf,
|
||||
drvp->path_prefix,
|
||||
VFS_CFG_PATHLEN_MAX + 1) == (size_t)0) {
|
||||
ret = CH_RET_ENAMETOOLONG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Passing the combined path to the overlaid driver.*/
|
||||
ret = drvp->overlaid_drv->vmt->rename((void *)drvp->overlaid_drv,
|
||||
oldbuf, newbuf);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Mixed, not allowing it.*/
|
||||
ret = CH_RET_EXDEV;
|
||||
}
|
||||
} while (false);
|
||||
|
||||
/* Buffers returned, note, in reverse order.*/
|
||||
|
|
Loading…
Reference in New Issue