1 /* ------------------------------------------------------------------------ */
3 /* lhext.c -- LHarc extract */
5 /* Copyright (C) MCMLXXXIX Yooichi.Tagawa */
6 /* Modified Nobutaka Watazaki */
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 /* ------------------------------------------------------------------------ */
17 /* ------------------------------------------------------------------------ */
18 static int skip_flg = FALSE; /* FALSE..No Skip , TRUE..Skip */
19 static char *methods[] =
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,
28 /* ------------------------------------------------------------------------ */
36 if (stat(name, &stbuf) >= 0) {
37 if (!is_regularfile(&stbuf)) {
38 error("\"%s\" already exists (not a file)", name);
43 printf("EXTRACT %s but file is exist.\n", name);
50 switch (inquire("OverWrite ?(Yes/[No]/All/Skip)", name, "YyNnAaSs\n")) {
70 printf("EXTRACT %s\n", name);
75 /* ------------------------------------------------------------------------ */
77 make_parent_path(name)
80 char path[FILENAME_LENGTH];
84 /* make parent directory name into PATH for recursive call */
86 for (p = path + strlen(path); p > path; p--)
93 message("invalid path name \"%s\"", name);
94 return FALSE; /* no more parent. */
97 if (GETSTAT(path, &stbuf) >= 0) {
98 if (is_directory(&stbuf))
103 message("Making directory \"%s\".", path);
105 #if defined __MINGW32__
106 if (mkdir(path) >= 0)
109 if (mkdir(path, 0777) >= 0) /* try */
110 return TRUE; /* successful done. */
113 if (!make_parent_path(path))
116 #if defined __MINGW32__
117 if (mkdir(path) < 0) { /* try again */
118 error("Cannot make directory \"%s\"", path);
122 if (mkdir(path, 0777) < 0) { /* try again */
123 error("Cannot make directory \"%s\"", path);
131 /* ------------------------------------------------------------------------ */
133 open_with_make_path(name)
138 if ((fp = fopen(name, WRITE_BINARY)) == NULL) {
139 if (!make_parent_path(name) ||
140 (fp = fopen(name, WRITE_BINARY)) == NULL)
141 error("Cannot extract a file \"%s\"", name);
146 /* ------------------------------------------------------------------------ */
148 adjust_info(name, hdr)
152 struct utimbuf utimebuf;
154 /* adjust file stamp */
155 utimebuf.actime = utimebuf.modtime = hdr->unix_last_modified_stamp;
157 if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) != UNIX_FILE_SYMLINK)
158 utime(name, &utimebuf);
160 if (hdr->extend_type == EXTEND_UNIX
161 || hdr->extend_type == EXTEND_OS68K
162 || hdr->extend_type == EXTEND_XOSK) {
163 #ifdef NOT_COMPATIBLE_MODE
164 Please need your modification in this space.
166 if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) != UNIX_FILE_SYMLINK)
167 chmod(name, hdr->unix_mode);
170 uid_t uid = hdr->unix_uid;
171 gid_t gid = hdr->unix_gid;
173 #if HAVE_GETPWNAM && HAVE_GETGRNAM
175 struct passwd *ent = getpwnam(hdr->user);
176 if (ent) uid = ent->pw_uid;
179 struct group *ent = getgrnam(hdr->group);
180 if (ent) gid = ent->gr_gid;
185 if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_SYMLINK)
186 lchown(name, uid, gid);
188 #endif /* HAVE_LCHWON */
189 chown(name, uid, gid);
194 /* On Cygwin, execute permission should be set for .exe or .dll. */
197 umask(m = umask(0)); /* get current umask */
198 chmod(name, 0777 & ~m);
203 /* ------------------------------------------------------------------------ */
205 extract_one(afp, hdr)
206 FILE *afp; /* archive file */
209 FILE *fp; /* output file */
211 char name[FILENAME_LENGTH];
214 boolean save_quiet, save_verbose, up_flag;
215 char *q = hdr->name, c;
217 if (ignore_directory && strrchr(hdr->name, '/')) {
218 q = (char *) strrchr(hdr->name, '/') + 1;
224 * if OSK then strip device name
226 if (hdr->extend_type == EXTEND_OS68K
227 || hdr->extend_type == EXTEND_XOSK) {
230 while (c && c != '/');
232 q = "."; /* if device name only */
237 if (extract_directory)
238 xsnprintf(name, sizeof(name), "%s/%s", extract_directory, q);
243 /* LZHDIRS_METHOD¤ò»ý¤Ä¥Ø¥Ã¥À¤ò¥Á¥§¥Ã¥¯¤¹¤ë */
244 /* 1999.4.30 t.okamoto */
245 for (method = 0;; method++) {
246 if (methods[method] == NULL) {
247 error("Unknown method \"%.*s\"; \"%s\" will be skiped ...",
248 5, hdr->method, name);
251 if (memcmp(hdr->method, methods[method], 5) == 0)
255 if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR
256 && method != LZHDIRS_METHOD_NUM) {
259 for (method = 0;; method++) {
260 if (methods[method] == NULL) {
261 error("Unknown method \"%.*s\"; \"%s\" will be skiped ...",
262 5, hdr->method, name);
265 if (memcmp(hdr->method, methods[method], 5) == 0)
270 reading_filename = archive_name;
271 writing_filename = name;
272 if (output_to_stdout || verify_mode) {
274 printf("%s %s\n", verify_mode ? "VERIFY" : "EXTRACT", name);
276 int i = hdr->packed_size;
284 save_verbose = verbose;
285 if (!quiet && output_to_stdout) {
286 printf("::::::::\n%s\n::::::::\n", name);
290 else if (verify_mode) {
299 old_mode = setmode(fileno(stdout), O_BINARY);
303 (afp, stdout, hdr->original_size, hdr->packed_size, name, method);
306 setmode(fileno(stdout), old_mode);
310 verbose = save_verbose;
313 if (skip_flg == FALSE) {
314 up_flag = inquire_extract(name);
315 if (up_flag == FALSE && force == FALSE) {
320 if (skip_flg == TRUE) { /* if skip_flg */
321 if (stat(name, &stbuf) == 0 && force != TRUE) {
322 if (stbuf.st_mtime >= hdr->unix_last_modified_stamp) {
324 printf("%s : Skipped...\n", name);
331 int i = hdr->packed_size;
338 signal(SIGINT, interrupt);
340 signal(SIGHUP, interrupt);
344 remove_extracting_file_when_interrupt = TRUE;
346 if ((fp = open_with_make_path(name)) != NULL) {
348 (afp, fp, hdr->original_size, hdr->packed_size, name, method);
351 remove_extracting_file_when_interrupt = FALSE;
352 signal(SIGINT, SIG_DFL);
354 signal(SIGHUP, SIG_DFL);
360 if (hdr->has_crc && crc != hdr->crc)
361 error("CRC error: \"%s\"", name);
363 else if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY
364 || (hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_SYMLINK
365 || method == LZHDIRS_METHOD_NUM) {
366 /* ¢¬¤³¤ì¤Ç¡¢Symbolic Link ¤Ï¡¢Âç¾æÉפ«¡© */
367 if (!ignore_directory && !verify_mode) {
370 printf("EXTRACT %s (directory)\n", name);
373 /* NAME has trailing SLASH '/', (^_^) */
374 if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_SYMLINK) {
378 if (skip_flg == FALSE) {
379 up_flag = inquire_extract(name);
380 if (up_flag == FALSE && force == FALSE) {
384 if (GETSTAT(name, &stbuf) == 0 && force != TRUE) {
385 if (stbuf.st_mtime >= hdr->unix_last_modified_stamp) {
387 printf("%s : Skipped...\n", name);
394 make_parent_path(name);
395 l_code = symlink(hdr->realname, name);
398 warning("Can't make Symbolic Link \"%s\" -> \"%s\"",
399 hdr->realname, name);
402 message("Symbolic Link %s -> %s",
403 hdr->realname, name);
406 warning("Can't make Symbolic Link %s -> %s",
407 hdr->realname, name);
410 } else { /* make directory */
411 if (!output_to_stdout && !make_parent_path(name))
417 if (force) /* force extract */
418 goto extract_regular;
420 error("Unknown file type: \"%s\". use `f' option to force extract.", name);
423 if (!output_to_stdout)
424 adjust_info(name, hdr);
427 /* ------------------------------------------------------------------------ */
428 /* EXTRACT COMMAND MAIN */
429 /* ------------------------------------------------------------------------ */
437 /* open archive file */
438 if ((afp = open_old_archive()) == NULL)
439 fatal_error("Cannot open archive file \"%s\"", archive_name);
441 if (archive_is_msdos_sfx1(archive_name))
442 seek_lha_header(afp);
444 /* extract each files */
445 while (get_header(afp, &hdr)) {
446 if (need_file(hdr.name)) {
448 extract_one(afp, &hdr);
449 /* when error occurred in extract_one(), should adjust
450 point of file stream */
452 fseek(afp, pos + hdr.packed_size, SEEK_SET);
454 /* FIXME: assume that the extract_one() has read
455 packed_size bytes from stdin. */
457 while (i--) fgetc(afp);
461 fseek(afp, hdr.packed_size, SEEK_CUR);
463 int i = hdr.packed_size;
470 /* close archive file */