1 /* $OpenBSD: file.c,v 1.9 2006/02/09 09:54:46 otto 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 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 /* try mmap first; if it fails, try stdio */ 142 if ((f->mmf = mmopen(fname, mode)) != NULL) { 143 f->type = FILE_MMAP; 144 return f; 145 } 146 f->type = FILE_STDIO; 147 if ((f->f = fopen(path, mode)) != NULL) 148 return f; 149 } 150 151 free(f); 152 return NULL; 153 } 154 155 int 156 grep_bin_file(file_t *f) 157 { 158 if (f->noseek) 159 return 0; 160 161 switch (f->type) { 162 case FILE_STDIO: 163 return bin_file(f->f); 164 case FILE_MMAP: 165 return mmbin_file(f->mmf); 166 #ifndef NOZ 167 case FILE_GZIP: 168 return gzbin_file(f->gzf); 169 #endif 170 default: 171 /* can't happen */ 172 errx(2, "invalid file type"); 173 } 174 } 175 176 char * 177 grep_fgetln(file_t *f, size_t *l) 178 { 179 switch (f->type) { 180 case FILE_STDIO: 181 return fgetln(f->f, l); 182 case FILE_MMAP: 183 return mmfgetln(f->mmf, l); 184 #ifndef NOZ 185 case FILE_GZIP: 186 return gzfgetln(f->gzf, l); 187 #endif 188 default: 189 /* can't happen */ 190 errx(2, "invalid file type"); 191 } 192 } 193 194 void 195 grep_close(file_t *f) 196 { 197 switch (f->type) { 198 case FILE_STDIO: 199 fclose(f->f); 200 break; 201 case FILE_MMAP: 202 mmclose(f->mmf); 203 break; 204 #ifndef NOZ 205 case FILE_GZIP: 206 gzclose(f->gzf); 207 break; 208 #endif 209 default: 210 /* can't happen */ 211 errx(2, "invalid file type"); 212 } 213 free(f); 214 } 215