xref: /freebsd/contrib/libarchive/unzip/la_getline.c (revision bd66c1b43e33540205dbc1187c2f2a15c58b57ba)
1 /*	$NetBSD: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp $	*/
2 
3 /*-
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2011 The NetBSD Foundation, Inc.
7  * All rights reserved.
8  */
9 
10 #include "bsdunzip_platform.h"
11 #ifndef HAVE_GETLINE
12 
13 #ifdef HAVE_STDLIB_H
14 #include <stdlib.h>
15 #endif
16 #ifdef HAVE_STDIO_H
17 #include <stdio.h>
18 #endif
19 #ifdef HAVE_UNISTD_H
20 #include <unistd.h>
21 #endif
22 #ifdef HAVE_ERRNO_H
23 #include <errno.h>
24 #endif
25 #ifdef HAVE_STRING_H
26 #include <string.h>
27 #endif
28 
29 static ssize_t
la_getdelim(char ** buf,size_t * bufsiz,int delimiter,FILE * fp)30 la_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
31 {
32 	char *ptr, *eptr;
33 
34 
35 	if (*buf == NULL || *bufsiz == 0) {
36 		*bufsiz = BUFSIZ;
37 		if ((*buf = malloc(*bufsiz)) == NULL)
38 			return -1;
39 	}
40 
41 	for (ptr = *buf, eptr = *buf + *bufsiz;;) {
42 		int c = fgetc(fp);
43 		if (c == -1) {
44 			if (feof(fp)) {
45 				ssize_t diff = (ssize_t)(ptr - *buf);
46 				if (diff != 0) {
47 					*ptr = '\0';
48 					return diff;
49 				}
50 			}
51 			return -1;
52 		}
53 		*ptr++ = c;
54 		if (c == delimiter) {
55 			*ptr = '\0';
56 			return ptr - *buf;
57 		}
58 		if (ptr + 2 >= eptr) {
59 			char *nbuf;
60 			size_t nbufsiz = *bufsiz * 2;
61 			ssize_t d = ptr - *buf;
62 			if ((nbuf = realloc(*buf, nbufsiz)) == NULL)
63 				return -1;
64 			*buf = nbuf;
65 			*bufsiz = nbufsiz;
66 			eptr = nbuf + nbufsiz;
67 			ptr = nbuf + d;
68 		}
69 	}
70 }
71 
72 ssize_t
getline(char ** buf,size_t * bufsiz,FILE * fp)73 getline(char **buf, size_t *bufsiz, FILE *fp)
74 {
75 	return la_getdelim(buf, bufsiz, '\n', fp);
76 }
77 #endif
78