diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2009-04-27 20:14:06 +1000 |
---|---|---|
committer | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2009-04-28 14:31:59 +1000 |
commit | 1756cc5943aa545f2f18fff60d56ad0886ef6145 (patch) | |
tree | 7bbc6daad68365a33898e54ee1a1161b4cfd596a | |
parent | 0c970511cc230abd19c1a30058174cbf03222648 (diff) | |
download | busybox-w32-1756cc5943aa545f2f18fff60d56ad0886ef6145.tar.gz busybox-w32-1756cc5943aa545f2f18fff60d56ad0886ef6145.tar.bz2 busybox-w32-1756cc5943aa545f2f18fff60d56ad0886ef6145.zip |
libbb/strbuf_file: stdio emulation layer for handling with Winsock handles
not really robust, but enough to make wget works
-rw-r--r-- | include/strbuf_file.h | 69 | ||||
-rw-r--r-- | libbb/Kbuild | 1 | ||||
-rw-r--r-- | libbb/strbuf_file.c | 119 |
3 files changed, 189 insertions, 0 deletions
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 @@ | |||
1 | #include "strbuf.h" | ||
2 | |||
3 | struct strbuf_file { | ||
4 | struct strbuf input; | ||
5 | int has_error; | ||
6 | int fd; | ||
7 | }; | ||
8 | |||
9 | struct strbuf_file *sfdopen(int fd, const char *mode); | ||
10 | int sfclose(struct strbuf_file *sf); | ||
11 | int sfprintf(struct strbuf_file *sf, const char *fmt, ...); | ||
12 | void sfclearerr(struct strbuf_file *sf); | ||
13 | int sfread(char *buf, int size, int n, struct strbuf_file *sf); | ||
14 | char *sfgets(char *buf, int size, struct strbuf_file *sf); | ||
15 | int sfgetc(struct strbuf_file *sf); | ||
16 | |||
17 | #ifdef REPLACE_STDIO | ||
18 | |||
19 | #ifdef FILE | ||
20 | #undef FILE | ||
21 | #endif | ||
22 | #define FILE struct strbuf_file | ||
23 | |||
24 | #ifdef fdopen | ||
25 | #undef fdopen | ||
26 | #endif | ||
27 | #define fdopen(fd,mode) sfdopen(fd,mode) | ||
28 | |||
29 | #ifdef fclose | ||
30 | #undef fclose | ||
31 | #endif | ||
32 | #define fclose(fp) sfclose(fp) | ||
33 | |||
34 | #ifdef fprintf | ||
35 | #undef fprintf | ||
36 | #endif | ||
37 | #define fprintf sfprintf | ||
38 | |||
39 | #ifdef fread | ||
40 | #undef fread | ||
41 | #endif | ||
42 | #define fread(buf,s,n,fp) sfread(buf,s,n,fp) | ||
43 | |||
44 | #ifdef clearerr | ||
45 | #undef clearerr | ||
46 | #endif | ||
47 | #define clearerr(fp) sfclearerr(fp) | ||
48 | |||
49 | #ifdef ferror | ||
50 | #undef ferror | ||
51 | #endif | ||
52 | #define ferror(fp) ((fp)->has_error) | ||
53 | |||
54 | #ifdef fgets | ||
55 | #undef fgets | ||
56 | #endif | ||
57 | #define fgets(buf,n,fp) sfgets(buf,n,fp) | ||
58 | |||
59 | #ifdef getc | ||
60 | #undef getc | ||
61 | #endif | ||
62 | #define getc(fp) sfgetc(fp) | ||
63 | |||
64 | #ifdef fflush | ||
65 | #undef fflush | ||
66 | #endif | ||
67 | #define fflush(fp) 0 | ||
68 | |||
69 | #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 | |||
136 | lib-$(CONFIG_MINGW32) += run-command.o | 136 | lib-$(CONFIG_MINGW32) += run-command.o |
137 | lib-$(CONFIG_MINGW32) += setenv.o | 137 | lib-$(CONFIG_MINGW32) += setenv.o |
138 | lib-$(CONFIG_MINGW32) += strbuf.o | 138 | lib-$(CONFIG_MINGW32) += strbuf.o |
139 | lib-$(CONFIG_MINGW32) += strbuf_file.o | ||
139 | lib-$(CONFIG_MINGW32) += strlcpy.o | 140 | lib-$(CONFIG_MINGW32) += strlcpy.o |
140 | lib-$(CONFIG_MINGW32) += trace.o | 141 | lib-$(CONFIG_MINGW32) += trace.o |
141 | lib-$(CONFIG_MINGW32) += usage.o | 142 | 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 @@ | |||
1 | #include "libbb.h" | ||
2 | #include "strbuf_file.h" | ||
3 | |||
4 | struct strbuf_file *sfdopen(int fd, const char *mode) | ||
5 | { | ||
6 | struct strbuf_file *s; | ||
7 | |||
8 | s = xmalloc(sizeof(*s)); | ||
9 | strbuf_init(&s->input, 0); | ||
10 | s->has_error = 0; | ||
11 | s->fd = fd; | ||
12 | return s; | ||
13 | } | ||
14 | |||
15 | int sfclose(struct strbuf_file *sf) | ||
16 | { | ||
17 | strbuf_release(&sf->input); | ||
18 | close(sf->fd); | ||
19 | free(sf); | ||
20 | return 0; | ||
21 | } | ||
22 | |||
23 | int sfprintf(struct strbuf_file *sf, const char *fmt, ...) | ||
24 | { | ||
25 | int len; | ||
26 | va_list ap; | ||
27 | struct strbuf sb = STRBUF_INIT; | ||
28 | |||
29 | strbuf_grow(&sb, 64); | ||
30 | va_start(ap, fmt); | ||
31 | len = vsnprintf(sb.buf + sb.len, sb.alloc - sb.len, fmt, ap); | ||
32 | va_end(ap); | ||
33 | if (len < 0) | ||
34 | die("your vsnprintf is broken"); | ||
35 | if (len > strbuf_avail(&sb)) { | ||
36 | strbuf_grow(&sb, len); | ||
37 | va_start(ap, fmt); | ||
38 | len = vsnprintf(sb.buf + sb.len, sb.alloc - sb.len, fmt, ap); | ||
39 | va_end(ap); | ||
40 | if (len > strbuf_avail(&sb)) { | ||
41 | die("this should not happen, your snprintf is broken"); | ||
42 | } | ||
43 | } | ||
44 | strbuf_setlen(&sb, sb.len + len); | ||
45 | len = write(sf->fd, sb.buf, sb.len); | ||
46 | strbuf_release(&sb); | ||
47 | return len; | ||
48 | } | ||
49 | |||
50 | void sfclearerr(struct strbuf_file *sf) | ||
51 | { | ||
52 | sf->has_error = 0; | ||
53 | } | ||
54 | |||
55 | int sfread(char *buf, int size, int n, struct strbuf_file *sf) | ||
56 | { | ||
57 | int avail = size * n; | ||
58 | int len = avail > sf->input.len ? sf->input.len : avail; | ||
59 | char *p; | ||
60 | struct strbuf *sb = &sf->input; | ||
61 | |||
62 | if (len) { | ||
63 | memcpy(buf, sb->buf, len); | ||
64 | strbuf_setlen(sb, sb->len - len); | ||
65 | avail -= len; | ||
66 | } | ||
67 | |||
68 | p = buf + len; | ||
69 | while ((len = read(sf->fd, p, avail)) > 0) { | ||
70 | p += len; | ||
71 | avail -= len; | ||
72 | if (!avail) | ||
73 | break; | ||
74 | } | ||
75 | if (len == -1) | ||
76 | sf->has_error = 1; | ||
77 | /* just in case we have some leftover */ | ||
78 | if ((p-buf) % size) { | ||
79 | len = (p-buf) % size; | ||
80 | strbuf_grow(sb, len); | ||
81 | strbuf_add(sb, p-len, len); | ||
82 | } | ||
83 | return (p-buf) / size; | ||
84 | } | ||
85 | |||
86 | int sfgetc(struct strbuf_file *sf) | ||
87 | { | ||
88 | int ret; | ||
89 | char ch; | ||
90 | if (sf->input.len) { | ||
91 | ret = sf->input.buf[0]; | ||
92 | memcpy(sf->input.buf, sf->input.buf+1, sf->input.len); | ||
93 | sf->input.len--; | ||
94 | return ret; | ||
95 | } | ||
96 | ret = read(sf->fd, &ch, 1); | ||
97 | if (ret > 0) | ||
98 | return ch; | ||
99 | if (ret == -1) | ||
100 | sf->has_error = 1; | ||
101 | return EOF; | ||
102 | } | ||
103 | |||
104 | char *sfgets(char *buf, int size, struct strbuf_file *sf) | ||
105 | { | ||
106 | char *p = buf; | ||
107 | int ch = -1; | ||
108 | while (size > 1 && (ch = sfgetc(sf)) != EOF) { | ||
109 | *p++ = ch; | ||
110 | size--; | ||
111 | if (ch == '\n') | ||
112 | break; | ||
113 | } | ||
114 | if (p > buf && size > 0) { | ||
115 | *p++ = '\0'; | ||
116 | return buf; | ||
117 | } | ||
118 | return NULL; | ||
119 | } | ||