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