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