static void test_linkify_old_cpio(void)
{
    struct archive_entry *entry, *e2;
    struct archive_entry_linkresolver *resolver;

    /* Initialize the resolver. */
    assert(NULL != (resolver = archive_entry_linkresolver_new()));
    archive_entry_linkresolver_set_strategy(resolver,
        ARCHIVE_FORMAT_CPIO_POSIX);

    /* Create an entry with 2 link and try to linkify it. */
    assert(NULL != (entry = archive_entry_new()));
    archive_entry_set_pathname(entry, "test1");
    archive_entry_set_ino(entry, 1);
    archive_entry_set_dev(entry, 2);
    archive_entry_set_nlink(entry, 2);
    archive_entry_set_size(entry, 10);
    archive_entry_linkify(resolver, &entry, &e2);

    /* Shouldn't have been changed. */
    assert(e2 == NULL);
    assertEqualInt(10, archive_entry_size(entry));
    assertEqualString("test1", archive_entry_pathname(entry));

    /* Still shouldn't be matched. */
    archive_entry_linkify(resolver, &entry, &e2);
    assert(e2 == NULL);
    assertEqualString("test1", archive_entry_pathname(entry));
    assertEqualString(NULL, archive_entry_hardlink(entry));
    assertEqualInt(10, archive_entry_size(entry));

    archive_entry_free(entry);
    archive_entry_linkresolver_free(resolver);
}
Beispiel #2
0
static int
cleanup(struct archive_read *a)
{
	struct mtree *mtree;
	struct mtree_entry *p, *q;

	mtree = (struct mtree *)(a->format->data);

	p = mtree->entries;
	while (p != NULL) {
		q = p->next;
		free(p->name);
		free_options(p->options);
		free(p);
		p = q;
	}
	archive_string_free(&mtree->line);
	archive_string_free(&mtree->current_dir);
	archive_string_free(&mtree->contents_name);
	archive_entry_linkresolver_free(mtree->resolver);

	free(mtree->buff);
	free(mtree);
	(a->format->data) = NULL;
	return (ARCHIVE_OK);
}
Beispiel #3
0
static void
mode_pass(struct cpio *cpio, const char *destdir)
{
	struct lafe_line_reader *lr;
	const char *p;
	int r;

	/* Ensure target dir has a trailing '/' to simplify path surgery. */
	cpio->destdir = malloc(strlen(destdir) + 8);
	strcpy(cpio->destdir, destdir);
	if (destdir[strlen(destdir) - 1] != '/')
		strcat(cpio->destdir, "/");

	cpio->archive = archive_write_disk_new();
	if (cpio->archive == NULL)
		lafe_errc(1, 0, "Failed to allocate archive object");
	r = archive_write_disk_set_options(cpio->archive, cpio->extract_flags);
	if (r != ARCHIVE_OK)
		lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
	cpio->linkresolver = archive_entry_linkresolver_new();
	archive_write_disk_set_standard_lookup(cpio->archive);

	cpio->archive_read_disk = archive_read_disk_new();
	if (cpio->archive_read_disk == NULL)
		lafe_errc(1, 0, "Failed to allocate archive object");
	if (cpio->option_follow_links)
		archive_read_disk_set_symlink_logical(cpio->archive_read_disk);
	else
		archive_read_disk_set_symlink_physical(cpio->archive_read_disk);
	archive_read_disk_set_standard_lookup(cpio->archive_read_disk);

	lr = lafe_line_reader("-", cpio->option_null);
	while ((p = lafe_line_reader_next(lr)) != NULL)
		file_to_archive(cpio, p);
	lafe_line_reader_free(lr);

	archive_entry_linkresolver_free(cpio->linkresolver);
	r = archive_write_close(cpio->archive);
	if (cpio->dot)
		fprintf(stderr, "\n");
	if (r != ARCHIVE_OK)
		lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));

	if (!cpio->quiet) {
		int64_t blocks =
			(archive_filter_bytes(cpio->archive, 0) + 511)
			/ 512;
		fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
		    blocks == 1 ? "block" : "blocks");
	}

	archive_write_free(cpio->archive);
}
Beispiel #4
0
static void
mode_pass(struct cpio *cpio, const char *destdir)
{
	unsigned long blocks;
	struct line_reader *lr;
	const char *p;
	int r;

	/* Ensure target dir has a trailing '/' to simplify path surgery. */
	cpio->destdir = malloc(strlen(destdir) + 8);
	strcpy(cpio->destdir, destdir);
	if (destdir[strlen(destdir) - 1] != '/')
		strcat(cpio->destdir, "/");

	cpio->archive = archive_write_disk_new();
	if (cpio->archive == NULL)
		cpio_errc(1, 0, "Failed to allocate archive object");
	r = archive_write_disk_set_options(cpio->archive, cpio->extract_flags);
	if (r != ARCHIVE_OK)
		cpio_errc(1, 0, archive_error_string(cpio->archive));
	cpio->linkresolver = archive_entry_linkresolver_new();
	archive_write_disk_set_standard_lookup(cpio->archive);
	lr = process_lines_init("-", cpio->line_separator);
	while ((p = process_lines_next(lr)) != NULL)
		file_to_archive(cpio, p);
	process_lines_free(lr);

	archive_entry_linkresolver_free(cpio->linkresolver);
	r = archive_write_close(cpio->archive);
	if (r != ARCHIVE_OK)
		cpio_errc(1, 0, archive_error_string(cpio->archive));

	if (!cpio->quiet) {
		blocks = (archive_position_uncompressed(cpio->archive) + 511)
			      / 512;
		fprintf(stderr, "%lu %s\n", blocks,
		    blocks == 1 ? "block" : "blocks");
	}

	archive_write_finish(cpio->archive);
}
Beispiel #5
0
static void
make_dist(const char *pkg, const char *suffix, const package_t *plist)
{
	char *archive_name;
	const char *owner, *group;
	const plist_t *p;
	struct archive *archive;
	struct archive_entry *entry, *sparse_entry;
	struct archive_entry_linkresolver *resolver;
	char *initial_cwd;
	
	archive = archive_write_new();
	archive_write_set_format_pax_restricted(archive);
	if ((resolver = archive_entry_linkresolver_new()) == NULL)
		errx(2, "cannot create link resolver");
	archive_entry_linkresolver_set_strategy(resolver,
	    archive_format(archive));

	if (CompressionType == NULL) {
		if (strcmp(suffix, "tbz") == 0 ||
		    strcmp(suffix, "tar.bz2") == 0)
			CompressionType = "bzip2";
		else if (strcmp(suffix, "tgz") == 0 ||
		    strcmp(suffix, "tar.gz") == 0)
			CompressionType = "gzip";
		else
			CompressionType = "none";
	}

	if (strcmp(CompressionType, "bzip2") == 0)
		archive_write_set_compression_bzip2(archive);
	else if (strcmp(CompressionType, "gzip") == 0)
		archive_write_set_compression_gzip(archive);
	else if (strcmp(CompressionType, "xz") == 0)
		archive_write_set_compression_xz(archive);
	else if (strcmp(CompressionType, "none") == 0)
		archive_write_set_compression_none(archive);
	else
		errx(1, "Unspported compression type for -F: %s",
		    CompressionType);

	archive_name = xasprintf("%s.%s", pkg, suffix);

	if (archive_write_open_file(archive, archive_name))
		errx(2, "cannot create archive: %s", archive_error_string(archive));

	free(archive_name);

	owner = DefaultOwner;
	group = DefaultGroup;

	write_meta_file(contents_file, archive);
	write_meta_file(comment_file, archive);
	write_meta_file(desc_file, archive);

	if (Install)
		write_meta_file(install_file, archive);
	if (DeInstall)
		write_meta_file(deinstall_file, archive);
	if (Display)
		write_meta_file(display_file, archive);
	if (BuildVersion)
		write_meta_file(build_version_file, archive);
	if (BuildInfo)
		write_meta_file(build_info_file, archive);
	if (SizePkg)
		write_meta_file(size_pkg_file, archive);
	if (SizeAll)
		write_meta_file(size_all_file, archive);
	if (Preserve)
		write_meta_file(preserve_file, archive);
	if (create_views)
		write_meta_file(views_file, archive);

	initial_cwd = getcwd(NULL, 0);

	for (p = plist->head; p; p = p->next) {
		if (p->type == PLIST_FILE) {
			write_normal_file(p->name, archive, resolver, owner, group);
		} else if (p->type == PLIST_CWD) {
			chdir(p->name);
		} else if (p->type == PLIST_IGNORE) {
			p = p->next;
		} else if (p->type == PLIST_CHOWN) {
			if (p->name != NULL)
				owner = p->name;
			else
				owner = DefaultOwner;
		} else if (p->type == PLIST_CHGRP) {
			if (p->name != NULL)
				group = p->name;
			else
				group = DefaultGroup;
		}
	}

	entry = NULL;
	archive_entry_linkify(resolver, &entry, &sparse_entry);
	while (entry != NULL) {
		write_entry(archive, entry);
		entry = NULL;
		archive_entry_linkify(resolver, &entry, &sparse_entry);
	}

	archive_entry_linkresolver_free(resolver);

	if (archive_write_close(archive))
		errx(2, "cannot finish archive: %s", archive_error_string(archive));
	archive_write_finish(archive);

	free(initial_cwd);
}
Beispiel #6
0
/*
 * Write user-specified files/dirs to opened archive.
 */
