xref: /freebsd-src/contrib/libarchive/unzip/la_getline.c (revision bd66c1b43e33540205dbc1187c2f2a15c58b57ba)
164884e0dSMartin Matuska /*	$NetBSD: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp $	*/
264884e0dSMartin Matuska 
364884e0dSMartin Matuska /*-
4*bd66c1b4SMartin Matuska  * SPDX-License-Identifier: BSD-2-Clause
5*bd66c1b4SMartin Matuska  *
664884e0dSMartin Matuska  * Copyright (c) 2011 The NetBSD Foundation, Inc.
764884e0dSMartin Matuska  * All rights reserved.
864884e0dSMartin Matuska  */
964884e0dSMartin Matuska 
1064884e0dSMartin Matuska #include "bsdunzip_platform.h"
1164884e0dSMartin Matuska #ifndef HAVE_GETLINE
1264884e0dSMartin Matuska 
1364884e0dSMartin Matuska #ifdef HAVE_STDLIB_H
1464884e0dSMartin Matuska #include <stdlib.h>
1564884e0dSMartin Matuska #endif
1664884e0dSMartin Matuska #ifdef HAVE_STDIO_H
1764884e0dSMartin Matuska #include <stdio.h>
1864884e0dSMartin Matuska #endif
1964884e0dSMartin Matuska #ifdef HAVE_UNISTD_H
2064884e0dSMartin Matuska #include <unistd.h>
2164884e0dSMartin Matuska #endif
2264884e0dSMartin Matuska #ifdef HAVE_ERRNO_H
2364884e0dSMartin Matuska #include <errno.h>
2464884e0dSMartin Matuska #endif
2564884e0dSMartin Matuska #ifdef HAVE_STRING_H
2664884e0dSMartin Matuska #include <string.h>
2764884e0dSMartin Matuska #endif
2864884e0dSMartin Matuska 
2964884e0dSMartin Matuska static ssize_t
3064884e0dSMartin Matuska la_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
3164884e0dSMartin Matuska {
3264884e0dSMartin Matuska 	char *ptr, *eptr;
3364884e0dSMartin Matuska 
3464884e0dSMartin Matuska 
3564884e0dSMartin Matuska 	if (*buf == NULL || *bufsiz == 0) {
3664884e0dSMartin Matuska 		*bufsiz = BUFSIZ;
3764884e0dSMartin Matuska 		if ((*buf = malloc(*bufsiz)) == NULL)
3864884e0dSMartin Matuska 			return -1;
3964884e0dSMartin Matuska 	}
4064884e0dSMartin Matuska 
4164884e0dSMartin Matuska 	for (ptr = *buf, eptr = *buf + *bufsiz;;) {
4264884e0dSMartin Matuska 		int c = fgetc(fp);
4364884e0dSMartin Matuska 		if (c == -1) {
4464884e0dSMartin Matuska 			if (feof(fp)) {
4564884e0dSMartin Matuska 				ssize_t diff = (ssize_t)(ptr - *buf);
4664884e0dSMartin Matuska 				if (diff != 0) {
4764884e0dSMartin Matuska 					*ptr = '\0';
4864884e0dSMartin Matuska 					return diff;
4964884e0dSMartin Matuska 				}
5064884e0dSMartin Matuska 			}
5164884e0dSMartin Matuska 			return -1;
5264884e0dSMartin Matuska 		}
5364884e0dSMartin Matuska 		*ptr++ = c;
5464884e0dSMartin Matuska 		if (c == delimiter) {
5564884e0dSMartin Matuska 			*ptr = '\0';
5664884e0dSMartin Matuska 			return ptr - *buf;
5764884e0dSMartin Matuska 		}
5864884e0dSMartin Matuska 		if (ptr + 2 >= eptr) {
5964884e0dSMartin Matuska 			char *nbuf;
6064884e0dSMartin Matuska 			size_t nbufsiz = *bufsiz * 2;
6164884e0dSMartin Matuska 			ssize_t d = ptr - *buf;
6264884e0dSMartin Matuska 			if ((nbuf = realloc(*buf, nbufsiz)) == NULL)
6364884e0dSMartin Matuska 				return -1;
6464884e0dSMartin Matuska 			*buf = nbuf;
6564884e0dSMartin Matuska 			*bufsiz = nbufsiz;
6664884e0dSMartin Matuska 			eptr = nbuf + nbufsiz;
6764884e0dSMartin Matuska 			ptr = nbuf + d;
6864884e0dSMartin Matuska 		}
6964884e0dSMartin Matuska 	}
7064884e0dSMartin Matuska }
7164884e0dSMartin Matuska 
7264884e0dSMartin Matuska ssize_t
7364884e0dSMartin Matuska getline(char **buf, size_t *bufsiz, FILE *fp)
7464884e0dSMartin Matuska {
7564884e0dSMartin Matuska 	return la_getdelim(buf, bufsiz, '\n', fp);
7664884e0dSMartin Matuska }
7764884e0dSMartin Matuska #endif
78