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