1 /* $OpenBSD: file.c,v 1.10 2008/10/16 22:56:32 deraadt 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 #ifndef NOZ 40 static char *lnbuf; 41 static size_t lnbuflen; 42 #endif 43 44 #define FILE_STDIO 0 45 #define FILE_MMAP 1 46 #define FILE_GZIP 2 47 48 struct file { 49 int type; 50 int noseek; 51 FILE *f; 52 mmf_t *mmf; 53 gzFile *gzf; 54 }; 55 56 #ifndef NOZ 57 static char * 58 gzfgetln(gzFile *f, size_t *len) 59 { 60 size_t n; 61 int c; 62 63 for (n = 0; ; ++n) { 64 c = gzgetc(f); 65 if (c == -1) { 66 const char *gzerrstr; 67 int gzerr; 68 69 if (gzeof(f)) 70 break; 71 72 gzerrstr = gzerror(f, &gzerr); 73 if (gzerr == Z_ERRNO) 74 err(2, "%s", fname); 75 else 76 errx(2, "%s: %s", fname, gzerrstr); 77 } 78 if (n >= lnbuflen) { 79 lnbuflen *= 2; 80 lnbuf = grep_realloc(lnbuf, ++lnbuflen); 81 } 82 if (c == '\n') 83 break; 84 lnbuf[n] = c; 85 } 86 87 if (gzeof(f) && n == 0) 88 return NULL; 89 *len = n; 90 return lnbuf; 91 } 92 #endif 93 94 file_t * 95 grep_fdopen(int fd, char *mode) 96 { 97 file_t *f; 98 99 if (fd == STDIN_FILENO) 100 snprintf(fname, sizeof fname, "(standard input)"); 101 else 102 snprintf(fname, sizeof fname, "(fd %d)", fd); 103 104 f = grep_malloc(sizeof *f); 105 106 #ifndef NOZ 107 if (Zflag) { 108 f->type = FILE_GZIP; 109 f->noseek = lseek(fd, 0L, SEEK_SET) == -1; 110 if ((f->gzf = gzdopen(fd, mode)) != NULL) 111 return f; 112 } else 113 #endif 114 { 115 f->type = FILE_STDIO; 116 f->noseek = isatty(fd); 117 if ((f->f = fdopen(fd, mode)) != NULL) 118 return f; 119 } 120 121 free(f); 122 return NULL; 123 } 124 125 file_t * 126 grep_open(char *path, char *mode) 127 { 128 file_t *f; 129 130 snprintf(fname, sizeof fname, "%s", path); 131 132 f = grep_malloc(sizeof *f); 133 f->noseek = 0; 134 135 #ifndef NOZ 136 if (Zflag) { 137 f->type = FILE_GZIP; 138 if ((f->gzf = gzopen(fname, mode)) != NULL) 139 return f; 140 } else 141 #endif 142 { 143 /* try mmap first; if it fails, try stdio */ 144 if ((f->mmf = mmopen(fname, mode)) != NULL) { 145 f->type = FILE_MMAP; 146 return f; 147 } 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 case FILE_MMAP: 167 return mmbin_file(f->mmf); 168 #ifndef NOZ 169 case FILE_GZIP: 170 return gzbin_file(f->gzf); 171 #endif 172 default: 173 /* can't happen */ 174 errx(2, "invalid file type"); 175 } 176 } 177 178 char * 179 grep_fgetln(file_t *f, size_t *l) 180 { 181 switch (f->type) { 182 case FILE_STDIO: 183 return fgetln(f->f, l); 184 case FILE_MMAP: 185 return mmfgetln(f->mmf, l); 186 #ifndef NOZ 187 case FILE_GZIP: 188 return gzfgetln(f->gzf, l); 189 #endif 190 default: 191 /* can't happen */ 192 errx(2, "invalid file type"); 193 } 194 } 195 196 void 197 grep_close(file_t *f) 198 { 199 switch (f->type) { 200 case FILE_STDIO: 201 fclose(f->f); 202 break; 203 case FILE_MMAP: 204 mmclose(f->mmf); 205 break; 206 #ifndef NOZ 207 case FILE_GZIP: 208 gzclose(f->gzf); 209 break; 210 #endif 211 default: 212 /* can't happen */ 213 errx(2, "invalid file type"); 214 } 215 free(f); 216 } 217