xref: /openbsd-src/usr.bin/grep/file.c (revision 897fc685943471cf985a0fe38ba076ea6fe74fa5)
1 /*	$OpenBSD: file.c,v 1.13 2015/03/16 13:27:59 millert Exp $	*/
2 
3 /*-
4  * Copyright (c) 1999 James Howard and Dag-Erling Co�dan Sm�rgrav
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <err.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <zlib.h>
33 
34 #include "grep.h"
35 
36 static char	 fname[PATH_MAX];
37 #ifndef NOZ
38 static char	*lnbuf;
39 static size_t	 lnbuflen;
40 #endif
41 
42 #define FILE_STDIO	0
43 #define FILE_MMAP	1
44 #define FILE_GZIP	2
45 
46 struct file {
47 	int	 type;
48 	int	 noseek;
49 	FILE	*f;
50 	mmf_t	*mmf;
51 	gzFile	*gzf;
52 };
53 
54 #ifndef NOZ
55 static char *
56 gzfgetln(gzFile *f, size_t *len)
57 {
58 	size_t		n;
59 	int		c;
60 
61 	for (n = 0; ; ++n) {
62 		c = gzgetc(f);
63 		if (c == -1) {
64 			const char *gzerrstr;
65 			int gzerr;
66 
67 			if (gzeof(f))
68 				break;
69 
70 			gzerrstr = gzerror(f, &gzerr);
71 			if (gzerr == Z_ERRNO)
72 				err(2, "%s", fname);
73 			else
74 				errx(2, "%s: %s", fname, gzerrstr);
75 		}
76 		if (n >= lnbuflen) {
77 			lnbuflen *= 2;
78 			lnbuf = grep_realloc(lnbuf, ++lnbuflen);
79 		}
80 		if (c == '\n')
81 			break;
82 		lnbuf[n] = c;
83 	}
84 
85 	if (gzeof(f) && n == 0)
86 		return NULL;
87 	*len = n;
88 	return lnbuf;
89 }
90 #endif
91 
92 file_t *
93 grep_fdopen(int fd, char *mode)
94 {
95 	file_t *f;
96 
97 	if (fd == STDIN_FILENO)
98 		snprintf(fname, sizeof fname, "(standard input)");
99 	else
100 		snprintf(fname, sizeof fname, "(fd %d)", fd);
101 
102 	f = grep_malloc(sizeof *f);
103 
104 #ifndef NOZ
105 	if (Zflag) {
106 		f->type = FILE_GZIP;
107 		f->noseek = lseek(fd, 0L, SEEK_SET) == -1;
108 		if ((f->gzf = gzdopen(fd, mode)) != NULL)
109 			return f;
110 	} else
111 #endif
112 	{
113 		f->type = FILE_STDIO;
114 		f->noseek = isatty(fd);
115 		if ((f->f = fdopen(fd, mode)) != NULL)
116 			return f;
117 	}
118 
119 	free(f);
120 	return NULL;
121 }
122 
123 file_t *
124 grep_open(char *path, char *mode)
125 {
126 	file_t *f;
127 
128 	snprintf(fname, sizeof fname, "%s", path);
129 
130 	f = grep_malloc(sizeof *f);
131 	f->noseek = 0;
132 
133 #ifndef NOZ
134 	if (Zflag) {
135 		f->type = FILE_GZIP;
136 		if ((f->gzf = gzopen(fname, mode)) != NULL)
137 			return f;
138 	} else
139 #endif
140 	{
141 #ifndef SMALL
142 		/* try mmap first; if it fails, try stdio */
143 		if ((f->mmf = mmopen(fname, mode)) != NULL) {
144 			f->type = FILE_MMAP;
145 			return f;
146 		}
147 #endif
148 		f->type = FILE_STDIO;
149 		if ((f->f = fopen(path, mode)) != NULL)
150 			return f;
151 	}
152 
153 	free(f);
154 	return NULL;
155 }
156 
157 int
158 grep_bin_file(file_t *f)
159 {
160 	if (f->noseek)
161 		return 0;
162 
163 	switch (f->type) {
164 	case FILE_STDIO:
165 		return bin_file(f->f);
166 #ifndef SMALL
167 	case FILE_MMAP:
168 		return mmbin_file(f->mmf);
169 #endif
170 #ifndef NOZ
171 	case FILE_GZIP:
172 		return gzbin_file(f->gzf);
173 #endif
174 	default:
175 		/* can't happen */
176 		errx(2, "invalid file type");
177 	}
178 }
179 
180 char *
181 grep_fgetln(file_t *f, size_t *l)
182 {
183 	switch (f->type) {
184 	case FILE_STDIO:
185 		return fgetln(f->f, l);
186 #ifndef SMALL
187 	case FILE_MMAP:
188 		return mmfgetln(f->mmf, l);
189 #endif
190 #ifndef NOZ
191 	case FILE_GZIP:
192 		return gzfgetln(f->gzf, l);
193 #endif
194 	default:
195 		/* can't happen */
196 		errx(2, "invalid file type");
197 	}
198 }
199 
200 void
201 grep_close(file_t *f)
202 {
203 	switch (f->type) {
204 	case FILE_STDIO:
205 		fclose(f->f);
206 		break;
207 #ifndef SMALL
208 	case FILE_MMAP:
209 		mmclose(f->mmf);
210 		break;
211 #endif
212 #ifndef NOZ
213 	case FILE_GZIP:
214 		gzclose(f->gzf);
215 		break;
216 #endif
217 	default:
218 		/* can't happen */
219 		errx(2, "invalid file type");
220 	}
221 	free(f);
222 }
223