Parse > 2GiB file sizes correctly
We were using atol(), which on 32 bit, cannot handle values greater than 2GiB, which is fail. Switch to a strtoull() wrapper function tailored toward parsing off_t values. This allows parsing of very large positive integer values. off_t is a signed type, but in our usages, we never parse or have a need for negative values, so the function will return -1 on error. Before: $ pacman -Si flightgear-data | grep Size Download Size : 2097152.00 K Installed Size : 2097152.00 K After: $ ./src/pacman/pacman -Si flightgear-data | grep Size Download Size : 2312592.52 KiB Installed Size : 5402896.00 KiB Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
parent
d74dad79b7
commit
234b6ffc2c
6 changed files with 32 additions and 6 deletions
|
@ -619,7 +619,7 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)
|
|||
READ_AND_STORE(info->packager);
|
||||
} else if(strcmp(line, "%REASON%") == 0) {
|
||||
READ_NEXT();
|
||||
info->reason = (alpm_pkgreason_t)atol(line);
|
||||
info->reason = (alpm_pkgreason_t)atoi(line);
|
||||
} else if(strcmp(line, "%SIZE%") == 0) {
|
||||
/* NOTE: the CSIZE and SIZE fields both share the "size" field
|
||||
* in the pkginfo_t struct. This can be done b/c CSIZE
|
||||
|
@ -627,7 +627,7 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)
|
|||
* only used in local databases.
|
||||
*/
|
||||
READ_NEXT();
|
||||
info->size = atol(line);
|
||||
info->size = _alpm_strtoofft(line);
|
||||
/* also store this value to isize */
|
||||
info->isize = info->size;
|
||||
} else if(strcmp(line, "%REPLACES%") == 0) {
|
||||
|
|
|
@ -187,7 +187,7 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t *
|
|||
STRDUP(newpkg->arch, ptr, return -1);
|
||||
} else if(strcmp(key, "size") == 0) {
|
||||
/* size in the raw package is uncompressed (installed) size */
|
||||
newpkg->isize = atol(ptr);
|
||||
newpkg->isize = _alpm_strtoofft(ptr);
|
||||
} else if(strcmp(key, "depend") == 0) {
|
||||
alpm_depend_t *dep = _alpm_splitdep(ptr);
|
||||
newpkg->depends = alpm_list_add(newpkg->depends, dep);
|
||||
|
|
|
@ -566,14 +566,14 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive,
|
|||
* in sync databases, and SIZE is only used in local databases.
|
||||
*/
|
||||
READ_NEXT();
|
||||
pkg->size = atol(line);
|
||||
pkg->size = _alpm_strtoofft(line);
|
||||
/* also store this value to isize if isize is unset */
|
||||
if(pkg->isize == 0) {
|
||||
pkg->isize = pkg->size;
|
||||
}
|
||||
} else if(strcmp(line, "%ISIZE%") == 0) {
|
||||
READ_NEXT();
|
||||
pkg->isize = atol(line);
|
||||
pkg->isize = _alpm_strtoofft(line);
|
||||
} else if(strcmp(line, "%MD5SUM%") == 0) {
|
||||
READ_AND_STORE(pkg->md5sum);
|
||||
} else if(strcmp(line, "%SHA256SUM%") == 0) {
|
||||
|
|
|
@ -299,7 +299,7 @@ alpm_delta_t *_alpm_delta_parse(char *line)
|
|||
tmp2 = tmp;
|
||||
tmp = strchr(tmp, ' ');
|
||||
*(tmp++) = '\0';
|
||||
delta->delta_size = atol(tmp2);
|
||||
delta->delta_size = _alpm_strtoofft(tmp2);
|
||||
|
||||
tmp2 = tmp;
|
||||
tmp = strchr(tmp, ' ');
|
||||
|
|
|
@ -1074,6 +1074,31 @@ unsigned long _alpm_hash_sdbm(const char *str)
|
|||
return hash;
|
||||
}
|
||||
|
||||
off_t _alpm_strtoofft(const char *line)
|
||||
{
|
||||
char *end;
|
||||
unsigned long long result;
|
||||
errno = 0;
|
||||
|
||||
/* we are trying to parse bare numbers only, no leading anything */
|
||||
if(line[0] < '1' || line[0] > '9') {
|
||||
return (off_t)-1;
|
||||
}
|
||||
result = strtoull(line, &end, 10);
|
||||
if (result == 0 && end == line) {
|
||||
/* line was not a number */
|
||||
return (off_t)-1;
|
||||
} else if (result == ULLONG_MAX && errno == ERANGE) {
|
||||
/* line does not fit in unsigned long long */
|
||||
return (off_t)-1;
|
||||
} else if (*end) {
|
||||
/* line began with a number but has junk left over at the end */
|
||||
return (off_t)-1;
|
||||
}
|
||||
|
||||
return (off_t)result;
|
||||
}
|
||||
|
||||
long _alpm_parsedate(const char *line)
|
||||
{
|
||||
if(isalpha((unsigned char)line[0])) {
|
||||
|
|
|
@ -119,6 +119,7 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b);
|
|||
int _alpm_splitname(const char *target, char **name, char **version,
|
||||
unsigned long *name_hash);
|
||||
unsigned long _alpm_hash_sdbm(const char *str);
|
||||
off_t _alpm_strtoofft(const char *line);
|
||||
long _alpm_parsedate(const char *line);
|
||||
int _alpm_raw_cmp(const char *first, const char *second);
|
||||
int _alpm_raw_ncmp(const char *first, const char *second, size_t max);
|
||||
|
|
Loading…
Add table
Reference in a new issue