diff options
Diffstat (limited to 'firmware/common/pathfuncs.c')
-rw-r--r-- | firmware/common/pathfuncs.c | 69 |
1 files changed, 21 insertions, 48 deletions
diff --git a/firmware/common/pathfuncs.c b/firmware/common/pathfuncs.c index b95cbab354..fa296cc2ed 100644 --- a/firmware/common/pathfuncs.c +++ b/firmware/common/pathfuncs.c | |||
@@ -447,22 +447,10 @@ void path_remove_dot_segments (char *dstpath, const char *path) | |||
447 | *dstp = 0; | 447 | *dstp = 0; |
448 | } | 448 | } |
449 | 449 | ||
450 | /* helper function copy n chars of a string to a dst buffer of dst_sz | ||
451 | * returns the length of the string it created or attempted to create | ||
452 | */ | ||
453 | static inline size_t copynchars(char *dst, size_t dst_sz, const char *src, size_t src_max) | ||
454 | { | ||
455 | int cpychrs = -1; | ||
456 | if (src_max < -1u) /* we could be dealing with unterminated strings */ | ||
457 | cpychrs = src_max; | ||
458 | /* testing shows this to be on par with using discreet functions and safer ;) */ | ||
459 | int ret = snprintf(dst, dst_sz, "%.*s", cpychrs, src); | ||
460 | if (ret >= 0) | ||
461 | return ret; | ||
462 | |||
463 | return 0; /* Error */ | ||
464 | } | ||
465 | /* Appends one path to another, adding separators between components if needed. | 450 | /* Appends one path to another, adding separators between components if needed. |
451 | * basepath_max can be used to truncate the basepath if desired | ||
452 | * NOTE: basepath is truncated after copying to the buffer so there must be enough | ||
453 | * free space for the entirety of the basepath even if the resulting string would fit | ||
466 | * | 454 | * |
467 | * Return value and behavior is otherwise as strlcpy so that truncation may be | 455 | * Return value and behavior is otherwise as strlcpy so that truncation may be |
468 | * detected. | 456 | * detected. |
@@ -470,52 +458,45 @@ static inline size_t copynchars(char *dst, size_t dst_sz, const char *src, size_ | |||
470 | * For basepath and component: | 458 | * For basepath and component: |
471 | * PA_SEP_HARD adds a separator even if the base path is empty | 459 | * PA_SEP_HARD adds a separator even if the base path is empty |
472 | * PA_SEP_SOFT adds a separator only if the base path is not empty | 460 | * PA_SEP_SOFT adds a separator only if the base path is not empty |
473 | * | ||
474 | * basepath_max can be used to truncate the basepath if desired | ||
475 | * component_max can be used to truncate the component if desired | ||
476 | * | ||
477 | * (Supply -1u to disable truncation) | ||
478 | */ | 461 | */ |
479 | size_t path_append_ex(char *buf, const char *basepath, size_t basepath_max, | 462 | size_t path_append_ex(char *buf, const char *basepath, size_t basepath_max, |
480 | const char *component, size_t component_max, size_t bufsize) | 463 | const char *component, size_t bufsize) |
481 | { | 464 | { |
482 | size_t len; | 465 | size_t len; |
483 | bool check_base = (basepath_max == 0); | ||
484 | bool separate = false; | 466 | bool separate = false; |
485 | const char *base = basepath && !check_base && basepath[0] ? basepath : buf; | 467 | const char *base = basepath && basepath[0] ? basepath : buf; |
486 | |||
487 | if (!base) | 468 | if (!base) |
488 | return bufsize; /* won't work to get lengths from buf */ | 469 | return bufsize; /* won't work to get lengths from buf */ |
489 | 470 | ||
490 | if (!buf) | 471 | if (!buf) |
491 | { | ||
492 | static char fbuf; /* fake buffer to elide later null checks */ | ||
493 | buf = &fbuf; | ||
494 | bufsize = 0; | 472 | bufsize = 0; |
495 | } | 473 | |
496 | if (!component) | ||
497 | { | ||
498 | check_base = true; | ||
499 | component = ""; | ||
500 | } | ||
501 | if (path_is_absolute(component)) | 474 | if (path_is_absolute(component)) |
502 | { | 475 | { |
503 | /* 'component' is absolute; replace all */ | 476 | /* 'component' is absolute; replace all */ |
504 | basepath = component; | 477 | basepath = component; |
505 | basepath_max = component_max; | ||
506 | component = ""; | 478 | component = ""; |
479 | basepath_max = -1u; | ||
507 | } | 480 | } |
508 | 481 | ||
509 | /* if basepath is not null or empty, buffer contents are replaced, | 482 | /* if basepath is not null or empty, buffer contents are replaced, |
510 | otherwise buf contains the base path */ | 483 | otherwise buf contains the base path */ |
484 | |||
511 | if (base == buf) | 485 | if (base == buf) |
512 | len = strlen(buf); | 486 | len = strlen(buf); |
513 | else | 487 | else |
514 | len = copynchars(buf, bufsize, basepath, basepath_max); | 488 | { |
489 | len = strlcpy(buf, basepath, bufsize); | ||
490 | if (basepath_max < len) | ||
491 | { | ||
492 | len = basepath_max; | ||
493 | buf[basepath_max] = '\0'; | ||
494 | } | ||
495 | } | ||
515 | 496 | ||
516 | if (!basepath || basepath_max == 0 || check_base) | 497 | if (!basepath || !component || basepath_max == 0) |
517 | separate = !len || base[len-1] != PATH_SEPCH; | 498 | separate = !len || base[len-1] != PATH_SEPCH; |
518 | else if (component[0] && component_max > 0) | 499 | else if (component[0]) |
519 | separate = len && base[len-1] != PATH_SEPCH; | 500 | separate = len && base[len-1] != PATH_SEPCH; |
520 | 501 | ||
521 | /* caller might lie about size of buf yet use buf as the base */ | 502 | /* caller might lie about size of buf yet use buf as the base */ |
@@ -528,22 +509,14 @@ size_t path_append_ex(char *buf, const char *basepath, size_t basepath_max, | |||
528 | if (separate && (len++, bufsize > 0) && --bufsize > 0) | 509 | if (separate && (len++, bufsize > 0) && --bufsize > 0) |
529 | *buf++ = PATH_SEPCH; | 510 | *buf++ = PATH_SEPCH; |
530 | 511 | ||
531 | return len + copynchars(buf, bufsize, component, component_max); | 512 | return len + strlcpy(buf, component ?: "", bufsize); |
532 | } | 513 | } |
533 | 514 | ||
534 | /* Appends one path to another, adding separators between components if needed. | 515 | |
535 | * | ||
536 | * Return value and behavior is otherwise as strlcpy so that truncation may be | ||
537 | * detected. | ||
538 | * | ||
539 | * For basepath and component: | ||
540 | * PA_SEP_HARD adds a separator even if the base path is empty | ||
541 | * PA_SEP_SOFT adds a separator only if the base path is not empty | ||
542 | */ | ||
543 | size_t path_append(char *buf, const char *basepath, | 516 | size_t path_append(char *buf, const char *basepath, |
544 | const char *component, size_t bufsize) | 517 | const char *component, size_t bufsize) |
545 | { | 518 | { |
546 | return path_append_ex(buf, basepath, -1u, component, -1u, bufsize); | 519 | return path_append_ex(buf, basepath, -1u, component, bufsize); |
547 | } | 520 | } |
548 | /* Returns the location and length of the next path component, consuming the | 521 | /* Returns the location and length of the next path component, consuming the |
549 | * input in the process. | 522 | * input in the process. |