summaryrefslogtreecommitdiffstats
path: root/lib/libarchive
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2009-04-17 01:01:15 +0000
committerkientzle <kientzle@FreeBSD.org>2009-04-17 01:01:15 +0000
commit4fc369c955c149ac6d739e592667c90ba1986a97 (patch)
tree636739847bb56aa119a279d2552d9176ecdfae0f /lib/libarchive
parent89890db5f1bc854480bafcdf319941de52ebbcdd (diff)
downloadFreeBSD-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.c73
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__) */
OpenPOWER on IntegriCloud