diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dirent.c | 152 | ||||
-rw-r--r-- | src/dirent.h | 35 | ||||
-rw-r--r-- | src/local.mk | 2 |
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 \ |