static void
write_archive(struct archive *a, struct bsdtar *bsdtar)
{
	const char *arg;
	struct archive_entry *entry, *sparse_entry;

	/* Choose a suitable copy buffer size */
	bsdtar->buff_size = 64 * 1024;
	while (bsdtar->buff_size < (size_t)bsdtar->bytes_per_block)
	  bsdtar->buff_size *= 2;
	/* Try to compensate for space we'll lose to alignment. */
	bsdtar->buff_size += 16 * 1024;

	/* Allocate a buffer for file data. */
	if ((bsdtar->buff = malloc(bsdtar->buff_size)) == NULL)
		lafe_errc(1, 0, "cannot allocate memory");

	if ((bsdtar->resolver = archive_entry_linkresolver_new()) == NULL)
		lafe_errc(1, 0, "cannot create link resolver");
	archive_entry_linkresolver_set_strategy(bsdtar->resolver,
	    archive_format(a));

	/* Create a read_disk object. */
	if ((bsdtar->diskreader = archive_read_disk_new()) == NULL)
		lafe_errc(1, 0, "Cannot create read_disk object");
	/* Tell the read_disk how handle symlink. */
	switch (bsdtar->symlink_mode) {
	case 'H':
		archive_read_disk_set_symlink_hybrid(bsdtar->diskreader);
		break;
	case 'L':
		archive_read_disk_set_symlink_logical(bsdtar->diskreader);
		break;
	default:
		archive_read_disk_set_symlink_physical(bsdtar->diskreader);
		break;
	}
	/* Register entry filters. */
	archive_read_disk_set_matching(bsdtar->diskreader,
	    bsdtar->matching, excluded_callback, bsdtar);
	archive_read_disk_set_metadata_filter_callback(
	    bsdtar->diskreader, metadata_filter, bsdtar);
	/* Set the behavior of archive_read_disk. */
	archive_read_disk_set_behavior(bsdtar->diskreader,
	    bsdtar->readdisk_flags);
	archive_read_disk_set_standard_lookup(bsdtar->diskreader);

	if (bsdtar->names_from_file != NULL)
		archive_names_from_file(bsdtar, a);

	while (*bsdtar->argv) {
		arg = *bsdtar->argv;
		if (arg[0] == '-' && arg[1] == 'C') {
			arg += 2;
			if (*arg == '\0') {
				bsdtar->argv++;
				arg = *bsdtar->argv;
				if (arg == NULL) {
					lafe_warnc(0, "%s",
					    "Missing argument for -C");
					bsdtar->return_value = 1;
					goto cleanup;
				}
				if (*arg == '\0') {
					lafe_warnc(0,
					    "Meaningless argument for -C: ''");
					bsdtar->return_value = 1;
					goto cleanup;
				}
			}
			set_chdir(bsdtar, arg);
		} else {
			if (*arg != '/' && (arg[0] != '@' || arg[1] != '/'))
				do_chdir(bsdtar); /* Handle a deferred -C */
			if (*arg == '@') {
				if (append_archive_filename(bsdtar, a,
				    arg + 1) != 0)
					break;
			} else
				write_hierarchy(bsdtar, a, arg);
		}
		bsdtar->argv++;
	}

	archive_read_disk_set_matching(bsdtar->diskreader, NULL, NULL, NULL);
	archive_read_disk_set_metadata_filter_callback(
	    bsdtar->diskreader, NULL, NULL);
	entry = NULL;
	archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry);
	while (entry != NULL) {
		int r;
		struct archive_entry *entry2;
		struct archive *disk = bsdtar->diskreader;

		/*
		 * This tricky code here is to correctly read the cotents
		 * of the entry because the disk reader bsdtar->diskreader
		 * is pointing at does not have any information about the
		 * entry by this time and using archive_read_data_block()
		 * with the disk reader consequently must fail. And we
		 * have to re-open the entry to read the contents.
		 */
		/* TODO: Work with -C option as well. */
		r = archive_read_disk_open(disk,
			archive_entry_sourcepath(entry));
		if (r != ARCHIVE_OK) {
			lafe_warnc(archive_errno(disk),
			    "%s", archive_error_string(disk));
			bsdtar->return_value = 1;
			archive_entry_free(entry);
			continue;
		}

		/*
		 * Invoke archive_read_next_header2() to work
		 * archive_read_data_block(), which is called via write_file(),
		 * without failure.
		 */
		entry2 = archive_entry_new();
		r = archive_read_next_header2(disk, entry2);
		archive_entry_free(entry2);
		if (r != ARCHIVE_OK) {
			lafe_warnc(archive_errno(disk),
			    "%s", archive_error_string(disk));
			if (r == ARCHIVE_FATAL)
				bsdtar->return_value = 1;
			else
				archive_read_close(disk);
			archive_entry_free(entry);
			continue;
		}

		write_file(bsdtar, a, entry);
		archive_entry_free(entry);
		archive_read_close(disk);
		entry = NULL;
		archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry);
	}

	if (archive_write_close(a)) {
		lafe_warnc(0, "%s", archive_error_string(a));
		bsdtar->return_value = 1;
	}

