summaryrefslogtreecommitdiff
path: root/firmware/common/pathfuncs.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/common/pathfuncs.c')
-rw-r--r--firmware/common/pathfuncs.c69
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 */
453static 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 */
479size_t path_append_ex(char *buf, const char *basepath, size_t basepath_max, 462size_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 */
543size_t path_append(char *buf, const char *basepath, 516size_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.