long uproc_io_getline(char **lineptr, size_t *n, uproc_io_stream *stream) { #if defined(_GNU_SOURCE) || _POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700 if (stream->type == UPROC_IO_STDIO) { ssize_t res = getline(lineptr, n, stream->s.fp); if (res == -1) { if (ferror(stream->s.fp)) { uproc_error(UPROC_ERRNO); } else { uproc_error(UPROC_SUCCESS); } } return res; } #endif char buf[4097]; size_t len, total = 0; do { if (!uproc_io_gets(buf, sizeof buf, stream)) { if (!total) { uproc_error(UPROC_SUCCESS); return -1; } break; } len = strlen(buf); if (!*lineptr || *n < total + len + 1) { void *tmp = realloc(*lineptr, total + len + 1); if (!tmp) { uproc_error(UPROC_ENOMEM); return -1; } *lineptr = tmp; *n = total + len + 1; } memcpy(*lineptr + total, buf, len + 1); total += len; } while (buf[len - 1] != '\n'); return total; }
static uproc_io_stream * io_open(const char *path, const char *mode, enum uproc_io_type type) { uproc_io_stream *stream = malloc(sizeof *stream); if (!stream) { uproc_error(UPROC_ENOMEM); return NULL; } stream->type = type; stream->stdstream = false; switch (stream->type) { case UPROC_IO_GZIP: #if HAVE_ZLIB_H if (!(stream->s.gz = gzopen(path, mode))) { /* gzopen sets errno to 0 if memory allocation failed */ if (!errno) { uproc_error(UPROC_ENOMEM); goto error; } goto error_errno; } (void) gzbuffer(stream->s.gz, GZIP_BUFSZ); break; #endif case UPROC_IO_STDIO: if (!(stream->s.fp = fopen(path, mode))) { goto error_errno; } break; default: goto error; } return stream; error_errno: uproc_error_msg(UPROC_ERRNO, "can't open \"%s\" with mode \"%s\"", path, mode); error: free(stream); return NULL; }
/* Reallocate the list data pointer to the given new capacity or at * least MIN_CAPACITY. Fails if memory can't be reallocated */ static int list_realloc(struct uproc_list_s *list, long n) { unsigned char *tmp; if (n < MIN_CAPACITY) { n = MIN_CAPACITY; } tmp = realloc(list->data, n * list->value_size); if (!tmp) { return uproc_error(UPROC_ENOMEM); } list->data = tmp; list->capacity = n; return 0; }
uproc_list *uproc_list_create(size_t value_size) { struct uproc_list_s *list; if (!value_size) { uproc_error_msg(UPROC_EINVAL, "value size must be non-zero"); return NULL; } list = malloc(sizeof *list); if (!list) { uproc_error(UPROC_ENOMEM); return NULL; } list->size = list->capacity = 0; list->value_size = value_size; list->data = NULL; if (list_realloc(list, 0)) { free(list); return NULL; } return list; }