summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--opkg-opk/dirent.c56
-rw-r--r--opkg-opk/dirent.h3
-rw-r--r--tests/dirent.c17
3 files changed, 75 insertions, 1 deletions
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;
}