Skip to content

Commit

Permalink
strbuf: instate cleanup rule in case of non-memory errors
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
René Scharfe authored and Junio C Hamano committed Jan 7, 2009
1 parent 2d642a6 commit 2fc6470
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 6 deletions.
11 changes: 9 additions & 2 deletions Documentation/technical/api-strbuf.txt
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,10 @@ Functions

* Adding data to the buffer

NOTE: All of these functions in this section will grow the buffer as
necessary.
NOTE: All of the functions in this section will grow the buffer as necessary.
If they fail for some reason other than memory shortage and the buffer hadn't
been allocated before (i.e. the `struct strbuf` was set to `STRBUF_INIT`),
then they will free() it.

`strbuf_addch`::

Expand Down Expand Up @@ -235,6 +237,11 @@ same behaviour as well.
Read the contents of a file, specified by its path. The third argument
can be used to give a hint about the file size, to avoid reallocs.

`strbuf_readlink`::

Read the target of a symbolic link, specified by its path. The third
argument can be used to give a hint about the size, to avoid reallocs.

`strbuf_getline`::

Read a line from a FILE* pointer. The second argument specifies the line
Expand Down
17 changes: 13 additions & 4 deletions strbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,26 +256,32 @@ size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder,
size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
{
size_t res;
size_t oldalloc = sb->alloc;

strbuf_grow(sb, size);
res = fread(sb->buf + sb->len, 1, size, f);
if (res > 0) {
if (res > 0)
strbuf_setlen(sb, sb->len + res);
}
else if (res < 0 && oldalloc == 0)
strbuf_release(sb);
return res;
}

ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
{
size_t oldlen = sb->len;
size_t oldalloc = sb->alloc;

strbuf_grow(sb, hint ? hint : 8192);
for (;;) {
ssize_t cnt;

cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
if (cnt < 0) {
strbuf_setlen(sb, oldlen);
if (oldalloc == 0)
strbuf_release(sb);
else
strbuf_setlen(sb, oldlen);
return -1;
}
if (!cnt)
Expand All @@ -292,6 +298,8 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)

int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
{
size_t oldalloc = sb->alloc;

if (hint < 32)
hint = 32;

Expand All @@ -311,7 +319,8 @@ int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
/* .. the buffer was too small - try again */
hint *= 2;
}
strbuf_release(sb);
if (oldalloc == 0)
strbuf_release(sb);
return -1;
}

Expand Down

0 comments on commit 2fc6470

Please sign in to comment.