Compare commits
6 commits
dccbb40798
...
be27cccf45
Author | SHA1 | Date | |
---|---|---|---|
be27cccf45 | |||
6e9a68711d | |||
50f3806f15 | |||
c8494b86bd | |||
e7b8a47e49 | |||
c35c6f0389 |
4 changed files with 124 additions and 51 deletions
147
src/config.c
147
src/config.c
|
@ -1,14 +1,17 @@
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
#define PMSG(t, x) fprintf(stderr, t ":%s:%d: " x "\n", path, line)
|
#define PMSG(t, x) fprintf(stderr, "%s:%d:%d: " t ": " x "\n", path, line, col)
|
||||||
|
|
||||||
#define BUF_STORE(name) { \
|
#define BUF_STORE(name, len) { \
|
||||||
if (i >= 10) { \
|
if (i >= len) { \
|
||||||
PMSG("error", name " is too big"); \
|
PMSG("error", name " is too long"); \
|
||||||
err = 1; \
|
err = 1; \
|
||||||
} else { \
|
} else { \
|
||||||
ibuf[i] = ch; \
|
ibuf[i] = ch; \
|
||||||
|
@ -16,11 +19,13 @@
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int parse_conf_opts(struct conf_opts_t *, char *);
|
||||||
|
|
||||||
config_t *
|
config_t *
|
||||||
parse_config(char *path)
|
parse_config(char *path)
|
||||||
{
|
{
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
int res, state, line, ws, comment, err, i;
|
int state, line, ws, comment, err, i, col;
|
||||||
#define ST_FILENAME 0
|
#define ST_FILENAME 0
|
||||||
#define ST_EXT 1
|
#define ST_EXT 1
|
||||||
#define ST_START 2
|
#define ST_START 2
|
||||||
|
@ -29,7 +34,7 @@ parse_config(char *path)
|
||||||
#define ST_SKIP_B 5
|
#define ST_SKIP_B 5
|
||||||
#define ST_OPTS 6
|
#define ST_OPTS 6
|
||||||
char ch;
|
char ch;
|
||||||
char ibuf[11];
|
char ibuf[32];
|
||||||
config_t *conf, *cur;
|
config_t *conf, *cur;
|
||||||
|
|
||||||
fd = fopen(path, "r");
|
fd = fopen(path, "r");
|
||||||
|
@ -38,75 +43,100 @@ parse_config(char *path)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
conf = malloc(sizeof(config_t));
|
conf = calloc(1, sizeof(config_t));
|
||||||
if (conf == NULL) {
|
if (conf == NULL) {
|
||||||
perror("couldn't allocate config");
|
perror("couldn't allocate config");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(conf, 0, sizeof(config_t));
|
|
||||||
|
|
||||||
state = ST_FILENAME;
|
state = ST_FILENAME;
|
||||||
line = 1;
|
line = col = 1;
|
||||||
ws = comment = err = 0;
|
ws = comment = err = 0;
|
||||||
i = 0;
|
i = 0;
|
||||||
|
cur = conf;
|
||||||
while ((ch = getc(fd)) != EOF) {
|
while ((ch = getc(fd)) != EOF) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case '\t':
|
case '\t':
|
||||||
case ' ':
|
case ' ':
|
||||||
if (comment)
|
if (comment) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only run on the first whitespace */
|
||||||
if (!ws) {
|
if (!ws) {
|
||||||
i = 0;
|
DPRINTF(("i = %d\n", i));
|
||||||
ws = 1;
|
ws = 1;
|
||||||
state++;
|
state++;
|
||||||
|
DPRINTF(("%s:%d:%d: switching to state %d\n", path, line, col, state));
|
||||||
|
switch (state-1) {
|
||||||
|
case ST_FILENAME:
|
||||||
|
cur->filename[i] = 0;
|
||||||
|
break;
|
||||||
|
case ST_EXT:
|
||||||
|
cur->ext[i] = 0;
|
||||||
|
break;
|
||||||
/* convert offsets to uint32_t (or close enough) */
|
/* convert offsets to uint32_t (or close enough) */
|
||||||
switch (state) {
|
|
||||||
case ST_START:
|
case ST_START:
|
||||||
cur->start = strtoul(ibuf, ibuf+strlen(ibuf), 10);
|
cur->start = strtoul(ibuf, NULL, 10);
|
||||||
break;
|
break;
|
||||||
case ST_END:
|
case ST_END:
|
||||||
cur->end = strtoul(ibuf, ibuf+strlen(ibuf), 10);
|
cur->end = strtoul(ibuf, NULL, 10);
|
||||||
break;
|
break;
|
||||||
case ST_SKIP_A:
|
case ST_SKIP_A:
|
||||||
cur->skip_a = strtoul(ibuf, ibuf+strlen(ibuf), 10);
|
cur->skip_a = strtoul(ibuf, NULL, 10);
|
||||||
break;
|
break;
|
||||||
case ST_SKIP_B:
|
case ST_SKIP_B:
|
||||||
cur->skip_b = strtoul(ibuf, ibuf+strlen(ibuf), 10);
|
cur->skip_b = strtoul(ibuf, NULL, 10);
|
||||||
break;
|
break;
|
||||||
/* TODO: probably handle ST_OPTS here? */
|
|
||||||
}
|
}
|
||||||
memset(ibuf, 0, 11);
|
i = 0;
|
||||||
|
memset(ibuf, 0, 32);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '\r': /* dos line end */
|
case '\r': /* dos line end */
|
||||||
(void)getc(fd);
|
(void)getc(fd);
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case '\n':
|
case '\n':
|
||||||
cur->next = malloc(sizeof(config_t));
|
/*
|
||||||
if (cur == NULL) {
|
* Only start a new struct if we didn't have a comment at the
|
||||||
perror("couldn't allocate config");
|
* beginning of a line.
|
||||||
err = 1;
|
*/
|
||||||
break;
|
if (state != ST_FILENAME || !comment) {
|
||||||
}
|
cur->next = calloc(1, sizeof(config_t));
|
||||||
|
if (cur == NULL) {
|
||||||
|
perror("couldn't allocate config");
|
||||||
|
err = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (state != ST_OPTS) {
|
if (state != ST_OPTS) {
|
||||||
PMSG("warn", "line ends early")
|
PMSG("error", "line ends early");
|
||||||
|
err = 1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
DPRINTF(("filename: %s.%s\n", cur->filename, cur->ext));
|
||||||
|
if (parse_conf_opts(&cur->opts, ibuf) != 0) {
|
||||||
|
PMSG("error", "unable to parse opts (see above)");
|
||||||
|
err = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reset state for next line */
|
/* reset state for next line */
|
||||||
state = ST_FILENAME;
|
state = ST_FILENAME;
|
||||||
cur = cur->next;
|
ws = col = i = 0;
|
||||||
memset(cur, 0, sizeof(config_t));
|
comment = 0;
|
||||||
ws = i = comment = 0;
|
|
||||||
line++;
|
line++;
|
||||||
break;
|
break;
|
||||||
case '#':
|
case '#':
|
||||||
comment = 1;
|
comment = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (comment)
|
if (comment) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ws = 0;
|
ws = 0;
|
||||||
|
|
||||||
|
@ -117,7 +147,7 @@ parse_config(char *path)
|
||||||
PMSG("error", "filename must be less than eight characters");
|
PMSG("error", "filename must be less than eight characters");
|
||||||
err = 1;
|
err = 1;
|
||||||
} else {
|
} else {
|
||||||
cur->filename[i] = ch;
|
cur->filename[i] = toupper(ch);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -126,20 +156,25 @@ parse_config(char *path)
|
||||||
PMSG("error", "ext must be less than three characters");
|
PMSG("error", "ext must be less than three characters");
|
||||||
err = 1;
|
err = 1;
|
||||||
} else {
|
} else {
|
||||||
cur->ext[i] = ch;
|
cur->ext[i] = toupper(ch);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ST_START:
|
case ST_START:
|
||||||
BUF_STORE("start byte")
|
BUF_STORE("start byte", 10);
|
||||||
|
break;
|
||||||
case ST_END:
|
case ST_END:
|
||||||
BUF_STORE("end byte")
|
BUF_STORE("end byte", 10);
|
||||||
|
break;
|
||||||
case ST_SKIP_A:
|
case ST_SKIP_A:
|
||||||
BUF_STORE("first byte skip")
|
BUF_STORE("first byte skip", 10);
|
||||||
|
break;
|
||||||
case ST_SKIP_B:
|
case ST_SKIP_B:
|
||||||
BUF_STORE("second byte skip")
|
BUF_STORE("second byte skip", 10);
|
||||||
|
break;
|
||||||
case ST_OPTS:
|
case ST_OPTS:
|
||||||
/* TODO */
|
BUF_STORE("option string", 31);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
PMSG("error", "too many columns");
|
PMSG("error", "too many columns");
|
||||||
err = 1;
|
err = 1;
|
||||||
|
@ -148,6 +183,8 @@ parse_config(char *path)
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
col++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -160,6 +197,42 @@ parse_config(char *path)
|
||||||
return conf;
|
return conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define STORE_VAL(name, var, lim) { \
|
||||||
|
val = strtoul(cur+4, NULL, 10); \
|
||||||
|
if (val > lim) { \
|
||||||
|
fprintf(stderr, "err: " name " value out of bounds\n"); \
|
||||||
|
return 1; \
|
||||||
|
} else { \
|
||||||
|
var = val; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parses the options column of the config, ex.
|
||||||
|
* "xor=10,add=5,shl=2"
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
parse_conf_opts(struct conf_opts_t *opts, char *parse)
|
||||||
|
{
|
||||||
|
char *cur, *last;
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
for ((cur = strtok_r(parse, ",", &last)); cur;
|
||||||
|
(cur = strtok_r(NULL, ",", &last))) {
|
||||||
|
if (!strncmp(cur, "xor=", 4)) {
|
||||||
|
STORE_VAL("xor", opts->bit_xor, 0xff);
|
||||||
|
} else if (!strncmp(cur, "add=", 4)) {
|
||||||
|
STORE_VAL("add", opts->add, 0xff);
|
||||||
|
} else if (!strncmp(cur, "shr=", 4)) {
|
||||||
|
STORE_VAL("shr", opts->shr, 8);
|
||||||
|
} else if (!strncmp(cur, "shl=", 4)) {
|
||||||
|
STORE_VAL("shl", opts->shl, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
free_config(config_t *conf)
|
free_config(config_t *conf)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define _DEBUG_H
|
#define _DEBUG_H
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define DPRINTF(x) printf(x)
|
#define DPRINTF(x) printf x
|
||||||
#else
|
#else
|
||||||
#define DPRINTF(x)
|
#define DPRINTF(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
24
src/dosfs.c
24
src/dosfs.c
|
@ -35,13 +35,13 @@ open_image(const char *path, int flags, dosfs_t *fsd)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fsd->ib.jmp[0] != 0xEB || fsd->ib.jmp[2] != 0x90) {
|
if (fsd->ib.jmp[0] != 0xEB || fsd->ib.jmp[2] != 0x90) {
|
||||||
DPRINTF("hm... doesn't look like a FAT image?\n");
|
DPRINTF(("hm... doesn't look like a FAT image?\n"));
|
||||||
close(ifd);
|
close(ifd);
|
||||||
return EOPNOTSUPP;
|
return EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fsd->ib.sect_ct == 0 || fsd->ib.fat_size == 0) {
|
if (fsd->ib.sect_ct == 0 || fsd->ib.fat_size == 0) {
|
||||||
DPRINTF("sect_ct or fat_size == 0, likely fat>32 (unsupported)\n");
|
DPRINTF(("sect_ct or fat_size == 0, likely fat>32 (unsupported)\n"));
|
||||||
close(ifd);
|
close(ifd);
|
||||||
return EOPNOTSUPP;
|
return EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ open_image(const char *path, int flags, dosfs_t *fsd)
|
||||||
} else if (fsd->data_size < FAT16_MAX_CLUSTERS) {
|
} else if (fsd->data_size < FAT16_MAX_CLUSTERS) {
|
||||||
fsd->fs_ver = 16;
|
fsd->fs_ver = 16;
|
||||||
} else {
|
} else {
|
||||||
DPRINTF("data_size >= FAT12_MAX_CLUSTERS, likely fat>32 (unsupported)\n");
|
DPRINTF(("data_size >= FAT12_MAX_CLUSTERS, likely fat>32 (unsupported)\n"));
|
||||||
close(ifd);
|
close(ifd);
|
||||||
return EOPNOTSUPP;
|
return EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ dos_listdir(dosfs_t *fsd, unsigned int offset)
|
||||||
|
|
||||||
start = malloc(sizeof(dosfile_t));
|
start = malloc(sizeof(dosfile_t));
|
||||||
if (start == NULL) {
|
if (start == NULL) {
|
||||||
DPRINTF("malloc failed\n");
|
DPRINTF(("malloc failed\n"));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,14 +107,14 @@ dos_listdir(dosfs_t *fsd, unsigned int offset)
|
||||||
|
|
||||||
res = reallocarr(&dirs, root_ents, sizeof(struct dos_dirent));
|
res = reallocarr(&dirs, root_ents, sizeof(struct dos_dirent));
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
DPRINTF("reallocarr failed\n");
|
DPRINTF(("reallocarr failed\n"));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = pread(fsd->ifd, dirs, (root_ents * sizeof(struct dos_dirent)),
|
res = pread(fsd->ifd, dirs, (root_ents * sizeof(struct dos_dirent)),
|
||||||
offset);
|
offset);
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
DPRINTF("pread failed\n");
|
DPRINTF(("pread failed\n"));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ dos_listdir(dosfs_t *fsd, unsigned int offset)
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
cur->next = malloc(sizeof(dosfile_t));
|
cur->next = malloc(sizeof(dosfile_t));
|
||||||
if (cur->next == NULL) {
|
if (cur->next == NULL) {
|
||||||
DPRINTF("inner malloc failed!?\n");
|
DPRINTF(("inner malloc failed!?\n"));
|
||||||
res = -1;
|
res = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,7 @@ read_fat_chain(dosfs_t *fsd, unsigned int first, int *length)
|
||||||
len++;
|
len++;
|
||||||
res = reallocarr(&chain, len, sizeof(unsigned int));
|
res = reallocarr(&chain, len, sizeof(unsigned int));
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
DPRINTF("reallocarr failed\n");
|
DPRINTF(("reallocarr failed\n"));
|
||||||
free(chain);
|
free(chain);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@ read_fat_chain(dosfs_t *fsd, unsigned int first, int *length)
|
||||||
/* XXX: endianness */
|
/* XXX: endianness */
|
||||||
res = pread(fsd->ifd, &next, 2, byte_off);
|
res = pread(fsd->ifd, &next, 2, byte_off);
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
DPRINTF("pread failed\n");
|
DPRINTF(("pread failed\n"));
|
||||||
free(chain);
|
free(chain);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -243,12 +243,12 @@ read_fat_chain(dosfs_t *fsd, unsigned int first, int *length)
|
||||||
* offset, i.e. one that can be used with lseek()/pread().
|
* offset, i.e. one that can be used with lseek()/pread().
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
get_byte_offset(dosfs_t *fsd, dosfile_t *file, int f_offset)
|
get_byte_offset(dosfs_t *fsd, dosfile_t *file, unsigned int f_offset)
|
||||||
{
|
{
|
||||||
int coff, csz;
|
int coff, csz;
|
||||||
|
|
||||||
if (f_offset > file->ent.size) {
|
if (f_offset > file->ent.size) {
|
||||||
DPRINTF("offset requested is out of bounds!\n");
|
DPRINTF(("offset requested is out of bounds!\n"));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +259,7 @@ get_byte_offset(dosfs_t *fsd, dosfile_t *file, int f_offset)
|
||||||
coff = f_offset / csz;
|
coff = f_offset / csz;
|
||||||
|
|
||||||
if (coff > file->fc_len) {
|
if (coff > file->fc_len) {
|
||||||
DPRINTF("offset is within filesize, but not enough clusters??\n");
|
DPRINTF(("offset is within filesize, but not enough clusters??\n"));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,6 @@ void close_image(dosfs_t *);
|
||||||
dosfile_t *dos_listdir(dosfs_t *, unsigned int);
|
dosfile_t *dos_listdir(dosfs_t *, unsigned int);
|
||||||
void dos_freedir(dosfile_t *);
|
void dos_freedir(dosfile_t *);
|
||||||
|
|
||||||
int get_byte_offset(dosfs_t *, dosfile_t *, int);
|
int get_byte_offset(dosfs_t *, dosfile_t *, unsigned int);
|
||||||
|
|
||||||
#endif /* !_FAT12_H */
|
#endif /* !_FAT12_H */
|
||||||
|
|
Loading…
Reference in a new issue