mirror of
https://github.com/clearlinux/swupd-client.git
synced 2026-10-03 15:29:29 +00:00
archive: Use libarchive to check for tar contents
Stop using binary tar to check for tar contents. Use libarchive instead Signed-off-by: Otavio Pontes <otavio.pontes@intel.com>
This commit is contained in:
+6
-50
@@ -906,58 +906,14 @@ int link_or_rename(const char *orig, const char *dest)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* list the tarfile content, and verify it contains only one line equal to the expected hash.
|
||||
* loop through all the content to detect the case where archive contains more than one file.
|
||||
*/
|
||||
static int check_tarfile_content(struct file *file, const char *tarfilename)
|
||||
static int check_single_file_tarball(const char *tarfilename, struct file *file)
|
||||
{
|
||||
int err;
|
||||
char *tarcommand;
|
||||
FILE *tar;
|
||||
int count = 0;
|
||||
char *filename;
|
||||
|
||||
string_or_die(&tarcommand, TAR_COMMAND " -tf %s/download/%s.tar 2> /dev/null", state_dir, file->hash);
|
||||
|
||||
err = access(tarfilename, R_OK);
|
||||
if (err) {
|
||||
goto free_tarcommand;
|
||||
}
|
||||
|
||||
tar = popen(tarcommand, "r");
|
||||
if (tar == NULL) {
|
||||
err = -1;
|
||||
goto free_tarcommand;
|
||||
}
|
||||
|
||||
while (!feof(tar)) {
|
||||
char *c;
|
||||
char buffer[PATH_MAXLEN];
|
||||
|
||||
if (fgets(buffer, PATH_MAXLEN, tar) == NULL) {
|
||||
if (count != 1) {
|
||||
err = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
c = strchr(buffer, '\n');
|
||||
if (c) {
|
||||
*c = 0;
|
||||
}
|
||||
if (c && (c != buffer) && (*(c - 1) == '/')) {
|
||||
/* strip trailing '/' from directory tar */
|
||||
*(c - 1) = 0;
|
||||
}
|
||||
if (strcmp(buffer, file->hash) != 0) {
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
pclose(tar);
|
||||
free_tarcommand:
|
||||
free_string(&tarcommand);
|
||||
string_or_die(&filename, "%s%s", file->hash, file->is_dir ? "/" : "");
|
||||
err = archives_check_single_file_tarball(tarfilename, filename);
|
||||
free(filename);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -1004,7 +960,7 @@ int untar_full_download(void *data)
|
||||
}
|
||||
free_string(&tar_dotfile);
|
||||
|
||||
err = check_tarfile_content(file, tarfile);
|
||||
err = check_single_file_tarball(tarfile, file);
|
||||
if (err) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
+70
-16
@@ -86,6 +86,43 @@ static int copy_data(struct archive *ar, struct archive *aw)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int archive_from_filename(struct archive **a, const char *tarfile)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
if (!a) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*a = archive_read_new();
|
||||
if (!*a) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
r = archive_read_support_format_tar(*a);
|
||||
if (_archive_check_err(*a, r)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = archive_read_support_filter_all(*a);
|
||||
if (_archive_check_err(*a, r)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = archive_read_open_filename(*a, tarfile, 10240);
|
||||
if (_archive_check_err(*a, r)) {
|
||||
/* could not open archive for read */
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
archive_read_close(*a);
|
||||
archive_read_free(*a);
|
||||
return r;
|
||||
}
|
||||
|
||||
int archives_extract_to(const char *tarfile, const char *outputdir)
|
||||
{
|
||||
struct archive *a, *ext;
|
||||
@@ -104,15 +141,9 @@ int archives_extract_to(const char *tarfile, const char *outputdir)
|
||||
flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT;
|
||||
|
||||
/* set up read */
|
||||
a = archive_read_new();
|
||||
r = archive_read_support_format_tar(a);
|
||||
if (_archive_check_err(a, r)) {
|
||||
goto out_read;
|
||||
}
|
||||
|
||||
r = archive_read_support_filter_all(a);
|
||||
if (_archive_check_err(a, r)) {
|
||||
goto out_read;
|
||||
r = archive_from_filename(&a, tarfile);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* set up write */
|
||||
@@ -127,12 +158,6 @@ int archives_extract_to(const char *tarfile, const char *outputdir)
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = archive_read_open_filename(a, tarfile, 10240);
|
||||
if (_archive_check_err(a, r)) {
|
||||
/* could not open archive for read */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* read and write loop */
|
||||
for (;;) {
|
||||
r = archive_read_next_header(a, &entry);
|
||||
@@ -191,8 +216,37 @@ out:
|
||||
* error. If 'goto out' is called, we already have an error we are handling
|
||||
* so don't overwrite that returncode. */
|
||||
archive_write_free(ext);
|
||||
out_read:
|
||||
archive_read_close(a);
|
||||
archive_read_free(a);
|
||||
return r;
|
||||
}
|
||||
|
||||
int archives_check_single_file_tarball(const char *tarfilename, const char *file)
|
||||
{
|
||||
struct archive *a;
|
||||
struct archive_entry *entry;
|
||||
int r;
|
||||
bool found = false;
|
||||
|
||||
/* set up read */
|
||||
r = archive_from_filename(&a, tarfilename);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
if (!found && strcmp(archive_entry_pathname(entry), file) == 0) {
|
||||
found = true;
|
||||
} else {
|
||||
found = false;
|
||||
goto end;
|
||||
}
|
||||
archive_read_data_skip(a);
|
||||
}
|
||||
|
||||
end:
|
||||
archive_read_close(a);
|
||||
archive_read_free(a);
|
||||
|
||||
return found ? 0 : -ENOENT;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,12 @@ extern "C" {
|
||||
*/
|
||||
int archives_extract_to(const char *tarfile, const char *outputdir);
|
||||
|
||||
/*
|
||||
* Check if this tarball is valid and if it contains only one file with the
|
||||
* specified name.
|
||||
*/
|
||||
int archives_check_single_file_tarball(const char *tarfilename, const char *file);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -11,6 +11,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/archives.h"
|
||||
#include "lib/formatter_json.h"
|
||||
#include "lib/list.h"
|
||||
#include "lib/log.h"
|
||||
@@ -18,7 +19,6 @@
|
||||
#include "lib/progress.h"
|
||||
#include "lib/strings.h"
|
||||
#include "lib/sys.h"
|
||||
#include "lib/archives.h"
|
||||
#include "manifest.h"
|
||||
#include "scripts.h"
|
||||
#include "swupd_curl.h"
|
||||
|
||||
Reference in New Issue
Block a user