cleanup:
	/* Free file data buffer. */
	free(bsdtar->buff);
	archive_entry_linkresolver_free(bsdtar->resolver);
	bsdtar->resolver = NULL;
	archive_read_free(bsdtar->diskreader);
	bsdtar->diskreader = NULL;

	if (bsdtar->option_totals) {
		fprintf(stderr, "Total bytes written: %s\n",
		    tar_i64toa(archive_filter_bytes(a, -1)));
	}

	archive_write_free(a);
}
static void test_linkify_tar(void)
{
    struct archive_entry *entry, *e2;
    struct archive_entry_linkresolver *resolver;

    /* Initialize the resolver. */
    assert(NULL != (resolver = archive_entry_linkresolver_new()));
    archive_entry_linkresolver_set_strategy(resolver,
        ARCHIVE_FORMAT_TAR_USTAR);

    /* Create an entry with only 1 link and try to linkify it. */
    assert(NULL != (entry = archive_entry_new()));
    archive_entry_set_pathname(entry, "test1");
    archive_entry_set_ino(entry, 1);
    archive_entry_set_dev(entry, 2);
    archive_entry_set_nlink(entry, 1);
    archive_entry_set_size(entry, 10);
    archive_entry_linkify(resolver, &entry, &e2);

    /* Shouldn't have been changed. */
    assert(e2 == NULL);
    assertEqualInt(10, archive_entry_size(entry));
    assertEqualString("test1", archive_entry_pathname(entry));

    /* Now, try again with an entry that has 2 links. */
    archive_entry_set_pathname(entry, "test2");
    archive_entry_set_nlink(entry, 2);
    archive_entry_set_ino(entry, 2);
    archive_entry_linkify(resolver, &entry, &e2);
    /* Shouldn't be altered, since it wasn't seen before. */
    assert(e2 == NULL);
    assertEqualString("test2", archive_entry_pathname(entry));
    assertEqualString(NULL, archive_entry_hardlink(entry));
    assertEqualInt(10, archive_entry_size(entry));

    /* Match again and make sure it does get altered. */
    archive_entry_linkify(resolver, &entry, &e2);
    assert(e2 == NULL);
    assertEqualString("test2", archive_entry_pathname(entry));
    assertEqualString("test2", archive_entry_hardlink(entry));
    assertEqualInt(0, archive_entry_size(entry));


    /* Dirs should never be matched as hardlinks, regardless. */
    archive_entry_set_pathname(entry, "test3");
    archive_entry_set_nlink(entry, 2);
    archive_entry_set_filetype(entry, AE_IFDIR);
    archive_entry_set_ino(entry, 3);
    archive_entry_set_hardlink(entry, NULL);
    archive_entry_linkify(resolver, &entry, &e2);
    /* Shouldn't be altered, since it wasn't seen before. */
    assert(e2 == NULL);
    assertEqualString("test3", archive_entry_pathname(entry));
    assertEqualString(NULL, archive_entry_hardlink(entry));

    /* Dir, so it shouldn't get matched. */
    archive_entry_linkify(resolver, &entry, &e2);
    assert(e2 == NULL);
    assertEqualString("test3", archive_entry_pathname(entry));
    assertEqualString(NULL, archive_entry_hardlink(entry));

    archive_entry_free(entry);
    archive_entry_linkresolver_free(resolver);
}
static void test_linkify_new_cpio(void)
{
    struct archive_entry *entry, *e2;
    struct archive_entry_linkresolver *resolver;

    /* Initialize the resolver. */
    assert(NULL != (resolver = archive_entry_linkresolver_new()));
    archive_entry_linkresolver_set_strategy(resolver,
        ARCHIVE_FORMAT_CPIO_SVR4_NOCRC);

    /* Create an entry with only 1 link and try to linkify it. */
    assert(NULL != (entry = archive_entry_new()));
    archive_entry_set_pathname(entry, "test1");
    archive_entry_set_ino(entry, 1);
    archive_entry_set_dev(entry, 2);
    archive_entry_set_nlink(entry, 1);
    archive_entry_set_size(entry, 10);
    archive_entry_linkify(resolver, &entry, &e2);

    /* Shouldn't have been changed. */
    assert(e2 == NULL);
    assertEqualInt(10, archive_entry_size(entry));
    assertEqualString("test1", archive_entry_pathname(entry));

    /* Now, try again with an entry that has 3 links. */
    archive_entry_set_pathname(entry, "test2");
    archive_entry_set_nlink(entry, 3);
    archive_entry_set_ino(entry, 2);
    archive_entry_linkify(resolver, &entry, &e2);

    /* First time, it just gets swallowed. */
    assert(entry == NULL);
    assert(e2 == NULL);

    /* Match again. */
    assert(NULL != (entry = archive_entry_new()));
    archive_entry_set_pathname(entry, "test3");
    archive_entry_set_ino(entry, 2);
    archive_entry_set_dev(entry, 2);
    archive_entry_set_nlink(entry, 2);
    archive_entry_set_size(entry, 10);
    archive_entry_linkify(resolver, &entry, &e2);

    /* Should get back "test2" and nothing else. */
    assertEqualString("test2", archive_entry_pathname(entry));
    assertEqualInt(0, archive_entry_size(entry));
    archive_entry_free(entry);
    assert(NULL == e2);
    archive_entry_free(e2); /* This should be a no-op. */

    /* Match a third time. */
    assert(NULL != (entry = archive_entry_new()));
    archive_entry_set_pathname(entry, "test4");
    archive_entry_set_ino(entry, 2);
    archive_entry_set_dev(entry, 2);
    archive_entry_set_nlink(entry, 3);
    archive_entry_set_size(entry, 10);
    archive_entry_linkify(resolver, &entry, &e2);

    /* Should get back "test3". */
    assertEqualString("test3", archive_entry_pathname(entry));
    assertEqualInt(0, archive_entry_size(entry));

    /* Since "test4" was the last link, should get it back also. */
    assertEqualString("test4", archive_entry_pathname(e2));
    assertEqualInt(10, archive_entry_size(e2));

    archive_entry_free(entry);
    archive_entry_free(e2);
    archive_entry_linkresolver_free(resolver);
}
Beispiel #9
0
/*
 * Write user-specified files/dirs to opened archive.
 */
