/* * pool_btt_lseek -- (internal) perform lseek in BTT file mode */ static inline off_t pool_btt_lseek(struct pool_data *pool, off_t offset, int whence) { off_t result; if ((result = util_lseek(pool->set_file->fd, offset, whence)) == -1) ERR("!lseek"); return result; }
/* * util_poolset_parse -- (internal) parse pool set config file * * Returns 1 if the file is a valid pool set config file, 0 if the file * is not a pool set header, and -1 in case of any error. * * XXX: use memory mapped file */ int util_poolset_parse(const char *path, int fd, struct pool_set **setp) { LOG(3, "path %s fd %d setp %p", path, fd, setp); struct pool_set *set; enum parser_codes result; char line[PARSER_MAX_LINE]; char *s; char *ppath; char *pool_desc; char *node_addr; char *cp; size_t psize; FILE *fs; if (util_lseek(fd, 0, SEEK_SET) != 0) { ERR("!lseek %d", fd); return -1; } fd = dup(fd); if (fd < 0) { ERR("!dup"); return -1; } /* associate a stream with the file descriptor */ if ((fs = fdopen(fd, "r")) == NULL) { ERR("!fdopen %d", fd); close(fd); return -1; } unsigned nlines = 0; unsigned nparts = 0; /* number of parts in current replica */ /* read the first line */ s = fgets(line, PARSER_MAX_LINE, fs); nlines++; set = Zalloc(sizeof(struct pool_set)); if (set == NULL) { ERR("!Malloc for pool set"); goto err; } /* check also if the last character is '\n' */ if (s && strncmp(line, POOLSET_HDR_SIG, POOLSET_HDR_SIG_LEN) == 0 && line[POOLSET_HDR_SIG_LEN] == '\n') { /* 'PMEMPOOLSET' signature detected */ LOG(10, "PMEMPOOLSET"); int ret = util_parse_add_replica(&set); if (ret != 0) goto err; nparts = 0; result = PARSER_CONTINUE; } else { result = PARSER_PMEMPOOLSET; } while (result == PARSER_CONTINUE) { /* read next line */ s = fgets(line, PARSER_MAX_LINE, fs); nlines++; if (s) { /* chop off newline and comments */ if ((cp = strchr(line, '\n')) != NULL) *cp = '\0'; if (cp != s && (cp = strchr(line, '#')) != NULL) *cp = '\0'; /* skip comments and blank lines */ if (cp == s) continue; } if (!s) { if (nparts >= 1) { result = PARSER_FORMAT_OK; } else { if (set->nreplicas == 1) result = PARSER_SET_NO_PARTS; else result = PARSER_REP_NO_PARTS; } } else if (strncmp(line, POOLSET_REPLICA_SIG, POOLSET_REPLICA_SIG_LEN) == 0) { if (line[POOLSET_REPLICA_SIG_LEN] != '\0') { /* something more than 'REPLICA' */ if (!isblank(line[POOLSET_REPLICA_SIG_LEN])) { result = PARSER_REPLICA; continue; } /* check if it is a remote replica */ result = parser_read_replica( line + POOLSET_REPLICA_SIG_LEN, &node_addr, &pool_desc); if (result == PARSER_CONTINUE) { /* remote REPLICA */ LOG(10, "REMOTE REPLICA " "node address '%s' " "pool set descriptor '%s'", node_addr, pool_desc); if (util_parse_add_remote_replica(&set, node_addr, pool_desc)) goto err; } } else if (nparts >= 1) { /* 'REPLICA' signature detected */ LOG(10, "REPLICA"); int ret = util_parse_add_replica(&set); if (ret != 0) goto err; nparts = 0; result = PARSER_CONTINUE; } else { if (set->nreplicas == 1) result = PARSER_SET_NO_PARTS; else result = PARSER_REP_NO_PARTS; } } else { /* read size and path */ result = parser_read_line(line, &psize, &ppath); if (result == PARSER_CONTINUE) { /* add a new pool's part to the list */ int ret = util_parse_add_part(set, ppath, psize); if (ret != 0) goto err; nparts++; } } } if (result == PARSER_FORMAT_OK) { LOG(4, "set file format correct (%s)", path); (void) fclose(fs); util_poolset_set_size(set); *setp = set; return 0; } else { ERR("%s [%s:%d]", path, parser_errstr[result], nlines); errno = EINVAL; } err: (void) fclose(fs); if (set) util_poolset_free(set); return -1; }