Date: Fri, 17 Apr 2009 01:01:15 +0000 (UTC) From: Tim Kientzle <kientzle@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r191178 - head/lib/libarchive Message-ID: <200904170101.n3H11FYi099652@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kientzle Date: Fri Apr 17 01:01:15 2009 New Revision: 191178 URL: http://svn.freebsd.org/changeset/base/191178 Log: 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. Modified: head/lib/libarchive/archive_read_disk_set_standard_lookup.c Modified: head/lib/libarchive/archive_read_disk_set_standard_lookup.c ============================================================================== --- head/lib/libarchive/archive_read_disk_set_standard_lookup.c Fri Apr 17 01:00:11 2009 (r191177) +++ head/lib/libarchive/archive_read_disk_set_standard_lookup.c Fri Apr 17 01:01:15 2009 (r191178) @@ -61,6 +61,8 @@ static const char * const NO_NAME = "(no 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__) */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200904170101.n3H11FYi099652>