1/* ----------------------------------------------------------------------------- 2 * file.c 3 * 4 * This file implements a file-like object that can be built around an 5 * ordinary FILE * or integer file descriptor. 6 * 7 * Author(s) : David Beazley (beazley@cs.uchicago.edu) 8 * 9 * Copyright (C) 1999-2000. The University of Chicago 10 * See the file LICENSE for information on usage and redistribution. 11 * ----------------------------------------------------------------------------- */ 12 13char cvsroot_file_c[] = "$Id: file.c 10898 2008-11-03 12:51:45Z wsfulton $"; 14 15#include "dohint.h" 16 17#ifdef DOH_INTFILE 18#include <unistd.h> 19#endif 20#include <errno.h> 21 22typedef struct { 23 FILE *filep; 24 int fd; 25 int closeondel; 26} DohFile; 27 28/* ----------------------------------------------------------------------------- 29 * DelFile() 30 * ----------------------------------------------------------------------------- */ 31 32static void DelFile(DOH *fo) { 33 DohFile *f = (DohFile *) ObjData(fo); 34 if (f->closeondel) { 35 if (f->filep) { 36 fclose(f->filep); 37 } 38#ifdef DOH_INTFILE 39 if (f->fd) { 40 close(f->fd); 41 } 42#endif 43 } 44 DohFree(f); 45} 46 47/* ----------------------------------------------------------------------------- 48 * File_read() 49 * ----------------------------------------------------------------------------- */ 50 51static int File_read(DOH *fo, void *buffer, int len) { 52 DohFile *f = (DohFile *) ObjData(fo); 53 54 if (f->filep) { 55 return fread(buffer, 1, len, f->filep); 56 } else if (f->fd) { 57#ifdef DOH_INTFILE 58 return read(f->fd, buffer, len); 59#endif 60 } 61 return -1; 62} 63 64/* ----------------------------------------------------------------------------- 65 * File_write() 66 * ----------------------------------------------------------------------------- */ 67 68static int File_write(DOH *fo, void *buffer, int len) { 69 DohFile *f = (DohFile *) ObjData(fo); 70 if (f->filep) { 71 int ret = (int) fwrite(buffer, 1, len, f->filep); 72 int err = (ret != len) ? ferror(f->filep) : 0; 73 return err ? -1 : ret; 74 } else if (f->fd) { 75#ifdef DOH_INTFILE 76 return write(f->fd, buffer, len); 77#endif 78 } 79 return -1; 80} 81 82/* ----------------------------------------------------------------------------- 83 * File_seek() 84 * ----------------------------------------------------------------------------- */ 85 86static int File_seek(DOH *fo, long offset, int whence) { 87 DohFile *f = (DohFile *) ObjData(fo); 88 if (f->filep) { 89 return fseek(f->filep, offset, whence); 90 } else if (f->fd) { 91#ifdef DOH_INTFILE 92 return lseek(f->fd, offset, whence); 93#endif 94 } 95 return -1; 96} 97 98/* ----------------------------------------------------------------------------- 99 * File_tell() 100 * ----------------------------------------------------------------------------- */ 101 102static long File_tell(DOH *fo) { 103 DohFile *f = (DohFile *) ObjData(fo); 104 if (f->filep) { 105 return ftell(f->filep); 106 } else if (f->fd) { 107#ifdef DOH_INTFILE 108 return lseek(f->fd, 0, SEEK_CUR); 109#endif 110 } 111 return -1; 112} 113 114/* ----------------------------------------------------------------------------- 115 * File_putc() 116 * ----------------------------------------------------------------------------- */ 117 118static int File_putc(DOH *fo, int ch) { 119 DohFile *f = (DohFile *) ObjData(fo); 120 if (f->filep) { 121 return fputc(ch, f->filep); 122 } else if (f->fd) { 123#ifdef DOH_INTFILE 124 char c; 125 c = (char) ch; 126 return write(f->fd, &c, 1); 127#endif 128 } 129 return -1; 130} 131 132/* ----------------------------------------------------------------------------- 133 * File_getc() 134 * ----------------------------------------------------------------------------- */ 135 136static int File_getc(DOH *fo) { 137 DohFile *f = (DohFile *) ObjData(fo); 138 if (f->filep) { 139 return fgetc(f->filep); 140 } else if (f->fd) { 141#ifdef DOH_INTFILE 142 unsigned char c; 143 if (read(f->fd, &c, 1) < 0) 144 return EOF; 145 return c; 146#endif 147 } 148 return EOF; 149} 150 151/* ----------------------------------------------------------------------------- 152 * File_ungetc() 153 * 154 * Put a character back onto the input 155 * ----------------------------------------------------------------------------- */ 156 157static int File_ungetc(DOH *fo, int ch) { 158 DohFile *f = (DohFile *) ObjData(fo); 159 if (f->filep) { 160 return ungetc(ch, f->filep); 161 } else if (f->fd) { 162#ifdef DOH_INTFILE 163 /* Not implemented yet */ 164#endif 165 } 166 return -1; 167} 168 169/* ----------------------------------------------------------------------------- 170 * File_close() 171 * 172 * Close the file 173 * ----------------------------------------------------------------------------- */ 174 175static int File_close(DOH *fo) { 176 int ret = 0; 177 DohFile *f = (DohFile *) ObjData(fo); 178 if (f->filep) { 179 ret = fclose(f->filep); 180 f->filep = 0; 181 } else if (f->fd) { 182#ifdef DOH_INTFILE 183 ret = close(f->fd); 184 f->fd = 0; 185#endif 186 } 187 return ret; 188} 189 190static DohFileMethods FileFileMethods = { 191 File_read, 192 File_write, 193 File_putc, 194 File_getc, 195 File_ungetc, 196 File_seek, 197 File_tell, 198 File_close, /* close */ 199}; 200 201static DohObjInfo DohFileType = { 202 "DohFile", /* objname */ 203 DelFile, /* doh_del */ 204 0, /* doh_copy */ 205 0, /* doh_clear */ 206 0, /* doh_str */ 207 0, /* doh_data */ 208 0, /* doh_dump */ 209 0, /* doh_len */ 210 0, /* doh_hash */ 211 0, /* doh_cmp */ 212 0, /* doh_equal */ 213 0, /* doh_first */ 214 0, /* doh_next */ 215 0, /* doh_setfile */ 216 0, /* doh_getfile */ 217 0, /* doh_setline */ 218 0, /* doh_getline */ 219 0, /* doh_mapping */ 220 0, /* doh_sequence */ 221 &FileFileMethods, /* doh_file */ 222 0, /* doh_string */ 223 0, /* doh_callable */ 224 0, /* doh_position */ 225}; 226 227/* ----------------------------------------------------------------------------- 228 * NewFile() 229 * 230 * Create a new file from a given filename and mode. 231 * If newfiles is non-zero, the filename is added to the list of new files. 232 * ----------------------------------------------------------------------------- */ 233 234DOH *DohNewFile(DOH *filename, const char *mode, DOHList *newfiles) { 235 DohFile *f; 236 FILE *file; 237 char *filen; 238 239 filen = Char(filename); 240 file = fopen(filen, mode); 241 if (!file) 242 return 0; 243 244 f = (DohFile *) DohMalloc(sizeof(DohFile)); 245 if (!f) { 246 fclose(file); 247 return 0; 248 } 249 if (newfiles) 250 Append(newfiles, filename); 251 f->filep = file; 252 f->fd = 0; 253 f->closeondel = 1; 254 return DohObjMalloc(&DohFileType, f); 255} 256 257/* ----------------------------------------------------------------------------- 258 * NewFileFromFile() 259 * 260 * Create a file object from an already open FILE *. 261 * ----------------------------------------------------------------------------- */ 262 263DOH *DohNewFileFromFile(FILE *file) { 264 DohFile *f; 265 f = (DohFile *) DohMalloc(sizeof(DohFile)); 266 if (!f) 267 return 0; 268 f->filep = file; 269 f->fd = 0; 270 f->closeondel = 0; 271 return DohObjMalloc(&DohFileType, f); 272} 273 274/* ----------------------------------------------------------------------------- 275 * NewFileFromFd() 276 * 277 * Create a file object from an already open FILE *. 278 * ----------------------------------------------------------------------------- */ 279 280DOH *DohNewFileFromFd(int fd) { 281 DohFile *f; 282 f = (DohFile *) DohMalloc(sizeof(DohFile)); 283 if (!f) 284 return 0; 285 f->filep = 0; 286 f->fd = fd; 287 f->closeondel = 0; 288 return DohObjMalloc(&DohFileType, f); 289} 290 291/* ----------------------------------------------------------------------------- 292 * FileErrorDisplay() 293 * 294 * Display cause of one of the NewFile functions failing. 295 * ----------------------------------------------------------------------------- */ 296 297void DohFileErrorDisplay(DOHString * filename) { 298 Printf(stderr, "Unable to open file %s: %s\n", filename, strerror(errno)); 299} 300