aboutsummaryrefslogtreecommitdiffstats
path: root/params.c
diff options
context:
space:
mode:
Diffstat (limited to 'params.c')
-rw-r--r--params.c399
1 files changed, 131 insertions, 268 deletions
diff --git a/params.c b/params.c
index 3fe324c..08272d6 100644
--- a/params.c
+++ b/params.c
@@ -18,18 +18,18 @@
*/
#include <assert.h>
-#include <ctype.h>
#include <dirent.h>
#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <glob.h>
-#include <limits.h>
+#include <sys/stat.h>
+#include <ctype.h>
-#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;
}