Some comments about the format of the on-disk reg file, as well as
[Samba/gebeck_regimport.git] / source3 / lib / xfile.c
blob1534dd855e9e2b72202231e5382a1bcd03f3b1fe
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
46 #define X_FLAG_EINVAL 3
48 /* simulate setvbuf() */
49 int x_setvbuf(XFILE *f, char *buf, int mode, size_t size)
51 x_fflush(f);
52 if (f->bufused) return -1;
54 /* on files being read full buffering is the only option */
55 if ((f->open_flags & O_ACCMODE) == O_RDONLY) {
56 mode = X_IOFBF;
59 /* destroy any earlier buffer */
60 SAFE_FREE(f->buf);
61 f->buf = 0;
62 f->bufsize = 0;
63 f->next = NULL;
64 f->bufused = 0;
65 f->buftype = mode;
67 if (f->buftype == X_IONBF) return 0;
69 /* if buffering then we need some size */
70 if (size == 0) size = XBUFSIZE;
72 f->bufsize = size;
73 f->bufused = 0;
75 return 0;
78 /* allocate the buffer */
79 static int x_allocate_buffer(XFILE *f)
81 if (f->buf) return 1;
82 if (f->bufsize == 0) return 0;
83 f->buf = malloc(f->bufsize);
84 if (!f->buf) return 0;
85 f->next = f->buf;
86 return 1;
90 /* this looks more like open() than fopen(), but that is quite deliberate.
91 I want programmers to *think* about O_EXCL, O_CREAT etc not just
92 get them magically added
94 XFILE *x_fopen(const char *fname, int flags, mode_t mode)
96 XFILE *ret;
98 ret = (XFILE *)malloc(sizeof(XFILE));
99 if (!ret) return NULL;
101 memset(ret, 0, sizeof(XFILE));
103 if ((flags & O_ACCMODE) == O_RDWR) {
104 /* we don't support RDWR in XFILE - use file
105 descriptors instead */
106 errno = EINVAL;
107 return NULL;
110 ret->open_flags = flags;
112 ret->fd = sys_open(fname, flags, mode);
113 if (ret->fd == -1) {
114 SAFE_FREE(ret);
115 return NULL;
118 x_setvbuf(ret, NULL, X_IOFBF, XBUFSIZE);
120 return ret;
123 /* simulate fclose() */
124 int x_fclose(XFILE *f)
126 int ret;
128 /* make sure we flush any buffered data */
129 x_fflush(f);
131 ret = close(f->fd);
132 f->fd = -1;
133 if (f->buf) {
134 /* make sure data can't leak into a later malloc */
135 memset(f->buf, 0, f->bufsize);
136 SAFE_FREE(f->buf);
138 SAFE_FREE(f);
139 return ret;
142 /* simulate fwrite() */
143 size_t x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f)
145 ssize_t ret;
146 size_t total=0;
148 /* we might be writing unbuffered */
149 if (f->buftype == X_IONBF ||
150 (!f->buf && !x_allocate_buffer(f))) {
151 ret = write(f->fd, p, size*nmemb);
152 if (ret == -1) return -1;
153 return ret/size;
157 while (total < size*nmemb) {
158 size_t n = f->bufsize - f->bufused;
159 n = MIN(n, (size*nmemb)-total);
161 if (n == 0) {
162 /* it's full, flush it */
163 x_fflush(f);
164 continue;
167 memcpy(f->buf + f->bufused, total+(const char *)p, n);
168 f->bufused += n;
169 total += n;
172 /* when line buffered we need to flush at the last linefeed. This can
173 flush a bit more than necessary, but that is harmless */
174 if (f->buftype == X_IOLBF && f->bufused) {
175 int i;
176 for (i=(size*nmemb)-1; i>=0; i--) {
177 if (*(i+(const char *)p) == '\n') {
178 x_fflush(f);
179 break;
184 return total/size;
187 /* thank goodness for asprintf() */
188 int x_vfprintf(XFILE *f, const char *format, va_list ap)
190 char *p;
191 int len, ret;
192 va_list ap2;
194 VA_COPY(ap2, ap);
196 len = vasprintf(&p, format, ap2);
197 if (len <= 0) return len;
198 ret = x_fwrite(p, 1, len, f);
199 SAFE_FREE(p);
200 return ret;
203 int x_fprintf(XFILE *f, const char *format, ...)
205 va_list ap;
206 int ret;
208 va_start(ap, format);
209 ret = x_vfprintf(f, format, ap);
210 va_end(ap);
211 return ret;
214 /* at least fileno() is simple! */
215 int x_fileno(XFILE *f)
217 return f->fd;
220 /* simulate fflush() */
221 int x_fflush(XFILE *f)
223 int ret;
225 if (f->flags & X_FLAG_ERROR) return -1;
227 if ((f->open_flags & O_ACCMODE) != O_WRONLY) {
228 errno = EINVAL;
229 return -1;
232 if (f->bufused == 0) return 0;
234 ret = write(f->fd, f->buf, f->bufused);
235 if (ret == -1) return -1;
237 f->bufused -= ret;
238 if (f->bufused > 0) {
239 f->flags |= X_FLAG_ERROR;
240 memmove(f->buf, ret + (char *)f->buf, f->bufused);
241 return -1;
244 return 0;
247 /* simulate setbuffer() */
248 void x_setbuffer(XFILE *f, char *buf, size_t size)
250 x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, size);
253 /* simulate setbuf() */
254 void x_setbuf(XFILE *f, char *buf)
256 x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, XBUFSIZE);
259 /* simulate setlinebuf() */
260 void x_setlinebuf(XFILE *f)
262 x_setvbuf(f, NULL, X_IOLBF, 0);
266 /* simulate feof() */
267 int x_feof(XFILE *f)
269 if (f->flags & X_FLAG_EOF) return 1;
270 return 0;
273 /* simulate ferror() */
274 int x_ferror(XFILE *f)
276 if (f->flags & X_FLAG_ERROR) return 1;
277 return 0;
280 /* fill the read buffer */
281 static void x_fillbuf(XFILE *f)
283 int n;
285 if (f->bufused) return;
287 if (!f->buf && !x_allocate_buffer(f)) return;
289 n = read(f->fd, f->buf, f->bufsize);
290 if (n <= 0) return;
291 f->bufused = n;
292 f->next = f->buf;
295 /* simulate fgetc() */
296 int x_fgetc(XFILE *f)
298 int ret;
300 if (f->flags & (X_FLAG_EOF | X_FLAG_ERROR)) return EOF;
302 if (f->bufused == 0) x_fillbuf(f);
304 if (f->bufused == 0) {
305 f->flags |= X_FLAG_EOF;
306 return EOF;
309 ret = *(unsigned char *)(f->next);
310 f->next++;
311 f->bufused--;
312 return ret;
315 /* simulate fread */
316 size_t x_fread(void *p, size_t size, size_t nmemb, XFILE *f)
318 size_t total = 0;
319 while (total < size*nmemb) {
320 int c = x_fgetc(f);
321 if (c == EOF) break;
322 (total+(char *)p)[0] = (char)c;
323 total++;
325 return total/size;
328 /* simulate fgets() */
329 char *x_fgets(char *s, int size, XFILE *stream)
331 char *s0 = s;
332 int l = size;
333 while (l>1) {
334 int c = x_fgetc(stream);
335 if (c == EOF) break;
336 *s++ = (char)c;
337 l--;
338 if (c == '\n') break;
340 if (l==size || x_ferror(stream)) {
341 return 0;
343 *s = 0;
344 return s0;
347 /* trivial seek, works only for SEEK_SET and SEEK_END if SEEK_CUR is
348 * set then an error is returned */
349 off_t x_tseek(XFILE *f, off_t offset, int whence)
351 if (f->flags & X_FLAG_ERROR)
352 return -1;
354 /* only SEEK_SET and SEEK_END are supported */
355 /* SEEK_CUR needs internal offset counter */
356 if (whence != SEEK_SET && whence != SEEK_END) {
357 f->flags |= X_FLAG_EINVAL;
358 errno = EINVAL;
359 return -1;
362 /* empty the buffer */
363 switch (f->open_flags & O_ACCMODE) {
364 case O_RDONLY:
365 f->bufused = 0;
366 break;
367 case O_WRONLY:
368 if (x_fflush(f) != 0)
369 return -1;
370 break;
371 default:
372 errno = EINVAL;
373 return -1;
376 f->flags &= ~X_FLAG_EOF;
377 return (off_t)sys_lseek(f->fd, offset, whence);