OSDN Git Service

should include sys/types.h for mode_t
[lha/olha.git] / extract.c
1 #include <errno.h>
2 #include <utime.h>
3 #include <string.h>
4 #include <sys/stat.h>
5 #include <sys/types.h>
6 #include "ar.h"
7
8 static void
9 copy_stream_crc(FILE *arcfile, FILE *outfile,
10                 unsigned long remainder, unsigned int *crc)
11 {
12     char buf[BUFSIZ];
13
14     while (remainder != 0) {
15         uint n = (uint)MIN(remainder, BUFSIZ);
16
17         /* no compress */
18         if (fread(buf, 1, n, arcfile) != n)
19             error("Can't read");
20         fwrite_crc(buf, n, outfile, crc);
21         if (outfile != stdout && opts.quiet < 1) {
22             putc('.', stdout);
23         }
24         remainder -= n;
25     }
26 }
27
28 static void
29 extract(struct lzh_istream *rp, FILE *outfile, struct lzh_header *h)
30 {
31     unsigned int crc;
32     crc = INIT_CRC;
33
34     if (opts.method->dicbit != 0)
35         decode(rp, outfile, h->origsize, &crc);
36     else
37         copy_stream_crc(rp->fp, outfile, h->origsize, &crc);
38
39     if ((crc ^ INIT_CRC) != h->file_crc)
40         error("CRC error");
41 }
42
43 void
44 extract_to_file(struct lzh_istream *rp, struct lzh_header *h)
45 {
46     FILE *outfile;
47     char filename[1024];
48
49     if (opts.outdir)
50         makepath(filename, sizeof(filename),
51                  opts.outdir, h->filename, NULL);
52     else
53         string_copy(filename, h->filename, sizeof(filename));
54
55     if (memcmp(h->method, "-lhd-", sizeof(h->method)) == 0) {
56         /* directory */
57         if (opts.quiet < 2)
58             printf("Extracting %s\n", filename);
59         return;
60     }
61
62     /* create regular file */
63     if (file_exists(filename)) {
64         if (!opts.force_extract) {
65             message("'%s' has been already exist. skip", filename);
66             skip(rp->fp, h);
67             return;
68         }
69     }
70
71     if (mkdir_parent(filename) == -1) {
72         if (errno != EEXIST)
73             error("cannot make directory \"%s\"", opts.outdir);
74     }
75
76     outfile = fopen(filename, "wb");
77     if (outfile == NULL) {
78         fprintf(stderr, "Can't open %s (skip)\n", filename);
79
80         skip(rp->fp, h);
81         return;
82     }
83     if (opts.quiet < 2)
84         printf("Extracting %s ", filename);
85
86     extract(rp, outfile, h);
87     fclose(outfile);
88
89     /* adjust file information (timestamp etc) */
90     {
91         struct utimbuf ut;
92
93         ut.actime = ut.modtime = h->mtime;
94         utime(filename, &ut);
95     }
96
97     if (opts.quiet < 2)
98         fprintf(stdout, "\n");
99 }
100
101 void
102 extract_to_stdout(struct lzh_istream *rp, struct lzh_header *h)
103 {
104     if (memcmp(h->method, "-lhd-", sizeof(h->method)) == 0) {
105         return;
106     }
107
108     if (opts.quiet < 2)
109         printf("===== %s =====\n", h->filename);
110
111     /* extract */
112     extract(rp, stdout, h);
113 }