"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: */