ssize_t getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) { ssize_t result; size_t cur_len = 0; if (lineptr == NULL || n == NULL || fp == NULL) { errno = EINVAL; return -1; } flockfile (fp); if (*lineptr == NULL || *n == 0) { char *new_lineptr; *n = 120; new_lineptr = (char *) realloc (*lineptr, *n); if (new_lineptr == NULL) { result = -1; goto unlock_return; } *lineptr = new_lineptr; } for (;;) { int i; i = getc_maybe_unlocked (fp); if (i == EOF) { result = -1; break; } /* Make enough space for len+1 (for final NUL) bytes. */ if (cur_len + 1 >= *n) { size_t needed_max = SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; size_t needed = 2 * *n + 1; /* Be generous. */ char *new_lineptr; if (needed_max < needed) needed = needed_max; if (cur_len + 1 >= needed) { result = -1; errno = EOVERFLOW; goto unlock_return; } new_lineptr = (char *) realloc (*lineptr, needed); if (new_lineptr == NULL) { result = -1; goto unlock_return; } *lineptr = new_lineptr; *n = needed; } (*lineptr)[cur_len] = i; cur_len++; if (i == delimiter) break; } (*lineptr)[cur_len] = '\0'; result = cur_len ? cur_len : result; unlock_return: funlockfile (fp); /* doesn't set errno */ return result; }
/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and NUL-terminate it). *LINEPTR is a pointer returned from malloc (or NULL), pointing to *N characters of space. It is realloc'ed as necessary. Returns the number of characters read (not including the null terminator), or -1 on error or EOF. */ ssize_t getdelim(char **lineptr, size_t *n, int delimiter, FILE *fp) { ssize_t result = 0UL; size_t cur_len = 0UL; if ((lineptr == NULL) || (n == NULL) || (fp == NULL)) { errno = EINVAL; return -1; } flockfile(fp); if ((*lineptr == NULL) || (*n == 0)) { char *new_lineptr; *n = 120; new_lineptr = (char *)realloc(*lineptr, *n); if (new_lineptr == NULL) { result = -1L; goto unlock_return; } *lineptr = new_lineptr; } for (;;) { int i; i = getc_maybe_unlocked(fp); if (i == EOF) { result = -1L; break; } /* Make enough space for len+1 (for final NUL) bytes: */ if ((cur_len + 1) >= *n) { size_t needed_max = ((SSIZE_MAX < SIZE_MAX) ? ((size_t)SSIZE_MAX + 1L) : SIZE_MAX); size_t needed = ((2 * *n) + 1); /* Be generous. */ char *new_lineptr; if (needed_max < needed) { needed = needed_max; } if ((cur_len + 1) >= needed) { result = -1L; errno = EOVERFLOW; goto unlock_return; } new_lineptr = (char *)realloc(*lineptr, needed); if (new_lineptr == NULL) { result = -1L; goto unlock_return; } *lineptr = new_lineptr; *n = needed; } (*lineptr)[cur_len] = (char)i; cur_len++; if (i == delimiter) { break; } } (*lineptr)[cur_len] = '\0'; result = (ssize_t)(cur_len ? cur_len : (size_t)result); unlock_return: funlockfile(fp); /* does NOT set errno */ return result; }