add another registry rpc (opnum 0x14). Have no idea what it's real name
[Samba.git] / source / lib / xfile.c
blobb5710f3a39e15e648f349c21f379d11eaa87489b
1 /*
2 Unix SMB/CIFS implementation.
3 stdio replacement
4 Copyright (C) Andrew Tridgell 2001
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 stdio is very convenient, but on some systems the file descriptor
23 in FILE* is 8 bits, so it fails when more than 255 files are open.
25 XFILE replaces stdio. It is less efficient, but at least it works
26 when you have lots of files open
28 The main restriction on XFILE is that it doesn't support seeking,
29 and doesn't support O_RDWR. That keeps the code simple.
32 #include "includes.h"
34 #define XBUFSIZE BUFSIZ
36 static XFILE _x_stdin = { 0, NULL, NULL, XBUFSIZE, 0, O_RDONLY, X_IOFBF, 0 };
37 static XFILE _x_stdout = { 1, NULL, NULL, XBUFSIZE, 0, O_WRONLY, X_IOLBF, 0 };
38 static XFILE _x_stderr = { 2, NULL, NULL, 0, 0, O_WRONLY, X_IONBF, 0 };
40 XFILE *x_stdin = &_x_stdin;
41 XFILE *x_stdout = &_x_stdout;
42 XFILE *x_stderr = &_x_stderr;
44 #define X_FLAG_EOF 1
45 #define X_FLAG_ERROR 2
47 /* simulate setvbuf() */
48 int x_setvbuf(XFILE *f, char *buf, int mode, size_t size)
50 x_fflush(f);
51 if (f->bufused) return -1;
53 /* on files being read full buffering is the only option */
54 if ((f->open_flags & O_ACCMODE) == O_RDONLY) {
55 mode = X_IOFBF;
58 /* destroy any earlier buffer */
59 SAFE_FREE(f->buf);
60 f->buf = 0;
61 f->bufsize = 0;
62 f->next = NULL;
63 f->bufused = 0;
64 f->buftype = mode;
66 if (f->buftype == X_IONBF) return 0;
68 /* if buffering then we need some size */
69 if (size == 0) size = XBUFSIZE;
71 f->bufsize = size;
72 f->bufused = 0;
74 return 0;
77 /* allocate the buffer */
78 static int x_allocate_buffer(XFILE *f)
80 if (f->buf) return 1;
81 if (f->bufsize == 0) return 0;
82 f->buf = malloc(f->bufsize);
83 if (!f->buf) return 0;
84 f->next = f->buf;
85 return 1;
89 /* this looks more like open() than fopen(), but that is quite deliberate.
90 I want programmers to *think* about O_EXCL, O_CREAT etc not just
91 get them magically added
93 XFILE *x_fopen(const char *fname, int flags, mode_t mode)
95 XFILE *ret;
97 ret = (XFILE *)malloc(sizeof(XFILE));
98 if (!ret) return NULL;
100 memset(ret, 0, sizeof(XFILE));
102 if ((flags & O_ACCMODE) == O_RDWR) {
103 /* we don't support RDWR in XFILE - use file
104 descriptors instead */
105 errno = EINVAL;
106 return NULL;
109 ret->open_flags = flags;
111 ret->fd = sys_open(fname, flags, mode);
112 if (ret->fd == -1) {
113 SAFE_FREE(ret);
114 return NULL;
117 x_setvbuf(ret, NULL, X_IOFBF, XBUFSIZE);
119 return ret;
122 /* simulate fclose() */
123 int x_fclose(XFILE *f)
125 int ret;
127 /* make sure we flush any buffered data */
128 x_fflush(f);
130 ret = close(f->fd);
131 f->fd = -1;
132 if (f->buf) {
133 /* make sure data can't leak into a later malloc */
134 memset(f->buf, 0, f->bufsize);
135 SAFE_FREE(f->buf);
137 SAFE_FREE(f);
138 return ret;
141 /* simulate fwrite() */
142 int x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f)
144 int ret, total=0;
146 /* we might be writing unbuffered */
147 if (f->buftype == X_IONBF ||
148 (!f->buf && !x_allocate_buffer(f))) {
149 ret = write(f->fd, p, size*nmemb);
150 if (ret == -1) return -1;
151 return ret/size;
155 while (total < size*nmemb) {
156 int n = f->bufsize - f->bufused;
157 n = MIN(n, (size*nmemb)-total);
159 if (n == 0) {
160 /* it's full, flush it */
161 x_fflush(f);
162 continue;
165 memcpy(f->buf + f->bufused, total+(const char *)p, n);
166 f->bufused += n;
167 total += n;
170 /* when line buffered we need to flush at the last linefeed. This can
171 flush a bit more than necessary, but that is harmless */
172 if (f->buftype == X_IOLBF && f->bufused) {
173 int i;
174 for (i=(size*nmemb)-1; i>=0; i--) {
175 if (*(i+(const char *)p) == '\n') {
176 x_fflush(f);
177 break;
182 return total/size;
185 /* thank goodness for asprintf() */
186 int x_vfprintf(XFILE *f, const char *format, va_list ap)
188 char *p;
189 int len, ret;
190 va_list ap2;
192 VA_COPY(ap2, ap);
194 len = vasprintf(&p, format, ap2);
195 if (len <= 0) return len;
196 ret = x_fwrite(p, 1, len, f);
197 SAFE_FREE(p);
198 return ret;
201 int x_fprintf(XFILE *f, const char *format, ...)
203 va_list ap;
204 int ret;
206 va_start(ap, format);
207 ret = x_vfprintf(f, format, ap);
208 va_end(ap);
209 return ret;
212 /* at least fileno() is simple! */
213 int x_fileno(XFILE *f)
215 return f->fd;
218 /* simulate fflush() */
219 int x_fflush(XFILE *f)
221 int ret;
223 if (f->flags & X_FLAG_ERROR) return -1;
225 if ((f->open_flags & O_ACCMODE) != O_WRONLY) {
226 errno = EINVAL;
227 return -1;
230 if (f->bufused == 0) return 0;
232 ret = write(f->fd, f->buf, f->bufused);
233 if (ret == -1) return -1;
235 f->bufused -= ret;
236 if (f->bufused > 0) {
237 f->flags |= X_FLAG_ERROR;
238 memmove(f->buf, ret + (char *)f->buf, f->bufused);
239 return -1;
242 return 0;
245 /* simulate setbuffer() */
246 void x_setbuffer(XFILE *f, char *buf, size_t size)
248 x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, size);
251 /* simulate setbuf() */
252 void x_setbuf(XFILE *f, char *buf)
254 x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, XBUFSIZE);
257 /* simulate setlinebuf() */
258 void x_setlinebuf(XFILE *f)
260 x_setvbuf(f, NULL, X_IOLBF, 0);
264 /* simulate feof() */
265 int x_feof(XFILE *f)
267 if (f->flags & X_FLAG_EOF) return 1;
268 return 0;
271 /* simulate ferror() */
272 int x_ferror(XFILE *f)
274 if (f->flags & X_FLAG_ERROR) return 1;
275 return 0;
278 /* fill the read buffer */
279 static void x_fillbuf(XFILE *f)
281 int n;
283 if (f->bufused) return;
285 if (!f->buf && !x_allocate_buffer(f)) return;
287 n = read(f->fd, f->buf, f->bufsize);
288 if (n <= 0) return;
289 f->bufused = n;
290 f->next = f->buf;
293 /* simulate fgetc() */
294 int x_fgetc(XFILE *f)
296 int ret;
298 if (f->flags & (X_FLAG_EOF | X_FLAG_ERROR)) return EOF;
300 if (f->bufused == 0) x_fillbuf(f);
302 if (f->bufused == 0) {
303 f->flags |= X_FLAG_EOF;
304 return EOF;
307 ret = *(unsigned char *)(f->next);
308 f->next++;
309 f->bufused--;
310 return ret;
313 /* simulate fread */
314 size_t x_fread(void *p, size_t size, size_t nmemb, XFILE *f)
316 size_t total = 0;
317 while (total < size*nmemb) {
318 int c = x_fgetc(f);
319 if (c == EOF) break;
320 (total+(char *)p)[0] = (char)c;
321 total++;
323 return total/size;
326 /* simulate fgets() */
327 char *x_fgets(char *s, int size, XFILE *stream)
329 char *s0 = s;
330 int l = size;
331 while (l>1) {
332 int c = x_fgetc(stream);
333 if (c == EOF) break;
334 *s++ = (char)c;
335 l--;
336 if (c == '\n') break;
338 if (l==size || x_ferror(stream)) {
339 return 0;
341 *s = 0;
342 return s0;