From dfc517b05395d925a4d7b1ce9633a849f9468e70 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 23 Feb 2006 15:52:24 +0000 Subject: r13658: More moving around of files: - Collect the generic utility functions into a lib/util/ (a la GLib is for the GNOME folks) - Remove even more files from include/ (This used to be commit ba62880f5b05c2a505dc7f54676b231197a7e707) --- source4/lib/util/xfile.c | 384 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 384 insertions(+) create mode 100644 source4/lib/util/xfile.c (limited to 'source4/lib/util/xfile.c') diff --git a/source4/lib/util/xfile.c b/source4/lib/util/xfile.c new file mode 100644 index 0000000000..794e3f0f5e --- /dev/null +++ b/source4/lib/util/xfile.c @@ -0,0 +1,384 @@ +/* + Unix SMB/CIFS implementation. + stdio replacement + Copyright (C) Andrew Tridgell 2001 + + 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 2 of the License, 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. +*/ + +/* + stdio is very convenient, but on some systems the file descriptor + in FILE* is 8 bits, so it fails when more than 255 files are open. + + XFILE replaces stdio. It is less efficient, but at least it works + when you have lots of files open + + The main restriction on XFILE is that it doesn't support seeking, + and doesn't support O_RDWR. That keeps the code simple. +*/ + +#include "includes.h" +#include "system/filesys.h" + +#define XBUFSIZE BUFSIZ + +static XFILE _x_stdin = { 0, NULL, NULL, XBUFSIZE, 0, O_RDONLY, X_IOFBF, 0 }; +static XFILE _x_stdout = { 1, NULL, NULL, XBUFSIZE, 0, O_WRONLY, X_IOLBF, 0 }; +static XFILE _x_stderr = { 2, NULL, NULL, 0, 0, O_WRONLY, X_IONBF, 0 }; + +XFILE *x_stdin = &_x_stdin; +XFILE *x_stdout = &_x_stdout; +XFILE *x_stderr = &_x_stderr; + +#define X_FLAG_EOF 1 +#define X_FLAG_ERROR 2 +#define X_FLAG_EINVAL 3 + +/* simulate setvbuf() */ +int x_setvbuf(XFILE *f, char *buf, int mode, size_t size) +{ + x_fflush(f); + if (f->bufused) return -1; + + /* on files being read full buffering is the only option */ + if ((f->open_flags & O_ACCMODE) == O_RDONLY) { + mode = X_IOFBF; + } + + /* destroy any earlier buffer */ + SAFE_FREE(f->buf); + f->buf = 0; + f->bufsize = 0; + f->next = NULL; + f->bufused = 0; + f->buftype = mode; + + if (f->buftype == X_IONBF) return 0; + + /* if buffering then we need some size */ + if (size == 0) size = XBUFSIZE; + + f->bufsize = size; + f->bufused = 0; + + return 0; +} + +/* allocate the buffer */ +static int x_allocate_buffer(XFILE *f) +{ + if (f->buf) return 1; + if (f->bufsize == 0) return 0; + f->buf = malloc(f->bufsize); + if (!f->buf) return 0; + f->next = f->buf; + return 1; +} + + +/* this looks more like open() than fopen(), but that is quite deliberate. + I want programmers to *think* about O_EXCL, O_CREAT etc not just + get them magically added +*/ +XFILE *x_fopen(const char *fname, int flags, mode_t mode) +{ + XFILE *ret; + + ret = malloc_p(XFILE); + if (!ret) return NULL; + + memset(ret, 0, sizeof(XFILE)); + + if ((flags & O_ACCMODE) == O_RDWR) { + /* we don't support RDWR in XFILE - use file + descriptors instead */ + errno = EINVAL; + return NULL; + } + + ret->open_flags = flags; + + ret->fd = open(fname, flags, mode); + if (ret->fd == -1) { + SAFE_FREE(ret); + return NULL; + } + + x_setvbuf(ret, NULL, X_IOFBF, XBUFSIZE); + + return ret; +} + +/* simulate fclose() */ +int x_fclose(XFILE *f) +{ + int ret; + + /* make sure we flush any buffered data */ + x_fflush(f); + + ret = close(f->fd); + f->fd = -1; + if (f->buf) { + /* make sure data can't leak into a later malloc */ + memset(f->buf, 0, f->bufsize); + SAFE_FREE(f->buf); + } + /* check the file descriptor given to the function is NOT one of the static + * descriptor of this libreary or we will free unallocated memory + * --sss */ + if (f != x_stdin && f != x_stdout && f != x_stderr) { + SAFE_FREE(f); + } + return ret; +} + +/* simulate fwrite() */ +size_t x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f) +{ + ssize_t ret; + size_t total=0; + + /* we might be writing unbuffered */ + if (f->buftype == X_IONBF || + (!f->buf && !x_allocate_buffer(f))) { + ret = write(f->fd, p, size*nmemb); + if (ret == -1) return -1; + return ret/size; + } + + + while (total < size*nmemb) { + size_t n = f->bufsize - f->bufused; + n = MIN(n, (size*nmemb)-total); + + if (n == 0) { + /* it's full, flush it */ + x_fflush(f); + continue; + } + + memcpy(f->buf + f->bufused, total+(const char *)p, n); + f->bufused += n; + total += n; + } + + /* when line buffered we need to flush at the last linefeed. This can + flush a bit more than necessary, but that is harmless */ + if (f->buftype == X_IOLBF && f->bufused) { + int i; + for (i=(size*nmemb)-1; i>=0; i--) { + if (*(i+(const char *)p) == '\n') { + x_fflush(f); + break; + } + } + } + + return total/size; +} + +/* thank goodness for asprintf() */ + int x_vfprintf(XFILE *f, const char *format, va_list ap) +{ + char *p; + int len, ret; + va_list ap2; + + VA_COPY(ap2, ap); + + len = vasprintf(&p, format, ap2); + if (len <= 0) return len; + ret = x_fwrite(p, 1, len, f); + SAFE_FREE(p); + return ret; +} + + int x_fprintf(XFILE *f, const char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = x_vfprintf(f, format, ap); + va_end(ap); + return ret; +} + +/* at least fileno() is simple! */ +int x_fileno(XFILE *f) +{ + return f->fd; +} + +/* simulate fflush() */ +int x_fflush(XFILE *f) +{ + int ret; + + if (f->flags & X_FLAG_ERROR) return -1; + + if ((f->open_flags & O_ACCMODE) != O_WRONLY) { + errno = EINVAL; + return -1; + } + + if (f->bufused == 0) return 0; + + ret = write(f->fd, f->buf, f->bufused); + if (ret == -1) return -1; + + f->bufused -= ret; + if (f->bufused > 0) { + f->flags |= X_FLAG_ERROR; + memmove(f->buf, ret + (char *)f->buf, f->bufused); + return -1; + } + + return 0; +} + +/* simulate setbuffer() */ +void x_setbuffer(XFILE *f, char *buf, size_t size) +{ + x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, size); +} + +/* simulate setbuf() */ +void x_setbuf(XFILE *f, char *buf) +{ + x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, XBUFSIZE); +} + +/* simulate setlinebuf() */ +void x_setlinebuf(XFILE *f) +{ + x_setvbuf(f, NULL, X_IOLBF, 0); +} + + +/* simulate feof() */ +int x_feof(XFILE *f) +{ + if (f->flags & X_FLAG_EOF) return 1; + return 0; +} + +/* simulate ferror() */ +int x_ferror(XFILE *f) +{ + if (f->flags & X_FLAG_ERROR) return 1; + return 0; +} + +/* fill the read buffer */ +static void x_fillbuf(XFILE *f) +{ + int n; + + if (f->bufused) return; + + if (!f->buf && !x_allocate_buffer(f)) return; + + n = read(f->fd, f->buf, f->bufsize); + if (n <= 0) return; + f->bufused = n; + f->next = f->buf; +} + +/* simulate fgetc() */ +int x_fgetc(XFILE *f) +{ + int ret; + + if (f->flags & (X_FLAG_EOF | X_FLAG_ERROR)) return EOF; + + if (f->bufused == 0) x_fillbuf(f); + + if (f->bufused == 0) { + f->flags |= X_FLAG_EOF; + return EOF; + } + + ret = *(uint8_t *)(f->next); + f->next++; + f->bufused--; + return ret; +} + +/* simulate fread */ +size_t x_fread(void *p, size_t size, size_t nmemb, XFILE *f) +{ + size_t total = 0; + while (total < size*nmemb) { + int c = x_fgetc(f); + if (c == EOF) break; + (total+(char *)p)[0] = (char)c; + total++; + } + return total/size; +} + +/* simulate fgets() */ +char *x_fgets(char *s, int size, XFILE *stream) +{ + char *s0 = s; + int l = size; + while (l>1) { + int c = x_fgetc(stream); + if (c == EOF) break; + *s++ = (char)c; + l--; + if (c == '\n') break; + } + if (l==size || x_ferror(stream)) { + return 0; + } + *s = 0; + return s0; +} + +/* trivial seek, works only for SEEK_SET and SEEK_END if SEEK_CUR is + * set then an error is returned */ +off_t x_tseek(XFILE *f, off_t offset, int whence) +{ + if (f->flags & X_FLAG_ERROR) + return -1; + + /* only SEEK_SET and SEEK_END are supported */ + /* SEEK_CUR needs internal offset counter */ + if (whence != SEEK_SET && whence != SEEK_END) { + f->flags |= X_FLAG_EINVAL; + errno = EINVAL; + return -1; + } + + /* empty the buffer */ + switch (f->open_flags & O_ACCMODE) { + case O_RDONLY: + f->bufused = 0; + break; + case O_WRONLY: + if (x_fflush(f) != 0) + return -1; + break; + default: + errno = EINVAL; + return -1; + } + + f->flags &= ~X_FLAG_EOF; + return lseek(f->fd, offset, whence); +} -- cgit From aa04388943fe5d7d8c873a6ee8a4cc9af2491532 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 28 Feb 2006 13:12:39 +0000 Subject: r13752: Add doxyfile and fix formatting of comments. Current output is available at http://samba.org/~jelmer/util-api/ (This used to be commit 90812203df151a5e62394306827c72adfe13c63c) --- source4/lib/util/xfile.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/lib/util/xfile.c') diff --git a/source4/lib/util/xfile.c b/source4/lib/util/xfile.c index 794e3f0f5e..43f0f85f52 100644 --- a/source4/lib/util/xfile.c +++ b/source4/lib/util/xfile.c @@ -18,6 +18,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/** + * @file + * @brief scalable FILE replacement + */ + /* stdio is very convenient, but on some systems the file descriptor in FILE* is 8 bits, so it fails when more than 255 files are open. -- cgit From c287cc247d90c996894cab18e870c992e7f84f85 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 6 Mar 2006 00:24:51 +0000 Subject: r13851: More doc improvements. (This used to be commit 936d26ae64b93ef8f8b2fbc632b1c2fd60840405) --- source4/lib/util/xfile.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'source4/lib/util/xfile.c') diff --git a/source4/lib/util/xfile.c b/source4/lib/util/xfile.c index 43f0f85f52..97bab2ef9a 100644 --- a/source4/lib/util/xfile.c +++ b/source4/lib/util/xfile.c @@ -51,7 +51,7 @@ XFILE *x_stderr = &_x_stderr; #define X_FLAG_ERROR 2 #define X_FLAG_EINVAL 3 -/* simulate setvbuf() */ +/** simulate setvbuf() */ int x_setvbuf(XFILE *f, char *buf, int mode, size_t size) { x_fflush(f); @@ -93,7 +93,7 @@ static int x_allocate_buffer(XFILE *f) } -/* this looks more like open() than fopen(), but that is quite deliberate. +/** this looks more like open() than fopen(), but that is quite deliberate. I want programmers to *think* about O_EXCL, O_CREAT etc not just get them magically added */ @@ -126,7 +126,7 @@ XFILE *x_fopen(const char *fname, int flags, mode_t mode) return ret; } -/* simulate fclose() */ +/** simulate fclose() */ int x_fclose(XFILE *f) { int ret; @@ -150,7 +150,7 @@ int x_fclose(XFILE *f) return ret; } -/* simulate fwrite() */ +/** simulate fwrite() */ size_t x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f) { ssize_t ret; @@ -195,7 +195,7 @@ size_t x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f) return total/size; } -/* thank goodness for asprintf() */ +/** thank goodness for asprintf() */ int x_vfprintf(XFILE *f, const char *format, va_list ap) { char *p; @@ -228,7 +228,7 @@ int x_fileno(XFILE *f) return f->fd; } -/* simulate fflush() */ +/** simulate fflush() */ int x_fflush(XFILE *f) { int ret; @@ -255,33 +255,33 @@ int x_fflush(XFILE *f) return 0; } -/* simulate setbuffer() */ +/** simulate setbuffer() */ void x_setbuffer(XFILE *f, char *buf, size_t size) { x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, size); } -/* simulate setbuf() */ +/** simulate setbuf() */ void x_setbuf(XFILE *f, char *buf) { x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, XBUFSIZE); } -/* simulate setlinebuf() */ +/** simulate setlinebuf() */ void x_setlinebuf(XFILE *f) { x_setvbuf(f, NULL, X_IOLBF, 0); } -/* simulate feof() */ +/** simulate feof() */ int x_feof(XFILE *f) { if (f->flags & X_FLAG_EOF) return 1; return 0; } -/* simulate ferror() */ +/** simulate ferror() */ int x_ferror(XFILE *f) { if (f->flags & X_FLAG_ERROR) return 1; @@ -303,7 +303,7 @@ static void x_fillbuf(XFILE *f) f->next = f->buf; } -/* simulate fgetc() */ +/** simulate fgetc() */ int x_fgetc(XFILE *f) { int ret; @@ -323,7 +323,7 @@ int x_fgetc(XFILE *f) return ret; } -/* simulate fread */ +/** simulate fread */ size_t x_fread(void *p, size_t size, size_t nmemb, XFILE *f) { size_t total = 0; @@ -336,7 +336,7 @@ size_t x_fread(void *p, size_t size, size_t nmemb, XFILE *f) return total/size; } -/* simulate fgets() */ +/** simulate fgets() */ char *x_fgets(char *s, int size, XFILE *stream) { char *s0 = s; @@ -355,7 +355,8 @@ char *x_fgets(char *s, int size, XFILE *stream) return s0; } -/* trivial seek, works only for SEEK_SET and SEEK_END if SEEK_CUR is +/** + * trivial seek, works only for SEEK_SET and SEEK_END if SEEK_CUR is * set then an error is returned */ off_t x_tseek(XFILE *f, off_t offset, int whence) { -- cgit From 4a61e4901ebc751fea57880424f9045e3bdf238e Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 8 Apr 2006 16:05:21 +0000 Subject: r14999: Remove more unused autoconf code Simplify va_copy() replacement code a bit (This used to be commit a5c87360a7f14a90b831ea372277f4f89ee4c5f1) --- source4/lib/util/xfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/util/xfile.c') diff --git a/source4/lib/util/xfile.c b/source4/lib/util/xfile.c index 97bab2ef9a..1cf77a3220 100644 --- a/source4/lib/util/xfile.c +++ b/source4/lib/util/xfile.c @@ -202,7 +202,7 @@ size_t x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f) int len, ret; va_list ap2; - VA_COPY(ap2, ap); + va_copy(ap2, ap); len = vasprintf(&p, format, ap2); if (len <= 0) return len; -- cgit From 8538af1107a6e894d4941708b77e79fac587e35d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 6 Feb 2007 05:26:25 +0000 Subject: r21174: many thanks to Paul Wayper for pointing out that C99 requires a matching va_end() for each va_copy(). This doesn't matter for most architectures, but there could be some obscure ones where it does matter. some of this should be ported to Samba3 (This used to be commit 21eb316473486cb6b73bb3ff9c5f3a44ecd57e4a) --- source4/lib/util/xfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/util/xfile.c') diff --git a/source4/lib/util/xfile.c b/source4/lib/util/xfile.c index 1cf77a3220..870cd4c136 100644 --- a/source4/lib/util/xfile.c +++ b/source4/lib/util/xfile.c @@ -203,8 +203,8 @@ size_t x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f) va_list ap2; va_copy(ap2, ap); - len = vasprintf(&p, format, ap2); + va_end(ap2); if (len <= 0) return len; ret = x_fwrite(p, 1, len, f); SAFE_FREE(p); -- cgit From 0479a2f1cbae51fcd8dbdc3c148c808421fb4d25 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 02:07:03 +0000 Subject: r23792: convert Samba4 to GPLv3 There are still a few tidyups of old FSF addresses to come (in both s3 and s4). More commits soon. (This used to be commit fcf38a38ac691abd0fa51b89dc951a08e89fdafa) --- source4/lib/util/xfile.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source4/lib/util/xfile.c') diff --git a/source4/lib/util/xfile.c b/source4/lib/util/xfile.c index 870cd4c136..8b90e30868 100644 --- a/source4/lib/util/xfile.c +++ b/source4/lib/util/xfile.c @@ -5,7 +5,7 @@ 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 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ /** -- cgit From dccf3f99e45137b6cd18c1de1c79808ad67130d1 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 8 Sep 2007 13:27:14 +0000 Subject: r25027: Fix more warnings. (This used to be commit 5085c53fcfade614e83d21fc2c1a5bc43bb2a729) --- source4/lib/util/xfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/util/xfile.c') diff --git a/source4/lib/util/xfile.c b/source4/lib/util/xfile.c index 8b90e30868..a016031a77 100644 --- a/source4/lib/util/xfile.c +++ b/source4/lib/util/xfile.c @@ -85,7 +85,7 @@ static int x_allocate_buffer(XFILE *f) { if (f->buf) return 1; if (f->bufsize == 0) return 0; - f->buf = malloc(f->bufsize); + f->buf = (char *)malloc(f->bufsize); if (!f->buf) return 0; f->next = f->buf; return 1; -- cgit