config files are usually short enough that we can read in full. This allows the parser to parse in-memory config, for example from a blob. Signed-off-by: Nguyán ThÃi Ngác Duy <pclouds@xxxxxxxxx> --- config.c | 62 +++++++++++++++++++++++++++++++++++--------------------------- 1 files changed, 35 insertions(+), 27 deletions(-) diff --git a/config.c b/config.c index f138c34..c8bf46f 100644 --- a/config.c +++ b/config.c @@ -12,7 +12,8 @@ #define MAXNAME (256) -static FILE *config_file; +static char *config_file; +static size_t config_file_size, config_file_pos; static const char *config_file_name; static int config_linenr; static int config_file_eof; @@ -108,28 +109,26 @@ int git_config_parse_environment(void) { static int get_next_char(void) { - int c; - FILE *f; + size_t unread = config_file_size - config_file_pos; + + if (config_file == NULL) + return '\n'; - c = '\n'; - if ((f = config_file) != NULL) { - c = fgetc(f); + if (unread) { + char c = config_file[config_file_pos++]; if (c == '\r') { /* DOS like systems */ - c = fgetc(f); - if (c != '\n') { - ungetc(c, f); - c = '\r'; - } + if (unread > 1 && + config_file[config_file_pos] == '\n') + c = config_file[config_file_pos++]; } if (c == '\n') config_linenr++; - if (c == EOF) { - config_file_eof = 1; - c = '\n'; - } + return c; } - return c; + + config_file_eof = 1; + return '\n'; } static char *parse_value(void) @@ -786,19 +785,27 @@ int git_default_config(const char *var, const char *value, void *dummy) int git_config_from_file(config_fn_t fn, const char *filename, void *data) { - int ret; - FILE *f = fopen(filename, "r"); + struct stat st; + int ret = -1, fd; + + if (lstat(filename, &st)) + return -1; + fd = open(filename, O_RDONLY); + if (fd == -1) + return -1; - ret = -1; - if (f) { - config_file = f; + config_file = xmalloc(st.st_size); + if (read_in_full(fd, config_file, st.st_size) == st.st_size) { + config_file_pos = 0; + config_file_size = st.st_size; config_file_name = filename; config_linenr = 1; config_file_eof = 0; ret = git_parse_file(fn, data); - fclose(f); - config_file_name = NULL; } + close(fd); + free(config_file); + config_file_name = NULL; return ret; } @@ -921,7 +928,7 @@ static int store_aux(const char *key, const char *value, void *cb) return 1; } - store.offset[store.seen] = ftell(config_file); + store.offset[store.seen] = config_file_pos; store.seen++; } break; @@ -948,19 +955,19 @@ static int store_aux(const char *key, const char *value, void *cb) * Do not increment matches: this is no match, but we * just made sure we are in the desired section. */ - store.offset[store.seen] = ftell(config_file); + store.offset[store.seen] = config_file_pos; /* fallthru */ case SECTION_END_SEEN: case START: if (matches(key, value)) { - store.offset[store.seen] = ftell(config_file); + store.offset[store.seen] = config_file_pos; store.state = KEY_SEEN; store.seen++; } else { if (strrchr(key, '.') - key == store.baselen && !strncmp(key, store.key, store.baselen)) { store.state = SECTION_SEEN; - store.offset[store.seen] = ftell(config_file); + store.offset[store.seen] = config_file_pos; } } } @@ -1380,6 +1387,7 @@ int git_config_rename_section(const char *old_name, const char *new_name) { int ret = 0, remove = 0; char *config_filename; + FILE *config_file; struct lock_file *lock = xcalloc(sizeof(struct lock_file), 1); int out_fd; char buf[1024]; -- 1.7.3.3.476.g893a9 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html