/* * params.c -- Device parameter file handling. * * Copyright (C) 2016 Tomasz Kramkowski * * This program 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. * * This program 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 this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include "eprintf.h" #include "params.h" #include "util.h" /* TODO: make this dynamic */ #define SZMAX_PFILE 1024 #ifndef DATADIR #define DATADIR "hktool" #endif /* readparams: read a file's param definition */ static void readparams(struct flashparams *fp, const char *file) { char cont[SZMAX_PFILE], *pos; size_t contsz; FILE *f; assert(file); assert(fp); f = fopen(file, "r"); if (f == NULL) eprintf("Could not open '%s':", file); contsz = fread(cont, 1, SZMAX_PFILE, f); if (contsz >= sizeof cont) eprintf("Parameter file '%s' is longer than %zu", file, sizeof cont - 1); pos = cont; for (int i = 0; i < 4; i++) { char *end; unsigned long long val; errno = 0; val = strtoull(pos, &end, 0); if (pos == end) eprintf("Parameter file '%s' is malformed (offset:%zd not a number)", file, pos - cont); pos = end; if (errno == ERANGE || val > SIZE_MAX) eprintf("Parameter file '%s' is malformed (offset:%zd number too large)", file, pos - cont); switch (i) { case 0: fp->memsz = val; break; case 1: fp->blksz = val; break; case 2: fp->cmdsz = val; break; case 3: fp->addrshft = val; break; } } fclose(f); } static void printcname(const char *file) { bool wasspace; FILE *f; int c, field; assert(file); f = fopen(file, "r"); if (f == NULL) { printf(": Malformed file '%s'", file); return; } field = 0; wasspace = false; while (c = fgetc(f), c != EOF) { if (isspace(c)) { wasspace = true; continue; } if (wasspace) { wasspace = false; field++; } if (field >= 4) { ungetc(c, f); break; } } if (c == EOF) return; printf(": "); while (c = fgetc(f), c != EOF) if (c != '\n') putchar(c); } /* getparams: Locate a parameter file and load it or show names of all files */ bool getparams(struct flashparams *fp, const char *name) { char pathbuf[PATH_MAX], *dirname, *fullpath; struct dirent *de; size_t pathsize; bool found; DIR *dir; assert((fp == NULL && name == NULL) || (fp != NULL && name != NULL)); fullpath = pathbuf; pathsize = sizeof pathbuf; dirname = getenv("HKTOOL_DATADIR"); if (dirname == NULL || strlen(dirname) == 0) dirname = DATADIR; dir = opendir(dirname); if (dir == NULL) eprintf("Could not open directory '%s':", dirname); if (name == NULL) printf("Searching '%s' for Device Parameter Files:\n", dirname); found = false; while (errno = 0, de = readdir(dir), de != NULL) { bool ismatch, doprint; doprint = name == NULL; if (doprint) ismatch = strcmp(de->d_name, name) == 0; else ismatch = false; if (doprint || ismatch) { int size; size = snprintf(NULL, 0, "%s/%s", dirname, de->d_name); assert(size > 0); if ((size_t)size > pathsize) { if (fullpath == pathbuf) fullpath = NULL; fullpath = erealloc(fullpath, size); pathsize = size; } size = snprintf(fullpath, pathsize, "%s/%s", dirname, de->d_name); assert(size > 0); assert((size_t)size < pathsize); } if (doprint) { printf("%s", de->d_name); printcname(fullpath); putchar('\n'); continue; }; if (!ismatch) continue; readparams(fp, fullpath); found = true; errno = 0; break; } if (errno) weprintf("Could not read directory '%s':", dirname); if (fullpath != pathbuf) free(fullpath); if (closedir(dir) == -1) eprintf("Could not close directory '%s':", dirname); return found; }