1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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)
bb_error_msg_and_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)) {
bb_error_msg_and_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;
}
|