diff options
author | kientzle <kientzle@FreeBSD.org> | 2009-04-17 01:01:15 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2009-04-17 01:01:15 +0000 |
commit | 4fc369c955c149ac6d739e592667c90ba1986a97 (patch) | |
tree | 636739847bb56aa119a279d2552d9176ecdfae0f /lib/libarchive | |
parent | 89890db5f1bc854480bafcdf319941de52ebbcdd (diff) | |
download | FreeBSD-src-4fc369c955c149ac6d739e592667c90ba1986a97.zip FreeBSD-src-4fc369c955c149ac6d739e592667c90ba1986a97.tar.gz |
Dynamically size the buffer we pass to getgrgid_r() and getpwuid_r().
Keep the buffer in the cache object so we don't have to keep doing this.
Diffstat (limited to 'lib/libarchive')
-rw-r--r-- | lib/libarchive/archive_read_disk_set_standard_lookup.c | 73 |
1 files changed, 57 insertions, 16 deletions
diff --git a/lib/libarchive/archive_read_disk_set_standard_lookup.c b/lib/libarchive/archive_read_disk_set_standard_lookup.c index 68e8074..60054f9 100644 --- a/lib/libarchive/archive_read_disk_set_standard_lookup.c +++ b/lib/libarchive/archive_read_disk_set_standard_lookup.c @@ -61,6 +61,8 @@ static const char * const NO_NAME = "(noname)"; struct name_cache { struct archive *archive; + char *buff; + size_t buff_size; int probes; int hits; size_t size; @@ -73,8 +75,8 @@ struct name_cache { static const char * lookup_gname(void *, gid_t); static const char * lookup_uname(void *, uid_t); static void cleanup(void *); -static const char * lookup_gname_helper(struct archive *, id_t gid); -static const char * lookup_uname_helper(struct archive *, id_t uid); +static const char * lookup_gname_helper(struct name_cache *, id_t gid); +static const char * lookup_uname_helper(struct name_cache *, id_t uid); /* * Installs functions that use getpwuid()/getgrgid()---along with @@ -128,6 +130,7 @@ cleanup(void *data) cache->cache[i].name != NO_NAME) free((void *)(uintptr_t)cache->cache[i].name); } + free(cache->buff); free(cache); } } @@ -137,7 +140,7 @@ cleanup(void *data) */ static const char * lookup_name(struct name_cache *cache, - const char * (*lookup_fn)(struct archive *, id_t), id_t id) + const char * (*lookup_fn)(struct name_cache *, id_t), id_t id) { const char *name; int slot; @@ -158,7 +161,7 @@ lookup_name(struct name_cache *cache, cache->cache[slot].name = NULL; } - name = (lookup_fn)(cache->archive, id); + name = (lookup_fn)(cache, id); if (name == NULL) { /* Cache and return the negative response. */ cache->cache[slot].name = NO_NAME; @@ -180,23 +183,43 @@ lookup_uname(void *data, uid_t uid) } static const char * -lookup_uname_helper(struct archive *a, id_t id) +lookup_uname_helper(struct name_cache *cache, id_t id) { - char buffer[512]; struct passwd pwent, *result; int r; - errno = 0; - r = getpwuid_r((uid_t)id, &pwent, buffer, sizeof(buffer), &result); + if (cache->buff_size == 0) { + cache->buff_size = 256; + cache->buff = malloc(cache->buff_size); + } + if (cache->buff == NULL) + return (NULL); + for (;;) { + r = getpwuid_r((uid_t)id, &pwent, + cache->buff, cache->buff_size, &result); + if (r == 0) + break; + if (r != ERANGE) + break; + /* ERANGE means our buffer was too small, but POSIX + * doesn't tell us how big the buffer should be, so + * we just double it and try again. Because the buffer + * is kept around in the cache object, we shouldn't + * have to do this very often. */ + cache->buff_size *= 2; + cache->buff = realloc(cache->buff, cache->buff_size); + if (cache->buff == NULL) + break; + } if (r != 0) { - archive_set_error(a, errno, + archive_set_error(cache->archive, errno, "Can't lookup user for id %d", (int)id); return (NULL); } if (result == NULL) return (NULL); - return strdup(pwent.pw_name); + return strdup(result->pw_name); } static const char * @@ -208,22 +231,40 @@ lookup_gname(void *data, gid_t gid) } static const char * -lookup_gname_helper(struct archive *a, id_t id) +lookup_gname_helper(struct name_cache *cache, id_t id) { - char buffer[512]; struct group grent, *result; int r; - errno = 0; - r = getgrgid_r((gid_t)id, &grent, buffer, sizeof(buffer), &result); + if (cache->buff_size == 0) { + cache->buff_size = 256; + cache->buff = malloc(cache->buff_size); + } + if (cache->buff == NULL) + return (NULL); + for (;;) { + r = getgrgid_r((gid_t)id, &grent, + cache->buff, cache->buff_size, &result); + if (r == 0) + break; + if (r != ERANGE) + break; + /* ERANGE means our buffer was too small, but POSIX + * doesn't tell us how big the buffer should be, so + * we just double it and try again. */ + cache->buff_size *= 2; + cache->buff = realloc(cache->buff, cache->buff_size); + if (cache->buff == NULL) + break; + } if (r != 0) { - archive_set_error(a, errno, + archive_set_error(cache->archive, errno, "Can't lookup group for id %d", (int)id); return (NULL); } if (result == NULL) return (NULL); - return strdup(grent.gr_name); + return strdup(result->gr_name); } #endif /* ! (_WIN32 && !__CYGWIN__) */ |