summaryrefslogtreecommitdiffstats
path: root/lib/libalpm/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/util.c')
-rw-r--r--lib/libalpm/util.c88
1 files changed, 54 insertions, 34 deletions
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index 12286c6a..a60062bc 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -158,12 +158,10 @@ int _alpm_copyfile(const char *src, const char *dest)
}
}
- /* chmod dest to permissions of src, as long as it is not a symlink */
+ /* chmod dest to permissions of src */
struct stat statbuf;
- if(!stat(src, &statbuf)) {
- if(! S_ISLNK(statbuf.st_mode)) {
- fchmod(fileno(out), statbuf.st_mode);
- }
+ if(!fstat(fileno(in), &statbuf)) {
+ fchmod(fileno(out), statbuf.st_mode);
} else {
/* stat was unsuccessful */
ret = 1;
@@ -311,18 +309,11 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix,
}
while(archive_read_next_header(_archive, &entry) == ARCHIVE_OK) {
- const struct stat *st;
- const char *entryname; /* the name of the file in the archive */
+ const char *entryname;
+ mode_t mode;
- st = archive_entry_stat(entry);
entryname = archive_entry_pathname(entry);
- if(S_ISREG(st->st_mode)) {
- archive_entry_set_perm(entry, 0644);
- } else if(S_ISDIR(st->st_mode)) {
- archive_entry_set_perm(entry, 0755);
- }
-
/* If specific files were requested, skip entries that don't match. */
if(list) {
char *entry_prefix = strdup(entryname);
@@ -343,6 +334,13 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix,
}
}
+ mode = archive_entry_mode(entry);
+ if(S_ISREG(mode)) {
+ archive_entry_set_perm(entry, 0644);
+ } else if(S_ISDIR(mode)) {
+ archive_entry_set_perm(entry, 0755);
+ }
+
/* Extract the archive entry. */
int readret = archive_read_extract(_archive, entry, 0);
if(readret == ARCHIVE_WARN) {
@@ -553,6 +551,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]
}
umask(0022);
execv(path, argv);
+ /* execv only returns if there was an error */
fprintf(stderr, _("call to execv failed (%s)\n"), strerror(errno));
exit(1);
} else {
@@ -914,16 +913,16 @@ int _alpm_test_checksum(const char *filepath, const char *expected,
/* Note: does NOT handle sparse files on purpose for speed. */
int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)
{
- char *i = NULL;
- int64_t offset;
- int done = 0;
-
/* ensure we start populating our line buffer at the beginning */
b->line_offset = b->line;
while(1) {
+ size_t block_remaining;
+ char *eol;
+
/* have we processed this entire block? */
if(b->block + b->block_size == b->block_offset) {
+ int64_t offset;
if(b->ret == ARCHIVE_EOF) {
/* reached end of archive on the last read, now we are out of data */
goto cleanup;
@@ -933,20 +932,20 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)
b->ret = archive_read_data_block(a, (void *)&b->block,
&b->block_size, &offset);
b->block_offset = b->block;
+ block_remaining = b->block_size;
/* error, cleanup */
if(b->ret < ARCHIVE_OK) {
goto cleanup;
}
+ } else {
+ block_remaining = b->block + b->block_size - b->block_offset;
}
- /* loop through the block looking for EOL characters */
- for(i = b->block_offset; i < (b->block + b->block_size); i++) {
- /* check if read value was null or newline */
- if(*i == '\0' || *i == '\n') {
- done = 1;
- break;
- }
+ /* look through the block looking for EOL characters */
+ eol = memchr(b->block_offset, '\n', block_remaining);
+ if(!eol) {
+ eol = memchr(b->block_offset, '\0', block_remaining);
}
/* allocate our buffer, or ensure our existing one is big enough */
@@ -956,8 +955,10 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)
b->line_size = b->block_size + 1;
b->line_offset = b->line;
} else {
- size_t needed = (size_t)((b->line_offset - b->line)
- + (i - b->block_offset) + 1);
+ /* note: we know eol > b->block_offset and b->line_offset > b->line,
+ * so we know the result is unsigned and can fit in size_t */
+ size_t new = eol ? (size_t)(eol - b->block_offset) : block_remaining;
+ size_t needed = (size_t)((b->line_offset - b->line) + new + 1);
if(needed > b->max_line_size) {
b->ret = -ERANGE;
goto cleanup;
@@ -974,11 +975,11 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)
}
}
- if(done) {
- size_t len = (size_t)(i - b->block_offset);
+ if(eol) {
+ size_t len = (size_t)(eol - b->block_offset);
memcpy(b->line_offset, b->block_offset, len);
b->line_offset[len] = '\0';
- b->block_offset = ++i;
+ b->block_offset = eol + 1;
/* this is the main return point; from here you can read b->line */
return ARCHIVE_OK;
} else {
@@ -986,7 +987,7 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)
size_t len = (size_t)(b->block + b->block_size - b->block_offset);
memcpy(b->line_offset, b->block_offset, len);
b->line_offset += len;
- b->block_offset = i;
+ b->block_offset = b->block + b->block_size;
/* there was no new data, return what is left; saved ARCHIVE_EOF will be
* returned on next call */
if(len == 0) {
@@ -1103,8 +1104,12 @@ off_t _alpm_strtoofft(const char *line)
return (off_t)result;
}
-time_t _alpm_parsedate(const char *line)
+alpm_time_t _alpm_parsedate(const char *line)
{
+ char *end;
+ long long result;
+ errno = 0;
+
if(isalpha((unsigned char)line[0])) {
/* initialize to null in case of failure */
struct tm tmp_tm;
@@ -1112,9 +1117,24 @@ time_t _alpm_parsedate(const char *line)
setlocale(LC_TIME, "C");
strptime(line, "%a %b %e %H:%M:%S %Y", &tmp_tm);
setlocale(LC_TIME, "");
- return mktime(&tmp_tm);
+ return (alpm_time_t)mktime(&tmp_tm);
}
- return (time_t)atol(line);
+
+ result = strtoll(line, &end, 10);
+ if (result == 0 && end == line) {
+ /* line was not a number */
+ errno = EINVAL;
+ return 0;
+ } else if (errno == ERANGE) {
+ /* line does not fit in long long */
+ return 0;
+ } else if (*end) {
+ /* line began with a number but has junk left over at the end */
+ errno = EINVAL;
+ return 0;
+ }
+
+ return (alpm_time_t)result;
}
/**