summaryrefslogtreecommitdiffstats
path: root/src/opk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/opk.c')
-rw-r--r--src/opk.c121
1 files changed, 103 insertions, 18 deletions
diff --git a/src/opk.c b/src/opk.c
index db35cab..62b09f2 100644
--- a/src/opk.c
+++ b/src/opk.c
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
#include <time.h>
#include "defs.h"
#include "gzip.h"
@@ -41,6 +42,7 @@ struct opkg_opk_opk {
struct _opkg_opk_opk_seek_name *print_data_tail;
int list_control;
int list_data;
+ const char *control_dir;
FILE *file;
char file_buffer[8192];
struct opkg_opk_gzip *outer_gzip;
@@ -66,6 +68,7 @@ opkg_opk_opk_init(void)
opk->print_data_tail = NULL;
opk->list_control = 0;
opk->list_data = 0;
+ opk->control_dir = NULL;
opk->previously_printed = 0;
return opk;
@@ -128,6 +131,13 @@ opkg_opk_opk_list_data(struct opkg_opk_opk *opk)
return OPKG_OPK_OK;
}
+int
+opkg_opk_opk_control_dir(struct opkg_opk_opk *opk, const char *dir)
+{
+ opk->control_dir = dir;
+ return OPKG_OPK_OK;
+}
+
static int
_opkg_opk_opk_file_read(void *user_data, char **buffer, size_t *size)
{
@@ -213,58 +223,116 @@ _opkg_opk_opk_check_name(const char *member_name,
static int
_opkg_opk_opk_read_control(struct opkg_opk_opk *opk)
{
+ struct stat stat_buf;
+ char *path;
struct opkg_opk_ustar_member *member;
int ret_list;
+ FILE *fp;
+ int print;
int ret_read;
char *buffer;
size_t size;
struct _opkg_opk_opk_seek_name *seek_name;
- if (opk->list_control == 0 && opk->print_control_head == NULL) {
+ if (opk->control_dir != NULL) {
+ if (stat(opk->control_dir, &stat_buf) == 0) {
+ if (!S_ISDIR(stat_buf.st_mode)) {
+ fputs(_("Error: Cannot create control directory"
+ "\n"), stderr);
+ return OPKG_OPK_ERROR;
+ }
+ } else if (mkdir(opk->control_dir, 0755) != 0) {
+ fputs(_("Error: Cannot create control directory"
+ "\n"), stderr);
+ return OPKG_OPK_ERROR;
+ }
+ path = malloc(strlen(opk->control_dir) +
+ OPKG_OPK_USTAR_NAME_SIZE + 1);
+ if (path == NULL) {
+ return OPKG_OPK_ERROR;
+ }
+ } else if (opk->list_control == 0 && opk->print_control_head == NULL) {
/* Not listing or printing any control files. */
return OPKG_OPK_OK;
}
if (_opkg_opk_opk_init_inner(opk) != OPKG_OPK_OK) {
+ if (opk->control_dir != NULL) {
+ free(path);
+ }
return OPKG_OPK_ERROR;
}
while ((ret_list = opkg_opk_ustar_list(opk->inner_ustar, &member)) ==
OPKG_OPK_OK) {
- if (opk->list_control > 0) {
- buffer = member->name;
- if (buffer[0] == '.' && buffer[1] == '/') {
- buffer += 2;
+ /* Remove leading "./" if present and skip if nothing's left. */
+ buffer = member->name;
+ if (buffer[0] == '.' && buffer[1] == '/') {
+ buffer += 2;
+ }
+ if (buffer[0] == '\0') {
+ free(member);
+ continue;
+ }
+
+ /* Open file for extraction. */
+ if (opk->control_dir != NULL) {
+ if (sprintf(path, "%s/%s", opk->control_dir,
+ member->name) <= 0) {
+ free(member);
+ _opkg_opk_opk_free_inner(opk);
+ free(path);
+ return OPKG_OPK_ERROR;
}
- if (buffer[0] != '\0') {
- puts(buffer);
- opk->previously_printed = 1;
+ fp = fopen(path, "wb");
+ if (fp == NULL) {
+ fputs(_("Error: Failed to extract control file"
+ "\n"), stderr);
+ free(member);
+ _opkg_opk_opk_free_inner(opk);
+ free(path);
+ return OPKG_OPK_ERROR;
}
}
- if (opk->print_control_head == NULL) {
- free(member);
- continue;
+ if (opk->list_control > 0) {
+ puts(buffer);
+ opk->previously_printed = 1;
}
- if (_opkg_opk_opk_check_name(member->name,
+
+ if (opk->print_control_head != NULL &&
+ _opkg_opk_opk_check_name(member->name,
&opk->print_control_head,
- &opk->print_control_tail) !=
+ &opk->print_control_tail) ==
OPKG_OPK_OK) {
- /* Name not requested for printing. */
- free(member);
- continue;
+ /* Name requested for printing. */
+ print = 1;
+ } else {
+ print = 0;
}
free(member);
- if (opk->previously_printed == 1) {
+ if (print == 1 && opk->previously_printed == 1) {
puts("");
}
while ((ret_read = opkg_opk_ustar_read(opk->inner_ustar,
&buffer, &size)) == OPKG_OPK_OK)
{
- if (fwrite(buffer, 1, size, stdout) != size) {
+ if (print == 1 && fwrite(buffer, 1, size, stdout) !=
+ size) {
fputs(_("Error: Failed to print control file\n")
, stderr);
_opkg_opk_opk_free_inner(opk);
+ if (opk->control_dir != NULL) {
+ free(path);
+ }
+ return OPKG_OPK_ERROR;
+ }
+ if (opk->control_dir != NULL && fwrite(buffer, 1, size,
+ fp) != size) {
+ fputs(_("Error: Failed to write control file\n")
+ , stderr);
+ _opkg_opk_opk_free_inner(opk);
+ free(path);
return OPKG_OPK_ERROR;
}
}
@@ -272,9 +340,25 @@ _opkg_opk_opk_read_control(struct opkg_opk_opk *opk)
fputs(_("Error: Failed to read control file\n"),
stderr);
_opkg_opk_opk_free_inner(opk);
+ if (opk->control_dir != NULL) {
+ free(path);
+ }
return OPKG_OPK_ERROR;
}
opk->previously_printed = 1;
+
+ /* Close file for extraction. */
+ if (opk->control_dir != NULL) {
+ if (fclose(fp) != 0) {
+ _opkg_opk_opk_free_inner(opk);
+ free(path);
+ return OPKG_OPK_ERROR;
+ }
+ }
+ }
+ if (opk->control_dir != NULL) {
+ /* Done with path buffer. */
+ free(path);
}
if (ret_list == OPKG_OPK_ERROR) {
fputs(_("Error: Failed to list control files\n"), stderr);
@@ -337,6 +421,7 @@ _opkg_opk_opk_read_data(struct opkg_opk_opk *opk)
size_max = 0;
while ((ret = opkg_opk_ustar_list(opk->inner_ustar, &member)) ==
OPKG_OPK_OK) {
+ /* If listing, link members and update max column widths. */
if (opk->list_data > 0) {
if (head == NULL) {
head = member;