Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / usr.bin / grep / file.c
blob0650a5ea9f2e2c0561055008677791bbe1e10333
1 /* $NetBSD: file.c,v 1.2 2006/05/15 21:12:21 rillig Exp $ */
3 /*-
4 * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
5 * All rights reserved.
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.
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.
30 #include <sys/cdefs.h>
31 #ifndef lint
32 __RCSID("$NetBSD: file.c,v 1.2 2006/05/15 21:12:21 rillig Exp $");
33 #endif /* not lint */
35 #include <sys/param.h>
37 #include <zlib.h>
38 #include <err.h>
39 #include <stdio.h>
40 #include <stdlib.h>
42 #include "grep.h"
44 static char fname[MAXPATHLEN];
45 static char *lnbuf;
46 static size_t lnbuflen;
48 #define FILE_STDIO 0
49 #define FILE_MMAP 1
50 #define FILE_GZIP 2
52 struct file {
53 int type;
54 FILE *f;
55 mmf_t *mmf;
56 gzFile *gzf;
59 static char *
60 grepfgetln(FILE *f, size_t *len)
62 size_t n;
63 int c;
65 for (n = 0; ; ++n) {
66 c = getc(f);
67 if (c == EOF) {
68 if (feof(f))
69 break;
70 err(2, "%s", fname);
71 /* ERROR */
74 if (c == line_endchar)
75 break;
76 if (n >= lnbuflen) {
77 lnbuflen *= 2;
78 lnbuf = grep_realloc(lnbuf, ++lnbuflen);
80 lnbuf[n] = c;
82 if (feof(f) && n == 0)
83 return NULL;
84 *len = n;
85 return lnbuf;
88 static char *
89 gzfgetln(gzFile *f, size_t *len)
91 size_t n;
92 int c;
94 for (n = 0; ; ++n) {
95 c = gzgetc(f);
96 if (c == -1) {
97 const char *gzerrstr;
98 int gzerr;
100 if (gzeof(f))
101 break;
103 gzerrstr = gzerror(f, &gzerr);
104 if (gzerr == Z_ERRNO)
105 err(2, "%s", fname);
106 else
107 errx(2, "%s: %s", fname, gzerrstr);
109 if (c == line_endchar)
110 break;
111 if (n >= lnbuflen) {
112 lnbuflen *= 2;
113 lnbuf = grep_realloc(lnbuf, ++lnbuflen);
115 lnbuf[n] = c;
118 if (gzeof(f) && n == 0)
119 return NULL;
120 *len = n;
121 return lnbuf;
124 file_t *
125 grep_fdopen(int fd, const char *mode)
127 file_t *f;
129 if (fd == 0)
130 sprintf(fname, "(standard input)");
131 else
132 sprintf(fname, "(fd %d)", fd);
134 f = grep_malloc(sizeof *f);
136 if (zgrep) {
137 f->type = FILE_GZIP;
138 if ((f->gzf = gzdopen(fd, mode)) != NULL)
139 return f;
140 } else {
141 f->type = FILE_STDIO;
142 if ((f->f = fdopen(fd, mode)) != NULL)
143 return f;
146 free(f);
147 return NULL;
150 file_t *
151 grep_open(const char *path, const char *mode)
153 file_t *f;
155 snprintf(fname, MAXPATHLEN, "%s", path);
157 f = grep_malloc(sizeof *f);
159 if (zgrep) {
160 f->type = FILE_GZIP;
161 if ((f->gzf = gzopen(fname, mode)) != NULL)
162 return f;
163 } else {
164 /* try mmap first; if it fails, try stdio */
165 if ((f->mmf = mmopen(fname, mode)) != NULL) {
166 f->type = FILE_MMAP;
167 return f;
169 f->type = FILE_STDIO;
170 if ((f->f = fopen(path, mode)) != NULL)
171 return f;
174 free(f);
175 return NULL;
179 grep_bin_file(file_t *f)
181 switch (f->type) {
182 case FILE_STDIO:
183 return bin_file(f->f);
184 case FILE_MMAP:
185 return mmbin_file(f->mmf);
186 case FILE_GZIP:
187 return gzbin_file(f->gzf);
188 default:
189 /* can't happen */
190 errx(2, "invalid file type");
194 char *
195 grep_fgetln(file_t *f, size_t *l)
197 switch (f->type) {
198 case FILE_STDIO:
199 if (line_endchar == '\n')
200 return fgetln(f->f, l);
201 else
202 return grepfgetln(f->f, l);
203 case FILE_MMAP:
204 return mmfgetln(f->mmf, l);
205 case FILE_GZIP:
206 return gzfgetln(f->gzf, l);
207 default:
208 /* can't happen */
209 errx(2, "invalid file type");
213 void
214 grep_close(file_t *f)
216 switch (f->type) {
217 case FILE_STDIO:
218 fclose(f->f);
219 break;
220 case FILE_MMAP:
221 mmclose(f->mmf);
222 break;
223 case FILE_GZIP:
224 gzclose(f->gzf);
225 break;
226 default:
227 /* can't happen */
228 errx(2, "invalid file type");