/* * IRC - Internet Relay Chat, ircd/fileio.c * Copyright (C) 1998 Thomas Helvey * Copyright (C) 1990 Jarkko Oikarinen and * University of Oulu, Co Center * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" #include "fileio.h" #include "ircd_alloc.h" /* MyMalloc, MyFree */ #include /* assert */ #include /* O_RDONLY, O_WRONLY, ... */ #include /* BUFSIZ, EOF */ #include /* struct stat */ #include /* read, write, open, close */ #include #define FB_EOF 0x01 #define FB_FAIL 0x02 struct FileBuf { int fd; /* file descriptor */ char *endp; /* one past the end */ char *ptr; /* current read pos */ int flags; /* file state */ char buf[BUFSIZ]; /* buffer */ }; FBFILE* fbopen(const char *filename, const char *mode) { int openmode = 0; int pmode = 0; FBFILE *fb = NULL; int fd; assert(filename); assert(mode); while (*mode) { switch (*mode) { case 'r': openmode = O_RDONLY; break; case 'w': openmode = O_WRONLY | O_CREAT | O_TRUNC; pmode = S_IRUSR | S_IWUSR; break; case 'a': openmode = O_WRONLY | O_CREAT | O_APPEND; pmode = S_IRUSR | S_IWUSR; break; case '+': openmode &= ~(O_RDONLY | O_WRONLY); openmode |= O_RDWR; break; default: break; } ++mode; } /* * stop NFS hangs...most systems should be able to open a file in * 3 seconds. -avalon (curtesy of wumpus) */ alarm(3); if ((fd = open(filename, openmode, pmode)) == -1) { alarm(0); return fb; } alarm(0); if (NULL == (fb = fdbopen(fd, NULL))) close(fd); return fb; } FBFILE* fdbopen(int fd, const char *mode) { /* * ignore mode, if file descriptor hasn't been opened with the * correct mode, the first use will fail */ FBFILE *fb = (FBFILE *) MyMalloc(sizeof(FBFILE)); assert(0 != fb); fb->ptr = fb->endp = fb->buf; fb->fd = fd; fb->flags = 0; return fb; } void fbclose(FBFILE* fb) { assert(fb); close(fb->fd); MyFree(fb); } static int fbfill(FBFILE * fb) { int n; assert(fb); if (fb->flags) return -1; n = read(fb->fd, fb->buf, BUFSIZ); if (0 < n) { fb->ptr = fb->buf; fb->endp = fb->buf + n; } else if (n < 0) fb->flags |= FB_FAIL; else fb->flags |= FB_EOF; return n; } int fbgetc(FBFILE * fb) { assert(fb); if (fb->ptr < fb->endp || fbfill(fb) > 0) return *fb->ptr++; return EOF; } char *fbgets(char *buf, size_t len, FBFILE * fb) { char *p = buf; assert(buf); assert(fb); assert(0 < len); if (fb->ptr == fb->endp && fbfill(fb) < 1) return 0; --len; while (len--) { *p = *fb->ptr++; if ('\n' == *p) { ++p; break; } /* * deal with CR's */ else if ('\r' == *p) { if (fb->ptr < fb->endp || fbfill(fb) > 0) { if ('\n' == *fb->ptr) ++fb->ptr; } *p++ = '\n'; break; } ++p; if (fb->ptr == fb->endp && fbfill(fb) < 1) break; } *p = '\0'; return buf; } int fbputs(const char *str, FBFILE * fb) { int n = -1; assert(str); assert(fb); if (0 == fb->flags) { n = write(fb->fd, str, strlen(str)); if (-1 == n) fb->flags |= FB_FAIL; } return n; } int fbstat(struct stat *sb, FBFILE * fb) { assert(sb); assert(fb); return fstat(fb->fd, sb); }