static void
write_archive(struct archive *a, struct bsdtar *bsdtar)
{
	const char *arg;
	struct archive_entry *entry, *sparse_entry;

	/* Choose a suitable copy buffer size */
	bsdtar->buff_size = 64 * 1024;
	while (bsdtar->buff_size < (size_t)bsdtar->bytes_per_block)
	  bsdtar->buff_size *= 2;
	/* Try to compensate for space we'll lose to alignment. */
	bsdtar->buff_size += 16 * 1024;

	/* Allocate a buffer for file data. */
	if ((bsdtar->buff = malloc(bsdtar->buff_size)) == NULL)
		lafe_errc(1, 0, "cannot allocate memory");

	if ((bsdtar->resolver = archive_entry_linkresolver_new()) == NULL)
		lafe_errc(1, 0, "cannot create link resolver");
	archive_entry_linkresolver_set_strategy(bsdtar->resolver,
	    archive_format(a));
	if ((bsdtar->diskreader = archive_read_disk_new()) == NULL)
		lafe_errc(1, 0, "Cannot create read_disk object");
	archive_read_disk_set_standard_lookup(bsdtar->diskreader);

	if (bsdtar->names_from_file != NULL)
		archive_names_from_file(bsdtar, a);

	while (*bsdtar->argv) {
		arg = *bsdtar->argv;
		if (arg[0] == '-' && arg[1] == 'C') {
			arg += 2;
			if (*arg == '\0') {
				bsdtar->argv++;
				arg = *bsdtar->argv;
				if (arg == NULL) {
					lafe_warnc(0, "%s",
					    "Missing argument for -C");
					bsdtar->return_value = 1;
					goto cleanup;
				}
				if (*arg == '\0') {
					lafe_warnc(0,
					    "Meaningless argument for -C: ''");
					bsdtar->return_value = 1;
					goto cleanup;
				}
			}
			set_chdir(bsdtar, arg);
		} else {
			if (*arg != '/' && (arg[0] != '@' || arg[1] != '/'))
				do_chdir(bsdtar); /* Handle a deferred -C */
			if (*arg == '@') {
				if (append_archive_filename(bsdtar, a,
				    arg + 1) != 0)
					break;
			} else
				write_hierarchy(bsdtar, a, arg);
		}
		bsdtar->argv++;
	}

	entry = NULL;
	archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry);
	while (entry != NULL) {
		write_file(bsdtar, a, entry);
		archive_entry_free(entry);
		entry = NULL;
		archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry);
	}

	if (archive_write_close(a)) {
		lafe_warnc(0, "%s", archive_error_string(a));
		bsdtar->return_value = 1;
	}

