"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "lha-114i/src/lhadd.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 /*				lhadd.c -- LHarc Add Command								*/
    4 /*																			*/
    5 /*		Copyright (C) MCMLXXXIX Yooichi.Tagawa								*/
    6 /*		Modified          		Nobutaka Watazaki							*/
    7 /*																			*/
    8 /*	Ver. 1.14 	Source All chagned				1995.01.14	N.Watazaki		*/
    9 /* ------------------------------------------------------------------------ */
   10 #include "lha.h"
   11 /* ------------------------------------------------------------------------ */
   12 static void     remove_files();
   13 
   14 static char     new_archive_name_buffer[FILENAME_LENGTH];
   15 static char    *new_archive_name;
   16 /* ------------------------------------------------------------------------ */
   17 static void
   18 add_one(fp, nafp, hdr)
   19 	FILE           *fp, *nafp;
   20 	LzHeader       *hdr;
   21 {
   22 	long            header_pos, next_pos, org_pos, data_pos;
   23 	long            v_original_size, v_packed_size;
   24 	int             mode;
   25 
   26 	reading_filename = hdr->name;
   27 	writting_filename = temporary_name;
   28 
   29 	if (!fp && generic_format)	/* [generic] doesn't need directory
   30 					 * info. */
   31 		return;
   32 	header_pos = ftell(nafp);
   33 	write_header(nafp, hdr);/* DUMMY */
   34 
   35 	if ((hdr->unix_mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK) {
   36 		char            buf[256], *b1, *b2;
   37 		if (!quiet) {
   38 			strcpy(buf, hdr->name);
   39 			b1 = strtok(buf, "|");
   40 			b2 = strtok(NULL, "|");
   41 			printf("%s -> %s\t- Symbolic Link\n", b1, b2);
   42 		}		/* if quiet .. */
   43 	}
   44 
   45 	if (hdr->original_size == 0)	/* empty file or directory */
   46 		return;		/* previous write_header is not DUMMY. (^_^) */
   47 
   48 	org_pos = ftell(fp);
   49 	data_pos = ftell(nafp);
   50 
   51 	hdr->crc = encode_lzhuf(fp, nafp, hdr->original_size,
   52 		  &v_original_size, &v_packed_size, hdr->name, hdr->method);
   53 
   54 	if (v_packed_size < v_original_size) {
   55 		next_pos = ftell(nafp);
   56 	}
   57 	else {			/* retry by stored method */
   58 		fseek(fp, org_pos, SEEK_SET);
   59 		fseek(nafp, data_pos, SEEK_SET);
   60 		hdr->crc = encode_stored_crc(fp, nafp, hdr->original_size,
   61 					  &v_original_size, &v_packed_size);
   62 		fflush(nafp);
   63 		next_pos = ftell(nafp);
   64 #ifndef NOFTRUNCATE
   65 		ftruncate(fileno(nafp), next_pos);
   66 #endif
   67 		bcopy(LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
   68 	}
   69 	hdr->original_size = v_original_size;
   70 	hdr->packed_size = v_packed_size;
   71 	fseek(nafp, header_pos, SEEK_SET);
   72 	write_header(nafp, hdr);
   73 	fseek(nafp, next_pos, SEEK_SET);
   74 }
   75 
   76 
   77 /* ------------------------------------------------------------------------ */
   78 FILE           *
   79 append_it(name, oafp, nafp)
   80 	char           *name;
   81 	FILE           *oafp, *nafp;
   82 {
   83 	LzHeader        ahdr, hdr;
   84 	FILE           *fp;
   85 	long            old_header;
   86 	int             cmp;
   87 	int             filec;
   88 	char          **filev;
   89 	int             i;
   90 	struct stat     stbuf /*, lstbuf*/;
   91 
   92 	boolean         directory, symlink;
   93 
   94 	if (GETSTAT(name, &stbuf) < 0) {
   95 		error("Cannot access", name);	/* See cleaning_files, Why? */
   96 		return oafp;
   97 	}
   98 
   99 	directory = is_directory(&stbuf);
  100 #ifdef S_IFLNK
  101 	symlink = is_symlink(&stbuf);
  102 #else
  103 	symlink = 0;
  104 #endif
  105 	init_header(name, &stbuf, &hdr);
  106 
  107 	if (!directory && !noexec)
  108 		if (symlink)
  109 			fp = NULL;
  110 		else
  111 			fp = xfopen(name, READ_BINARY);
  112 	else {
  113 		fp = NULL;
  114 	}
  115 
  116 	while (oafp) {
  117 		old_header = ftell(oafp);
  118 		if (!get_header(oafp, &ahdr)) {
  119 			fclose(oafp);
  120 			oafp = NULL;
  121 			break;
  122 		} else {
  123 #if 0
  124 			cmp = STRING_COMPARE(ahdr.name, hdr.name);
  125 #endif
  126 			/* for symbolic link. t.okamoto */
  127 			cmp = strcmp_filename(ahdr.name, hdr.name);
  128 			if (cmp < 0) {	/* SKIP */
  129 				/* copy old to new */
  130 				if (!noexec) {
  131 					fseek(oafp, old_header, SEEK_SET);
  132 					copy_old_one(oafp, nafp, &ahdr);
  133 				}
  134 				else
  135 					fseek(oafp, ahdr.packed_size, SEEK_CUR);
  136 			} else if (cmp == 0) {	/* REPLACE */
  137 				/* drop old archive's */
  138 				fseek(oafp, ahdr.packed_size, SEEK_CUR);
  139 				break;
  140 			} else {	/* cmp > 0, INSERT */
  141 				fseek(oafp, old_header, SEEK_SET);
  142 				break;
  143 			}
  144 		}
  145 	}
  146 
  147 	if (update_if_newer) {
  148 		if (!oafp ||	/* not in archive */
  149 		    cmp > 0 ||	/* // */
  150 		    ahdr.unix_last_modified_stamp <	/* newer than archive's */
  151 		    hdr.unix_last_modified_stamp) {
  152 			if (noexec)
  153 				printf("ADD %s\n", name);
  154 			else
  155 				add_one(fp, nafp, &hdr);
  156 		} else {		/* cmp == 0 *//* copy old to new */
  157 			if (!noexec) {
  158 				fseek(oafp, old_header, SEEK_SET);
  159 				copy_old_one(oafp, nafp, &ahdr);
  160 			}
  161 		}
  162 	} else {
  163 		if (!oafp || cmp > 0) {	/* not in archive or dropped */
  164 			if (noexec)
  165 				printf("ADD %s\n", name);
  166 			else
  167 				add_one(fp, nafp, &hdr);
  168 		}
  169 		else {		/* cmp == 0 */
  170 			/* replace */
  171 			if (noexec)
  172 				printf("REPLACE\n");
  173 			else
  174 				add_one(fp, nafp, &hdr);
  175 		}
  176 	}
  177 
  178 	if (!directory) {
  179 		if (!noexec)
  180 			if (!symlink)
  181 				fclose(fp);
  182 	}
  183 	else {			/* recurcive call */
  184 		if (find_files(name, &filec, &filev)) {
  185 			for (i = 0; i < filec; i++)
  186 				oafp = append_it(filev[i], oafp, nafp);
  187 			free_files(filec, filev);
  188 		}
  189 	}
  190 	return oafp;
  191 }
  192 
  193 /* ------------------------------------------------------------------------ */
  194 static void
  195 find_update_files(oafp)
  196 	FILE           *oafp;	/* old archive */
  197 {
  198 	char            name[FILENAME_LENGTH];
  199 	struct string_pool sp;
  200 	LzHeader        hdr;
  201 	long            pos;
  202 	struct stat     stbuf;
  203 	int             len;
  204 
  205 	pos = ftell(oafp);
  206 
  207 	init_sp(&sp);
  208 	while (get_header(oafp, &hdr)) {
  209 		if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR) {
  210 			if (stat(hdr.name, &stbuf) >= 0)	/* exist ? */
  211 				add_sp(&sp, hdr.name, strlen(hdr.name) + 1);
  212 		}
  213 		else if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY) {
  214 			strcpy(name, hdr.name);
  215 			len = strlen(name);
  216 			if (len > 0 && name[len - 1] == '/')
  217 				name[--len] = '\0';	/* strip tail '/' */
  218 			if (stat(name, &stbuf) >= 0)	/* exist ? */
  219 				add_sp(&sp, name, len + 1);
  220 		}
  221 		fseek(oafp, hdr.packed_size, SEEK_CUR);
  222 	}
  223 
  224 	fseek(oafp, pos, SEEK_SET);
  225 
  226 	finish_sp(&sp, &cmd_filec, &cmd_filev);
  227 }
  228 
  229 /* ------------------------------------------------------------------------ */
  230 static void
  231 delete(oafp, nafp)
  232 	FILE           *oafp, *nafp;
  233 {
  234 	LzHeader        ahdr;
  235 	long            old_header_pos;
  236 	char            lpath[256], *b1, *b2;
  237 
  238 	old_header_pos = ftell(oafp);
  239 	while (get_header(oafp, &ahdr)) {
  240 		strcpy(lpath, ahdr.name);
  241 		b1 = strtok(lpath, "|");
  242 		b2 = strtok(NULL, "|");
  243 		if (need_file(b1)) {	/* skip */
  244 			fseek(oafp, ahdr.packed_size, SEEK_CUR);
  245 			if (noexec || !quiet)
  246 				if (b2 != NULL)
  247 					printf("delete %s -> %s\n", b1, b2);
  248 				else
  249 					printf("delete %s\n", b1);
  250 		}
  251 		else {		/* copy */
  252 			if (noexec) {
  253 				fseek(oafp, ahdr.packed_size, SEEK_CUR);
  254 			}
  255 			else {
  256 				fseek(oafp, old_header_pos, SEEK_SET);
  257 				copy_old_one(oafp, nafp, &ahdr);
  258 			}
  259 		}
  260 		old_header_pos = ftell(oafp);
  261 	}
  262 	return;
  263 }
  264 
  265 /* ------------------------------------------------------------------------ */
  266 /*																			*/
  267 /* ------------------------------------------------------------------------ */
  268 static FILE    *
  269 build_temporary_file()
  270 {
  271 	int             old_umask;
  272 	FILE           *afp;
  273 
  274 	build_temporary_name();
  275 	signal(SIGINT, interrupt);
  276 	signal(SIGHUP, interrupt);
  277 
  278 	old_umask = umask(077);
  279 	afp = xfopen(temporary_name, WRITE_BINARY);
  280 	remove_temporary_at_error = TRUE;
  281 	temporary_fp = afp;
  282 	umask(old_umask);
  283 
  284 	return afp;
  285 }
  286 
  287 /* ------------------------------------------------------------------------ */
  288 static void
  289 build_backup_file()
  290 {
  291 
  292 	build_backup_name(backup_archive_name, archive_name);
  293 	if (!noexec) {
  294 		signal(SIGINT, SIG_IGN);
  295 		signal(SIGHUP, SIG_IGN);
  296 		if (rename(archive_name, backup_archive_name) < 0)
  297 			fatal_error(archive_name);
  298 		recover_archive_when_interrupt = TRUE;
  299 		signal(SIGINT, interrupt);
  300 		signal(SIGHUP, interrupt);
  301 	}
  302 }
  303 
  304 /* ------------------------------------------------------------------------ */
  305 static void
  306 report_archive_name_if_different()
  307 {
  308 	if (!quiet && new_archive_name == new_archive_name_buffer) {
  309 		/* warning at old archive is SFX */
  310 		printf("New archive file is \"%s\"\n", new_archive_name);
  311 	}
  312 }
  313 
  314 /* ------------------------------------------------------------------------ */
  315 #ifdef TMP_FILENAME_TEMPLATE
  316 void
  317 temporary_to_new_archive_file(new_archive_size)
  318 	long            new_archive_size;
  319 {
  320 	FILE           *oafp, *nafp;
  321 
  322 	oafp = xfopen(temporary_name, READ_BINARY);
  323 	if (!strcmp(new_archive_name, "-")) {
  324 		nafp = stdout;
  325 		writting_filename = "starndard output";
  326 	}
  327 	else {
  328 		nafp = xfopen(new_archive_name, WRITE_BINARY);
  329 		writting_filename = archive_name;
  330 	}
  331 	reading_filename = temporary_name;
  332 	copyfile(oafp, nafp, new_archive_size, 0);
  333 	if (nafp != stdout)
  334 		fclose(nafp);
  335 	fclose(oafp);
  336 
  337 	recover_archive_when_interrupt = FALSE;
  338 	unlink(temporary_name);
  339 
  340 	remove_temporary_at_error = FALSE;
  341 }
  342 #else
  343 temporary_to_new_archive_file(new_archive_size)
  344 	long            new_archive_size;
  345 {
  346 	char           *p;
  347 	p = (char *) rindex(new_archive_name, '/');
  348 	p = p ? p + 1 : new_archive_name;
  349 	unlink(new_archive_name);
  350 	if (rename(temporary_name, p) < 0) {
  351 		fprintf(stderr, "Can't rename temporary_name '%s'\n", new_archive_name);
  352 		exit(1);
  353 	}
  354 }
  355 #endif
  356 
  357 /* ------------------------------------------------------------------------ */
  358 static void
  359 set_archive_file_mode()
  360 {
  361 	int             umask_value;
  362 	struct stat     stbuf;
  363 
  364 	if (archive_file_gid < 0) {
  365 		umask(umask_value = umask(0));
  366 		archive_file_mode = (~umask_value) & 0666;	/* rw-rw-rw- */
  367 		if (stat(".", &stbuf) >= 0)
  368 			archive_file_gid = stbuf.st_gid;
  369 	}
  370 	if (archive_file_gid >= 0)
  371 		chown(new_archive_name, getuid(), archive_file_gid);
  372 
  373 	chmod(new_archive_name, archive_file_mode);
  374 }
  375 
  376 /* ------------------------------------------------------------------------ */
  377 /*							REMOVE FILE/DIRECTORY							*/
  378 /* ------------------------------------------------------------------------ */
  379 static void
  380 remove_one(name)
  381 	char           *name;
  382 {
  383 	struct stat     stbuf;
  384 	int             filec;
  385 	char          **filev;
  386 
  387 	if (GETSTAT(name, &stbuf) < 0) {
  388 		warning("Cannot access", name);
  389 	}
  390 	else if (is_directory(&stbuf)) {
  391 		if (find_files(name, &filec, &filev)) {
  392 			remove_files(filec, filev);
  393 			free_files(filec, filev);
  394 		}
  395 		else
  396 			warning("Cannot open directory", name);
  397 
  398 		if (noexec)
  399 			printf("REMOVE DIRECTORY %s\n", name);
  400 		else if (rmdir(name) < 0)
  401 			warning("Cannot remove directory", name);
  402 		else if (verbose)
  403 			printf("Removed %s.\n", name);
  404 	}
  405 	else if (is_regularfile(&stbuf)) {
  406 		if (noexec)
  407 			printf("REMOVE FILE %s.\n", name);
  408 		else if (unlink(name) < 0)
  409 			warning("Cannot remove", name);
  410 		else if (verbose)
  411 			printf("Removed %s.\n", name);
  412 	}
  413 #ifdef S_IFLNK
  414 	else if (is_symlink(&stbuf)) {
  415 		if (noexec)
  416 			printf("REMOVE SYMBOLIC LINK %s.\n", name);
  417 		else if (unlink(name) < 0)
  418 			warning("Cannot remove", name);
  419 		else if (verbose)
  420 			printf("Removed %s.\n", name);
  421 	}
  422 #endif
  423 	else {
  424 		error("Cannot remove (not a file or directory)", name);
  425 	}
  426 }
  427 
  428 static void
  429 remove_files(filec, filev)
  430 	int             filec;
  431 	char          **filev;
  432 {
  433 	int             i;
  434 
  435 	for (i = 0; i < filec; i++)
  436 		remove_one(filev[i]);
  437 }
  438 
  439 /* ------------------------------------------------------------------------ */
  440 /*																			*/
  441 /* ------------------------------------------------------------------------ */
  442 void
  443 cmd_add()
  444 {
  445 	LzHeader        ahdr;
  446 	FILE           *oafp, *nafp;
  447 	int             i;
  448 	long            old_header;
  449 	boolean         old_archive_exist;
  450 	long            new_archive_size;
  451 
  452 	/* exit if no operation */
  453 	if (!update_if_newer && cmd_filec == 0) {
  454 		error("No files given in argument, do nothing.", "");
  455 		return;
  456 	}
  457 
  458 	/* open old archive if exist */
  459 	if ((oafp = open_old_archive()) == NULL)
  460 		old_archive_exist = FALSE;
  461 	else
  462 		old_archive_exist = TRUE;
  463 
  464 	if (update_if_newer && cmd_filec == 0 && !oafp)
  465 		fatal_error(archive_name);	/* exit if cannot execute
  466 						 * automatic update */
  467 	errno = 0;
  468 
  469 	if (new_archive && old_archive_exist) {
  470 		fclose(oafp);
  471 		oafp = NULL;
  472 	}
  473 
  474 	if (oafp && archive_is_msdos_sfx1(archive_name)) {
  475 		skip_msdos_sfx1_code(oafp);
  476 		build_standard_archive_name(new_archive_name_buffer, archive_name);
  477 		new_archive_name = new_archive_name_buffer;
  478 	}
  479 	else {
  480 		new_archive_name = archive_name;
  481 	}
  482 
  483 	/* build temporary file */
  484 	if (!noexec)
  485 		nafp = build_temporary_file();
  486 
  487 	/* find needed files when automatic update */
  488 	if (update_if_newer && cmd_filec == 0)
  489 		find_update_files(oafp);
  490 
  491 	/* build new archive file */
  492 	/* cleaning arguments */
  493 	cleaning_files(&cmd_filec, &cmd_filev);
  494 	if (cmd_filec == 0) {
  495 		if (oafp)
  496 			fclose(oafp);
  497 		if (!noexec)
  498 			fclose(nafp);
  499 		return;
  500 	}
  501 
  502 	for (i = 0; i < cmd_filec; i++)
  503 		oafp = append_it(cmd_filev[i], oafp, nafp);
  504 	if (oafp) {
  505 		old_header = ftell(oafp);
  506 		while (get_header(oafp, &ahdr)) {
  507 			if (noexec)
  508 				fseek(oafp, ahdr.packed_size, SEEK_CUR);
  509 			else {
  510 				fseek(oafp, old_header, SEEK_SET);
  511 				copy_old_one(oafp, nafp, &ahdr);
  512 			}
  513 			old_header = ftell(oafp);
  514 		}
  515 		fclose(oafp);
  516 	}
  517 	if (!noexec) {
  518 		write_archive_tail(nafp);
  519 		new_archive_size = ftell(nafp);
  520 		fclose(nafp);
  521 	}
  522 
  523 	/* build backup archive file */
  524 	if (old_archive_exist)
  525 		build_backup_file();
  526 
  527 	report_archive_name_if_different();
  528 
  529 	/* copy temporary file to new archive file */
  530 	if (!noexec && (!strcmp(new_archive_name, "-") ||
  531 			rename(temporary_name, new_archive_name) < 0))
  532 		temporary_to_new_archive_file(new_archive_size);
  533 
  534 	/* set new archive file mode/group */
  535 	set_archive_file_mode();
  536 
  537 	/* remove archived files */
  538 	if (delete_after_append)
  539 		remove_files(cmd_filec, cmd_filev);
  540 
  541 	return;
  542 }
  543 
  544 /* ------------------------------------------------------------------------ */
  545 void
  546 cmd_delete()
  547 {
  548 	FILE           *oafp, *nafp;
  549 	long            new_archive_size;
  550 
  551 	/* open old archive if exist */
  552 	if ((oafp = open_old_archive()) == NULL)
  553 		fatal_error(archive_name);
  554 	errno = 0;
  555 
  556 	/* exit if no operation */
  557 	if (cmd_filec == 0) {
  558 		fclose(oafp);
  559 		warning("No files given in argument, do nothing.", "");
  560 		return;
  561 	}
  562 
  563 	if (archive_is_msdos_sfx1(archive_name)) {
  564 		skip_msdos_sfx1_code(oafp);
  565 		build_standard_archive_name(new_archive_name_buffer, archive_name);
  566 		new_archive_name = new_archive_name_buffer;
  567 	}
  568 	else {
  569 		new_archive_name = archive_name;
  570 	}
  571 
  572 	/* build temporary file */
  573 	if (!noexec)
  574 		nafp = build_temporary_file();
  575 
  576 	/* build new archive file */
  577 	delete(oafp, nafp);
  578 	fclose(oafp);
  579 
  580 	if (!noexec) {
  581 		write_archive_tail(nafp);
  582 		new_archive_size = ftell(nafp);
  583 		fclose(nafp);
  584 	}
  585 
  586 	/* build backup archive file */
  587 	build_backup_file();
  588 
  589 	/* 1999.5.24 t.oka */
  590 	if(!noexec && new_archive_size <= 1){
  591 		unlink(temporary_name);
  592 		printf("New archive file \"%s\" is not created because it would be empty.\n", new_archive_name);
  593 		return;
  594 	}
  595 
  596 	report_archive_name_if_different();
  597 
  598 	/* copy temporary file to new archive file */
  599 	if (!noexec && rename(temporary_name, new_archive_name) < 0)
  600 		temporary_to_new_archive_file(new_archive_size);
  601 
  602 	/* set new archive file mode/group */
  603 	set_archive_file_mode();
  604 
  605 	return;
  606 }
  607 
  608 /* for symbolic link name. t.okamoto 96/2/20 */
  609 int strcmp_filename( str1, str2 )
  610 char *str1;
  611 char *str2;
  612 {
  613 	char *p, *q;
  614 
  615 	p = str1; q = str2;
  616 	while (*p != 0 && *q != 0) {
  617 		if (*p == '|') {
  618 			if (*q == 0) return 0;
  619 			else if (*q != '|') return -1;
  620 		} else if (*q == '|') {
  621 			if (*p == 0) return 0;
  622 			else if (*q != '|') return 1;
  623 		} else if (*p != *q) break;
  624 		p++; q++;
  625 	}
  626 	return (int)*p-(int)*q;
  627 }
  628 
  629 
  630 /* Local Variables: */
  631 /* mode:c */
  632 /* tab-width:4 */
  633 /* compile-command:"gcc -c lhadd.c" */
  634 /* End: */