xref: /openbsd/usr.bin/grep/file.c (revision db3296cf)
1 /*	$OpenBSD: file.c,v 1.4 2003/07/10 17:02:48 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 <sys/param.h>
30 
31 #include <err.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <zlib.h>
35 
36 #include "grep.h"
37 
38 static char	 fname[MAXPATHLEN];
39 static char	*lnbuf;
40 static size_t	 lnbuflen;
41 
42 #define FILE_STDIO	0
43 #define FILE_MMAP	1
44 #define FILE_GZIP	2
45 
46 struct file {
47 	int	 type;
48 	FILE	*f;
49 	mmf_t	*mmf;
50 	gzFile	*gzf;
51 };
52 
53 #ifndef NOZ
54 static char *
55 gzfgetln(gzFile *f, size_t *len)
56 {
57 	size_t		n;
58 	int		c;
59 
60 	for (n = 0; ; ++n) {
61 		c = gzgetc(f);
62 		if (c == -1) {
63 			const char *gzerrstr;
64 			int gzerr;
65 
66 			if (gzeof(f))
67 				break;
68 
69 			gzerrstr = gzerror(f, &gzerr);
70 			if (gzerr == Z_ERRNO)
71 				err(2, "%s", fname);
72 			else
73 				errx(2, "%s: %s", fname, gzerrstr);
74 		}
75 		if (c == '\n')
76 			break;
77 		if (n >= lnbuflen) {
78 			lnbuflen *= 2;
79 			lnbuf = grep_realloc(lnbuf, ++lnbuflen);
80 		}
81 		lnbuf[n] = c;
82 	}
83 
84 	if (gzeof(f) && n == 0)
85 		return NULL;
86 	*len = n;
87 	return lnbuf;
88 }
89 #endif
90 
91 file_t *
92 grep_fdopen(int fd, char *mode)
93 {
94 	file_t *f;
95 
96 	if (fd == 0)
97 		snprintf(fname, sizeof fname, "(standard input)");
98 	else
99 		snprintf(fname, sizeof fname, "(fd %d)", fd);
100 
101 	f = grep_malloc(sizeof *f);
102 
103 #ifndef NOZ
104 	if (Zflag) {
105 		f->type = FILE_GZIP;
106 		if ((f->gzf = gzdopen(fd, mode)) != NULL)
107 			return f;
108 	} else
109 #endif
110 	{
111 		f->type = FILE_STDIO;
112 		if ((f->f = fdopen(fd, mode)) != NULL)
113 			return f;
114 	}
115 
116 	free(f);
117 	return NULL;
118 }
119 
120 file_t *
121 grep_open(char *path, char *mode)
122 {
123 	file_t *f;
124 
125 	snprintf(fname, sizeof fname, "%s", path);
126 
127 	f = grep_malloc(sizeof *f);
128 
129 #ifndef NOZ
130 	if (Zflag) {
131 		f->type = FILE_GZIP;
132 		if ((f->gzf = gzopen(fname, mode)) != NULL)
133 			return f;
134 	} else
135 #endif
136 	{
137 		/* try mmap first; if it fails, try stdio */
138 		if ((f->mmf = mmopen(fname, mode)) != NULL) {
139 			f->type = FILE_MMAP;
140 			return f;
141 		}
142 		f->type = FILE_STDIO;
143 		if ((f->f = fopen(path, mode)) != NULL)
144 			return f;
145 	}
146 
147 	free(f);
148 	return NULL;
149 }
150 
151 int
152 grep_bin_file(file_t *f)
153 {
154 	switch (f->type) {
155 	case FILE_STDIO:
156 		return bin_file(f->f);
157 	case FILE_MMAP:
158 		return mmbin_file(f->mmf);
159 #ifndef NOZ
160 	case FILE_GZIP:
161 		return gzbin_file(f->gzf);
162 #endif
163 	default:
164 		/* can't happen */
165 		errx(2, "invalid file type");
166 	}
167 }
168 
169 long
170 grep_tell(file_t *f)
171 {
172 	switch (f->type) {
173 	case FILE_STDIO:
174 		return ftell(f->f);
175 	case FILE_MMAP:
176 		return mmtell(f->mmf);
177 #ifndef NOZ
178 	case FILE_GZIP:
179 		return gztell(f->gzf);
180 #endif
181 	default:
182 		/* can't happen */
183 		errx(2, "invalid file type");
184 	}
185 }
186 
187 char *
188 grep_fgetln(file_t *f, size_t *l)
189 {
190 	switch (f->type) {
191 	case FILE_STDIO:
192 		return fgetln(f->f, l);
193 	case FILE_MMAP:
194 		return mmfgetln(f->mmf, l);
195 #ifndef NOZ
196 	case FILE_GZIP:
197 		return gzfgetln(f->gzf, l);
198 #endif
199 	default:
200 		/* can't happen */
201 		errx(2, "invalid file type");
202 	}
203 }
204 
205 void
206 grep_close(file_t *f)
207 {
208 	switch (f->type) {
209 	case FILE_STDIO:
210 		fclose(f->f);
211 		break;
212 	case FILE_MMAP:
213 		mmclose(f->mmf);
214 		break;
215 #ifndef NOZ
216 	case FILE_GZIP:
217 		gzclose(f->gzf);
218 		break;
219 #endif
220 	default:
221 		/* can't happen */
222 		errx(2, "invalid file type");
223 	}
224 }
225