cleanup:
	/* Free file data buffer. */
	free(bsdtar->buff);
	archive_entry_linkresolver_free(bsdtar->resolver);
	bsdtar->resolver = NULL;
	archive_read_free(bsdtar->diskreader);
	bsdtar->diskreader = NULL;

	if (bsdtar->option_totals) {
		fprintf(stderr, "Total bytes written: %s\n",
		    tar_i64toa(archive_position_compressed(a)));
	}

	archive_write_free(a);
}
Beispiel #10
0
/*
 * Write user-specified files/dirs to opened archive.
 */
static void
write_archive(struct archive *a, struct bsdtar *bsdtar)
{
	struct sigaction sa;
	const char *arg;
	struct archive_entry *entry, *sparse_entry;

	/* We want to catch SIGINFO and SIGUSR1. */
	siginfo_init(bsdtar);

	/* We also want to catch SIGQUIT and ^Q. */
	if (sigquit_init())
		exit(1);

	/* And SIGUSR2, too. */
	sa.sa_handler = sigusr2_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	if (sigaction(SIGUSR2, &sa, NULL))
		bsdtar_errc(bsdtar, 1, 0, "cannot install signal handler");

	/* Allocate a buffer for file data. */
	if ((bsdtar->buff = malloc(FILEDATABUFLEN)) == NULL)
		bsdtar_errc(bsdtar, 1, 0, "cannot allocate memory");

	if ((bsdtar->resolver = archive_entry_linkresolver_new()) == NULL)
		bsdtar_errc(bsdtar, 1, 0, "cannot create link resolver");
	archive_entry_linkresolver_set_strategy(bsdtar->resolver,
	    archive_format(a));
	if ((bsdtar->diskreader = archive_read_disk_new()) == NULL)
		bsdtar_errc(bsdtar, 1, 0, "Cannot create read_disk object");
	archive_read_disk_set_standard_lookup(bsdtar->diskreader);

	if (bsdtar->names_from_file != NULL)
		archive_names_from_file(bsdtar, a);

	while (*bsdtar->argv) {
		if (truncate_archive(bsdtar))
			break;
		if (checkpoint_archive(bsdtar, 0))
			exit(1);

		arg = *bsdtar->argv;
		if (arg[0] == '-' && arg[1] == 'C') {
			arg += 2;
			if (*arg == '\0') {
				bsdtar->argv++;
				arg = *bsdtar->argv;
				if (arg == NULL) {
					bsdtar_warnc(bsdtar, 0,
					    "Missing argument for -C");
					bsdtar->return_value = 1;
					goto cleanup;
				}
				if (*arg == '\0') {
					bsdtar_warnc(bsdtar, 0,
					    "Meaningless argument for -C: ''");
					bsdtar->return_value = 1;
					goto cleanup;
				}
			}
			set_chdir(bsdtar, arg);
		} else {
			if (arg[0] != '/' &&
			    (arg[0] != '@' || arg[1] != '/') &&
			    (arg[0] != '@' || arg[1] != '@'))
				do_chdir(bsdtar); /* Handle a deferred -C */
			if (arg[0] == '@' && arg[1] == '@') {
				if (append_archive_tarsnap(bsdtar, a,
				    arg + 2) != 0)
					break;
			} else if (arg[0] == '@') {
				if (append_archive_filename(bsdtar, a,
				    arg + 1) != 0)
					break;
			} else
#if defined(_WIN32) && !defined(__CYGWIN__)
				write_hierarchy_win(bsdtar, a, arg,
				    write_hierarchy);
#else
				write_hierarchy(bsdtar, a, arg);
#endif
		}
		bsdtar->argv++;
	}

	/*
	 * This code belongs to bsdtar and is used when writing archives in
	 * "new cpio" format.  It has no effect in tarsnap, since tarsnap
	 * doesn't write archives in this format; but I'm leaving it in to
	 * make the diffs smaller.
	 */
	entry = NULL;
	archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry);
	while (entry != NULL) {
		write_entry_backend(bsdtar, a, entry, NULL, NULL);
		archive_entry_free(entry);
		entry = NULL;
		archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry);
	}

	if (archive_write_close(a)) {
		bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
		bsdtar->return_value = 1;
	}

