This commit was generated by cvs2svn to compensate for changes in r2,
[ircu2.10.12-pk.git] / ircd / fileio.c
diff --git a/ircd/fileio.c b/ircd/fileio.c
new file mode 100644 (file)
index 0000000..44f5090
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * IRC - Internet Relay Chat, ircd/fileio.c
+ * Copyright (C) 1998 Thomas Helvey <tomh@inxpress.net>
+ * 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 "fileio.h"
+#include "runmalloc.h"         /* RunMalloc, RunFree */
+#include <stdio.h>             /* BUFSIZ, EOF */
+#include <fcntl.h>             /* O_RDONLY, O_WRONLY, ... */
+#include <unistd.h>            /* read, write, open, close */
+#include <assert.h>            /* assert */
+
+#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_IREAD | S_IWRITE;
+       break;
+      case 'a':
+       openmode = O_WRONLY | O_CREAT | O_APPEND;
+       pmode = S_IREAD | S_IWRITE;
+       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 *) RunMalloc(sizeof(FBFILE));
+  if (NULL != fb)
+  {
+    fb->ptr = fb->endp = fb->buf;
+    fb->fd = fd;
+    fb->flags = 0;
+  }
+  return fb;
+}
+
+void fbclose(FBFILE * fb)
+{
+  assert(fb);
+  close(fb->fd);
+  RunFree(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);
+}