summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McDermott <patrick.mcdermott@libiquity.com>2023-04-29 22:25:50 (EDT)
committer Patrick McDermott <patrick.mcdermott@libiquity.com>2023-04-29 22:53:53 (EDT)
commit42156fbb5d41e2360336c32365e89b14fe5b01ca (patch)
treed14d179d39a1d9e95dda1ed244ca38625e306c45
parent781056d1ce7b5b1fe92f488f4294c9056695071e (diff)
dirent: Implement
-rw-r--r--src/dirent.c152
-rw-r--r--src/dirent.h35
-rw-r--r--src/local.mk2
3 files changed, 189 insertions, 0 deletions
diff --git a/src/dirent.c b/src/dirent.c
new file mode 100644
index 0000000..52e8f84
--- /dev/null
+++ b/src/dirent.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2023 Patrick McDermott
+ *
+ * This file is part of opkg-opk.
+ *
+ * opkg-opk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * opkg-opk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with opkg-opk. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "defs.h"
+#include "dirent.h"
+
+static 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, size_t *pref_len)
+{
+ size_t len;
+ char **buf;
+
+ len = strlen(dirent->name) + 1;
+ if (*name_len + len <= *name_buf_len) {
+ *name_buf_len -= len;
+ buf = name_buf;
+ } else if (*pref_len + len <= *pref_buf_len) {
+ *pref_buf_len -= len;
+ buf = pref_buf;
+ } else {
+ return OPKG_OPK_ERROR;
+ }
+
+ if (dirent->parent != NULL &&
+ _opkg_opk_dirent_name_prefix(dirent->parent,
+ name_buf, name_buf_len, pref_buf, pref_buf_len,
+ name_len, pref_len) == OPKG_OPK_ERROR) {
+ return OPKG_OPK_ERROR;
+ }
+
+ **buf = '/';
+ *buf += 1;
+ memcpy(*buf, dirent->name, len - 1);
+ *buf += len - 1;
+
+ return OPKG_OPK_OK;
+}
+
+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;
+
+ 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';
+ return OPKG_OPK_OK;
+}
+
+static char *
+_opkg_opk_dirent_full_name(struct opkg_opk_dirent *dirent, char **cur,
+ size_t *buf_len)
+{
+ size_t len;
+ char *buf;
+
+ len = strlen(dirent->name) + 1;
+ *buf_len += len;
+
+ if (dirent->parent == NULL) {
+ buf = malloc(*buf_len);
+ if (buf == NULL) {
+ return NULL;
+ }
+ *cur = buf;
+ } else if ((buf = _opkg_opk_dirent_full_name(dirent->parent, cur,
+ buf_len)) == NULL) {
+ return NULL;
+ }
+
+ **cur = '/';
+ *cur += 1;
+ memcpy(*cur, dirent->name, len - 1);
+ *cur += len - 1;
+
+ return buf;
+}
+
+char *
+opkg_opk_dirent_full_name(struct opkg_opk_dirent *dirent)
+{
+ char *name;
+ char *cur = NULL;
+ size_t buf_len = 1; /* 1 for NUL */
+
+ if ((name = _opkg_opk_dirent_full_name(dirent, &cur, &buf_len)) == NULL)
+ {
+ return NULL;
+ }
+ *cur = '\0';
+ return name;
+}
+
+int
+main()
+{
+ struct opkg_opk_dirent foo = {
+ .name = "foo",
+ .parent = NULL,
+ };
+ struct opkg_opk_dirent bar = {
+ .name = "bar",
+ .parent = &foo,
+ };
+ char *full_name;
+ char name[5];
+ char pref[5];
+
+ full_name = opkg_opk_dirent_full_name(&bar);
+ if (full_name == NULL) {
+ puts("Error building full name");
+ return EXIT_FAILURE;
+ }
+ puts(full_name);
+ free(full_name);
+
+ if (opkg_opk_dirent_name_prefix(&bar, name, 5, pref, 5) != OPKG_OPK_OK)
+ {
+ puts("Error building name parts");
+ return EXIT_FAILURE;
+ }
+ puts(name);
+ puts(pref);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/dirent.h b/src/dirent.h
new file mode 100644
index 0000000..44d33ea
--- /dev/null
+++ b/src/dirent.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 Patrick McDermott
+ *
+ * This file is part of opkg-opk.
+ *
+ * opkg-opk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * opkg-opk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with opkg-opk. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef OPKG_OPK_DIRENT_H_
+#define OPKG_OPK_DIRENT_H_
+
+struct opkg_opk_dirent {
+ const char *name;
+ struct opkg_opk_dirent *parent;
+};
+
+int
+opkg_opk_dirent_name_prefix(struct opkg_opk_dirent *dirent, char *name_buf,
+ size_t name_len, char *pref_buf, size_t pref_len);
+
+char *
+opkg_opk_dirent_full_name(struct opkg_opk_dirent *dirent);
+
+#endif /* OPKG_OPK_DIRENT_H_ */
diff --git a/src/local.mk b/src/local.mk
index 429aba3..e6d77cc 100644
--- a/src/local.mk
+++ b/src/local.mk
@@ -1,5 +1,7 @@
opkg_opk_SOURCES += \
%reldir%/defs.h \
+ %reldir%/dirent.c \
+ %reldir%/dirent.h \
%reldir%/gzip.c \
%reldir%/gzip.h \
%reldir%/i18n.h \