diff options
author | portix <portix@gmx.net> | 2013-05-20 01:37:09 +0200 |
---|---|---|
committer | portix <portix@gmx.net> | 2013-05-20 01:37:09 +0200 |
commit | 044e8c48518b72dee66121a06951c0ca256a827a (patch) | |
tree | 96780c9e62c9916ce4769c7b2c0daa1742420c42 | |
parent | 0a888d838e370623d7d741f72b3b5c4022bca7fa (diff) | |
download | dwb-044e8c48518b72dee66121a06951c0ca256a827a.zip |
Append nullterminated filename to exar-header
-rw-r--r-- | exar/exar.c | 267 | ||||
-rw-r--r-- | exar/exar.h | 18 |
2 files changed, 153 insertions, 132 deletions
diff --git a/exar/exar.c b/exar/exar.c index 0e466934..b742bc16 100644 --- a/exar/exar.c +++ b/exar/exar.c @@ -27,6 +27,7 @@ #include <stdarg.h> #include <unistd.h> #include <ftw.h> +#include <errno.h> #include <assert.h> #include "exar.h" @@ -34,23 +35,34 @@ #define EXAR_VERSION EXAR_VERSION_BASE "1" #define EXTENSION "exar" -#define SZ_VERSION 8 +#define SZ_VERSION 7 #define SZ_DFLAG 1 -#define SZ_NAME 100 -#define SZ_SIZE 12 -#define SZ_CHKSUM 7 +#define SZ_SIZE 14 -#define HDR_NAME (0) -#define HDR_DFLAG (HDR_NAME + SZ_NAME) +#define HDR_DFLAG (0) #define HDR_SIZE (HDR_DFLAG + SZ_DFLAG) -#define HDR_CHKSUM (HDR_SIZE + SZ_SIZE) -#define HDR_END (HDR_CHKSUM + SZ_CHKSUM) +#define HDR_NAME (HDR_SIZE + SZ_SIZE) #define DIR_FLAG (100) #define FILE_FLAG (102) + #define MAX_FILE_HANDLES 64 + #define MIN(X, Y) ((X) > (Y) ? (Y) : (X)) +#define EXAR_NAME_MAX 4096 + +#define EE_OK 0 +#define EE_ERROR -1 +#define EE_EOF -2 + +struct exar_header_s { + unsigned char eh_flag; + size_t eh_size; + char eh_name[EXAR_NAME_MAX]; +}; + + #define LOG(level, ...) do { if (s_verbose & EXAR_VERBOSE_L##level) { \ fprintf(stderr, "exar-log%d: ", level); \ fprintf(stderr, __VA_ARGS__); } } while(0) @@ -103,12 +115,12 @@ check_version(FILE *f, int verbose) if (fread(version, 1, SZ_VERSION, f) != SZ_VERSION) { if (feof(f)) - return 0; + return EE_EOF; else { if (verbose) fprintf(stderr, "Not an exar file?\n"); - return -1; + return EE_ERROR; } } memcpy(orig_version, EXAR_VERSION, sizeof(orig_version)); @@ -117,7 +129,7 @@ check_version(FILE *f, int verbose) { if (verbose) fprintf(stderr, "Not an exar file?\n"); - return -1; + return EE_ERROR; } LOG(1, "Found version %s\n", version); @@ -125,9 +137,9 @@ check_version(FILE *f, int verbose) { if (verbose) fprintf(stderr, "Incompatible version number\n"); - return -1; + return EE_ERROR; } - return 0; + return EE_OK; } static int write_version_header(FILE *f) @@ -139,9 +151,9 @@ write_version_header(FILE *f) if (fwrite(version, 1, sizeof(version), f) != sizeof(version)) { fprintf(stderr, "Failed to write %zu bytes", sizeof(version)); - return -1; + return EE_ERROR; } - return 0; + return EE_OK; } /* * Opens archive and checks version, mode is either read or read-write @@ -167,82 +179,76 @@ close_file(FILE *f, const char *archive) fclose(f); } } -static int -get_chksum(char *header) -{ - int chksum = 0; - for (int i=0; i<HDR_CHKSUM; i++) - { - chksum += (unsigned char)*header; - header++; - } - LOG(3, "Computing checksum (%d)\n", chksum); - return chksum; -} static int -get_file_header(FILE *f, char *name, char *flag, size_t *size) +get_file_header(FILE *f, struct exar_header_s *head) { char *endptr; - char header[HDR_END]; + char header[HDR_NAME]; size_t fs; - int chksum, fsum = 0; - *size = 0; + char rb; + size_t i = 0; + int st_version = 0; - if (check_version(f, 1) != 0) - return -1; + if ((st_version = check_version(f, 1)) != 0) + return st_version; LOG(2, "Reading file header\n"); - if (fread(header, 1, HDR_END, f) != HDR_END) - return -1; - - LOG(3, "Checking checksums\n"); - chksum = get_chksum(header); - fsum = strtoul(&header[HDR_CHKSUM], &endptr, 8); - if (*endptr || fsum != chksum) + if (fread(header, 1, HDR_NAME, f) != HDR_NAME) { - LOG(1, "Checksums differ (found: %d expected: %d)\n", chksum, fsum); - fprintf(stderr, "The archive seems to be corrupted\n"); - return -1; + fprintf(stderr, "Reading file header failed"); + return EE_ERROR; } - header[SZ_NAME-1] = 0; - strncpy(name, header, SZ_NAME); + head->eh_flag = header[HDR_DFLAG]; - *flag = header[HDR_DFLAG]; - - if (*flag != DIR_FLAG && *flag != FILE_FLAG) + if (head->eh_flag != DIR_FLAG && head->eh_flag != FILE_FLAG) { - LOG(1, "No file flag found for %s\n", name); + LOG(1, "No file flag found\n"); fprintf(stderr, "The archive seems to be corrupted\n"); - return -1; + return EE_ERROR; } - if (*flag == FILE_FLAG) + if (head->eh_flag == FILE_FLAG) { fs = strtoul(&header[HDR_SIZE], &endptr, 8); if (*endptr) { - LOG(1, "Cannot determine file size for %s\n", name); + LOG(1, "Cannot determine file size\n"); fprintf(stderr, "The archive seems to be corrupted\n"); - return -1; + return EE_ERROR; } - *size = fs; + head->eh_size = fs; } - LOG(2, "Found file header (%s, %c, %zu, %d)\n", name, *flag, *size, chksum); - return 0; + else + head->eh_size = 0; + + while (fread(&rb, 1, 1, f) > 0) + { + head->eh_name[i] = rb; + i++; + if (rb == '\0') + break; + else if (i == EXAR_NAME_MAX) + { + fprintf(stderr, "Cannot get filename\n"); + return EE_ERROR; + } + } + + LOG(2, "Found file header (%s, %c, %zu)\n", head->eh_name, head->eh_flag, head->eh_size); + return EE_OK; } static int find_cmp(const char *name, const char *search) { - char buffer[SZ_NAME]; - size_t offset = get_offset(buffer, SZ_NAME, name, NULL); + char buffer[EXAR_NAME_MAX]; + size_t offset = get_offset(buffer, EXAR_NAME_MAX, name, NULL); return strcmp(&name[offset], search); } static unsigned char * extract(const char *archive, const char *file, size_t *s, int (*cmp)(const char *, const char *)) { - char name[SZ_NAME] = {0}, flag = 0; - size_t fs = 0; + struct exar_header_s header; FILE *f = NULL; unsigned char *ret = NULL; if (s != NULL) @@ -250,23 +256,23 @@ extract(const char *archive, const char *file, size_t *s, int (*cmp)(const char if ((f = open_archive(archive, "r")) == NULL) goto finish; - while (get_file_header(f, name, &flag, &fs) == 0) + while (get_file_header(f, &header) == 0) { - if (cmp(name, file) == 0) + if (cmp(header.eh_name, file) == 0) { - if (flag == FILE_FLAG) + if (header.eh_flag == FILE_FLAG) { - ret = xmalloc(fs); - LOG(3, "Reading %s\n", name); - if (fread(ret, 1, fs, f) != fs) + ret = xmalloc(header.eh_size); + LOG(3, "Reading %s\n", header.eh_name); + if (fread(ret, 1, header.eh_size, f) != header.eh_size) { - fprintf(stderr, "Failed to read %s\n", name); + fprintf(stderr, "Failed to read %s\n", header.eh_name); *s = -1; free(ret); ret = NULL; } else if (s != NULL) - *s = fs; + *s = header.eh_size; } else { @@ -274,10 +280,10 @@ extract(const char *archive, const char *file, size_t *s, int (*cmp)(const char } goto finish; } - else if (flag == FILE_FLAG) + else if (header.eh_flag == FILE_FLAG) { - LOG(3, "Skipping %s\n", name); - fseek(f, fs, SEEK_CUR); + LOG(3, "Skipping %s\n", header.eh_name); + fseek(f, header.eh_size, SEEK_CUR); } } fprintf(stderr, "File %s was not found in %s\n", file, archive); @@ -289,22 +295,31 @@ finish: static int write_file_header(FILE *f, const char *name, char flag, size_t r) { - char buffer[HDR_END] = {0}; - int chksum; + char buffer[HDR_NAME] = {0}; + size_t l_name; + char term = 0; + + l_name = strlen(name); + if (l_name > EXAR_NAME_MAX) + { + fprintf(stderr, "Filename too long\n"); + return EE_ERROR; + } LOG(2, "Writing file header for %s\n", name); if (write_version_header(f) != 0) - return -1; + return EE_ERROR; memset(buffer, 0, sizeof(buffer)); - strncpy(buffer + HDR_NAME, name, SZ_NAME); buffer[HDR_DFLAG] = flag; - snprintf(buffer + HDR_SIZE, SZ_SIZE, "%.11o", (unsigned int)r); - chksum = get_chksum(buffer); - snprintf(buffer + HDR_CHKSUM, SZ_CHKSUM, "%.6o", (unsigned int)chksum); - if (fwrite(buffer, 1, HDR_END, f) != HDR_END) - return -1; - return 0; + snprintf(buffer + HDR_SIZE, SZ_SIZE, "%.13x", (unsigned int)r); + if (fwrite(buffer, 1, HDR_NAME, f) != HDR_NAME) + return EE_ERROR; + if (fwrite(name, 1, l_name, f) != l_name) + return EE_ERROR; + if (fwrite(&term, 1, 1, f) != 1) + return EE_ERROR; + return EE_OK; } @@ -378,12 +393,13 @@ exar_pack(const char *path) if ((s_out = fopen(buffer, "w")) == NULL) { perror(buffer); - return -1; + return EE_ERROR; } ret = ftw(path, pack, MAX_FILE_HANDLES); LOG(3, "Closing %s\n", buffer); + fclose(s_out); return ret; } @@ -393,9 +409,8 @@ exar_unpack(const char *archive, const char *dest) { assert(archive != NULL); - int ret = -1; - char name[SZ_NAME], flag; - size_t fs = 0; + struct exar_header_s header; + int ret = EE_ERROR; FILE *of, *f = NULL; unsigned char buf[512]; size_t r = 0; @@ -416,29 +431,33 @@ exar_unpack(const char *archive, const char *dest) while (1) { - if (get_file_header(f, name, &flag, &fs) != 0) + if (get_file_header(f, &header) != 0) break; - if (flag == DIR_FLAG) + if (header.eh_flag == DIR_FLAG) { - LOG(1, "Creating directory %s\n", name); - mkdir(name, 0755); + LOG(1, "Creating directory %s\n", header.eh_name); + if (mkdir(header.eh_name, 0755) != 0 && errno != EEXIST) + { + perror(header.eh_name); + goto finish; + } } else { - LOG(1, "Unpacking %s\n", name); + LOG(1, "Unpacking %s\n", header.eh_name); - LOG(3, "Opening %s for writing\n", name); - of = fopen(name, "w"); + LOG(3, "Opening %s for writing\n", header.eh_name); + of = fopen(header.eh_name, "w"); if (of == NULL) { - perror(name); + perror(header.eh_name); goto finish; } - LOG(2, "Writing %s (%zu bytes)\n", name, fs); - for (size_t i=0; i<fs; i += sizeof(buf)) + LOG(2, "Writing %s (%zu bytes)\n", header.eh_name, header.eh_size); + for (size_t i=0; i<header.eh_size; i += sizeof(buf)) { - if ( (r = fread(buf, 1, MIN(sizeof(buf), fs-i), f)) != 0) + if ( (r = fread(buf, 1, MIN(sizeof(buf), header.eh_size - i), f)) != 0) { if (fwrite(buf, 1, r, of) != r) { @@ -447,11 +466,11 @@ exar_unpack(const char *archive, const char *dest) } } } - LOG(3, "Closing %s\n", name); + LOG(3, "Closing %s\n", header.eh_name); fclose(of); } } - ret = 0; + ret = EE_OK; finish: close_file(f, archive); return ret; @@ -476,12 +495,11 @@ exar_delete(const char *archive, const char *file) { assert(archive != NULL && file != NULL); - int result = -1; - char name[SZ_NAME] = {0}, flag = 0; - size_t fs = 0; + int result = EE_ERROR; + struct exar_header_s header; FILE *f = NULL, *ftmp = NULL; char tmp_file[128]; - char dir_name[SZ_NAME + 1] = {0}; + char dir_name[EXAR_NAME_MAX-1] = {0}; unsigned char rbuf; size_t dir_length = 0; @@ -499,35 +517,35 @@ exar_delete(const char *archive, const char *file) if ((ftmp = fopen(tmp_file, "w")) == NULL) goto finish; - while (get_file_header(f, name, &flag, &fs) == 0) + while (get_file_header(f, &header) == 0) { - if (strcmp(name, file) == 0) + if (strcmp(header.eh_name, file) == 0) { - if (flag == FILE_FLAG) + if (header.eh_flag == FILE_FLAG) { - LOG(1, "Skipping %s\n", name); - fseek(f, fs, SEEK_CUR); + LOG(1, "Skipping %s\n", header.eh_name); + fseek(f, header.eh_size, SEEK_CUR); } - else if (flag == DIR_FLAG) - dir_length = snprintf(dir_name, sizeof(dir_name), "%s/", name); + else if (header.eh_flag == DIR_FLAG) + dir_length = snprintf(dir_name, sizeof(dir_name), "%s/", header.eh_name); } - else if (*dir_name && strncmp(dir_name, name, dir_length) == 0 && flag == FILE_FLAG) + else if (*dir_name && strncmp(dir_name, header.eh_name, dir_length) == 0 && header.eh_flag == FILE_FLAG) { - LOG(1, "Skipping %s\n", name); - fseek(f, fs, SEEK_CUR); + LOG(1, "Skipping %s\n", header.eh_name); + fseek(f, header.eh_size, SEEK_CUR); } else { - LOG(1, "Packing %s\n", name); - write_file_header(ftmp, name, flag, fs); - if (flag == FILE_FLAG) + LOG(1, "Packing %s\n", header.eh_name); + write_file_header(ftmp, header.eh_name, header.eh_flag, header.eh_size); + if (header.eh_flag == FILE_FLAG) { - LOG(2, "Copying %s (%zu bytes)\n", name, fs); - for (size_t s=0; s<fs; s++) + LOG(2, "Copying %s (%zu bytes)\n", header.eh_name, header.eh_size); + for (size_t s=0; s<header.eh_size; s++) { if (fread(&rbuf, 1, 1, f) != 1 || fwrite(&rbuf, 1, 1, ftmp) != 1) { - fprintf(stderr, "Error copying %s\n", name); + fprintf(stderr, "Error copying %s\n", header.eh_name); goto finish; } } @@ -538,7 +556,7 @@ exar_delete(const char *archive, const char *file) if (rename(tmp_file, archive) == -1) perror(archive); else - result = 0; + result = EE_OK; finish: close_file(f, archive); close_file(ftmp, tmp_file); @@ -548,16 +566,15 @@ void exar_info(const char *archive) { FILE *f = NULL; - char name[SZ_NAME], flag; - size_t fs; + struct exar_header_s header; if ((f = open_archive(archive, "r")) == NULL) goto finish; - while(get_file_header(f, name, &flag, &fs) == 0) + while(get_file_header(f, &header) == 0) { - fprintf(stdout, "%c %-12zu %s\n", flag, fs, name); - if (flag == FILE_FLAG) - fseek(f, fs, SEEK_CUR); + fprintf(stdout, "%c %-12zu %s\n", header.eh_flag, header.eh_size, header.eh_name); + if (header.eh_flag == FILE_FLAG) + fseek(f, header.eh_size, SEEK_CUR); } finish: close_file(f, archive); diff --git a/exar/exar.h b/exar/exar.h index ca061761..cb7a489d 100644 --- a/exar/exar.h +++ b/exar/exar.h @@ -25,19 +25,23 @@ * * File format: * - * [version header][file header][file][version header][file header][file][version ... + * [file header][file][file header][file][file he... * - * file header : 128 bytes - * - version : 8 bytes - * - filename : 100 bytes, (char*) - * - directory flag(d|f) : 1 byte (char) - * - file size : 12 bytes (char*, octal representation) - * - checksum: : 7 bytes (char*, octal representation) + * file header : - file info 22 bytes + * - 7 bytes version header, null terminated (char) + * - 1 byte filetype flag (d|f) (char) + * - 14 byte file size, null terminated (char, hex) + * - file name, null terminated, maximum 4096 bytes + * file : saved as unsigned char * */ #ifndef __EXAR_H__ #define __EXAR_H__ +#include <stdio.h> + + + enum { EXAR_VERBOSE_L1 = 1<<0, EXAR_VERBOSE_L2 = 1<<1, |