diff options
author | Stefan Bolte <sbolte@lavabit.com> | 2013-05-15 18:56:17 +0200 |
---|---|---|
committer | Stefan Bolte <sbolte@lavabit.com> | 2013-05-15 18:56:17 +0200 |
commit | 1bff1080c880407262c8bd207fd35986517cb299 (patch) | |
tree | 4fd95df7f3be7c3e395b697b56a5f24e93fc5a8d | |
parent | 08f377719611c4782a165b1398aa6fb01d59eabc (diff) | |
download | dwb-1bff1080c880407262c8bd207fd35986517cb299.zip |
Implementing exar_cat
-rw-r--r-- | tools/exar/exar.c | 136 | ||||
-rw-r--r-- | tools/exar/exar.h | 10 | ||||
-rw-r--r-- | tools/exar/main.c | 53 |
3 files changed, 152 insertions, 47 deletions
diff --git a/tools/exar/exar.c b/tools/exar/exar.c index b9ea9379..ca4d46a9 100644 --- a/tools/exar/exar.c +++ b/tools/exar/exar.c @@ -42,8 +42,9 @@ #define DIR_FLAG (100) #define FILE_FLAG (102) -#define LOG(level, format, ...) do { if (s_verbose & EXAR_VERBOSE_L##level) \ - fprintf(stderr, "exar-log%d: "format, level, __VA_ARGS__); } while(0) +#define LOG(level, ...) do { if (s_verbose & EXAR_VERBOSE_L##level) \ + fprintf(stderr, "exar-log%d: ", level); \ + fprintf(stderr, __VA_ARGS__); } while(0) static size_t s_offset; static FILE *s_out; @@ -99,14 +100,13 @@ pack(const char *fpath, const struct stat *st, int tf) return 0; } -int -exar_pack(const char *path) +size_t +get_offset(char *buffer, size_t n, const char *path, int *end) { - int ret, i=0; - unsigned char version[SZ_VERSION] = {0}; - char buffer[512]; const char *tmp = path, *slash; size_t len = strlen(path); + size_t offset = 0; + int i=0; // strip trailing '/' while (tmp[len-1] == '/') @@ -116,11 +116,25 @@ exar_pack(const char *path) // get base name offset slash = strrchr(buffer, '/'); if (slash != NULL) - s_offset = slash - buffer + 1; - - // construct filename + offset = slash - buffer + 1; for (tmp = path + s_offset; *tmp && *tmp != '/'; i++, tmp++) buffer[i] = *tmp; + if (end != NULL) + *end = i; + return offset; +} + + +int +exar_pack(const char *path) +{ + int ret; + unsigned char version[SZ_VERSION] = {0}; + char buffer[512]; + int i = 0; + + s_offset = get_offset(buffer, sizeof(buffer), path, &i); + strncpy(&buffer[i], "." EXTENSION, sizeof(buffer) - i); LOG(3, "Opening %s for writing\n", buffer); @@ -141,6 +155,35 @@ exar_pack(const char *path) fclose(s_out); return ret; } +static int +check_version(FILE *f, int verbose) +{ + unsigned char version[SZ_VERSION] = {0}, orig_version[SZ_VERSION] = {0}; + LOG(2, "Reading version header\n"); + if (fread(version, 1, sizeof(version), f) != sizeof(version)) + { + if (verbose) + fprintf(stderr, "Not an exar file?\n"); + return -1; + } + memcpy(orig_version, VERSION, sizeof(orig_version)); + LOG(2, "Checking filetype\n"); + if (strncmp((char*)version, VERSION_BASE, 5)) + { + if (verbose) + fprintf(stderr, "Not an exar file?\n"); + return -1; + } + + LOG(1, "Found version %s\n", version); + if (memcmp(version, orig_version, SZ_VERSION)) + { + if (verbose) + fprintf(stderr, "Incompatible version number\n"); + return -1; + } + return 0; +} int exar_unpack(const char *path, const char *dest) { @@ -149,7 +192,6 @@ exar_unpack(const char *path, const char *dest) size_t fs; FILE *of, *f = NULL; char *endptr; - unsigned char version[SZ_VERSION] = {0}, orig_version[SZ_VERSION] = {0}; LOG(3, "Opening %s for reading\n", path); if ((f = fopen(path, "r")) == NULL) @@ -157,29 +199,9 @@ exar_unpack(const char *path, const char *dest) fprintf(stderr, "Cannot open %s\n", path); return -1; } - // Compare version header - LOG(2, "Reading version header %s\n", ""); - if (fread(version, 1, sizeof(version), f) != sizeof(version)) - { - fprintf(stderr, "Not an exar file?\n"); + if (check_version(f, 1) != 0) goto error_out; - } - memcpy(orig_version, VERSION, sizeof(orig_version)); - - LOG(2, "Checking filetype%s", "\n"); - if (strncmp((char*)version, VERSION_BASE, 5)) - { - fprintf(stderr, "Not an exar file?\n"); - goto error_out; - } - - LOG(1, "Found version %s\n", version); - if (memcmp(version, orig_version, SZ_VERSION)) - { - fprintf(stderr, "Incompatible version number\n"); - goto error_out; - } if (dest != NULL) { LOG(2, "Changing to directory %s\n", dest); @@ -250,6 +272,56 @@ error_out: } return ret; } +int +exar_cat(const char *file1, const char *file2) +{ + int ret = -1; + size_t r; + FILE *f1 = NULL, *f2 = NULL; + char buffer[64]; + char offset_buffer[512]; + + LOG(3, "Opening file %s for writing\n", file1); + if ((f1 = fopen(file1, "a")) == NULL) + { + perror("fopen"); + goto error_out; + } + LOG(3, "Opening file %s for reading\n", file2); + if ((f2 = fopen(file2, "r")) == NULL) + { + perror("fopen"); + goto error_out; + } + if (check_version(f2, 0) == 0) + { + LOG(1, "Concatenating archive\n"); + while ((r = fread(buffer, 1, sizeof(buffer), f2)) > 0) + { + fwrite(buffer, 1, r, f1); + } + } + else + { + s_offset = get_offset(offset_buffer, sizeof(offset_buffer), file2, NULL); + LOG(1, "Concatenating regular files\n"); + s_out = f1; + ftw(file2, pack, 64); + } + ret = 0; +error_out: + if (f1 != NULL) + { + LOG(3, "Closing %s\n", file1); + fclose(f1); + } + if (f2 != NULL) + { + LOG(3, "Closing %s\n", file2); + fclose(f2); + } + return ret; +} void exar_verbose(unsigned char v) { diff --git a/tools/exar/exar.h b/tools/exar/exar.h index 93f73e48..26d3997b 100644 --- a/tools/exar/exar.h +++ b/tools/exar/exar.h @@ -61,6 +61,16 @@ exar_verbose(unsigned char v_flags); int exar_pack(const char *path); +/* + * Concatenates two archives or an archive and a file or directory + * @file1: The archive to append + * @file2: The archive, file or directory that will be appended + * + * @returns 0 on success and -1 on error + * */ +int +exar_cat(const char *file1, const char *file2); + /* * Unpacks a file * @path: Path to the extension archive diff --git a/tools/exar/main.c b/tools/exar/main.c index 194baf41..59333f3d 100644 --- a/tools/exar/main.c +++ b/tools/exar/main.c @@ -24,6 +24,7 @@ enum { FLAG_V = 1<<0, FLAG_P = 1<<3, FLAG_U = 1<<4, + FLAG_C = 1<<5, }; #ifndef MIN #define MIN(X, Y) ((X) > (Y) ? (Y) : (X)) @@ -37,18 +38,22 @@ help(int ret) printf("USAGE: \n" " exar option [arguments]\n\n" "OPTIONS:\n" - " h : Print this help and exit.\n" - " p[v] path : Pack file or directory 'path'.\n" - " u[v] file [dir] : Pack 'file' to directory 'dir' or to \n" - " current directory.\n" - " v : Verbose, pass multiple times (up to 3) to \n" - " get more verbose messages.\n\n" + " h : Print this help and exit.\n" + " c[v] archive file : Concatenates a file, directory or archive to \n" + " an existing archive.\n" + " p[v] path : Pack file or directory 'path'.\n" + " u[v] file [dir] : Pack 'file' to directory 'dir' or to \n" + " current directory.\n" + " v : Verbose, pass multiple times (up to 3) to \n" + " get more verbose messages.\n\n" "EXAMPLES:\n" - " exar p /tmp/foo -- pack /tmp/foo to foo.exar\n" - " exar uvvv foo.exar -- unpack foo.exar to current directory, \n" - " verbosity level 3\n" - " exar vu foo.exar /tmp -- unpack foo.exar to /tmp, verbosity \n" - " level 1\n"); + " exar p /tmp/foo -- pack /tmp/foo to foo.exar\n" + " exar c foo.exar bar.txt -- Concatenates bar.txt to archive foo.exar\n" + " exar c foo.exar bar.exar -- Concatenates archive bar.exar to archive foo.exar\n" + " exar uvvv foo.exar -- unpack foo.exar to current directory, \n" + " verbosity level 3\n" + " exar vu foo.exar /tmp -- unpack foo.exar to /tmp, verbosity \n" + " level 1\n"); exit(ret); } int @@ -70,6 +75,9 @@ main (int argc, char **argv) case 'u' : flag |= FLAG_U; break; + case 'c' : + flag |= FLAG_C; + break; case 'v' : flag |= MAX(FLAG_V, MIN(EXAR_VERBOSE_MASK, ((flag & EXAR_VERBOSE_MASK) << 1))); break; @@ -80,15 +88,30 @@ main (int argc, char **argv) } options++; } - if ((flag & (FLAG_U | FLAG_P)) == (FLAG_U | FLAG_P)) - help(EXIT_FAILURE); if (flag & EXAR_VERBOSE_MASK) exar_verbose(flag); if (flag & FLAG_U) - exar_unpack(argv[2], argv[3]); + { + if (flag & (FLAG_P | FLAG_C)) + help(EXIT_FAILURE); + else + exar_unpack(argv[2], argv[3]); + } else if (flag & FLAG_P) - exar_pack(argv[2]); + { + if (flag & (FLAG_U | FLAG_C)) + help(EXIT_FAILURE); + else + exar_pack(argv[2]); + } + else if (flag & FLAG_C) + { + if (flag & (FLAG_U | FLAG_P) || argc < 4) + help(EXIT_FAILURE); + else + exar_cat(argv[2], argv[3]); + } else help(EXIT_SUCCESS); |