summaryrefslogtreecommitdiff
path: root/release/src/router/busybox/archival/libunarchive/get_header_ar.c
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2015-01-03 12:04:58 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2015-01-03 12:04:58 +0100
commit008d0be72b2f160382c6e880765e96b64a050c65 (patch)
tree36f48a98a3815a408e2ce1693dd182af90f80305 /release/src/router/busybox/archival/libunarchive/get_header_ar.c
parent611becfb8726c60cb060368541ad98191d4532f5 (diff)
downloadtomato-008d0be72b2f160382c6e880765e96b64a050c65.tar.gz
tomato-008d0be72b2f160382c6e880765e96b64a050c65.tar.bz2
imported original firmware WRT54GL_v4.30.11_11_US
Diffstat (limited to 'release/src/router/busybox/archival/libunarchive/get_header_ar.c')
-rw-r--r--release/src/router/busybox/archival/libunarchive/get_header_ar.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/release/src/router/busybox/archival/libunarchive/get_header_ar.c b/release/src/router/busybox/archival/libunarchive/get_header_ar.c
new file mode 100644
index 00000000..6c576a8d
--- /dev/null
+++ b/release/src/router/busybox/archival/libunarchive/get_header_ar.c
@@ -0,0 +1,122 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "unarchive.h"
+#include "libbb.h"
+
+extern char get_header_ar(archive_handle_t *archive_handle)
+{
+ file_header_t *typed = archive_handle->file_header;
+ union {
+ char raw[60];
+ struct {
+ char name[16];
+ char date[12];
+ char uid[6];
+ char gid[6];
+ char mode[8];
+ char size[10];
+ char magic[2];
+ } formated;
+ } ar;
+#ifdef CONFIG_FEATURE_AR_LONG_FILENAMES
+ static char *ar_long_names;
+ static unsigned int ar_long_name_size;
+#endif
+
+ /* dont use bb_xread as we want to handle the error ourself */
+ if (read(archive_handle->src_fd, ar.raw, 60) != 60) {
+ /* End Of File */
+ return(EXIT_FAILURE);
+ }
+
+ /* Some ar entries have a trailing '\n' after the previous data entry */
+ if (ar.raw[0] == '\n') {
+ /* fix up the header, we started reading 1 byte too early */
+ memmove(ar.raw, &ar.raw[1], 59);
+ ar.raw[59] = bb_xread_char(archive_handle->src_fd);
+ archive_handle->offset++;
+ }
+ archive_handle->offset += 60;
+
+ /* align the headers based on the header magic */
+ if ((ar.formated.magic[0] != '`') || (ar.formated.magic[1] != '\n')) {
+ bb_error_msg_and_die("Invalid ar header");
+ }
+
+ typed->mode = strtol(ar.formated.mode, NULL, 8);
+ typed->mtime = atoi(ar.formated.date);
+ typed->uid = atoi(ar.formated.uid);
+ typed->gid = atoi(ar.formated.gid);
+ typed->size = atoi(ar.formated.size);
+
+ /* long filenames have '/' as the first character */
+ if (ar.formated.name[0] == '/') {
+#ifdef CONFIG_FEATURE_AR_LONG_FILENAMES
+ if (ar.formated.name[1] == '/') {
+ /* If the second char is a '/' then this entries data section
+ * stores long filename for multiple entries, they are stored
+ * in static variable long_names for use in future entries */
+ ar_long_name_size = typed->size;
+ ar_long_names = xmalloc(ar_long_name_size);
+ bb_xread_all(archive_handle->src_fd, ar_long_names, ar_long_name_size);
+ archive_handle->offset += ar_long_name_size;
+ /* This ar entries data section only contained filenames for other records
+ * they are stored in the static ar_long_names for future reference */
+ return (get_header_ar(archive_handle)); /* Return next header */
+ } else if (ar.formated.name[1] == ' ') {
+ /* This is the index of symbols in the file for compilers */
+ data_skip(archive_handle);
+ return (get_header_ar(archive_handle)); /* Return next header */
+ } else {
+ /* The number after the '/' indicates the offset in the ar data section
+ (saved in variable long_name) that conatains the real filename */
+ const unsigned int long_offset = atoi(&ar.formated.name[1]);
+ if (long_offset >= ar_long_name_size) {
+ bb_error_msg_and_die("Cant resolve long filename");
+ }
+ typed->name = bb_xstrdup(ar_long_names + long_offset);
+ }
+#else
+ bb_error_msg_and_die("long filenames not supported");
+#endif
+ } else {
+ /* short filenames */
+ typed->name = bb_xstrndup(ar.formated.name, 16);
+ }
+
+ typed->name[strcspn(typed->name, " /")] = '\0';
+
+ if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
+ archive_handle->action_header(typed);
+ if (archive_handle->sub_archive) {
+ while (archive_handle->action_data_subarchive(archive_handle->sub_archive) == EXIT_SUCCESS);
+ } else {
+ archive_handle->action_data(archive_handle);
+ }
+ } else {
+ data_skip(archive_handle);
+ }
+
+ archive_handle->offset += typed->size + 1;
+
+ return(EXIT_SUCCESS);
+}
+