1*75891f45Stb /* $OpenBSD: file.c,v 1.17 2021/12/15 19:22:44 tb Exp $ */
2fd6e2b5bSderaadt
3fe07e37bSderaadt /*-
4fe07e37bSderaadt * Copyright (c) 1999 James Howard and Dag-Erling Co�dan Sm�rgrav
5fe07e37bSderaadt * All rights reserved.
6fe07e37bSderaadt *
7fe07e37bSderaadt * Redistribution and use in source and binary forms, with or without
8fe07e37bSderaadt * modification, are permitted provided that the following conditions
9fe07e37bSderaadt * are met:
10fe07e37bSderaadt * 1. Redistributions of source code must retain the above copyright
11fe07e37bSderaadt * notice, this list of conditions and the following disclaimer.
12fe07e37bSderaadt * 2. Redistributions in binary form must reproduce the above copyright
13fe07e37bSderaadt * notice, this list of conditions and the following disclaimer in the
14fe07e37bSderaadt * documentation and/or other materials provided with the distribution.
15fe07e37bSderaadt *
16fe07e37bSderaadt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17fe07e37bSderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18fe07e37bSderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19fe07e37bSderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20fe07e37bSderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21fe07e37bSderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22fe07e37bSderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23fe07e37bSderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24fe07e37bSderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25fe07e37bSderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26fe07e37bSderaadt * SUCH DAMAGE.
27fe07e37bSderaadt */
28fe07e37bSderaadt
293a21e479Stedu #include <sys/stat.h>
30fe07e37bSderaadt #include <err.h>
313a21e479Stedu #include <errno.h>
323a21e479Stedu #include <fcntl.h>
33*75891f45Stb #include <limits.h>
34fe07e37bSderaadt #include <stdio.h>
35fe07e37bSderaadt #include <stdlib.h>
36*75891f45Stb #include <unistd.h>
37fe07e37bSderaadt #include <zlib.h>
38fe07e37bSderaadt
39fe07e37bSderaadt #include "grep.h"
40fe07e37bSderaadt
41b9fc9a72Sderaadt static char fname[PATH_MAX];
42fe07e37bSderaadt static char *lnbuf;
436ec3986fStedu static size_t lnbufsize;
44fe07e37bSderaadt
45fe07e37bSderaadt #define FILE_STDIO 0
46fe07e37bSderaadt #define FILE_MMAP 1
47fe07e37bSderaadt #define FILE_GZIP 2
48fe07e37bSderaadt
49fe07e37bSderaadt struct file {
50fe07e37bSderaadt int type;
5171d182b2Sotto int noseek;
52fe07e37bSderaadt FILE *f;
53fe07e37bSderaadt mmf_t *mmf;
5419739ec8Smillert gzFile gzf;
55fe07e37bSderaadt };
56fe07e37bSderaadt
5738d402d2Sderaadt #ifndef NOZ
58fe07e37bSderaadt static char *
gzfgetln(gzFile f,size_t * len)5919739ec8Smillert gzfgetln(gzFile f, size_t *len)
60fe07e37bSderaadt {
61fe07e37bSderaadt size_t n;
62fe07e37bSderaadt int c;
63fe07e37bSderaadt
64fe07e37bSderaadt for (n = 0; ; ++n) {
65fe07e37bSderaadt c = gzgetc(f);
66fe07e37bSderaadt if (c == -1) {
67fe07e37bSderaadt const char *gzerrstr;
68fe07e37bSderaadt int gzerr;
69fe07e37bSderaadt
70fe07e37bSderaadt if (gzeof(f))
71fe07e37bSderaadt break;
72fe07e37bSderaadt
73fe07e37bSderaadt gzerrstr = gzerror(f, &gzerr);
74fe07e37bSderaadt if (gzerr == Z_ERRNO)
75f91b5226Smillert err(2, "%s", fname);
76fe07e37bSderaadt else
77f91b5226Smillert errx(2, "%s: %s", fname, gzerrstr);
78fe07e37bSderaadt }
796ec3986fStedu if (n >= lnbufsize) {
806ec3986fStedu lnbufsize *= 2;
816ec3986fStedu lnbuf = grep_realloc(lnbuf, ++lnbufsize);
82fe07e37bSderaadt }
8325ef2405Scanacar if (c == '\n')
8425ef2405Scanacar break;
85fe07e37bSderaadt lnbuf[n] = c;
86fe07e37bSderaadt }
87fe07e37bSderaadt
88fe07e37bSderaadt if (gzeof(f) && n == 0)
89fe07e37bSderaadt return NULL;
90fe07e37bSderaadt *len = n;
91fe07e37bSderaadt return lnbuf;
92fe07e37bSderaadt }
9338d402d2Sderaadt #endif
94fe07e37bSderaadt
95fe07e37bSderaadt file_t *
grep_fdopen(int fd)963a21e479Stedu grep_fdopen(int fd)
97fe07e37bSderaadt {
98fe07e37bSderaadt file_t *f;
993a21e479Stedu struct stat sb;
100fe07e37bSderaadt
101c4dcc50fStedu if (fd == STDIN_FILENO)
10238d402d2Sderaadt snprintf(fname, sizeof fname, "(standard input)");
1033a21e479Stedu else if (fname[0] == '\0')
10438d402d2Sderaadt snprintf(fname, sizeof fname, "(fd %d)", fd);
105fe07e37bSderaadt
1063a21e479Stedu if (fstat(fd, &sb) == -1)
1073a21e479Stedu return NULL;
1083a21e479Stedu if (S_ISDIR(sb.st_mode)) {
1093a21e479Stedu errno = EISDIR;
1103a21e479Stedu return NULL;
1113a21e479Stedu }
1123a21e479Stedu
113fe07e37bSderaadt f = grep_malloc(sizeof *f);
114fe07e37bSderaadt
11538d402d2Sderaadt #ifndef NOZ
116fe07e37bSderaadt if (Zflag) {
117fe07e37bSderaadt f->type = FILE_GZIP;
11871d182b2Sotto f->noseek = lseek(fd, 0L, SEEK_SET) == -1;
1193a21e479Stedu if ((f->gzf = gzdopen(fd, "r")) != NULL)
120fe07e37bSderaadt return f;
121fe07e37bSderaadt }
1223a21e479Stedu #endif
1233a21e479Stedu f->noseek = isatty(fd);
1243a21e479Stedu #ifndef SMALL
1253a21e479Stedu /* try mmap first; if it fails, try stdio */
1263a21e479Stedu if (!f->noseek && (f->mmf = mmopen(fd, &sb)) != NULL) {
1273a21e479Stedu f->type = FILE_MMAP;
1283a21e479Stedu return f;
1293a21e479Stedu }
1303a21e479Stedu #endif
1313a21e479Stedu f->type = FILE_STDIO;
1323a21e479Stedu if ((f->f = fdopen(fd, "r")) != NULL)
1333a21e479Stedu return f;
134fe07e37bSderaadt
135fe07e37bSderaadt free(f);
136fe07e37bSderaadt return NULL;
137fe07e37bSderaadt }
138fe07e37bSderaadt
139fe07e37bSderaadt file_t *
grep_open(char * path)1403a21e479Stedu grep_open(char *path)
141fe07e37bSderaadt {
142fe07e37bSderaadt file_t *f;
1433a21e479Stedu int fd;
144fe07e37bSderaadt
14538d402d2Sderaadt snprintf(fname, sizeof fname, "%s", path);
146fe07e37bSderaadt
1473a21e479Stedu if ((fd = open(fname, O_RDONLY)) == -1)
148fe07e37bSderaadt return NULL;
1493a21e479Stedu
1503a21e479Stedu f = grep_fdopen(fd);
1513a21e479Stedu if (f == NULL)
1523a21e479Stedu close(fd);
1533a21e479Stedu return f;
154fe07e37bSderaadt }
155fe07e37bSderaadt
156fe07e37bSderaadt int
grep_bin_file(file_t * f)157fe07e37bSderaadt grep_bin_file(file_t *f)
158fe07e37bSderaadt {
15971d182b2Sotto if (f->noseek)
16071d182b2Sotto return 0;
16171d182b2Sotto
162fe07e37bSderaadt switch (f->type) {
163fe07e37bSderaadt case FILE_STDIO:
164fe07e37bSderaadt return bin_file(f->f);
1657fec5d18Snicm #ifndef SMALL
166fe07e37bSderaadt case FILE_MMAP:
167fe07e37bSderaadt return mmbin_file(f->mmf);
1687fec5d18Snicm #endif
16938d402d2Sderaadt #ifndef NOZ
170fe07e37bSderaadt case FILE_GZIP:
171fe07e37bSderaadt return gzbin_file(f->gzf);
17238d402d2Sderaadt #endif
173fe07e37bSderaadt default:
174fe07e37bSderaadt /* can't happen */
175f91b5226Smillert errx(2, "invalid file type");
176fe07e37bSderaadt }
177fe07e37bSderaadt }
178fe07e37bSderaadt
179fe07e37bSderaadt char *
grep_fgetln(file_t * f,size_t * l)180fe07e37bSderaadt grep_fgetln(file_t *f, size_t *l)
181fe07e37bSderaadt {
182fe07e37bSderaadt switch (f->type) {
183fe07e37bSderaadt case FILE_STDIO:
1846ec3986fStedu if ((*l = getline(&lnbuf, &lnbufsize, f->f)) == -1) {
1856ec3986fStedu if (ferror(f->f))
1866ec3986fStedu err(2, "%s: getline", fname);
1876ec3986fStedu else
1886ec3986fStedu return NULL;
1896ec3986fStedu }
1906ec3986fStedu return lnbuf;
1917fec5d18Snicm #ifndef SMALL
192fe07e37bSderaadt case FILE_MMAP:
193fe07e37bSderaadt return mmfgetln(f->mmf, l);
1947fec5d18Snicm #endif
19538d402d2Sderaadt #ifndef NOZ
196fe07e37bSderaadt case FILE_GZIP:
197fe07e37bSderaadt return gzfgetln(f->gzf, l);
19838d402d2Sderaadt #endif
199fe07e37bSderaadt default:
200fe07e37bSderaadt /* can't happen */
201f91b5226Smillert errx(2, "invalid file type");
202fe07e37bSderaadt }
203fe07e37bSderaadt }
204fe07e37bSderaadt
205fe07e37bSderaadt void
grep_close(file_t * f)206fe07e37bSderaadt grep_close(file_t *f)
207fe07e37bSderaadt {
208fe07e37bSderaadt switch (f->type) {
209fe07e37bSderaadt case FILE_STDIO:
210fe07e37bSderaadt fclose(f->f);
211fe07e37bSderaadt break;
2127fec5d18Snicm #ifndef SMALL
213fe07e37bSderaadt case FILE_MMAP:
214fe07e37bSderaadt mmclose(f->mmf);
215fe07e37bSderaadt break;
2167fec5d18Snicm #endif
21738d402d2Sderaadt #ifndef NOZ
218fe07e37bSderaadt case FILE_GZIP:
219fe07e37bSderaadt gzclose(f->gzf);
220fe07e37bSderaadt break;
22138d402d2Sderaadt #endif
222fe07e37bSderaadt default:
223fe07e37bSderaadt /* can't happen */
224f91b5226Smillert errx(2, "invalid file type");
225fe07e37bSderaadt }
2263faa8aa0Sotto free(f);
227fe07e37bSderaadt }
228