summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McDermott <patrick.mcdermott@libiquity.com>2023-05-10 06:11:03 (EDT)
committer Patrick McDermott <patrick.mcdermott@libiquity.com>2023-05-10 13:10:31 (EDT)
commitb251117ddd460bb2209f565d71121b17b4385881 (patch)
tree9def22dff83b7e182d1505e20b601017a6c54488
parent6b474997b57dafb81577dadd54ea5c3948346d9c (diff)
dirent: Fix separators and length limits
-rw-r--r--src/dirent.c77
1 files changed, 48 insertions, 29 deletions
diff --git a/src/dirent.c b/src/dirent.c
index b918a0d..7f361da 100644
--- a/src/dirent.c
+++ b/src/dirent.c
@@ -30,30 +30,43 @@ _opkg_opk_dirent_name_prefix(struct opkg_opk_dirent *dirent, char **name_buf,
{
size_t len;
char **buf;
+ int sep;
len = strlen(dirent->name);
- if (*name_len + len <= *name_buf_len) {
+ if (*name_len > 0 && *name_len + len + 1 <= *name_buf_len) {
+ /* Space available in name buffer. Not last node, so append
+ * separator. */
buf = name_buf;
- if (*buf == NULL) {
- return OPKG_OPK_ERROR;
- }
- if (**buf != '\0') {
- ++len;
- }
- *name_buf_len -= len;
- } else if (*pref_len + len <= *pref_buf_len) {
+ *name_len += len + 1;
+ sep = 1;
+ } else if (*name_len == 0 && *name_len + len <= *name_buf_len) {
+ /* Space available in name buffer. Last node (first in
+ * recursion), so don't append separator. */
+ buf = name_buf;
+ *name_len += len;
+ sep = 0;
+ } else if (*pref_len > 0 && *pref_len + len + 1 <= *pref_buf_len) {
+ /* Space available in prefix buffer. Not last node, so append
+ * separator. */
+ buf = pref_buf;
+ *pref_len += len + 1;
+ sep = 1;
+ } else if (*pref_len == 0 && *pref_len + len <= *pref_buf_len) {
+ /* Space available in prefix buffer. Last node (first in
+ * recursion), so don't append separator. */
buf = pref_buf;
- if (*buf == NULL) {
- return OPKG_OPK_ERROR;
- }
- if (**buf != '\0') {
- ++len;
- }
- *pref_buf_len -= len;
+ *pref_len += len;
+ sep = 0;
} else {
+ /* Both buffers full. */
+ return OPKG_OPK_ERROR;
+ }
+ if (*buf == NULL) {
+ /* Caller provided a NULL buffer pointer. */
return OPKG_OPK_ERROR;
}
+ /* Recurse. */
if (dirent->parent != NULL &&
_opkg_opk_dirent_name_prefix(dirent->parent,
name_buf, name_buf_len, pref_buf, pref_buf_len,
@@ -61,13 +74,13 @@ _opkg_opk_dirent_name_prefix(struct opkg_opk_dirent *dirent, char **name_buf,
return OPKG_OPK_ERROR;
}
- if (**buf != '\0') {
+ /* Copy node name and possibly separator suffix. */
+ memcpy(*buf, dirent->name, len);
+ *buf += len;
+ if (sep == 1) {
**buf = '/';
*buf += 1;
- --len;
}
- memcpy(*buf, dirent->name, len);
- *buf += len;
return OPKG_OPK_OK;
}
@@ -76,18 +89,24 @@ int
opkg_opk_dirent_name_prefix(struct opkg_opk_dirent *dirent, char *name_buf,
size_t name_buf_len, char *pref_buf, size_t pref_buf_len)
{
- size_t name_len = 0;
- size_t pref_len = 0;
+ size_t name_len = 0;
+ size_t pref_len = 0;
+ char *name = name_buf;
+ char *pref = pref_buf;
+
+ /* NUL bytes */
+ --name_buf_len;
+ --pref_buf_len;
- name_buf[0] = '\0';
- pref_buf[0] = '\0';
if (_opkg_opk_dirent_name_prefix(dirent, &name_buf, &name_buf_len,
&pref_buf, &pref_buf_len, &name_len, &pref_len)
== OPKG_OPK_ERROR) {
return OPKG_OPK_ERROR;
}
- name_buf[name_len] = '\0';
- pref_buf[pref_len] = '\0';
+
+ name[name_len] = '\0';
+ pref[pref_len] = '\0';
+
return OPKG_OPK_OK;
}
@@ -107,10 +126,10 @@ main()
.parent = &bar,
};
char name[8];
- char pref[5];
+ char pref[4];
- if (opkg_opk_dirent_name_prefix(&baz, name, 8, pref, 5) != OPKG_OPK_OK)
- {
+ if (opkg_opk_dirent_name_prefix(&baz, name, sizeof(name),
+ pref, sizeof(pref)) != OPKG_OPK_OK) {
puts("Error building name parts");
return EXIT_FAILURE;
}