"SfR Fresh" - the SfR Freeware/Shareware Archive 
Member "lha-114i/src/lhext.c" of archive lha-114i.tar.gz:
As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers.
Alternatively you can here view or download the uninterpreted source code file.
That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
1 /* ------------------------------------------------------------------------ */
2 /* LHa for UNIX */
3 /* lhext.c -- LHarc extract */
4 /* */
5 /* Copyright (C) MCMLXXXIX Yooichi.Tagawa */
6 /* Modified Nobutaka Watazaki */
7 /* */
8 /* Ver. 0.00 Original 1988.05.23 Y.Tagawa */
9 /* Ver. 1.00 Fixed 1989.09.22 Y.Tagawa */
10 /* Ver. 0.03 LHa for UNIX 1991.12.17 M.Oki */
11 /* Ver. 1.12 LHa for UNIX 1993.10.01 N.Watazaki */
12 /* Ver. 1.13b Symbolic Link Update Bug Fix 1994.06.21 N.Watazaki */
13 /* Ver. 1.14 Source All chagned 1995.01.14 N.Watazaki */
14 /* Ver. 1.14e bugfix 1999.04.30 T.Okamoto */
15 /* ------------------------------------------------------------------------ */
16 #include "lha.h"
17 /* ------------------------------------------------------------------------ */
18 static int skip_flg = FALSE; /* FALSE..No Skip , TRUE..Skip */
19 static char *methods[] =
20 {
21 LZHUFF0_METHOD, LZHUFF1_METHOD, LZHUFF2_METHOD, LZHUFF3_METHOD,
22 LZHUFF4_METHOD, LZHUFF5_METHOD, LZHUFF6_METHOD, LZHUFF7_METHOD,
23 LARC_METHOD, LARC5_METHOD, LARC4_METHOD,
24 LZHDIRS_METHOD,
25 NULL
26 };
27
28 /* ------------------------------------------------------------------------ */
29 static boolean
30 inquire_extract(name)
31 char *name;
32 {
33 struct stat stbuf;
34
35 skip_flg = FALSE;
36 if (stat(name, &stbuf) >= 0) {
37 if (!is_regularfile(&stbuf)) {
38 error("Already exist (not a file)", name);
39 return FALSE;
40 }
41
42 if (noexec) {
43 printf("EXTRACT %s but file is exist.\n", name);
44 return FALSE;
45 }
46 else if (!force) {
47 if (!isatty(0))
48 return FALSE;
49
50 switch (inquire("OverWrite ?(Yes/[No]/All/Skip)", name, "YyNnAaSs\n")) {
51 case 0:
52 case 1:/* Y/y */
53 break;
54 case 2:
55 case 3:/* N/n */
56 case 8:/* Return */
57 return FALSE;
58 case 4:
59 case 5:/* A/a */
60 force = TRUE;
61 break;
62 case 6:
63 case 7:/* S/s */
64 skip_flg = TRUE;
65 break;
66 }
67 }
68 }
69 if (noexec)
70 printf("EXTRACT %s\n", name);
71
72 return TRUE;
73 }
74
75 /* ------------------------------------------------------------------------ */
76 static boolean
77 make_parent_path(name)
78 char *name;
79 {
80 char path[FILENAME_LENGTH];
81 struct stat stbuf;
82 register char *p;
83
84 /* make parent directory name into PATH for recursive call */
85 strcpy(path, name);
86 for (p = path + strlen(path); p > path; p--)
87 if (p[-1] == '/') {
88 *--p = '\0';
89 break;
90 }
91
92 if (p == path) {
93 message("Why?", "ROOT");
94 return FALSE; /* no more parent. */
95 }
96
97 if (GETSTAT(path, &stbuf) >= 0) {
98 if (is_directory(&stbuf))
99 return TRUE;
100 error("Not a directory", path);
101 return FALSE;
102 }
103 errno = 0;
104
105 if (verbose)
106 printf("Making directory \"%s\".\n", path);
107
108 if (mkdir(path, 0777) >= 0) /* try */
109 return TRUE; /* successful done. */
110 errno = 0;
111
112 if (!make_parent_path(path))
113 return FALSE;
114
115 if (mkdir(path, 0777) < 0) { /* try again */
116 message("Cannot make directory", path);
117 return FALSE;
118 }
119
120 return TRUE;
121 }
122
123 /* ------------------------------------------------------------------------ */
124 static FILE *
125 open_with_make_path(name)
126 char *name;
127 {
128 FILE *fp;
129
130 if ((fp = fopen(name, WRITE_BINARY)) == NULL) {
131 errno = 0;
132 if (!make_parent_path(name) ||
133 (fp = fopen(name, WRITE_BINARY)) == NULL)
134 error("Cannot extract", name);
135 errno = 0;
136 }
137 return fp;
138 }
139
140 /* ------------------------------------------------------------------------ */
141 static void
142 adjust_info(name, hdr)
143 char *name;
144 LzHeader *hdr;
145 {
146 time_t utimebuf[2];
147
148 /* adjust file stamp */
149 utimebuf[0] = utimebuf[1] = hdr->unix_last_modified_stamp;
150
151 if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) != UNIX_FILE_SYMLINK)
152 utime(name, utimebuf);
153
154 if (hdr->extend_type == EXTEND_UNIX
155 || hdr->extend_type == EXTEND_OS68K
156 || hdr->extend_type == EXTEND_XOSK) {
157 #ifdef NOT_COMPATIBLE_MODE
158 Please need your modification in this space.
159 #else
160 if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) != UNIX_FILE_SYMLINK)
161 chmod(name, hdr->unix_mode);
162 #endif
163 if (!getuid()) {
164 #ifndef HAVE_NO_LCHOWN
165 if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_SYMLINK)
166 lchown(name, hdr->unix_uid, hdr->unix_gid);
167 else
168 #endif /* HAVE_NO_LCHWON */
169 chown(name, hdr->unix_uid, hdr->unix_gid);
170 }
171 errno = 0;
172 }
173 }
174
175 /* ------------------------------------------------------------------------ */
176 static void
177 extract_one(afp, hdr)
178 FILE *afp; /* archive file */
179 LzHeader *hdr;
180 {
181 FILE *fp; /* output file */
182 struct stat stbuf;
183 char name[257];
184 int crc;
185 int method;
186 boolean save_quiet, save_verbose, up_flag;
187 char *q = hdr->name, c;
188
189 if (ignore_directory && rindex(hdr->name, '/')) {
190 q = (char *) rindex(hdr->name, '/') + 1;
191 }
192 else {
193 if (*q == '/') {
194 q++;
195 /*
196 * if OSK then strip device name
197 */
198 if (hdr->extend_type == EXTEND_OS68K
199 || hdr->extend_type == EXTEND_XOSK) {
200 do
201 c = (*q++);
202 while (c && c != '/');
203 if (!c || !*q)
204 q = "."; /* if device name only */
205 }
206 }
207 }
208
209 if (extract_directory)
210 sprintf(name, "%s/%s", extract_directory, q);
211 else
212 strcpy(name, q);
213
214
215 /* LZHDIRS_METHODを持つヘッダをチェックする */
216 /* 1999.4.30 t.okamoto */
217 for (method = 0;; method++) {
218 if (methods[method] == NULL) {
219 error("Unknown method skiped ...", name);
220 return;
221 }
222 if (bcmp(hdr->method, methods[method], 5) == 0)
223 break;
224 }
225
226 if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR
227 && method != LZHDIRS_METHOD_NUM) {
228 #if 0
229 for (method = 0;; method++) {
230 if (methods[method] == NULL) {
231 error("Unknown method skiped ...", name);
232 return;
233 }
234 if (bcmp(hdr->method, methods[method], 5) == 0)
235 break;
236 }
237 #endif
238
239 reading_filename = archive_name;
240 writting_filename = name;
241 if (output_to_stdout || verify_mode) {
242 if (noexec) {
243 printf("%s %s\n", verify_mode ? "VERIFY" : "EXTRACT", name);
244 if (afp == stdin) {
245 int i = hdr->packed_size;
246 while (i--)
247 fgetc(afp);
248 }
249 return;
250 }
251
252 save_quiet = quiet;
253 save_verbose = verbose;
254 if (!quiet && output_to_stdout) {
255 printf("::::::::\n%s\n::::::::\n", name);
256 quiet = TRUE;
257 verbose = FALSE;
258 }
259 else if (verify_mode) {
260 quiet = FALSE;
261 verbose = TRUE;
262 }
263
264 crc = decode_lzhuf
265 (afp, stdout, hdr->original_size, hdr->packed_size, name, method);
266 quiet = save_quiet;
267 verbose = save_verbose;
268 }
269 else {
270 if (skip_flg == FALSE) {
271 up_flag = inquire_extract(name);
272 if (up_flag == FALSE && force == FALSE) {
273 return;
274 }
275 }
276
277 if (skip_flg == TRUE) { /* if skip_flg */
278 if (stat(name, &stbuf) == 0 && force != TRUE) {
279 if (stbuf.st_mtime >= hdr->unix_last_modified_stamp) {
280 if (quiet != TRUE)
281 printf("%s : Skipped...\n", name);
282 return;
283 }
284 }
285 }
286 if (noexec) {
287 if (afp == stdin) {
288 int i = hdr->packed_size;
289 while (i--)
290 fgetc(afp);
291 }
292 return;
293 }
294
295 signal(SIGINT, interrupt);
296 signal(SIGHUP, interrupt);
297
298 unlink(name);
299 errno = 0;
300 remove_extracting_file_when_interrupt = TRUE;
301
302 if ((fp = open_with_make_path(name)) != NULL) {
303 crc = decode_lzhuf
304 (afp, fp, hdr->original_size, hdr->packed_size, name, method);
305 fclose(fp);
306 }
307 remove_extracting_file_when_interrupt = FALSE;
308 signal(SIGINT, SIG_DFL);
309 signal(SIGHUP, SIG_DFL);
310
311 if (!fp)
312 return;
313 }
314
315 errno = 0;
316 if (hdr->has_crc && crc != hdr->crc)
317 error("CRC error", name);
318 }
319 else if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY
320 || (hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_SYMLINK
321 || method == LZHDIRS_METHOD_NUM) {
322 /* ↑これで、Symblic Link は、大丈夫か? */
323 if (!ignore_directory && !verify_mode) {
324 if (noexec) {
325 if (quiet != TRUE)
326 printf("EXTRACT %s (directory)\n", name);
327 return;
328 }
329 /* NAME has trailing SLASH '/', (^_^) */
330 if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_SYMLINK) {
331 char buf[256], *bb1, *bb2;
332 int l_code;
333 strcpy(buf, name);
334 bb1 = strtok(buf, "|");
335 bb2 = strtok(NULL, "|");
336
337 #ifdef S_IFLNK
338 if (skip_flg == FALSE) {
339 up_flag = inquire_extract(name);
340 if (up_flag == FALSE && force == FALSE) {
341 return;
342 }
343 } else {
344 if (GETSTAT(bb1, &stbuf) == 0 && force != TRUE) {
345 if (stbuf.st_mtime >= hdr->unix_last_modified_stamp) {
346 if (quiet != TRUE)
347 printf("%s : Skipped...\n", bb1);
348 return;
349 }
350 }
351 }
352
353 unlink(bb1);
354 l_code = symlink(bb2, bb1);
355 if (l_code < 0) {
356 if (quiet != TRUE)
357 warning("Can't make Symbolic Link : ");
358 }
359 if (quiet != TRUE) {
360 printf("Symbolic Link %s -> %s\n", bb1, bb2);
361 }
362 strcpy(name, bb1); /* Symbolic's name set */
363 #else
364 sprintf(buf, "%s -> %s", bb1, bb2);
365 warning("Can't make Symbolic Link", buf);
366 return;
367 #endif
368 } else { /* make directory */
369 if (!output_to_stdout && !make_parent_path(name))
370 return;
371 }
372 }
373 }
374 else {
375 error("Unknown information", name);
376 }
377
378 if (!output_to_stdout)
379 adjust_info(name, hdr);
380 }
381
382 /* ------------------------------------------------------------------------ */
383 /* EXTRACT COMMAND MAIN */
384 /* ------------------------------------------------------------------------ */
385 void
386 cmd_extract()
387 {
388 LzHeader hdr;
389 long pos;
390 FILE *afp;
391
392 /* open archive file */
393 if ((afp = open_old_archive()) == NULL)
394 fatal_error(archive_name);
395
396 if (archive_is_msdos_sfx1(archive_name))
397 skip_msdos_sfx1_code(afp);
398
399 /* extract each files */
400 while (get_header(afp, &hdr)) {
401 if (need_file(hdr.name)) {
402 pos = ftell(afp);
403 extract_one(afp, &hdr);
404 fseek(afp, pos + hdr.packed_size, SEEK_SET);
405 } else {
406 if (afp != stdin)
407 fseek(afp, hdr.packed_size, SEEK_CUR);
408 else {
409 int i = hdr.packed_size;
410 while (i--)
411 fgetc(afp);
412 }
413 }
414 }
415
416 /* close archive file */
417 fclose(afp);
418
419 return;
420 }
421
422 /* Local Variables: */
423 /* mode:c */
424 /* tab-width:4 */
425 /* End: */