diff options
-rw-r--r-- | configure.ac | 8 | ||||
-rw-r--r-- | specials.txt | 3 | ||||
-rw-r--r-- | src/local.mk | 2 | ||||
-rw-r--r-- | src/specials.c | 131 | ||||
-rw-r--r-- | src/specials.h | 38 |
5 files changed, 178 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac index 32061bb..516276b 100644 --- a/configure.ac +++ b/configure.ac @@ -43,10 +43,10 @@ test -d "${srcdir}/.git" || CFLAGS="${save_CFLAGS}" funcs_missing=false AC_CHECK_FUNCS( [\ - fclose feof ferror fopen fprintf fputs fread free fseek fwrite \ - getgrgid getpwuid localtime lstat malloc memcmp memcpy memset \ - mkdir printf puts readlink scandir snprintf sprintf stat \ - strchr strcmp strcpy strftime strlen strncpy strtol unlink + fclose feof ferror fopen fprintf fputs fread free fscanf fseek \ + fwrite getgrgid getpwuid localtime lstat malloc memcmp memcpy \ + memset mkdir printf puts readlink scandir snprintf sprintf \ + stat strchr strcmp strcpy strftime strlen strncpy strtol unlink ], [], [funcs_missing=true]) diff --git a/specials.txt b/specials.txt new file mode 100644 index 0000000..c97eef3 --- /dev/null +++ b/specials.txt @@ -0,0 +1,3 @@ +version=1 +type major minor name +c 1 3 /dev/null diff --git a/src/local.mk b/src/local.mk index e6d77cc..5e8e4bf 100644 --- a/src/local.mk +++ b/src/local.mk @@ -8,6 +8,8 @@ opkg_opk_SOURCES += \ %reldir%/main.c \ %reldir%/opk.c \ %reldir%/opk.h \ + %reldir%/specials.c \ + %reldir%/specials.h \ %reldir%/ustar.c \ %reldir%/ustar.h diff --git a/src/specials.c b/src/specials.c new file mode 100644 index 0000000..8a9fac3 --- /dev/null +++ b/src/specials.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2023 Patrick McDermott + * + * This file is part of opkg-opkg. + * + * opkg-opkg 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-opkg 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-opkg. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <inttypes.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "defs.h" +#include "specials.h" + +struct opkg_opk_specials { + char type; + uint32_t devmajor; + uint32_t devminor; + char *name; + struct opkg_opk_specials *next; +}; + +static int +_opkg_opk_specials_read_v1(FILE *fp, struct opkg_opk_specials **specials) +{ + struct opkg_opk_specials *special; + + *specials = NULL; + fscanf(fp, "%*[^\n]\n"); /* Header line */ + while (feof(fp) == 0) { + special = malloc(sizeof(*special)); + if (special == NULL) { + opkg_opk_specials_free(*specials); + return OPKG_OPK_ERROR; + } +/* POSIX specifies the assignment-allocation character 'm', but ISO + * C doesn't, so GCC prints a warning. */ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wformat" + if (fscanf(fp, " %c %" SCNu32 " %" SCNu32 " %ms \n", + &special->type, + &special->devmajor, &special->devminor, + &special->name) != 4) { +# pragma GCC diagnostic pop + opkg_opk_specials_free(*specials); + return OPKG_OPK_ERROR; + } + if (special->type != 'c' && special->type != 'b') { + opkg_opk_specials_free(*specials); + return OPKG_OPK_ERROR; + } + special->next = *specials; + *specials = special; + } + + return OPKG_OPK_OK; +} + +int +opkg_opk_specials_read(const char *file_name, + struct opkg_opk_specials **specials) +{ + FILE *fp; + unsigned int version; + + fp = fopen(file_name, "r"); + if (fp == NULL) { + return OPKG_OPK_ERROR; + } + if (fscanf(fp, " version = %u \n", &version) != 1) { + fclose(fp); + return OPKG_OPK_ERROR; + } + switch (version) { + case 1U: + if (_opkg_opk_specials_read_v1(fp, specials) != + OPKG_OPK_OK) { + fclose(fp); + return OPKG_OPK_ERROR; + } + break; + default: + fclose(fp); + return OPKG_OPK_ERROR; + } + + fclose(fp); /* Just reading, so OK to ignore errors */ + return OPKG_OPK_OK; +} + +int +opkg_opk_specials_find(struct opkg_opk_specials *specials, const char *find, + char *type, uint32_t *devmajor, uint32_t *devminor) +{ + for (; specials != NULL; specials = specials->next) { + if (strcmp(find, specials->name) == 0) { + *type = specials->type; + *devmajor = specials->devmajor; + *devminor = specials->devminor; + return OPKG_OPK_OK; + } + } + + return OPKG_OPK_END; +} + +void +opkg_opk_specials_free(struct opkg_opk_specials *specials) +{ + struct opkg_opk_specials *special; + + while (specials != NULL) { + special = specials; + specials = specials->next; + free(special->name); + free(special); + } +} diff --git a/src/specials.h b/src/specials.h new file mode 100644 index 0000000..2662f27 --- /dev/null +++ b/src/specials.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2023 Patrick McDermott + * + * This file is part of opkg-opkg. + * + * opkg-opkg 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-opkg 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-opkg. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef OPKG_OPK_SPECIALS_H_ +#define OPKG_OPK_SPECIALS_H_ + +#include <stdint.h> + +struct opkg_opk_specials; + +int +opkg_opk_specials_read(const char *file_name, + struct opkg_opk_specials **specials); + +int +opkg_opk_specials_find(struct opkg_opk_specials *specials, const char *find, + char *type, uint32_t *devmajor, uint32_t *devminor); + +void +opkg_opk_specials_free(struct opkg_opk_specials *specials); + +#endif /* OPKG_OPK_SPECIALS_H_ */ |