From f217727c24c3cf1ec566a888ef409302377bb8d3 Mon Sep 17 00:00:00 2001 From: Patrick McDermott Date: Sat, 29 Apr 2023 18:55:16 -0400 Subject: opk: Extract control files --- (limited to 'src/opk.c') 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 #include #include +#include #include #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; -- cgit v0.9.1