mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Even faster content load.
This commit is contained in:
parent
7f400289b8
commit
b21b3076f6
4 changed files with 486 additions and 261 deletions
|
|
@ -114,6 +114,7 @@ int main(int argc, char* argv[])
|
|||
block_off_t blockcount;
|
||||
int ret;
|
||||
tommy_list filterlist;
|
||||
char* e;
|
||||
|
||||
/* defaults */
|
||||
conf = CONF;
|
||||
|
|
@ -149,13 +150,15 @@ int main(int argc, char* argv[])
|
|||
tommy_list_insert_tail(&filterlist, &filter->node, filter);
|
||||
} break;
|
||||
case 's' :
|
||||
if (stru32(optarg, &blockstart) != 0) {
|
||||
blockstart = strtoul(optarg, &e, 0);
|
||||
if (!e || *e) {
|
||||
fprintf(stderr, "Invalid start position '%s'\n", optarg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case 't' :
|
||||
if (stru32(optarg, &blockcount) != 0) {
|
||||
blockcount = strtoul(optarg, &e, 0);
|
||||
if (!e || *e) {
|
||||
fprintf(stderr, "Invalid count number '%s'\n", optarg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
|
|||
364
state.c
364
state.c
|
|
@ -21,11 +21,6 @@
|
|||
#include "state.h"
|
||||
#include "util.h"
|
||||
|
||||
/**
|
||||
* Max length of a line in the configuration and content files.
|
||||
*/
|
||||
#define TEXT_LINE_MAX 1024
|
||||
|
||||
void state_init(struct snapraid_state* state)
|
||||
{
|
||||
state->verbose = 0;
|
||||
|
|
@ -87,49 +82,29 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
line = 0;
|
||||
line = 1;
|
||||
content_count = 0;
|
||||
while (1) {
|
||||
char buffer[TEXT_LINE_MAX];
|
||||
char* tag;
|
||||
char* s;
|
||||
char tag[PATH_MAX];
|
||||
char buffer[PATH_MAX];
|
||||
int ret;
|
||||
int c;
|
||||
|
||||
++line;
|
||||
/* skip initial spaces */
|
||||
strgetspace(f);
|
||||
|
||||
ret = strgets(buffer, TEXT_LINE_MAX, f);
|
||||
if (ret < 0) {
|
||||
/* read the command */
|
||||
ret = strgettoken(f, tag, sizeof(tag));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Error reading the configuration file '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (ret == 0)
|
||||
break;
|
||||
|
||||
/* start */
|
||||
s = buffer;
|
||||
|
||||
/* here we use strtoken_trim() to eat extra spaces inserted by the user */
|
||||
|
||||
/* skip ending spaces */
|
||||
--ret;
|
||||
while (ret>0 && isspace(s[ret-1])) {
|
||||
--ret;
|
||||
s[ret] = 0;
|
||||
}
|
||||
/* skip initial spaces */
|
||||
while (*s && isspace(*s)) {
|
||||
++s;
|
||||
}
|
||||
|
||||
/* ignore comments and empty lines */
|
||||
if (*s == '#' || *s == 0)
|
||||
continue;
|
||||
|
||||
tag = s;
|
||||
s = strtoken_trim(s);
|
||||
/* skip spaces after the command */
|
||||
strgetspace(f);
|
||||
|
||||
if (strcmp(tag, "block_size") == 0) {
|
||||
ret = stru32(s, &state->block_size);
|
||||
ret = strgetu32(f, &state->block_size);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'block_size' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -153,40 +128,120 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i
|
|||
fprintf(stderr, "Multiple 'parity' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
pathcpy(state->parity, sizeof(state->parity), s);
|
||||
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'parity' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pathcpy(state->parity, sizeof(state->parity), buffer);
|
||||
} else if (strcmp(tag, "q-parity") == 0) {
|
||||
if (*state->qarity) {
|
||||
fprintf(stderr, "Multiple 'q-parity' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
pathcpy(state->qarity, sizeof(state->qarity), s);
|
||||
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'q-parity' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pathcpy(state->qarity, sizeof(state->qarity), buffer);
|
||||
state->level = 2;
|
||||
} else if (strcmp(tag, "content") == 0) {
|
||||
struct snapraid_content* content = content_alloc(s);
|
||||
struct snapraid_content* content;
|
||||
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'content' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
content = content_alloc(buffer);
|
||||
|
||||
tommy_list_insert_tail(&state->contentlist, &content->node, content);
|
||||
++content_count;
|
||||
} else if (strcmp(tag, "disk") == 0) {
|
||||
char* name = s;
|
||||
s = strtoken_trim(s);
|
||||
tommy_array_insert(&state->diskarr, disk_alloc(name, s));
|
||||
char dir[PATH_MAX];
|
||||
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'disk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
strgetspace(f);
|
||||
|
||||
ret = strgettoken(f, dir, sizeof(dir));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'disk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
tommy_array_insert(&state->diskarr, disk_alloc(buffer, dir));
|
||||
} else if (strcmp(tag, "exclude") == 0) {
|
||||
struct snapraid_filter* filter = filter_alloc(-1, s);
|
||||
struct snapraid_filter* filter;
|
||||
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'exclude' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
filter = filter_alloc(-1, buffer);
|
||||
if (!filter) {
|
||||
fprintf(stderr, "Invalid 'exclude' specification '%s' in '%s' at line %u\n", s, path, line);
|
||||
fprintf(stderr, "Invalid 'exclude' specification '%s' in '%s' at line %u\n", buffer, path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
tommy_list_insert_tail(&state->filterlist, &filter->node, filter);
|
||||
} else if (strcmp(tag, "include") == 0) {
|
||||
struct snapraid_filter* filter = filter_alloc(1, s);
|
||||
struct snapraid_filter* filter;
|
||||
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'include' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
filter = filter_alloc(1, buffer);
|
||||
if (!filter) {
|
||||
fprintf(stderr, "Invalid 'include' specification '%s' in '%s' at line %u\n", s, path, line);
|
||||
fprintf(stderr, "Invalid 'include' specification '%s' in '%s' at line %u\n", buffer, path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
tommy_list_insert_tail(&state->filterlist, &filter->node, filter);
|
||||
} else if (tag[0] == 0) {
|
||||
/* allow empty lines */
|
||||
} else if (tag[0] == '#') {
|
||||
ret = strgetline(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid comment in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Unknown tag '%s' in '%s'\n", tag, path);
|
||||
fprintf(stderr, "Unknown tag '%s' in '%s' at line %u\n", tag, path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* skip final spaces */
|
||||
strgetspace(f);
|
||||
|
||||
/* next line */
|
||||
c = strgetcnl(f);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
if (c != '\n') {
|
||||
fprintf(stderr, "Extra char '%c' after command specification in '%s' at line %u\n", (char)c, path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
++line;
|
||||
}
|
||||
|
||||
if (ferror(f)) {
|
||||
fprintf(stderr, "Error reading the configuration file '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
|
@ -282,53 +337,71 @@ void state_read(struct snapraid_state* state)
|
|||
|
||||
disk = 0;
|
||||
file = 0;
|
||||
line = 0;
|
||||
line = 1;
|
||||
blockidx = 0;
|
||||
|
||||
while (1) {
|
||||
char buffer[TEXT_LINE_MAX];
|
||||
char* tag;
|
||||
char* s;
|
||||
char buffer[PATH_MAX];
|
||||
int ret;
|
||||
int cmd;
|
||||
int c;
|
||||
|
||||
++line;
|
||||
|
||||
ret = strgets(buffer, TEXT_LINE_MAX, f);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error reading the content file '%s' at line %u\n", path, line);
|
||||
/* decode the command */
|
||||
cmd = 0;
|
||||
c = strgetc(f);
|
||||
if (c == 'b') {
|
||||
if (strgetc(f) == 'l' && strgetc(f) == 'k') {
|
||||
c = strgetc(f);
|
||||
if (c == ' ') {
|
||||
cmd = 'b';
|
||||
} else if (c == 's' && strgetc(f) == 'i' && strgetc(f) == 'z' && strgetc(f) == 'e' && strgetc(f) == ' ') {
|
||||
cmd = 's';
|
||||
}
|
||||
}
|
||||
} else if (c == 'i') {
|
||||
if (strgetc(f) == 'n' && strgetc(f) == 'v' && strgetc(f) == ' ') {
|
||||
cmd = 'i';
|
||||
}
|
||||
} else if (c == 'f') {
|
||||
if (strgetc(f) == 'i' && strgetc(f) == 'l' && strgetc(f) == 'e' && strgetc(f) == ' ') {
|
||||
cmd = 'f';
|
||||
}
|
||||
} else if (c == 'c') {
|
||||
if (strgetc(f) == 'h' && strgetc(f) == 'e' && strgetc(f) == 'c' && strgetc(f) == 'k'
|
||||
&& strgetc(f) == 's' && strgetc(f) == 'u' && strgetc(f) == 'm' && strgetc(f) == ' ') {
|
||||
cmd = 'c';
|
||||
}
|
||||
} else if (c == '\n') {
|
||||
} else if (c == '\r') {
|
||||
c = strgetc(f);
|
||||
if (c != '\n') {
|
||||
fprintf(stderr, "Unexpected carrige return in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (c == '#') {
|
||||
int ret = strgetline(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid comment in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (c == EOF) {
|
||||
break;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown char '%c' in '%s' at line %u\n", (char)c, path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (ret == 0)
|
||||
break;
|
||||
|
||||
/* start */
|
||||
s = buffer;
|
||||
|
||||
/* here we use strtoken() to allow filenames starting and ending with spaces */
|
||||
|
||||
/* ignore comments and empty lines */
|
||||
if (*s == '#' || *s == 0)
|
||||
continue;
|
||||
|
||||
tag = s;
|
||||
s = strtoken(s);
|
||||
|
||||
if (strcmp(tag, "blk") == 0 || strcmp(tag, "inv") == 0) {
|
||||
char* pos;
|
||||
char* hash;
|
||||
if (cmd == 'b' || cmd == 'i') {
|
||||
/* "blk"/"inv" command */
|
||||
block_off_t v_pos;
|
||||
struct snapraid_block* block;
|
||||
char* e;
|
||||
|
||||
if (!file) {
|
||||
fprintf(stderr, "Unexpected 'blk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pos = s;
|
||||
s = strtoken(s);
|
||||
hash = s;
|
||||
|
||||
ret = stru32(pos, &v_pos);
|
||||
ret = strgetu32(f, &v_pos);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'blk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -348,10 +421,20 @@ void state_read(struct snapraid_state* state)
|
|||
|
||||
block->parity_pos = v_pos;
|
||||
|
||||
/* set the hash only if present */
|
||||
if (*hash != 0) {
|
||||
e = strdechex(block->hash, HASH_SIZE, hash);
|
||||
if (e) {
|
||||
/* check if we are at the end of the line */
|
||||
c = strgetcnl(f);
|
||||
if (c == '\n') {
|
||||
/* no hash present */
|
||||
ungetc(c, f);
|
||||
} else {
|
||||
if (c != ' ') {
|
||||
fprintf(stderr, "Invalid 'blk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* set the hash only if present */
|
||||
ret = strgethex(f, block->hash, HASH_SIZE);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'blk' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -360,7 +443,7 @@ void state_read(struct snapraid_state* state)
|
|||
}
|
||||
|
||||
/* set the parity only if present */
|
||||
if (tag[0] == 'b') /* blk */
|
||||
if (cmd == 'b')
|
||||
block_flag_set(block, BLOCK_HAS_PARITY);
|
||||
|
||||
/* parity implies hash */
|
||||
|
|
@ -382,12 +465,10 @@ void state_read(struct snapraid_state* state)
|
|||
|
||||
/* stat */
|
||||
++count_block;
|
||||
} else if (strcmp(tag, "file") == 0) {
|
||||
char* name;
|
||||
char* size;
|
||||
char* mtime;
|
||||
char* inode;
|
||||
char* sub;
|
||||
} else if (cmd == 'f') {
|
||||
/* file */
|
||||
char buffer[PATH_MAX];
|
||||
char sub[PATH_MAX];
|
||||
uint64_t v_size;
|
||||
uint64_t v_mtime;
|
||||
uint64_t v_inode;
|
||||
|
|
@ -398,29 +479,55 @@ void state_read(struct snapraid_state* state)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
name = s;
|
||||
s = strtoken(s);
|
||||
size = s;
|
||||
s = strtoken(s);
|
||||
mtime = s;
|
||||
s = strtoken(s);
|
||||
inode = s;
|
||||
s = strtoken(s);
|
||||
sub = s;
|
||||
|
||||
ret = stru64(size, &v_size);
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = stru64(mtime, &v_mtime);
|
||||
c = strgetc(f);
|
||||
if (c != ' ') {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = strgetu64(f, &v_size);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = stru64(inode, &v_inode);
|
||||
c = strgetc(f);
|
||||
if (c != ' ') {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = strgetu64(f, &v_mtime);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
c = strgetc(f);
|
||||
if (c != ' ') {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = strgetu64(f, &v_inode);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
c = strgetc(f);
|
||||
if (c != ' ') {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = strgetline(f, sub, sizeof(sub));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -434,11 +541,11 @@ void state_read(struct snapraid_state* state)
|
|||
/* find the disk */
|
||||
for(i=0;i<tommy_array_size(&state->diskarr);++i) {
|
||||
disk = tommy_array_get(&state->diskarr, i);
|
||||
if (strcmp(disk->name, name) == 0)
|
||||
if (strcmp(disk->name, buffer) == 0)
|
||||
break;
|
||||
}
|
||||
if (i == tommy_array_size(&state->diskarr)) {
|
||||
fprintf(stderr, "Disk named '%s' not found in '%s' at line %u\n", name, path, line);
|
||||
fprintf(stderr, "Disk named '%s' not found in '%s' at line %u\n", buffer, path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -460,10 +567,25 @@ void state_read(struct snapraid_state* state)
|
|||
|
||||
/* stat */
|
||||
++count_file;
|
||||
} else if (strcmp(tag, "blksize") == 0) {
|
||||
} else if (cmd == 'c') {
|
||||
ret = strgettoken(f, buffer, sizeof(buffer));
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'checksum' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strcmp(buffer, "md5") == 0) {
|
||||
state->hash = HASH_MD5;
|
||||
} else if (strcmp(buffer, "murmur3") == 0) {
|
||||
state->hash = HASH_MURMUR3;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid 'checksum' specification '%s' in '%s' at line %u\n", buffer, path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (cmd == 's') {
|
||||
block_off_t blksize;
|
||||
|
||||
ret = stru32(s, &blksize);
|
||||
ret = strgetu32(f, &blksize);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Invalid 'blksize' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -474,19 +596,23 @@ void state_read(struct snapraid_state* state)
|
|||
fprintf(stderr, "Please restore the 'block_size' value in the configuration file to '%u'\n", blksize / 1024);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (strcmp(tag, "checksum") == 0) {
|
||||
if (strcmp(s, "md5") == 0) {
|
||||
state->hash = HASH_MD5;
|
||||
} else if (strcmp(s, "murmur3") == 0) {
|
||||
state->hash = HASH_MURMUR3;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid 'checksum' specification '%s' in '%s' at line %u\n", s, path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Unknown tag '%s' in '%s' at line%u\n", tag, path, line);
|
||||
}
|
||||
|
||||
/* next line */
|
||||
c = strgetcnl(f);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
if (c != '\n') {
|
||||
fprintf(stderr, "Extra char '%c' after command specification in '%s' at line %u\n", (char)c, path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
++line;
|
||||
}
|
||||
|
||||
if (ferror(f)) {
|
||||
fprintf(stderr, "Error reading the content file '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (file) {
|
||||
|
|
|
|||
242
util.c
242
util.c
|
|
@ -22,95 +22,6 @@
|
|||
/****************************************************************************/
|
||||
/* string */
|
||||
|
||||
int strgets(char* s, unsigned size, FILE* f)
|
||||
{
|
||||
char* i = s;
|
||||
char* send = s + size;
|
||||
int c;
|
||||
|
||||
while (1) {
|
||||
#if HAVE_GETC_UNLOCKED
|
||||
c = getc_unlocked(f);
|
||||
#else
|
||||
c = getc(f);
|
||||
#endif
|
||||
if (c == EOF || c == '\n')
|
||||
break;
|
||||
|
||||
*i++ = c;
|
||||
|
||||
if (i == send) {
|
||||
return -1; /* return error if the buffer is full */
|
||||
}
|
||||
}
|
||||
|
||||
if (c == EOF) {
|
||||
if (
|
||||
#if HAVE_FERROR_UNLOCKED
|
||||
ferror_unlocked(f)
|
||||
#else
|
||||
ferror(f)
|
||||
#endif
|
||||
) {
|
||||
return -1;
|
||||
}
|
||||
if (i == s)
|
||||
return 0; /* return EOF only if nothing was read */
|
||||
}
|
||||
|
||||
/* remove ending carrige return to support the Windows CR+LF format */
|
||||
if (i != s && i[-1] == '\r')
|
||||
--i;
|
||||
|
||||
*i = 0;
|
||||
|
||||
return i - s + 1;
|
||||
}
|
||||
|
||||
int stru32(const char* s, uint32_t* value)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
if (!*s)
|
||||
return -1;
|
||||
|
||||
v = 0;
|
||||
while (*s>='0' && *s<='9') {
|
||||
v *= 10;
|
||||
v += *s - '0';
|
||||
++s;
|
||||
}
|
||||
|
||||
if (*s)
|
||||
return -1;
|
||||
|
||||
*value = v;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stru64(const char* s, uint64_t* value)
|
||||
{
|
||||
uint64_t v;
|
||||
|
||||
if (!*s)
|
||||
return -1;
|
||||
|
||||
v = 0;
|
||||
while (*s>='0' && *s<='9') {
|
||||
v *= 10;
|
||||
v += *s - '0';
|
||||
++s;
|
||||
}
|
||||
|
||||
if (*s)
|
||||
return -1;
|
||||
|
||||
*value = v;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char strhexset[16] = "0123456789abcdef";
|
||||
|
||||
void strenchex(char* str, const void* void_data, unsigned data_len)
|
||||
|
|
@ -172,6 +83,159 @@ char* strdechex(void* void_data, unsigned data_len, char* str)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* get */
|
||||
|
||||
int strgettoken(FILE* f, char* s, unsigned size)
|
||||
{
|
||||
char* i = s;
|
||||
char* send = s + size;
|
||||
int c;
|
||||
|
||||
while (1) {
|
||||
c = strgetc(f);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
if (c == ' ' || c == '\t') {
|
||||
ungetc(c, f);
|
||||
break;
|
||||
}
|
||||
if (c == '\n') {
|
||||
/* remove ending carrige return to support the Windows CR+LF format */
|
||||
if (i != s && i[-1] == '\r')
|
||||
--i;
|
||||
ungetc(c, f);
|
||||
break;
|
||||
}
|
||||
|
||||
*i++ = c;
|
||||
|
||||
if (i == send)
|
||||
return -1;
|
||||
}
|
||||
|
||||
*i = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strgetline(FILE* f, char* s, unsigned size)
|
||||
{
|
||||
char* i = s;
|
||||
char* send = s + size;
|
||||
int c;
|
||||
|
||||
while (1) {
|
||||
c = strgetc(f);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
if (c == '\n') {
|
||||
/* remove ending carrige return to support the Windows CR+LF format */
|
||||
if (i != s && i[-1] == '\r')
|
||||
--i;
|
||||
ungetc(c, f);
|
||||
break;
|
||||
}
|
||||
|
||||
*i++ = c;
|
||||
|
||||
if (i == send)
|
||||
return -1;
|
||||
}
|
||||
|
||||
*i = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strgetu32(FILE* f, uint32_t* value)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = strgetc(f);
|
||||
if (c>='0' && c<='9') {
|
||||
uint32_t v;
|
||||
|
||||
v = c - '0';
|
||||
|
||||
c = strgetc(f);
|
||||
while (c>='0' && c<='9') {
|
||||
v *= 10;
|
||||
v += c - '0';
|
||||
c = strgetc(f);
|
||||
}
|
||||
|
||||
*value = v;
|
||||
|
||||
ungetc(c, f);
|
||||
return 0;
|
||||
} else {
|
||||
/* nothing read */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int strgetu64(FILE* f, uint64_t* value)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = strgetc(f);
|
||||
if (c>='0' && c<='9') {
|
||||
uint64_t v;
|
||||
|
||||
v = c - '0';
|
||||
|
||||
c = strgetc(f);
|
||||
while (c>='0' && c<='9') {
|
||||
v *= 10;
|
||||
v += c - '0';
|
||||
c = strgetc(f);
|
||||
}
|
||||
|
||||
*value = v;
|
||||
|
||||
ungetc(c, f);
|
||||
return 0;
|
||||
} else {
|
||||
/* nothing read */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int strgethex(FILE* f, void* void_data, unsigned data_len)
|
||||
{
|
||||
unsigned char* data = void_data;
|
||||
unsigned i;
|
||||
|
||||
for(i=0;i<data_len;++i) {
|
||||
unsigned b0;
|
||||
unsigned b1;
|
||||
unsigned b;
|
||||
int c;
|
||||
|
||||
c = strgetc(f);
|
||||
if (c == EOF)
|
||||
return -1;
|
||||
b0 = strdecset[c];
|
||||
|
||||
c = strgetc(f);
|
||||
if (c == EOF)
|
||||
return -1;
|
||||
b1 = strdecset[c];
|
||||
|
||||
b = (b0 << 4) | b1;
|
||||
|
||||
if (b > 0xFF)
|
||||
return -1;
|
||||
|
||||
*data++ = b;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* path */
|
||||
|
||||
|
|
|
|||
134
util.h
134
util.h
|
|
@ -21,57 +21,6 @@
|
|||
/****************************************************************************/
|
||||
/* string */
|
||||
|
||||
/**
|
||||
* Marks the end of the current token, and skip one and only one separator if present.
|
||||
*/
|
||||
static inline char* strtoken(char* s)
|
||||
{
|
||||
while (*s && *s != ' ')
|
||||
++s;
|
||||
if (*s) {
|
||||
*s = 0;
|
||||
++s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like strtoken() but trim spaces.
|
||||
*/
|
||||
static inline char* strtoken_trim(char* s)
|
||||
{
|
||||
while (*s && !isspace(*s))
|
||||
++s;
|
||||
if (*s) {
|
||||
*s = 0;
|
||||
++s;
|
||||
}
|
||||
|
||||
/* skip spaces */
|
||||
while (*s && isspace(*s))
|
||||
++s;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a text line from a file.
|
||||
* Returns -1 on error, 0 on OEF, or the number of chars returned in the buffer, including the ending 0.
|
||||
*/
|
||||
int strgets(char* s, unsigned size, FILE* f);
|
||||
|
||||
/**
|
||||
* Convert a string to a 32 bit unsigned.
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int stru32(const char* s, uint32_t* value);
|
||||
|
||||
/**
|
||||
* Convert a string to a 64 bit unsigned.
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int stru64(const char* s, uint64_t* value);
|
||||
|
||||
/**
|
||||
* Encodes to hex.
|
||||
*/
|
||||
|
|
@ -82,6 +31,89 @@ void strenchex(char* str, const void* void_data, unsigned data_len);
|
|||
*/
|
||||
char* strdechex(void* void_data, unsigned data_len, char* str);
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* get */
|
||||
|
||||
/**
|
||||
* Get a char from a stream.
|
||||
*/
|
||||
static inline int strgetc(FILE* f)
|
||||
{
|
||||
#if HAVE_GETC_UNLOCKED
|
||||
return getc_unlocked(f);
|
||||
#else
|
||||
return getc(f);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a char from a stream, ignoring one '\r'.
|
||||
*/
|
||||
static inline int strgetcnl(FILE* f)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = strgetc(f);
|
||||
if (c == '\r')
|
||||
c = strgetc(f);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all the spaces and tabs.
|
||||
* Returns the number of spaces and tabs read.
|
||||
*/
|
||||
static inline int strgetspace(FILE* f)
|
||||
{
|
||||
int count = 0;
|
||||
int c;
|
||||
|
||||
c = strgetc(f);
|
||||
while (c == ' ' || c == '\t') {
|
||||
++count;
|
||||
c = strgetc(f);
|
||||
}
|
||||
|
||||
ungetc(c, f);
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read until the first space or tab.
|
||||
* Stops at the first ' ', '\t', '\n' or EOF.
|
||||
* Returns error if the buffer is too small.
|
||||
*/
|
||||
int strgettoken(FILE* f, char* str, unsigned size);
|
||||
|
||||
/**
|
||||
* Read until the end of line.
|
||||
* Stops at the first '\n' or EOF.
|
||||
* Returns error if the buffer is too small.
|
||||
*/
|
||||
int strgetline(FILE* f, char* str, unsigned size);
|
||||
|
||||
/**
|
||||
* Read a 32 bit number.
|
||||
* Stops at the first not digit char or EOF.
|
||||
* Returns error if there isn't enough to read.
|
||||
*/
|
||||
int strgetu32(FILE* f, uint32_t* value);
|
||||
|
||||
/**
|
||||
* Read a 64 bit number.
|
||||
* Stops at the first not digit char.
|
||||
* Returns error if there isn't enough to read.
|
||||
*/
|
||||
int strgetu64(FILE* f, uint64_t* value);
|
||||
|
||||
/**
|
||||
* Read an hexadecimal string of fixed length.
|
||||
* Returns error if there isn't enough to read.
|
||||
*/
|
||||
int strgethex(FILE* f, void* void_data, unsigned data_len);
|
||||
|
||||
/****************************************************************************/
|
||||
/* path */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue