From 8d6359867cb6bbed1edbd1de475caaa72c8427ab Mon Sep 17 00:00:00 2001 From: Tomasz Kramkowski Date: Mon, 22 May 2017 17:01:47 +0100 Subject: wip --- params.c | 399 +++++++++++++++++++++------------------------------------------ 1 file changed, 131 insertions(+), 268 deletions(-) (limited to 'params.c') diff --git a/params.c b/params.c index 3fe324c..08272d6 100644 --- a/params.c +++ b/params.c @@ -18,18 +18,18 @@ */ #include -#include #include #include +#include +#include +#include #include #include #include #include -#include -#include +#include +#include -#include "halfkay.h" -/*#include "log.h"*/ #include "eprintf.h" #include "params.h" #include "util.h" @@ -37,305 +37,168 @@ /* TODO: make this dynamic */ #define SZMAX_PFILE 1024 -struct params { - char *chip; - char *board; - struct flashparams fp; -}; - -static int paramc = 0; -static struct params *paramv = NULL; - -/* addparams: add a param definition to the param list */ -static void addparams(struct params *p) -{ - static int avail = 1; - - for (int i = 0; i < paramc; i++) { - if (xstrcasecmp(paramv[i].chip, p->chip) != 0) - continue; - return; - } - - if (paramc >= avail - 1) { - avail *= 2; - if ((unsigned)avail >= INT_MAX / 2 / sizeof *paramv) - eprintf("Too many parameter files (%d)", paramc); - paramv = erealloc(paramv, avail * sizeof *paramv); - } - - paramv[paramc].chip = estrdup(p->chip); - paramv[paramc].board = p->board != NULL ? estrdup(p->board) : NULL; - paramv[paramc].fp = p->fp; - paramc++; -} - -static void freeparams(struct params *p) -{ - free(p->chip); - free(p->board); - free(p); -} - -/* atosz: convert string to size_t */ -static int atosz(size_t *size, char *str) -{ - unsigned long long val; - char *endptr; - - assert(size); - assert(str); - - /* for some silly reason strtoull actually allows negatives */ - if (str[0] == '-') - return -1; - - errno = 0; - val = strtoull(str, &endptr, 0); - if (errno || *endptr) - return -1; - - if (val > SIZE_MAX) - return -1; - - *size = val; +#ifndef DATADIR +#define DATADIR "hktool" +#endif - return 0; -} - -/* TODO: remove the need for freeparams by not allocating this */ /* readparams: read a file's param definition */ -static struct params *readparams(const char *file) +static void readparams(struct flashparams *fp, const char *file) { - const char *chip, *board; - struct flashparams fp; - struct params *par; + char cont[SZMAX_PFILE], *pos; size_t contsz; - char cont[SZMAX_PFILE], *tok; FILE *f; assert(file); - - chip = file; - for (size_t i = 0; i < strlen(file); i++) - if (file[i] == '/') - chip = &file[i + 1]; - - assert(chip[0]); + assert(fp); f = fopen(file, "r"); - if (f == NULL) { - weprintf("Could not open '%s':", file); - NULL; - } + if (f == NULL) + eprintf("Could not open '%s':", file); contsz = fread(cont, 1, SZMAX_PFILE, f); - if (contsz >= sizeof cont) { - weprintf("Parameter file '%s' is longer than %zu", file, - sizeof cont - 1); - contsz = sizeof cont - 1; - } - for (size_t i = 0; i < contsz; i++) { - if (cont[i] == '\0') { - weprintf("Parameter file '%s' contains null byte", file); - cont[i] = ' '; - } else if (isspace(cont[i]) || !isprint(cont[i])) { - cont[i] = ' '; + 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; } } - cont[contsz] = '\0'; - - tok = strtok(cont, " "); - if (tok == NULL) - goto fail; - if (atosz(&fp.memsz, tok) != 0) - goto fail; - - tok = strtok(NULL, " "); - if (tok == NULL) - goto fail; - if (atosz(&fp.blksz, tok) != 0) - goto fail; - - tok = strtok(NULL, " "); - if (tok == NULL) - goto fail; - if (atosz(&fp.cmdsz, tok) != 0) - goto fail; - - tok = strtok(NULL, " "); - if (tok == NULL) - goto fail; - if (atosz(&fp.addrshft, tok) != 0) - goto fail; - - board = strtok(NULL, ""); - - par = emalloc(sizeof *par); - par->chip = estrdup(chip); - par->board = board != NULL ? estrdup(board) : NULL; - par->fp = fp; - -fail: - if (par == NULL) - weprintf("Parameter file '%s' is malformed", file); - fclose(f); - return par; + fclose(f); } -/* getdirs: returns a NULL terminated list of data paths */ -static char **getdirs(void) +static void printcname(const char *file) { - static const char *globsuffix = "/hktool/*"; - char **dirs, *xddirs, *tok; - int len = 0, avail = 1; - - xddirs = getenv("XDG_DATA_DIRS"); - if (!xddirs || !*xddirs) - xddirs = "/usr/local/share:/usr/share"; - xddirs = estrdup(xddirs); + bool wasspace; + FILE *f; + int c, field; - dirs = emalloc(sizeof *dirs); + assert(file); - for (char *s = xddirs; tok = strtok(s, ":"), tok != NULL; s = NULL) { - size_t slen; + f = fopen(file, "r"); + if (f == NULL) { + printf(": Malformed file '%s'", file); + return; + } - if (tok[0] == '\\') + field = 0; + wasspace = false; + while (c = fgetc(f), c != EOF) { + if (isspace(c)) { + wasspace = true; continue; - - if (len >= avail - 1) { - avail *= 2; - if ((unsigned)avail >= INT_MAX / 2 / sizeof *dirs) - eprintf("Too many data dirs (%d)", len); - dirs = erealloc(dirs, avail * sizeof *dirs); } - - if (SIZE_MAX - (strlen(tok) + 1) < strlen(globsuffix)) - eprintf("Data dir too long (\"%.20s\")", tok); - slen = strlen(tok) + strlen(globsuffix) + 1; - dirs[len] = emalloc(slen); - snprintf(dirs[len], slen, "%s%s", tok, globsuffix); - len++; + if (wasspace) { + wasspace = false; + field++; + } + if (field >= 4) { + ungetc(c, f); + break; + } } - free(xddirs); - - dirs[len++] = NULL; - dirs = erealloc(dirs, len * sizeof *dirs); - - return dirs; -} - -/* freedirs: frees list returned by getdirs */ -static void freedirs(char **dirs) -{ - assert(dirs); + if (c == EOF) + return; - for (size_t i = 0; dirs[i]; i++) - free(dirs[i]); - free(dirs); + printf(": "); + while (c = fgetc(f), c != EOF) + if (c != '\n') + putchar(c); } -/* loadparams: locate and load all param files */ -static void loadparams(void) +/* getparams: Locate a parameter file and load it or show names of all files */ +bool getparams(struct flashparams *fp, const char *name) { - char **dirs; - glob_t globbuf; - - if (paramv != NULL) - return; - - dirs = getdirs(); - - for (int i = 0; dirs[i]; i++) { - int ret; - - ret = glob(dirs[i], i != 0 ? GLOB_APPEND : 0, NULL, &globbuf); - if (ret == GLOB_NOSPACE) - eprintf("glob ran out of memory"); - if (ret == GLOB_NOMATCH) - continue; - if (ret == GLOB_ABORTED) { - weprintf("A call to glob resulted in a read error"); - continue; + 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); } - } - freedirs(dirs); - - for (size_t i = 0; i < globbuf.gl_pathc; i++) { - struct params *par; - par = readparams(globbuf.gl_pathv[i]); - if (par == NULL) + if (doprint) { + printf("%s", de->d_name); + printcname(fullpath); + putchar('\n'); continue; - addparams(par); - freeparams(par); - } - - globfree(&globbuf); -} - -static int b16len(size_t n) -{ - return snprintf(NULL, 0, "%zx", n); -} - -/* listparams: display a list of found parameter files */ -void listparams(void) -{ - int lengths[5] = { 0 }; - - loadparams(); + }; - for (int i = 0; i < paramc; i++) { - int clengths[5]; + if (!ismatch) + continue; - clengths[0] = strlen(paramv[i].chip); - clengths[1] = b16len(paramv[i].fp.memsz); - clengths[2] = b16len(paramv[i].fp.blksz); - clengths[3] = b16len(paramv[i].fp.cmdsz); - clengths[4] = b16len(paramv[i].fp.addrshft); - for (int j = 0; j < 5; j++) - if (clengths[j] > lengths[j]) - lengths[j] = clengths[j]; + readparams(fp, fullpath); + found = true; + errno = 0; + break; } + if (errno) + weprintf("Could not read directory '%s':", dirname); - for (int i = 0; i < paramc; i++) - printf("%-*s - (0x%.*zx 0x%.*zx 0x%.*zx 0x%.*zx) %s\n", - lengths[0], paramv[i].chip, - lengths[1], paramv[i].fp.memsz, lengths[2], paramv[i].fp.blksz, - lengths[3], paramv[i].fp.cmdsz, lengths[4], paramv[i].fp.addrshft, - paramv[i].board != NULL ? paramv[i].board : ""); -} - -/* getparams: return the flash params for the specified MCU */ -int getparams(struct flashparams *fp, const char *mcufile) -{ - assert(fp); - assert(mcufile); - - loadparams(); - - if (strchr(mcufile, '/') != NULL) { - struct params *par; - par = readparams(mcufile); - if (par == NULL) - return -1; - *fp = par->fp; - freeparams(par); - return 0; - } - - for (int i = 0; i < paramc; i++) { - if (xstrcasecmp(paramv[i].chip, mcufile) == 0) { - *fp = paramv[i].fp; - return 0; - } - } + if (fullpath != pathbuf) + free(fullpath); - weprintf("'%s' is not a valid MCU name", mcufile); + if (closedir(dir) == -1) + eprintf("Could not close directory '%s':", dirname); - return -1; + return found; } -- cgit v1.2.3-54-g00ecf