cleanup:
	/* Free file data buffer. */
	free(bsdtar->buff);
	archive_entry_linkresolver_free(bsdtar->resolver);
	bsdtar->resolver = NULL;
	archive_read_finish(bsdtar->diskreader);
	bsdtar->diskreader = NULL;

	if (bsdtar->option_totals && (bsdtar->return_value == 0)) {
		fprintf(stderr, "Total bytes written: " BSDTAR_FILESIZE_PRINTF "\n",
		    (BSDTAR_FILESIZE_TYPE)archive_position_compressed(a));
	}

	archive_write_finish(a);

	/* Restore old SIGINFO + SIGUSR1 handlers. */
	siginfo_done(bsdtar);
}
Beispiel #11
0
/*
 * Write user-specified files/dirs to opened archive.
 */
static void
write_archive(struct archive *a, struct bsdtar *bsdtar)
{
	const char *arg;
	struct archive_entry *entry, *sparse_entry;

	/* We want to catch SIGINFO and SIGUSR1. */
	siginfo_init(bsdtar);

	/* Allocate a buffer for file data. */
	if ((bsdtar->buff = malloc(FILEDATABUFLEN)) == NULL)
		bsdtar_errc(bsdtar, 1, 0, "cannot allocate memory");

	if ((bsdtar->resolver = archive_entry_linkresolver_new()) == NULL)
		bsdtar_errc(bsdtar, 1, 0, "cannot create link resolver");
	archive_entry_linkresolver_set_strategy(bsdtar->resolver,
	    archive_format(a));
	if ((bsdtar->diskreader = archive_read_disk_new()) == NULL)
		bsdtar_errc(bsdtar, 1, 0, "Cannot create read_disk object");
	archive_read_disk_set_standard_lookup(bsdtar->diskreader);

	if (bsdtar->names_from_file != NULL)
		archive_names_from_file(bsdtar, a);

	while (*bsdtar->argv) {
		arg = *bsdtar->argv;
		if (arg[0] == '-' && arg[1] == 'C') {
			arg += 2;
			if (*arg == '\0') {
				bsdtar->argv++;
				arg = *bsdtar->argv;
				if (arg == NULL) {
					bsdtar_warnc(bsdtar, 1, 0,
					    "Missing argument for -C");
					bsdtar->return_value = 1;
					goto cleanup;
				}
			}
			set_chdir(bsdtar, arg);
		} else {
			if (*arg != '/' && (arg[0] != '@' || arg[1] != '/'))
				do_chdir(bsdtar); /* Handle a deferred -C */
			if (*arg == '@') {
				if (append_archive_filename(bsdtar, a,
				    arg + 1) != 0)
					break;
			} else
#if defined(_WIN32) && !defined(__CYGWIN__)
				write_hierarchy_win(bsdtar, a, arg,
				    write_hierarchy);
#else
				write_hierarchy(bsdtar, a, arg);
#endif
		}
		bsdtar->argv++;
	}

	entry = NULL;
	archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry);
	while (entry != NULL) {
		write_entry_backend(bsdtar, a, entry);
		archive_entry_free(entry);
		entry = NULL;
		archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry);
	}

	if (archive_write_close(a)) {
		bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
		bsdtar->return_value = 1;
	}

cleanup:
	/* Free file data buffer. */
	free(bsdtar->buff);
	archive_entry_linkresolver_free(bsdtar->resolver);
	bsdtar->resolver = NULL;
	archive_read_finish(bsdtar->diskreader);
	bsdtar->diskreader = NULL;

	if (bsdtar->option_totals) {
		fprintf(stderr, "Total bytes written: " BSDTAR_FILESIZE_PRINTF "\n",
		    (BSDTAR_FILESIZE_TYPE)archive_position_compressed(a));
	}

	archive_write_finish(a);

	/* Restore old SIGINFO + SIGUSR1 handlers. */
	siginfo_done(bsdtar);
}