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