#include <sys/types.h>
#include "ar.h"
-void
-extract(struct lzh_istream *rp, int to_file, struct lzh_header *h)
+static void
+copy_stream_crc(FILE *arcfile, FILE *outfile,
+ unsigned long remainder, unsigned int *crc)
{
- int n;
- char buf[MAXDICSIZ];
- FILE *outfile = NULL;
-
- if (to_file) {
- if (memcmp(h->method, "-lhd-", sizeof(h->method)) == 0) {
- /* directory */
- if (mkdir(h->filename, 0777) == -1) {
- if (errno != EEXIST)
- error("cannot make directory \"%s\"", opts.outdir);
- }
- }
- else {
- /* regular file */
- if (file_exists(h->filename)) {
- if (!opts.force_extract) {
- message("'%s' has been already exist. skip", h->filename);
- skip(rp->fp, h);
- return;
- }
- }
- while ((outfile = fopen(h->filename, "wb")) == NULL) {
- fprintf(stderr, "Can't open %s\nNew filename: ", h->filename);
- if (get_line(h->filename, sizeof(h->filename)) == 0) {
- fprintf(stderr, "Not extracted\n");
- skip(rp->fp, h);
- return;
- }
- h->namelen = strlen(h->filename);
- }
+ char buf[BUFSIZ];
+
+ while (remainder != 0) {
+ uint n = (uint)MIN(remainder, BUFSIZ);
+
+ /* no compress */
+ if (fread(buf, 1, n, arcfile) != n)
+ error("Can't read");
+ fwrite_crc(buf, n, outfile, crc);
+ if (outfile != stdout && opts.quiet < 1) {
+ putc('.', stdout);
}
- if (opts.quiet < 2)
- printf("Extracting %s ", h->filename);
- }
- else {
- outfile = stdout;
- if (opts.quiet < 2)
- printf("===== %s =====\n", h->filename);
+ remainder -= n;
}
+}
+
+static void
+extract(struct lzh_istream *rp, FILE *outfile, struct lzh_header *h)
+{
+ unsigned int crc;
crc = INIT_CRC;
- opts.method = which_method(h->method);
- if (opts.method == NULL) {
- fprintf(stderr, "Unknown method: %.5s\n", h->method);
- skip(rp->fp, h);
- }
- else {
- crc = INIT_CRC;
- if (opts.method->dicbit != 0)
- decode_start(rp);
- while (h->origsize != 0) {
- n = (uint) ((h->origsize > MAXDICSIZ) ? MAXDICSIZ : h->origsize);
- if (opts.method->dicbit != 0)
- decode(rp, n, buf);
- else if (fread(buf, 1, n, rp->fp) != n)
- error("Can't read");
- fwrite_crc(buf, n, outfile);
- if (outfile != stdout && opts.quiet < 1) {
- putc('.', stdout);
- }
- h->origsize -= n;
- }
- }
+
+ if (opts.method->dicbit != 0)
+ decode(rp, outfile, h->origsize, &crc);
+ else
+ copy_stream_crc(rp->fp, outfile, h->origsize, &crc);
if ((crc ^ INIT_CRC) != h->file_crc)
error("CRC error");
+}
- if (to_file) {
- fprintf(stdout, "\n");
- if (outfile) {
- struct utimbuf ut;
+void
+extract_to_file(struct lzh_istream *rp, struct lzh_header *h)
+{
+ FILE *outfile;
+ char filename[1024];
- fclose(outfile);
+ if (opts.outdir)
+ makepath(filename, sizeof(filename),
+ opts.outdir, h->filename, NULL);
+ else
+ string_copy(filename, h->filename, sizeof(filename));
- ut.actime = ut.modtime = h->mtime;
- utime(h->filename, &ut);
+ if (memcmp(h->method, "-lhd-", sizeof(h->method)) == 0) {
+ /* directory */
+ if (opts.quiet < 2)
+ printf("Extracting %s\n", filename);
+ return;
+ }
+
+ /* create regular file */
+ if (file_exists(filename)) {
+ if (!opts.force_extract) {
+ message("'%s' has been already exist. skip", filename);
+ skip(rp->fp, h);
+ return;
}
}
- outfile = NULL;
+
+ if (mkdir_parent(filename) == -1) {
+ if (errno != EEXIST)
+ error("cannot make directory \"%s\"", opts.outdir);
+ }
+
+ outfile = fopen(filename, "wb");
+ if (outfile == NULL) {
+ fprintf(stderr, "Can't open %s (skip)\n", filename);
+
+ skip(rp->fp, h);
+ return;
+ }
+ if (opts.quiet < 2)
+ printf("Extracting %s ", filename);
+
+ extract(rp, outfile, h);
+ fclose(outfile);
+
+ /* adjust file information (timestamp etc) */
+ {
+ struct utimbuf ut;
+
+ ut.actime = ut.modtime = h->mtime;
+ utime(filename, &ut);
+ }
+
+ if (opts.quiet < 2)
+ fprintf(stdout, "\n");
+}
+
+void
+extract_to_stdout(struct lzh_istream *rp, struct lzh_header *h)
+{
+ if (memcmp(h->method, "-lhd-", sizeof(h->method)) == 0) {
+ return;
+ }
+
+ if (opts.quiet < 2)
+ printf("===== %s =====\n", h->filename);
+
+ /* extract */
+ extract(rp, stdout, h);
}