2 * IRC - Internet Relay Chat, ircd/fileio.c
3 * Copyright (C) 1998 Thomas Helvey <tomh@inxpress.net>
4 * Copyright (C) 1990 Jarkko Oikarinen and
5 * University of Oulu, Co Center
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 1, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * @brief ANSI FILE* clone API implementation.
28 #include "ircd_alloc.h" /* MyMalloc, MyFree */
30 #include <assert.h> /* assert */
31 #include <fcntl.h> /* O_RDONLY, O_WRONLY, ... */
32 #include <stdio.h> /* BUFSIZ, EOF */
33 #include <sys/stat.h> /* struct stat */
34 #include <unistd.h> /* read, write, open, close */
37 #define FB_EOF 0x01 /**< File has reached EOF. */
38 #define FB_FAIL 0x02 /**< File operation failed. */
40 /** Tracks status and buffer for a file on disk. */
42 int fd; /**< file descriptor */
43 char *endp; /**< one past the end */
44 char *ptr; /**< current read pos */
45 int flags; /**< file state */
46 char buf[BUFSIZ]; /**< buffer */
49 /** Open a new FBFILE.
50 * @param[in] filename Name of file to open.
51 * @param[in] mode fopen()-style mode string.
52 * @return Pointer to newly allocated FBFILE.
54 FBFILE* fbopen(const char *filename, const char *mode)
69 openmode = O_WRONLY | O_CREAT | O_TRUNC;
70 pmode = S_IREAD | S_IWRITE;
73 openmode = O_WRONLY | O_CREAT | O_APPEND;
74 pmode = S_IREAD | S_IWRITE;
77 openmode &= ~(O_RDONLY | O_WRONLY);
86 * stop NFS hangs...most systems should be able to open a file in
87 * 3 seconds. -avalon (curtesy of wumpus)
90 if ((fd = open(filename, openmode, pmode)) == -1) {
96 if (NULL == (fb = fdbopen(fd, NULL)))
101 /** Open a FBFILE from a file descriptor.
102 * @param[in] fd File descriptor to use.
103 * @param[in] mode fopen()-style mode string (ignored).
105 FBFILE* fdbopen(int fd, const char *mode)
108 * ignore mode, if file descriptor hasn't been opened with the
109 * correct mode, the first use will fail
111 FBFILE *fb = (FBFILE *) MyMalloc(sizeof(FBFILE));
113 fb->ptr = fb->endp = fb->buf;
121 * @param[in] fb File buffer to close.
123 void fbclose(FBFILE* fb)
130 /** Attempt to fill a file's buffer.
131 * @param[in] fb File to operate on.
132 * @return Number of bytes read into buffer, or a negative number on error.
134 static int fbfill(FBFILE * fb)
140 n = read(fb->fd, fb->buf, BUFSIZ);
144 fb->endp = fb->buf + n;
147 fb->flags |= FB_FAIL;
153 /** Get a single character from a file.
154 * @param[in] fb File to fetch from.
155 * @return Character value read, or EOF on error or end-of-file.
157 int fbgetc(FBFILE * fb)
160 if (fb->ptr < fb->endp || fbfill(fb) > 0)
165 /** Get a line of input from a file.
166 * @param[out] buf Output buffer to read to.
167 * @param[in] len Maximum number of bytes to write to buffer
168 * (including terminating NUL).
169 * @param[in] fb File to read from.
171 char *fbgets(char *buf, size_t len, FBFILE * fb)
178 if (fb->ptr == fb->endp && fbfill(fb) < 1)
191 else if ('\r' == *p) {
192 if (fb->ptr < fb->endp || fbfill(fb) > 0) {
193 if ('\n' == *fb->ptr)
200 if (fb->ptr == fb->endp && fbfill(fb) < 1)
207 /** Write a string to a file.
208 * @param[in] str String to write to file.
209 * @param[in] fb File to write to.
210 * @return Number of bytes written, or -1 on error.
212 int fbputs(const char *str, FBFILE * fb)
218 if (0 == fb->flags) {
219 n = write(fb->fd, str, strlen(str));
221 fb->flags |= FB_FAIL;
227 * @param[out] sb Receives file status.
228 * @param[in] fb File to get status for.
229 * @return Zero on success, -1 on error.
231 int fbstat(struct stat *sb, FBFILE * fb)
235 return fstat(fb->fd, sb);