From 1756cc5943aa545f2f18fff60d56ad0886ef6145 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Date: Mon, 27 Apr 2009 20:14:06 +1000 Subject: libbb/strbuf_file: stdio emulation layer for handling with Winsock handles not really robust, but enough to make wget works --- include/strbuf_file.h | 69 +++++++++++++++++++++++++++++ libbb/Kbuild | 1 + libbb/strbuf_file.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 189 insertions(+) create mode 100644 include/strbuf_file.h create mode 100644 libbb/strbuf_file.c diff --git a/include/strbuf_file.h b/include/strbuf_file.h new file mode 100644 index 000000000..73eff9193 --- /dev/null +++ b/include/strbuf_file.h @@ -0,0 +1,69 @@ +#include "strbuf.h" + +struct strbuf_file { + struct strbuf input; + int has_error; + int fd; +}; + +struct strbuf_file *sfdopen(int fd, const char *mode); +int sfclose(struct strbuf_file *sf); +int sfprintf(struct strbuf_file *sf, const char *fmt, ...); +void sfclearerr(struct strbuf_file *sf); +int sfread(char *buf, int size, int n, struct strbuf_file *sf); +char *sfgets(char *buf, int size, struct strbuf_file *sf); +int sfgetc(struct strbuf_file *sf); + +#ifdef REPLACE_STDIO + +#ifdef FILE +#undef FILE +#endif +#define FILE struct strbuf_file + +#ifdef fdopen +#undef fdopen +#endif +#define fdopen(fd,mode) sfdopen(fd,mode) + +#ifdef fclose +#undef fclose +#endif +#define fclose(fp) sfclose(fp) + +#ifdef fprintf +#undef fprintf +#endif +#define fprintf sfprintf + +#ifdef fread +#undef fread +#endif +#define fread(buf,s,n,fp) sfread(buf,s,n,fp) + +#ifdef clearerr +#undef clearerr +#endif +#define clearerr(fp) sfclearerr(fp) + +#ifdef ferror +#undef ferror +#endif +#define ferror(fp) ((fp)->has_error) + +#ifdef fgets +#undef fgets +#endif +#define fgets(buf,n,fp) sfgets(buf,n,fp) + +#ifdef getc +#undef getc +#endif +#define getc(fp) sfgetc(fp) + +#ifdef fflush +#undef fflush +#endif +#define fflush(fp) 0 + +#endif diff --git a/libbb/Kbuild b/libbb/Kbuild index 4c8f542fc..dca58d6f7 100644 --- a/libbb/Kbuild +++ b/libbb/Kbuild @@ -136,6 +136,7 @@ lib-$(CONFIG_MINGW32) += regex.o lib-$(CONFIG_MINGW32) += run-command.o lib-$(CONFIG_MINGW32) += setenv.o lib-$(CONFIG_MINGW32) += strbuf.o +lib-$(CONFIG_MINGW32) += strbuf_file.o lib-$(CONFIG_MINGW32) += strlcpy.o lib-$(CONFIG_MINGW32) += trace.o lib-$(CONFIG_MINGW32) += usage.o diff --git a/libbb/strbuf_file.c b/libbb/strbuf_file.c new file mode 100644 index 000000000..fb2ba7966 --- /dev/null +++ b/libbb/strbuf_file.c @@ -0,0 +1,119 @@ +#include "libbb.h" +#include "strbuf_file.h" + +struct strbuf_file *sfdopen(int fd, const char *mode) +{ + struct strbuf_file *s; + + s = xmalloc(sizeof(*s)); + strbuf_init(&s->input, 0); + s->has_error = 0; + s->fd = fd; + return s; +} + +int sfclose(struct strbuf_file *sf) +{ + strbuf_release(&sf->input); + close(sf->fd); + free(sf); + return 0; +} + +int sfprintf(struct strbuf_file *sf, const char *fmt, ...) +{ + int len; + va_list ap; + struct strbuf sb = STRBUF_INIT; + + strbuf_grow(&sb, 64); + va_start(ap, fmt); + len = vsnprintf(sb.buf + sb.len, sb.alloc - sb.len, fmt, ap); + va_end(ap); + if (len < 0) + die("your vsnprintf is broken"); + if (len > strbuf_avail(&sb)) { + strbuf_grow(&sb, len); + va_start(ap, fmt); + len = vsnprintf(sb.buf + sb.len, sb.alloc - sb.len, fmt, ap); + va_end(ap); + if (len > strbuf_avail(&sb)) { + die("this should not happen, your snprintf is broken"); + } + } + strbuf_setlen(&sb, sb.len + len); + len = write(sf->fd, sb.buf, sb.len); + strbuf_release(&sb); + return len; +} + +void sfclearerr(struct strbuf_file *sf) +{ + sf->has_error = 0; +} + +int sfread(char *buf, int size, int n, struct strbuf_file *sf) +{ + int avail = size * n; + int len = avail > sf->input.len ? sf->input.len : avail; + char *p; + struct strbuf *sb = &sf->input; + + if (len) { + memcpy(buf, sb->buf, len); + strbuf_setlen(sb, sb->len - len); + avail -= len; + } + + p = buf + len; + while ((len = read(sf->fd, p, avail)) > 0) { + p += len; + avail -= len; + if (!avail) + break; + } + if (len == -1) + sf->has_error = 1; + /* just in case we have some leftover */ + if ((p-buf) % size) { + len = (p-buf) % size; + strbuf_grow(sb, len); + strbuf_add(sb, p-len, len); + } + return (p-buf) / size; +} + +int sfgetc(struct strbuf_file *sf) +{ + int ret; + char ch; + if (sf->input.len) { + ret = sf->input.buf[0]; + memcpy(sf->input.buf, sf->input.buf+1, sf->input.len); + sf->input.len--; + return ret; + } + ret = read(sf->fd, &ch, 1); + if (ret > 0) + return ch; + if (ret == -1) + sf->has_error = 1; + return EOF; +} + +char *sfgets(char *buf, int size, struct strbuf_file *sf) +{ + char *p = buf; + int ch = -1; + while (size > 1 && (ch = sfgetc(sf)) != EOF) { + *p++ = ch; + size--; + if (ch == '\n') + break; + } + if (p > buf && size > 0) { + *p++ = '\0'; + return buf; + } + return NULL; +} -- cgit v1.2.3-55-g6feb