From 3ecd9acbc96a4798901e55599ca7fce195085994 Mon Sep 17 00:00:00 2001 From: Patrick McDermott Date: Mon, 31 Jul 2023 15:57:14 -0400 Subject: dirent: Add function to allocate & build long name And add test cases. Based on code from commit 42156fbb5d41e2360336c32365e89b14fe5b01ca, which was removed in commit bceab75f6330f82e55381c49026878e3a339a984. --- diff --git a/opkg-opk/dirent.c b/opkg-opk/dirent.c index 0080d44..9d27cfd 100644 --- a/opkg-opk/dirent.c +++ b/opkg-opk/dirent.c @@ -115,3 +115,59 @@ opkg_opk_dirent_name_prefix(struct opkg_opk_dirent *dirent, int is_dir, return OPKG_OPK_OK; } + +static char * +_opkg_opk_dirent_name_alloc(struct opkg_opk_dirent *dirent, int is_dir, + char **cur, size_t *buf_len) +{ + size_t len; + int sep; + char *buf; + + len = strlen(dirent->name); + if (*buf_len > 1 /* 1 for NUL */ || is_dir) { + /* Not last node, or is a directory, so append separator. */ + sep = 1; /* Used in math below, so must be 1, not just != 0. */ + ++len; + } else { + /* Last node (first in recursion), so don't append separator. */ + sep = 0; + } + *buf_len += len; + + if (dirent->parent == NULL) { + buf = malloc(*buf_len); + if (buf == NULL) { + return NULL; + } + *cur = buf; + } else if ((buf = _opkg_opk_dirent_name_alloc(dirent->parent, is_dir, + cur, buf_len)) == NULL) { + return NULL; + } + + /* Copy node name and possibly separator suffix. */ + memcpy(*cur, dirent->name, len - sep); + *cur += len - sep; + if (sep == 1) { + **cur = '/'; + *cur += 1; + } + + return buf; +} + +char * +opkg_opk_dirent_name_alloc(struct opkg_opk_dirent *dirent, int is_dir) +{ + char *buf; + char *cur = NULL; + size_t buf_len = 1; /* 1 for NUL */ + + if ((buf = _opkg_opk_dirent_name_alloc(dirent, is_dir, &cur, &buf_len)) + == NULL) { + return NULL; + } + *cur = '\0'; + return buf; +} diff --git a/opkg-opk/dirent.h b/opkg-opk/dirent.h index 959ca1b..6eefa54 100644 --- a/opkg-opk/dirent.h +++ b/opkg-opk/dirent.h @@ -30,4 +30,7 @@ opkg_opk_dirent_name_prefix(struct opkg_opk_dirent *dirent, int is_dir, char *name_buf, size_t name_buf_len, char *pref_buf, size_t pref_buf_len); +char * +opkg_opk_dirent_name_alloc(struct opkg_opk_dirent *dirent, int is_dir); + #endif /* OPKG_OPK_DIRENT_H_ */ diff --git a/tests/dirent.c b/tests/dirent.c index de20b86..bb84cf5 100644 --- a/tests/dirent.c +++ b/tests/dirent.c @@ -40,8 +40,9 @@ main() }; char name[9]; char pref[4]; + char *full_name; - puts("1..2"); + puts("1..4"); if (opkg_opk_dirent_name_prefix(&baz, 0, name, sizeof(name), pref, sizeof(pref)) != OPKG_OPK_OK || @@ -59,5 +60,19 @@ main() } printf("ok 2 - \"%s\" + \"%s\"\n", pref, name); + full_name = opkg_opk_dirent_name_alloc(&baz, 0); + if (full_name == NULL || strcmp(full_name, "foo/bar/baz") != 0) { + fputs("not ", stdout); + } + printf("ok 3 - \"%s\"\n", full_name); + free(full_name); + + full_name = opkg_opk_dirent_name_alloc(&baz, 1); + if (full_name == NULL || strcmp(full_name, "foo/bar/baz/") != 0) { + fputs("not ", stdout); + } + printf("ok 4 - \"%s\"\n", full_name); + free(full_name); + return EXIT_SUCCESS; } -- cgit v0.9.1