/* * 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 . */ #include #include #include #include #include #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); } }