strbuf: instate cleanup rule in case of non-memory errors
Make all strbuf functions that can fail free() their memory on error if they have allocated it. They don't shrink buffers that have been grown, though. This allows for easier error handling, as callers only need to call strbuf_release() if A) the command succeeded or B) if they would have had to do so anyway because they added something to the strbuf themselves. Bonus hunk: document strbuf_readlink. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>
René Scharfe committed
Jan 6, 2009 at 21:41 UTC
2fc647004ac7016128372a85db8245581e493812
2 files changed
+22
-6
Documentation/technical/api-strbuf.txt
+9
-2
@@ -133,8 +133,10 @@ Functions
133
134
* Adding data to the buffer
135
136
-NOTE: All of these functions in this section will grow the buffer as
137
- necessary.
136
+NOTE: All of the functions in this section will grow the buffer as necessary.
137
+If they fail for some reason other than memory shortage and the buffer hadn't
138
+been allocated before (i.e. the `struct strbuf` was set to `STRBUF_INIT`),
139
+then they will free() it.
140
141
`strbuf_addch`::
142
@@ -235,6 +237,11 @@ same behaviour as well.
237
Read the contents of a file, specified by its path. The third argument
238
can be used to give a hint about the file size, to avoid reallocs.
239
240
+`strbuf_readlink`::
241
+
242
+ Read the target of a symbolic link, specified by its path. The third
243
+ argument can be used to give a hint about the size, to avoid reallocs.
244
+
245
`strbuf_getline`::
246
247
Read a line from a FILE* pointer. The second argument specifies the line
strbuf.c
+13
-4
@@ -256,18 +256,21 @@ size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder,
256
size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
257
{
258
size_t res;
259
+ size_t oldalloc = sb->alloc;
260
261
strbuf_grow(sb, size);
262
res = fread(sb->buf + sb->len, 1, size, f);
262
- if (res > 0) {
263
+ if (res > 0)
264
strbuf_setlen(sb, sb->len + res);
264
- }
265
+ else if (res < 0 && oldalloc == 0)
266
+ strbuf_release(sb);
267
return res;
268
}
269
270
ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
271
{
272
size_t oldlen = sb->len;
273
+ size_t oldalloc = sb->alloc;
274
275
strbuf_grow(sb, hint ? hint : 8192);
276
for (;;) {
@@ -275,7 +278,10 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
278
279
cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
280
if (cnt < 0) {
278
- strbuf_setlen(sb, oldlen);
281
+ if (oldalloc == 0)
282
+ strbuf_release(sb);
283
+ else
284
+ strbuf_setlen(sb, oldlen);
285
return -1;
286
}
287
if (!cnt)
@@ -292,6 +298,8 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
298
299
int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
300
{
301
+ size_t oldalloc = sb->alloc;
302
+
303
if (hint < 32)
304
hint = 32;
305
@@ -311,7 +319,8 @@ int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
319
/* .. the buffer was too small - try again */
320
hint *= 2;
321
}
314
- strbuf_release(sb);
322
+ if (oldalloc == 0)
323
+ strbuf_release(sb);
324
return -1;
325
}
326