コード例 #1
0
ファイル: helper.c プロジェクト: jyizheng/dtar
void DTAR_writer_init()
{
	
        char compress=DTAR_user_opts->compress;
        char filename=DTAR_user_opts->dest_path;
  
        DTAR_writer->flags= O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC;
	DTAR_writer->a=archive_write_new();
	
        switch (compress) {
	case 'j': case 'y':
		archive_write_add_filter_bzip2(a);
		break;
	case 'Z':
		archive_write_add_filter_compress(a);
		break;
	case 'z':
		archive_write_add_filter_gzip(a);
		break;
	default:
		archive_write_add_filter_none(a);
		break;
	}
	archive_write_set_format_ustar(a);
        archive_write_set_bytes_per_block(a,0);

	if (strcmp(filename, "-") == 0)
		filename = NULL;
         
         DTAR_writer->fd_tar=open(filename,DTAR_writer->flags,0666);
         archive_write_open_fd(a, DTAR_writer->fd_tar); 
}
コード例 #2
0
ファイル: write.c プロジェクト: nanakom/freebsd
void
tar_mode_c(struct bsdtar *bsdtar)
{
    struct archive *a;
    const void *filter_name;
    int r;

    if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL)
        lafe_errc(1, 0, "no files or directories specified");

    a = archive_write_new();

    /* Support any format that the library supports. */
    if (cset_get_format(bsdtar->cset) == NULL) {
        r = archive_write_set_format_pax_restricted(a);
        cset_set_format(bsdtar->cset, "pax restricted");
    } else {
        r = archive_write_set_format_by_name(a,
                                             cset_get_format(bsdtar->cset));
    }
    if (r != ARCHIVE_OK) {
        fprintf(stderr, "Can't use format %s: %s\n",
                cset_get_format(bsdtar->cset),
                archive_error_string(a));
        usage();
    }

    archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block);
    archive_write_set_bytes_in_last_block(a, bsdtar->bytes_in_last_block);

    r = cset_write_add_filters(bsdtar->cset, a, &filter_name);
    if (r < ARCHIVE_WARN) {
        lafe_errc(1, 0, "Unsupported compression option --%s",
                  (const char *)filter_name);
    }

    set_writer_options(bsdtar, a);
    if (bsdtar->passphrase != NULL)
        r = archive_write_set_passphrase(a, bsdtar->passphrase);
    else
        r = archive_write_set_passphrase_callback(a, bsdtar,
                &passphrase_callback);
    if (r != ARCHIVE_OK)
        lafe_errc(1, 0, "%s", archive_error_string(a));
    if (ARCHIVE_OK != archive_write_open_filename(a, bsdtar->filename))
        lafe_errc(1, 0, "%s", archive_error_string(a));
    write_archive(a, bsdtar);
}
コード例 #3
0
ファイル: pc_archive.c プロジェクト: muyu/pcompress
/*
 * Archiving related functions.
 * This one creates a list of files to be included into the archive and
 * sets up the libarchive context.
 */
int
setup_archiver(pc_ctx_t *pctx, struct stat *sbuf)
{
	char *tmpfile, *tmp;
	int err, fd;
	uchar_t *pbuf;
	struct archive *arc;
	struct fn_list *fn;

	/*
	 * If sorting is enabled create the initial sort buffer.
	 */
	if (pctx->enable_archive_sort) {
		struct sort_buf *srt;
		srt = (struct sort_buf *)malloc(sizeof (struct sort_buf));
		if (srt == NULL) {
			log_msg(LOG_ERR, 0, "Out of memory.");
			return (-1);
		}
		srt->next = NULL;
		srt->pos = 0;
		pctx->archive_sort_buf = srt;
	}

	/*
	 * Create a temporary file to hold the generated list of pathnames to be archived.
	 * Storing in a file saves memory usage and allows scalability.
	 */
	tmpfile = pctx->archive_members_file;
	tmp = get_temp_dir();
	strcpy(tmpfile, tmp);
	free(tmp);

	strcat(tmpfile, "/.pcompXXXXXX");
	if ((fd = mkstemp(tmpfile)) == -1) {
		log_msg(LOG_ERR, 1, "mkstemp errored.");
		return (-1);
	}

	add_fname(tmpfile);
	pbuf = malloc(pctx->chunksize);
	if (pbuf == NULL) {
		log_msg(LOG_ERR, 0, "Out of memory.");
		close(fd);  unlink(tmpfile);
		return (-1);
	}

	/*
	 * Use nftw() to scan all the directory hierarchies provided on the command
	 * line and generate a consolidated list of pathnames to be archived. By
	 * doing this we can sort the pathnames and estimate the total archive size.
	 * Total archive size is needed by the subsequent compression stages.
	 */
	log_msg(LOG_INFO, 0, "Scanning files.");
	sbuf->st_size = 0;
	pctx->archive_size = 0;
	pctx->archive_members_count = 0;

	/*
	 * nftw requires using global state variable. So we lock to be mt-safe.
	 * This means only one directory tree scan can happen at a time.
	 */
	pthread_mutex_lock(&nftw_mutex);
	fn = pctx->fn;
	a_state.pbuf = pbuf;
	a_state.bufsiz = pctx->chunksize;
	a_state.bufpos = 0;
	a_state.fd = fd;
	a_state.srt = pctx->archive_sort_buf;
	a_state.srt_pos = 0;
	a_state.head = a_state.srt;
	a_state.pathlist_size = 0;

	while (fn) {
		struct stat sb;

		if (lstat(fn->filename, &sb) == -1) {
			log_msg(LOG_ERR, 1, "Ignoring %s.", fn->filename);
			fn = fn->next;
			continue;
		}

		a_state.arc_size = 0;
		a_state.fcount = 0;
		if (S_ISDIR(sb.st_mode)) {
			/*
			 * Depth-First scan, FTW_DEPTH, is needed to handle restoring
			 * all directory permissions correctly.
			 */
			err = nftw(fn->filename, add_pathname, 1024, FTW_PHYS | FTW_DEPTH);
		} else {
			int tflag;
			struct FTW ftwbuf;
			char *pos;

			if (S_ISLNK(sb.st_mode))
				tflag = FTW_SL;
			else
				tflag = FTW_F;

			/*
			 * Find out basename to mimic FTW.
			 */
			pos = strrchr(fn->filename, PATHSEP_CHAR);
			if (pos)
				ftwbuf.base = pos - fn->filename + 1;
			else
				ftwbuf.base = 0;
			add_pathname(fn->filename, &sb, tflag, &ftwbuf);
			a_state.arc_size = sb.st_size;
		}
		if (a_state.bufpos > 0) {
			ssize_t wrtn = Write(a_state.fd, a_state.pbuf, a_state.bufpos);
			if (wrtn < a_state.bufpos) {
				log_msg(LOG_ERR, 1, "Write failed.");
				close(fd);  unlink(tmpfile);
				return (-1);
			}
			a_state.bufpos = 0;
			a_state.pathlist_size += wrtn;
		}
		pctx->archive_size += a_state.arc_size;
		pctx->archive_members_count += a_state.fcount;
		fn = fn->next;
	}

	if (a_state.srt == NULL) {
		pctx->enable_archive_sort = 0;
	} else {
		log_msg(LOG_INFO, 0, "Sorting ...");
		a_state.srt->max = a_state.srt_pos - 1;
		qsort(a_state.srt->members, a_state.srt_pos, sizeof (member_entry_t), compare_members);
		pctx->archive_temp_size = a_state.pathlist_size;
	}
	pthread_mutex_unlock(&nftw_mutex);

	sbuf->st_size = pctx->archive_size;
	lseek(fd, 0, SEEK_SET);
	free(pbuf);
	sbuf->st_uid = geteuid();
	sbuf->st_gid = getegid();
	sbuf->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;

	arc = archive_write_new();
	if (!arc) {
		log_msg(LOG_ERR, 1, "Unable to create libarchive context.\n");
		close(fd);
		unlink(tmpfile);
		return (-1);
	}
	archive_write_set_format_pax_restricted(arc);
	archive_write_set_bytes_per_block(arc, 0);
	archive_write_open(arc, pctx, arc_open_callback,
			   creat_write_callback, creat_close_callback);
	pctx->archive_ctx = arc;
	pctx->archive_members_fd = fd;
	if (pctx->enable_archive_sort) {
		pctx->temp_mmap_len = TEMP_MMAP_SIZE;
		pctx->temp_mmap_buf = mmap(NULL, pctx->temp_mmap_len, PROT_READ,
					MAP_SHARED, pctx->archive_members_fd, 0);
		if (pctx->temp_mmap_buf == NULL) {
			log_msg(LOG_WARN, 1, "Unable to mmap pathlist file, switching to read().");
			pctx->temp_mmap_len = 0;
		}
	} else {
		pctx->temp_mmap_buf = NULL;
		pctx->temp_mmap_len = 0;
	}
	pctx->temp_mmap_pos = 0;
	pctx->arc_writing = 0;

	return (0);
}
コード例 #4
0
/*!
 * \brief Create pax archive with all metadata
 *
 * \param filename Target archive path
 * \param base_dir Base directory for \a paths
 * \param paths List of paths to add to the archive
 *
 * \return Whether the archive creation was successful
 */
bool libarchive_tar_create(const std::string &filename,
                           const std::string &base_dir,
                           const std::vector<std::string> &paths)
{
    if (base_dir.empty() && paths.empty()) {
        LOGE("%s: No base directory or paths specified", filename.c_str());
        return false;
    }

    autoclose::archive in(archive_read_disk_new(), archive_read_free);
    if (!in) {
        LOGE("%s: Out of memory when creating disk reader", __FUNCTION__);
        return false;
    }
    autoclose::archive out(archive_write_new(), archive_write_free);
    if (!out) {
        LOGE("%s: Out of memory when creating archive writer", __FUNCTION__);
        return false;
    }
    autoclose::archive_entry_linkresolver resolver(archive_entry_linkresolver_new(),
                                                   archive_entry_linkresolver_free);
    if (!resolver) {
        LOGE("%s: Out of memory when creating link resolver", __FUNCTION__);
        return false;
    }

    // Set up disk reader parameters
    archive_read_disk_set_symlink_physical(in.get());
    archive_read_disk_set_metadata_filter_callback(
            in.get(), metadata_filter, nullptr);
    archive_read_disk_set_behavior(in.get(), LIBARCHIVE_DISK_READER_FLAGS);
    // We don't want to look up usernames and group names on Android
    //archive_read_disk_set_standard_lookup(in.get());

    // Set up archive writer parameters
    // NOTE: We are creating POSIX pax archives instead of GNU tar archives
    //       because libarchive's GNU tar writer is very limited. In particular,
    //       it does not support storing sparse file information, xattrs, or
    //       ACLs. Since this information is stored as extended attributes in
    //       the pax archive, the GNU tar tool will not be able to extract any
    //       of this additional metadata. In other words, extracting and
    //       repacking a backup on a Linux machine with GNU tar will render the
    //       backup useless.
    //archive_write_set_format_gnutar(out.get());
    archive_write_set_format_pax_restricted(out.get());
    //archive_write_set_compression_bzip2(out.get());
    //archive_write_set_compression_gzip(out.get());
    //archive_write_set_compression_xz(out.get());
    archive_write_set_bytes_per_block(out.get(), 10240);

    // Set up link resolver parameters
    archive_entry_linkresolver_set_strategy(resolver.get(),
                                            archive_format(out.get()));

    // Open output file
    if (archive_write_open_filename(out.get(), filename.c_str()) != ARCHIVE_OK) {
        LOGE("%s: Failed to open file: %s",
             filename.c_str(), archive_error_string(out.get()));
        return false;
    }

    archive_entry *entry = nullptr;
    archive_entry *sparse_entry = nullptr;
    int ret;
    std::string full_path;

    // Add hierarchies
    for (const std::string &path : paths) {
        if (path.empty()) {
            LOGE("%s: Cannot add empty path to the archive", filename.c_str());
            return false;
        }

        // If the path is absolute, don't append it to the base directory
        if (path[0] == '/') {
            full_path = path;
        } else {
            full_path = base_dir;
            if (!full_path.empty() && full_path.back() != '/' && path[0] != '/') {
                full_path += '/';
            }
            full_path += path;
        }

        ret = archive_read_disk_open(in.get(), full_path.c_str());
        if (ret != ARCHIVE_OK) {
            LOGE("%s: %s", full_path.c_str(), archive_error_string(in.get()));
            return false;
        }

        while (true) {
            archive_entry_free(entry);
            entry = archive_entry_new();

            ret = archive_read_next_header2(in.get(), entry);
            if (ret == ARCHIVE_EOF) {
                break;
            } else if (ret != ARCHIVE_OK) {
                LOGE("%s: Failed to read next header: %s", full_path.c_str(),
                     archive_error_string(in.get()));
                archive_entry_free(entry);
                return false;
            }

            if (archive_entry_filetype(entry) != AE_IFREG) {
                archive_entry_set_size(entry, 0);
            }

            // If our current directory tree path is not an absolute path, set
            // the archive path to the relative path starting at base_dir
            const char *curpath = archive_entry_pathname(entry);
            if (curpath && path[0] != '/' && !base_dir.empty()) {
                std::string relpath;
                if (!util::relative_path(curpath, base_dir, &relpath)) {
                    LOGE("Failed to compute relative path of %s starting at %s: %s",
                         curpath, base_dir.c_str(), strerror(errno));
                    archive_entry_free(entry);
                    return false;
                }
                if (relpath.empty()) {
                    // If the relative path is empty, then the current path is
                    // the root of the directory tree. We don't need that, so
                    // skip it.
                    continue;
                }
                archive_entry_set_pathname(entry, relpath.c_str());
            }

            switch (archive_entry_filetype(entry)) {
            case AE_IFSOCK:
                LOGW("%s: Skipping socket", archive_entry_pathname(entry));
                continue;
            default:
                LOGV("%s", archive_entry_pathname(entry));
                break;
            }

            archive_entry_linkify(resolver.get(), &entry, &sparse_entry);

            if (entry) {
                if (!write_file(in.get(), out.get(), entry)) {
                    archive_entry_free(entry);
                    return false;
                }
                archive_entry_free(entry);
                entry = nullptr;
            }
            if (sparse_entry) {
                if (!write_file(in.get(), out.get(), sparse_entry)) {
                    archive_entry_free(sparse_entry);
                    return false;
                }
                archive_entry_free(sparse_entry);
                sparse_entry = nullptr;
            }
        }

        archive_entry_free(entry);
        entry = nullptr;
        archive_read_close(in.get());
    }

    archive_read_disk_set_metadata_filter_callback(in.get(), nullptr, nullptr);

    entry = nullptr;
    archive_entry_linkify(resolver.get(), &entry, &sparse_entry);

    while (entry) {
        // This tricky code here is to correctly read the contents of the entry
        // because the disk reader 'in' 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 hae to re-open the entry to read the contents.
        ret = archive_read_disk_open(in.get(), archive_entry_sourcepath(entry));
        if (ret != ARCHIVE_OK) {
            LOGE("%s: %s", archive_entry_sourcepath(entry),
                 archive_error_string(in.get()));
            return false;
        }

        // Invoke archive_read_next_header2() to work archive_read_data_block(),
        // which is called via write_file() without failure.
        archive_entry *entry2 = archive_entry_new();
        ret = archive_read_next_header2(in.get(), entry2);
        archive_entry_free(entry2);
        if (ret != ARCHIVE_OK) {
            LOGE("%s: %s", archive_entry_sourcepath(entry),
                 archive_error_string(in.get()));
            archive_entry_free(entry);
            return false;
        }

        if (!write_file(in.get(), out.get(), entry)) {
            archive_entry_free(entry);
            return false;
        }
        archive_entry_free(entry);
        archive_read_close(in.get());
        entry = nullptr;
        archive_entry_linkify(resolver.get(), &entry, &sparse_entry);
    }

    if (archive_write_close(out.get()) != ARCHIVE_OK) {
        LOGE("%s: %s", filename.c_str(), archive_error_string(out.get()));
        return false;
    }

    return true;
}
コード例 #5
0
static void
test_1(void)
{
	struct archive_entry *ae;
	struct archive *a;
	size_t used;
	size_t blocksize;
	int64_t offset, length;
	char *buff2;
	size_t buff2_size = 0x13000;
	char buff3[1024];
	long i;

	assert((buff2 = malloc(buff2_size)) != NULL);
	/* Repeat the following for a variety of odd blocksizes. */
	for (blocksize = 1; blocksize < 100000; blocksize += blocksize + 3) {
		/* Create a new archive in memory. */
		assert((a = archive_write_new()) != NULL);
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_write_set_format_pax(a));
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_write_set_compression_none(a));
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_write_set_bytes_per_block(a, (int)blocksize));
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_write_set_bytes_in_last_block(a, (int)blocksize));
		assertEqualInt(blocksize,
		    archive_write_get_bytes_in_last_block(a));
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_write_open_memory(a, buff, sizeof(buff), &used));
		assertEqualInt(blocksize,
		    archive_write_get_bytes_in_last_block(a));

		/*
		 * Write a file to it.
		 */
		assert((ae = archive_entry_new()) != NULL);
		archive_entry_set_mtime(ae, 1, 10);
		assertEqualInt(1, archive_entry_mtime(ae));
		assertEqualInt(10, archive_entry_mtime_nsec(ae));
		archive_entry_copy_pathname(ae, "file");
		assertEqualString("file", archive_entry_pathname(ae));
		archive_entry_set_mode(ae, S_IFREG | 0755);
		assertEqualInt(S_IFREG | 0755, archive_entry_mode(ae));
		archive_entry_set_size(ae, 0x81000);
		archive_entry_sparse_add_entry(ae, 0x10000, 0x1000);
		archive_entry_sparse_add_entry(ae, 0x80000, 0x1000);

		assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
		archive_entry_free(ae);
		memset(buff2, 'a', buff2_size);
		for (i = 0; i < 0x81000;) {
			size_t ws = buff2_size;
			if (i + ws > 0x81000)
				ws = 0x81000 - i;
			assertEqualInt(ws,
				archive_write_data(a, buff2, ws));
			i += ws;
		}

		/* Close out the archive. */
		assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
		assertEqualInt(ARCHIVE_OK, archive_write_free(a));

		/* This calculation gives "the smallest multiple of
		 * the block size that is at least 11264 bytes". */
		failure("blocksize=%d", blocksize);
		assertEqualInt(((11264 - 1)/blocksize+1)*blocksize, used);

		/*
		 * Now, read the data back.
		 */
		assert((a = archive_read_new()) != NULL);
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_read_support_format_all(a));
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_read_support_filter_all(a));
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_read_open_memory(a, buff, used));

		assertEqualIntA(a, ARCHIVE_OK,
		    archive_read_next_header(a, &ae));

		assertEqualInt(1, archive_entry_mtime(ae));
		assertEqualInt(10, archive_entry_mtime_nsec(ae));
		assertEqualInt(0, archive_entry_atime(ae));
		assertEqualInt(0, archive_entry_ctime(ae));
		assertEqualString("file", archive_entry_pathname(ae));
		assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
		assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae));
		assertEqualInt(0x81000, archive_entry_size(ae));
		/* Verify sparse information. */
		assertEqualInt(2, archive_entry_sparse_reset(ae));
		assertEqualInt(0,
			archive_entry_sparse_next(ae, &offset, &length));
		assertEqualInt(0x10000, offset);
		assertEqualInt(0x1000, length);
		assertEqualInt(0,
			archive_entry_sparse_next(ae, &offset, &length));
		assertEqualInt(0x80000, offset);
		assertEqualInt(0x1000, length);
		/* Verify file contents. */
		memset(buff3, 0, sizeof(buff3));
		for (i = 0; i < 0x10000; i += 1024) {
			assertEqualInt(1024, archive_read_data(a, buff2, 1024));
			failure("Read data(0x%lx - 0x%lx) should be all zero",
			    i, i + 1024);
			assertEqualMem(buff2, buff3, 1024);
		}
		memset(buff3, 'a', sizeof(buff3));
		for (i = 0x10000; i < 0x11000; i += 1024) {
			assertEqualInt(1024, archive_read_data(a, buff2, 1024));
			failure("Read data(0x%lx - 0x%lx) should be all 'a'",
			    i, i + 1024);
			assertEqualMem(buff2, buff3, 1024);
		}
		memset(buff3, 0, sizeof(buff3));
		for (i = 0x11000; i < 0x80000; i += 1024) {
			assertEqualInt(1024, archive_read_data(a, buff2, 1024));
			failure("Read data(0x%lx - 0x%lx) should be all zero",
			    i, i + 1024);
			assertEqualMem(buff2, buff3, 1024);
		}
		memset(buff3, 'a', sizeof(buff3));
		for (i = 0x80000; i < 0x81000; i += 1024) {
			assertEqualInt(1024, archive_read_data(a, buff2, 1024));
			failure("Read data(0x%lx - 0x%lx) should be all 'a'",
			    i, i + 1024);
			assertEqualMem(buff2, buff3, 1024);
		}

		/* Verify the end of the archive. */
		assertEqualIntA(a, ARCHIVE_EOF,
		    archive_read_next_header(a, &ae));
		assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
		assertEqualInt(ARCHIVE_OK, archive_read_free(a));
	}
	free(buff2);
}
コード例 #6
0
ファイル: ar_write.c プロジェクト: uudiin/lua-archive
//////////////////////////////////////////////////////////////////////
// Constructor:
static int ar_write(lua_State *L) {
    struct archive** self_ref;

    static struct {
        const char *name;
        int (*setter)(struct archive *);
    } names[] = {
        /* Copied from archive_write_set_format_by_name.c */
        { "ar",         archive_write_set_format_ar_bsd },
        { "arbsd",      archive_write_set_format_ar_bsd },
        { "argnu",      archive_write_set_format_ar_svr4 },
        { "arsvr4",     archive_write_set_format_ar_svr4 },
        { "cpio",       archive_write_set_format_cpio },
        { "mtree",      archive_write_set_format_mtree },
        { "newc",       archive_write_set_format_cpio_newc },
        { "odc",        archive_write_set_format_cpio },
        { "pax",        archive_write_set_format_pax },
        { "posix",      archive_write_set_format_pax },
        { "shar",       archive_write_set_format_shar },
        { "shardump",   archive_write_set_format_shar_dump },
        { "ustar",      archive_write_set_format_ustar },
        /* New ones to more closely match the C API */
        { "ar_bsd",     archive_write_set_format_ar_bsd },
        { "ar_svr4",    archive_write_set_format_ar_svr4 },
        { "cpio_newc",  archive_write_set_format_cpio_newc },
        { "pax_restricted", archive_write_set_format_pax_restricted },
        { "shar_dump",  archive_write_set_format_shar_dump },
        { NULL,         NULL }
    };
    int idx = 0;
    const char* name;

    luaL_checktype(L, 1, LUA_TTABLE);
    self_ref = (struct archive**)
        lua_newuserdata(L, sizeof(struct archive*)); // {ud}
    luaL_getmetatable(L, AR_WRITE); // {ud}, [write]
    lua_setmetatable(L, -2); // {ud}
    __ref_count++;
    *self_ref = archive_write_new();

    // Register it in the weak metatable:
    ar_registry_set(L, *self_ref);

    // Create an environment to store a reference to the writer:
    lua_createtable(L, 1, 0); // {ud}, {}
    lua_pushliteral(L, "writer"); // {ud}, {}, "writer"
    lua_rawget(L, 1); // {ud}, {}, fn
    if ( ! lua_isfunction(L, -1) ) {
        err("MissingArgument: required parameter 'writer' must be a function");
    }
    lua_setfield(L, -2, "writer");
    lua_setfenv(L, -2); // {ud}

    // Extract various fields and prepare the archive:
    lua_getfield(L, 1, "bytes_per_block");
    if ( ! lua_isnil(L, -1) &&
         ARCHIVE_OK != archive_write_set_bytes_per_block(*self_ref, lua_tointeger(L, -1)) )
    {
        err("archive_write_set_bytes_per_block: %s", archive_error_string(*self_ref));
    }
    lua_pop(L, 1);

    lua_getfield(L, 1, "bytes_in_last_block");
    if ( ! lua_isnil(L, -1) &&
         ARCHIVE_OK != archive_write_set_bytes_in_last_block(*self_ref, lua_tointeger(L, -1)) )
    {
        err("archive_write_set_bytes_in_last_block: %s", archive_error_string(*self_ref));
    }
    lua_pop(L, 1);

    lua_getfield(L, 1, "skip_file");
    if ( ! lua_isnil(L, -1) ) {
        dev_t dev;
        ino_t ino;

        if ( LUA_TTABLE != lua_type(L, -1) ) {
            err("skip_file member must be a table object");
        }

        lua_getfield(L, -1, "dev");
        if ( ! lua_isnumber(L, -1) ) {
            err("skip_file.dev member must be a number");
        }
        dev = (dev_t)lua_tonumber(L, -1);
        lua_pop(L, 1);

        lua_getfield(L, -1, "ino");
        if ( ! lua_isnumber(L, -1) ) {
            err("skip_file.ino member must be a number");
        }
        ino = (ino_t)lua_tonumber(L, -1);
        lua_pop(L, 1);

        if ( ARCHIVE_OK != archive_write_set_skip_file(*self_ref, dev, ino) ) {
            err("archive_write_set_skip_file: %s", archive_error_string(*self_ref));
        }
    }
    lua_pop(L, 1);

    lua_getfield(L, 1, "format");
    if ( lua_isnil(L, -1) ) {
        lua_pop(L, 1);
        lua_pushliteral(L, "posix");
    }
    name = lua_tostring(L, -1);
    for ( ;; idx++ ) {
        if ( names[idx].name == NULL ) {
            err("archive_write_set_format_*: No such format '%s'", name);
        }
        if ( strcmp(name, names[idx].name) == 0 ) break;
    }
    if ( ARCHIVE_OK != (names[idx].setter)(*self_ref) ) {
        err("archive_write_set_format_%s: %s", name, archive_error_string(*self_ref));
    }
    lua_pop(L, 1);

    lua_getfield(L, 1, "compression");
    if ( ! lua_isnil(L, -1) ) {
        static struct {
            const char *name;
            int (*setter)(struct archive *);
        } names[] = {
            { "bzip2",    archive_write_add_filter_bzip2 },
            { "compress", archive_write_add_filter_compress },
            { "gzip",     archive_write_add_filter_gzip },
            { "lzma",     archive_write_add_filter_lzma },
            { "xz",       archive_write_add_filter_xz },
            { NULL,       NULL }
        };
        int idx = 0;
        const char* name = lua_tostring(L, -1);
        for ( ;; idx++ ) {
            if ( names[idx].name == NULL ) {
                err("archive_write_set_compression_*: No such compression '%s'", name);
            }
            if ( strcmp(name, names[idx].name) == 0 ) break;
        }
        if ( ARCHIVE_OK != (names[idx].setter)(*self_ref) ) {
            err("archive_write_set_compression_%s: %s", name, archive_error_string(*self_ref));
        }
    }
    lua_pop(L, 1);

    lua_getfield(L, 1, "options");
    if ( ! lua_isnil(L, -1) &&
         ARCHIVE_OK != archive_write_set_options(*self_ref, lua_tostring(L, -1)) )
    {
        err("archive_write_set_options: %s",  archive_error_string(*self_ref));
    }
    lua_pop(L, 1);


    if ( ARCHIVE_OK != archive_write_open(*self_ref, L, NULL, &ar_write_cb, NULL) ) {
        err("archive_write_open: %s", archive_error_string(*self_ref));
    }

    return 1;
}
コード例 #7
0
static void
test_filename(const char *prefix, int dlen, int flen)
{
	char buff[8192];
	char filename[400];
	char dirname[400];
	struct archive_entry *ae;
	struct archive *a;
	size_t used;
	char *p;
	int i;

	p = filename;
	if (prefix) {
		strcpy(filename, prefix);
		p += strlen(p);
	}
	if (dlen > 0) {
		for (i = 0; i < dlen; i++)
			*p++ = 'a';
		*p++ = '/';
	}
	for (i = 0; i < flen; i++)
		*p++ = 'b';
	*p = '\0';

	strcpy(dirname, filename);

	/* Create a new archive in memory. */
	assert((a = archive_write_new()) != NULL);
	assertA(0 == archive_write_set_format_pax_restricted(a));
	assertA(0 == archive_write_set_compression_none(a));
	assertA(0 == archive_write_set_bytes_per_block(a,0));
	assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

	/*
	 * Write a file to it.
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_copy_pathname(ae, filename);
	archive_entry_set_mode(ae, S_IFREG | 0755);
	failure("Pathname %d/%d", dlen, flen);
	assertA(0 == archive_write_header(a, ae));
	archive_entry_free(ae);

	/*
	 * Write a dir to it (without trailing '/').
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_copy_pathname(ae, dirname);
	archive_entry_set_mode(ae, S_IFDIR | 0755);
	failure("Dirname %d/%d", dlen, flen);
	assertA(0 == archive_write_header(a, ae));
	archive_entry_free(ae);

	/* Tar adds a '/' to directory names. */
	strcat(dirname, "/");

	/*
	 * Write a dir to it (with trailing '/').
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_copy_pathname(ae, dirname);
	archive_entry_set_mode(ae, S_IFDIR | 0755);
	failure("Dirname %d/%d", dlen, flen);
	assertA(0 == archive_write_header(a, ae));
	archive_entry_free(ae);

	/* Close out the archive. */
	assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
	archive_write_finish(a);
#else
	assertA(0 == archive_write_finish(a));
#endif

	/*
	 * Now, read the data back.
	 */
	assert((a = archive_read_new()) != NULL);
	assertA(0 == archive_read_support_format_all(a));
	assertA(0 == archive_read_support_compression_all(a));
	assertA(0 == archive_read_open_memory(a, buff, used));

	/* Read the file and check the filename. */
	assertA(0 == archive_read_next_header(a, &ae));
#if ARCHIVE_VERSION_NUMBER < 1009000
	skipping("Leading '/' preserved on long filenames");
#else
	assertEqualString(filename, archive_entry_pathname(ae));
#endif
	assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));

	/*
	 * Read the two dirs and check the names.
	 *
	 * Both dirs should read back with the same name, since
	 * tar should add a trailing '/' to any dir that doesn't
	 * already have one.  We only report the first such failure
	 * here.
	 */
	assertA(0 == archive_read_next_header(a, &ae));
#if ARCHIVE_VERSION_NUMBER < 1009000
	skipping("Trailing '/' preserved on dirnames");
#else
	assertEqualString(dirname, archive_entry_pathname(ae));
#endif
	assert((S_IFDIR | 0755) == archive_entry_mode(ae));

	assertA(0 == archive_read_next_header(a, &ae));
#if ARCHIVE_VERSION_NUMBER < 1009000
	skipping("Trailing '/' added to dir names");
#else
	assertEqualString(dirname, archive_entry_pathname(ae));
#endif
	assert((S_IFDIR | 0755) == archive_entry_mode(ae));

	/* Verify the end of the archive. */
	assert(1 == archive_read_next_header(a, &ae));
	assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
	archive_read_finish(a);
#else
	assert(0 == archive_read_finish(a));
#endif
}
コード例 #8
0
ファイル: write.c プロジェクト: AAZemlyanukhin/freebsd
void
tar_mode_u(struct bsdtar *bsdtar)
{
	int64_t			 end_offset;
	struct archive		*a;
	struct archive_entry	*entry;
	int			 format;
	struct archive_dir_entry	*p;
	struct archive_dir	 archive_dir;

	bsdtar->archive_dir = &archive_dir;
	memset(&archive_dir, 0, sizeof(archive_dir));

	format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;

	/* Sanity-test some arguments and the file. */
	test_for_append(bsdtar);

	bsdtar->fd = open(bsdtar->filename, O_RDWR | O_BINARY);
	if (bsdtar->fd < 0)
		lafe_errc(1, errno,
		    "Cannot open %s", bsdtar->filename);

	a = archive_read_new();
	archive_read_support_filter_all(a);
	archive_read_support_format_tar(a);
	archive_read_support_format_gnutar(a);
	set_reader_options(bsdtar, a);
	if (archive_read_open_fd(a, bsdtar->fd, bsdtar->bytes_per_block)
	    != ARCHIVE_OK) {
		lafe_errc(1, 0,
		    "Can't open %s: %s", bsdtar->filename,
		    archive_error_string(a));
	}

	/* Build a list of all entries and their recorded mod times. */
	while (0 == archive_read_next_header(a, &entry)) {
		if (archive_filter_code(a, 0) != ARCHIVE_FILTER_NONE) {
			archive_read_free(a);
			close(bsdtar->fd);
			lafe_errc(1, 0,
			    "Cannot append to compressed archive.");
		}
		if (archive_match_exclude_entry(bsdtar->matching,
		    ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER |
		    ARCHIVE_MATCH_EQUAL, entry) != ARCHIVE_OK)
			lafe_errc(1, 0, "Error : %s",
			    archive_error_string(bsdtar->matching));
		/* Record the last format determination we see */
		format = archive_format(a);
		/* Keep going until we hit end-of-archive */
	}

	end_offset = archive_read_header_position(a);
	archive_read_free(a);

	/* Re-open archive for writing. */
	a = archive_write_new();
	/*
	 * Set format to same one auto-detected above.
	 */
	archive_write_set_format(a, format);
	archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block);
	archive_write_set_bytes_in_last_block(a, bsdtar->bytes_in_last_block);

	if (lseek(bsdtar->fd, end_offset, SEEK_SET) < 0)
		lafe_errc(1, errno, "Could not seek to archive end");
	set_writer_options(bsdtar, a);
	if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd))
		lafe_errc(1, 0, "%s", archive_error_string(a));

	write_archive(a, bsdtar);

	close(bsdtar->fd);
	bsdtar->fd = -1;

	while (bsdtar->archive_dir->head != NULL) {
		p = bsdtar->archive_dir->head->next;
		free(bsdtar->archive_dir->head->name);
		free(bsdtar->archive_dir->head);
		bsdtar->archive_dir->head = p;
	}
	bsdtar->archive_dir->tail = NULL;
}
コード例 #9
0
ファイル: write.c プロジェクト: zeha/tarsnap-deb
void
tarsnap_mode_c(struct bsdtar *bsdtar)
{
	struct archive *a;
	size_t i;

	if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL)
		bsdtar_errc(bsdtar, 1, 0, "no files or directories specified");

	for (i = 0; bsdtar->argv[i] != NULL; i++) {
		if (bsdtar->argv[i][0] == '-' && bsdtar->argv[i][1] == '-') {
			bsdtar_warnc(bsdtar, 0,
			    "List of objects to archive includes '%s'."
			    "  This might not be what you intended.",
			    bsdtar->argv[i]);
			break;
		}
	}

	a = archive_write_new();

	/* We only support the pax restricted format. */
	archive_write_set_format_pax_restricted(a);

	/* Set the block size to zero -- we don't want buffering. */
	archive_write_set_bytes_per_block(a, 0);

	/* Open the archive, keeping a cookie for talking to the tape layer. */
	bsdtar->write_cookie = archive_write_open_multitape(a,
	    bsdtar->machinenum, bsdtar->cachedir, bsdtar->tapenames[0],
	    bsdtar->argc_orig, bsdtar->argv_orig,
	    bsdtar->option_print_stats, bsdtar->option_dryrun,
	    bsdtar->creationtime);
	if (bsdtar->write_cookie == NULL)
		bsdtar_errc(bsdtar, 1, 0, "%s", archive_error_string(a));

	/*
	 * Remember the device and inode numbers of the cache directory, so
	 * that we can skip is in write_hierarchy().
	 */
	if (getdevino(a, bsdtar->cachedir,
	    &bsdtar->cachedir_dev, &bsdtar->cachedir_ino))
		bsdtar_errc(bsdtar, 1, 0, "%s", archive_error_string(a));

	/* If the chunkification cache is enabled, read it. */
	if ((bsdtar->cachecrunch < 2) && (bsdtar->cachedir != NULL)) {
		bsdtar->chunk_cache = ccache_read(bsdtar->cachedir);
		if (bsdtar->chunk_cache == NULL)
			bsdtar_errc(bsdtar, 1, errno, "Error reading cache");
	}

	write_archive(a, bsdtar);

	/*
	 * If this isn't a dry run and we're running with the chunkification
	 * cache enabled, write the cache back to disk.
	 */
	if ((bsdtar->option_dryrun == 0) && (bsdtar->cachecrunch < 2)) {
		if (ccache_write(bsdtar->chunk_cache, bsdtar->cachedir))
			bsdtar_errc(bsdtar, 1, errno, "Error writing cache");
	}

	/* Free the chunkification cache. */
	if (bsdtar->cachecrunch < 2)
		ccache_free(bsdtar->chunk_cache);
}
コード例 #10
0
static void
test_options(const char *options)
{
	struct archive_entry *ae;
	struct archive* a;
	char *buff, *data;
	size_t buffsize, datasize;
	char path[16];
	size_t used1;
	int i, r, use_prog = 0, filecount;

	assert((a = archive_write_new()) != NULL);
	r = archive_write_add_filter_lz4(a);
	if (archive_liblz4_version() == NULL) {
		if (!canLz4()) {
			skipping("lz4 writing not supported on this platform");
			assertEqualInt(ARCHIVE_WARN, r);
			assertEqualInt(ARCHIVE_OK, archive_write_free(a));
			return;
		} else {
			assertEqualInt(ARCHIVE_WARN, r);
			use_prog = 1;
		}
	} else {
		assertEqualInt(ARCHIVE_OK, r);
	}

	buffsize = 2000000;
	assert(NULL != (buff = (char *)malloc(buffsize)));

	datasize = 10000;
	assert(NULL != (data = (char *)calloc(1, datasize)));
	filecount = 10;

	/*
	 * Write a filecount files and read them all back.
	 */
	assert((a = archive_write_new()) != NULL);
	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
	assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK,
	    archive_write_add_filter_lz4(a));
	assertEqualIntA(a, ARCHIVE_OK,
	    archive_write_set_options(a, options));
	assertEqualIntA(a, ARCHIVE_OK,
	    archive_write_set_bytes_per_block(a, 1024));
	assertEqualIntA(a, ARCHIVE_OK,
	    archive_write_set_bytes_in_last_block(a, 1024));
	assertEqualInt(ARCHIVE_FILTER_LZ4, archive_filter_code(a, 0));
	assertEqualString("lz4", archive_filter_name(a, 0));
	assertEqualIntA(a, ARCHIVE_OK,
	    archive_write_open_memory(a, buff, buffsize, &used1));
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_set_filetype(ae, AE_IFREG);
	archive_entry_set_size(ae, datasize);
	for (i = 0; i < filecount; i++) {
		sprintf(path, "file%03d", i);
		archive_entry_copy_pathname(ae, path);
		assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
		assertA(datasize
		    == (size_t)archive_write_data(a, data, datasize));
	}
	archive_entry_free(ae);
	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));

	assert((a = archive_read_new()) != NULL);
	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
	r = archive_read_support_filter_lz4(a);
	if (r == ARCHIVE_WARN) {
		skipping("Can't verify lz4 writing by reading back;"
		    " lz4 reading not fully supported on this platform");
	} else {
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_read_open_memory(a, buff, used1));
		for (i = 0; i < filecount; i++) {
			sprintf(path, "file%03d", i);
			if (!assertEqualInt(ARCHIVE_OK,
				archive_read_next_header(a, &ae)))
				break;
			assertEqualString(path, archive_entry_pathname(ae));
			assertEqualInt((int)datasize, archive_entry_size(ae));
		}
		assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
	}
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));

	/*
	 * Clean up.
	 */
	free(data);
	free(buff);
}
コード例 #11
0
ファイル: write.c プロジェクト: marccodes/lfl
void
tar_mode_u(struct bsdtar *bsdtar)
{
	off_t			 end_offset;
	struct archive		*a;
	struct archive_entry	*entry;
	int			 format;
	struct archive_dir_entry	*p;
	struct archive_dir	 archive_dir;

	bsdtar->archive_dir = &archive_dir;
	memset(&archive_dir, 0, sizeof(archive_dir));

	format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;

	/* Sanity-test some arguments and the file. */
	test_for_append(bsdtar);

	bsdtar->fd = open(bsdtar->filename, O_RDWR);
	if (bsdtar->fd < 0)
		bsdtar_errc(bsdtar, 1, errno,
		    "Cannot open %s", bsdtar->filename);

	a = archive_read_new();
	archive_read_support_compression_all(a);
	archive_read_support_format_tar(a);
	archive_read_support_format_gnutar(a);
	if (archive_read_open_fd(a, bsdtar->fd,
	    bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block :
		DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) {
		bsdtar_errc(bsdtar, 1, 0,
		    "Can't open %s: %s", bsdtar->filename,
		    archive_error_string(a));
	}

	/* Build a list of all entries and their recorded mod times. */
	while (0 == archive_read_next_header(a, &entry)) {
		if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) {
			archive_read_finish(a);
			close(bsdtar->fd);
			bsdtar_errc(bsdtar, 1, 0,
			    "Cannot append to compressed archive.");
		}
		add_dir_list(bsdtar, archive_entry_pathname(entry),
		    archive_entry_mtime(entry),
		    archive_entry_mtime_nsec(entry));
		/* Record the last format determination we see */
		format = archive_format(a);
		/* Keep going until we hit end-of-archive */
	}

	end_offset = archive_read_header_position(a);
	archive_read_finish(a);

	/* Re-open archive for writing. */
	a = archive_write_new();
	archive_write_set_compression_none(a);
	/*
	 * Set format to same one auto-detected above, except that
	 * we don't write GNU tar format, so use ustar instead.
	 */
	if (format == ARCHIVE_FORMAT_TAR_GNUTAR)
		format = ARCHIVE_FORMAT_TAR_USTAR;
	archive_write_set_format(a, format);
	if (bsdtar->bytes_per_block != 0) {
		archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block);
		archive_write_set_bytes_in_last_block(a,
		    bsdtar->bytes_per_block);
	} else
		archive_write_set_bytes_per_block(a, DEFAULT_BYTES_PER_BLOCK);
	lseek(bsdtar->fd, end_offset, SEEK_SET);
	ftruncate(bsdtar->fd, end_offset);
	if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options))
		bsdtar_errc(bsdtar, 1, 0, archive_error_string(a));
	if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd))
		bsdtar_errc(bsdtar, 1, 0, archive_error_string(a));

	write_archive(a, bsdtar);

	close(bsdtar->fd);
	bsdtar->fd = -1;

	while (bsdtar->archive_dir->head != NULL) {
		p = bsdtar->archive_dir->head->next;
		free(bsdtar->archive_dir->head->name);
		free(bsdtar->archive_dir->head);
		bsdtar->archive_dir->head = p;
	}
	bsdtar->archive_dir->tail = NULL;
}
コード例 #12
0
ファイル: write.c プロジェクト: marccodes/lfl
void
tar_mode_c(struct bsdtar *bsdtar)
{
	struct archive *a;
	int r;

	if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL)
		bsdtar_errc(bsdtar, 1, 0, "no files or directories specified");

	a = archive_write_new();

	/* Support any format that the library supports. */
	if (bsdtar->create_format == NULL) {
		r = archive_write_set_format_pax_restricted(a);
		bsdtar->create_format = "pax restricted";
	} else {
		r = archive_write_set_format_by_name(a, bsdtar->create_format);
	}
	if (r != ARCHIVE_OK) {
		fprintf(stderr, "Can't use format %s: %s\n",
		    bsdtar->create_format,
		    archive_error_string(a));
		usage(bsdtar);
	}

	/*
	 * If user explicitly set the block size, then assume they
	 * want the last block padded as well.  Otherwise, use the
	 * default block size and accept archive_write_open_file()'s
	 * default padding decisions.
	 */
	if (bsdtar->bytes_per_block != 0) {
		archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block);
		archive_write_set_bytes_in_last_block(a,
		    bsdtar->bytes_per_block);
	} else
		archive_write_set_bytes_per_block(a, DEFAULT_BYTES_PER_BLOCK);

	if (bsdtar->compress_program) {
		archive_write_set_compression_program(a, bsdtar->compress_program);
	} else {
		switch (bsdtar->create_compression) {
		case 0:
			archive_write_set_compression_none(a);
			break;
#ifdef HAVE_LIBBZ2
		case 'j': case 'y':
			archive_write_set_compression_bzip2(a);
			break;
#endif
#ifdef HAVE_LIBLZMA
		case 'J':
			archive_write_set_compression_xz(a);
			break;
		case OPTION_LZMA:
			archive_write_set_compression_lzma(a);
			break;
#endif
#ifdef HAVE_LIBZ
		case 'z':
			archive_write_set_compression_gzip(a);
			break;
#endif
		case 'Z':
			archive_write_set_compression_compress(a);
			break;
		default:
			bsdtar_errc(bsdtar, 1, 0,
			    "Unrecognized compression option -%c",
			    bsdtar->create_compression);
		}
	}

	if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options))
		bsdtar_errc(bsdtar, 1, 0, archive_error_string(a));
	if (ARCHIVE_OK != archive_write_open_file(a, bsdtar->filename))
		bsdtar_errc(bsdtar, 1, 0, archive_error_string(a));
	write_archive(a, bsdtar);
}
コード例 #13
0
ファイル: cpio.c プロジェクト: marccodes/lfl
static void
mode_out(struct cpio *cpio)
{
	unsigned long blocks;
	struct archive_entry *entry, *spare;
	struct line_reader *lr;
	const char *p;
	int r;

	if (cpio->option_append)
		cpio_errc(1, 0, "Append mode not yet supported.");
	cpio->archive = archive_write_new();
	if (cpio->archive == NULL)
		cpio_errc(1, 0, "Failed to allocate archive object");
	switch (cpio->compress) {
#ifdef HAVE_BZLIB_H
	case 'j': case 'y':
		archive_write_set_compression_bzip2(cpio->archive);
		break;
#endif
#ifdef HAVE_ZLIB_H
	case 'z':
		archive_write_set_compression_gzip(cpio->archive);
		break;
#endif
	case 'Z':
		archive_write_set_compression_compress(cpio->archive);
		break;
	default:
		archive_write_set_compression_none(cpio->archive);
		break;
	}
	r = archive_write_set_format_by_name(cpio->archive, cpio->format);
	if (r != ARCHIVE_OK)
		cpio_errc(1, 0, archive_error_string(cpio->archive));
	archive_write_set_bytes_per_block(cpio->archive, cpio->bytes_per_block);
	cpio->linkresolver = archive_entry_linkresolver_new();
	archive_entry_linkresolver_set_strategy(cpio->linkresolver,
	    archive_format(cpio->archive));

	r = archive_write_open_file(cpio->archive, cpio->filename);
	if (r != ARCHIVE_OK)
		cpio_errc(1, 0, archive_error_string(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);

	/*
	 * The hardlink detection may have queued up a couple of entries
	 * that can now be flushed.
	 */
	entry = NULL;
	archive_entry_linkify(cpio->linkresolver, &entry, &spare);
	while (entry != NULL) {
		entry_to_archive(cpio, entry);
		archive_entry_free(entry);
		entry = NULL;
		archive_entry_linkify(cpio->linkresolver, &entry, &spare);
	}

	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);
}
コード例 #14
0
static void
test_filter_by_name(const char *filter_name, int filter_code,
    int (*can_filter_prog)(void))
{
	struct archive_entry *ae;
	struct archive *a;
	size_t used;
	size_t buffsize = 1024 * 128;
	char *buff;
	int r;

	assert((buff = malloc(buffsize)) != NULL);
	if (buff == NULL)
		return;

	/* Create a new archive in memory. */
	assert((a = archive_write_new()) != NULL);
	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
	r = archive_write_add_filter_by_name(a, filter_name);
	if (r == ARCHIVE_WARN) {
		if (!can_filter_prog()) {
			skipping("%s filter not suported on this platform",
			    filter_name);
			assertEqualInt(ARCHIVE_OK, archive_write_free(a));
			free(buff);
			return;
		}
	} else if (r == ARCHIVE_FATAL &&
	    (strcmp(archive_error_string(a),
		   "lzma compression not supported on this platform") == 0 ||
	     strcmp(archive_error_string(a),
		   "xz compression not supported on this platform") == 0)) {
		skipping("%s filter not suported on this platform", filter_name);
		assertEqualInt(ARCHIVE_OK, archive_write_free(a));
		free(buff);
		return;
	} else {
		if (!assertEqualIntA(a, ARCHIVE_OK, r)) {
			assertEqualInt(ARCHIVE_OK, archive_write_free(a));
			free(buff);
			return;
		}
	}
	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 10));
	assertEqualIntA(a, ARCHIVE_OK,
	    archive_write_open_memory(a, buff, buffsize, &used));

	/*
	 * Write a file to it.
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_set_mtime(ae, 1, 0);
	assertEqualInt(1, archive_entry_mtime(ae));
	archive_entry_set_ctime(ae, 1, 0);
	assertEqualInt(1, archive_entry_ctime(ae));
	archive_entry_set_atime(ae, 1, 0);
	assertEqualInt(1, archive_entry_atime(ae));
	archive_entry_copy_pathname(ae, "file");
	assertEqualString("file", archive_entry_pathname(ae));
	archive_entry_set_mode(ae, AE_IFREG | 0755);
	assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae));
	archive_entry_set_size(ae, 8);
	assertEqualInt(0, archive_write_header(a, ae));
	archive_entry_free(ae);
	assertEqualInt(8, archive_write_data(a, "12345678", 8));

	/* Close out the archive. */
	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));

	/*
	 * Now, read the data back.
	 */
	assert((a = archive_read_new()) != NULL);
	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
	assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used));

	/*
	 * Read and verify the file.
	 */
	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
	assertEqualInt(1, archive_entry_mtime(ae));
	assertEqualString("file", archive_entry_pathname(ae));
	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
	assertEqualInt(8, archive_entry_size(ae));

	/* Verify the end of the archive. */
	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));

	/* Verify archive format. */
	assertEqualIntA(a, filter_code, archive_filter_code(a, 0));
	assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a));

	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
	free(buff);
}
コード例 #15
0
/*
 * Create an entry starting from a wide-character Unicode pathname,
 * read it back into "C" locale, which doesn't support the name.
 * TODO: Figure out the "right" behavior here.
 */
static void
test_pax_filename_encoding_3(void)
{
	wchar_t badname[] = L"xxxAyyyBzzz";
	const char badname_utf8[] = "xxx\xE1\x88\xB4yyy\xE5\x99\xB8zzz";
	struct archive *a;
	struct archive_entry *entry;
	char buff[65536];
	size_t used;

	badname[3] = 0x1234;
	badname[7] = 0x5678;

	/* If it doesn't exist, just warn and return. */
	if (NULL == setlocale(LC_ALL, "C")) {
		skipping("Can't set \"C\" locale, so can't exercise "
		    "certain character-conversion failures");
		return;
	}

	/* If wctomb is broken, warn and return. */
	if (wctomb(buff, 0x1234) > 0) {
		skipping("Cannot test conversion failures because \"C\" "
		    "locale on this system has no invalid characters.");
		return;
	}

	/* If wctomb is broken, warn and return. */
	if (wctomb(buff, 0x1234) > 0) {
		skipping("Cannot test conversion failures because \"C\" "
		    "locale on this system has no invalid characters.");
		return;
	}

	/* Skip test if archive_entry_update_pathname_utf8() is broken. */
	/* In particular, this is currently broken on Win32 because
	 * setlocale() does not set the default encoding for CP_ACP. */
	entry = archive_entry_new();
	if (archive_entry_update_pathname_utf8(entry, badname_utf8)) {
		archive_entry_free(entry);
		skipping("Cannot test conversion failures.");
		return;
	}
	archive_entry_free(entry);

	assert((a = archive_write_new()) != NULL);
	assertEqualIntA(a, 0, archive_write_set_format_pax(a));
	assertEqualIntA(a, 0, archive_write_add_filter_none(a));
	assertEqualIntA(a, 0, archive_write_set_bytes_per_block(a, 0));
	assertEqualInt(0,
	    archive_write_open_memory(a, buff, sizeof(buff), &used));

	assert((entry = archive_entry_new()) != NULL);
	/* Set pathname to non-convertible wide value. */
	archive_entry_copy_pathname_w(entry, badname);
	archive_entry_set_filetype(entry, AE_IFREG);
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
	archive_entry_free(entry);

	assert((entry = archive_entry_new()) != NULL);
	archive_entry_copy_pathname_w(entry, L"abc");
	/* Set gname to non-convertible wide value. */
	archive_entry_copy_gname_w(entry, badname);
	archive_entry_set_filetype(entry, AE_IFREG);
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
	archive_entry_free(entry);

	assert((entry = archive_entry_new()) != NULL);
	archive_entry_copy_pathname_w(entry, L"abc");
	/* Set uname to non-convertible wide value. */
	archive_entry_copy_uname_w(entry, badname);
	archive_entry_set_filetype(entry, AE_IFREG);
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
	archive_entry_free(entry);

	assert((entry = archive_entry_new()) != NULL);
	archive_entry_copy_pathname_w(entry, L"abc");
	/* Set hardlink to non-convertible wide value. */
	archive_entry_copy_hardlink_w(entry, badname);
	archive_entry_set_filetype(entry, AE_IFREG);
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
	archive_entry_free(entry);

	assert((entry = archive_entry_new()) != NULL);
	archive_entry_copy_pathname_w(entry, L"abc");
	/* Set symlink to non-convertible wide value. */
	archive_entry_copy_symlink_w(entry, badname);
	archive_entry_set_filetype(entry, AE_IFLNK);
	assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
	archive_entry_free(entry);

	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));

	/*
	 * Now read the entries back.
	 */

	assert((a = archive_read_new()) != NULL);
	assertEqualInt(0, archive_read_support_format_tar(a));
	assertEqualInt(0, archive_read_open_memory(a, buff, used));

	failure("A non-convertible pathname should cause a warning.");
	assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
	assertEqualWString(badname, archive_entry_pathname_w(entry));
	failure("If native locale can't convert, we should get UTF-8 back.");
	assertEqualString(badname_utf8, archive_entry_pathname(entry));

	failure("A non-convertible gname should cause a warning.");
	assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
	assertEqualWString(badname, archive_entry_gname_w(entry));
	failure("If native locale can't convert, we should get UTF-8 back.");
	assertEqualString(badname_utf8, archive_entry_gname(entry));

	failure("A non-convertible uname should cause a warning.");
	assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
	assertEqualWString(badname, archive_entry_uname_w(entry));
	failure("If native locale can't convert, we should get UTF-8 back.");
	assertEqualString(badname_utf8, archive_entry_uname(entry));

	failure("A non-convertible hardlink should cause a warning.");
	assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
	assertEqualWString(badname, archive_entry_hardlink_w(entry));
	failure("If native locale can't convert, we should get UTF-8 back.");
	assertEqualString(badname_utf8, archive_entry_hardlink(entry));

	failure("A non-convertible symlink should cause a warning.");
	assertEqualInt(ARCHIVE_WARN, archive_read_next_header(a, &entry));
	assertEqualWString(badname, archive_entry_symlink_w(entry));
	assertEqualWString(NULL, archive_entry_hardlink_w(entry));
	failure("If native locale can't convert, we should get UTF-8 back.");
	assertEqualString(badname_utf8, archive_entry_symlink(entry));

	assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &entry));

	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
コード例 #16
0
static void
mode_out(struct cpio *cpio)
{
	struct archive_entry *entry, *spare;
	struct lafe_line_reader *lr;
	const char *p;
	int r;

	if (cpio->option_append)
		lafe_errc(1, 0, "Append mode not yet supported.");

	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);

	cpio->archive = archive_write_new();
	if (cpio->archive == NULL)
		lafe_errc(1, 0, "Failed to allocate archive object");
	switch (cpio->compress) {
	case 'J':
		r = archive_write_set_compression_xz(cpio->archive);
		break;
	case OPTION_LZMA:
		r = archive_write_set_compression_lzma(cpio->archive);
		break;
	case 'j': case 'y':
		r = archive_write_set_compression_bzip2(cpio->archive);
		break;
	case 'z':
		r = archive_write_set_compression_gzip(cpio->archive);
		break;
	case 'Z':
		r = archive_write_set_compression_compress(cpio->archive);
		break;
	default:
		r = archive_write_set_compression_none(cpio->archive);
		break;
	}
	if (r < ARCHIVE_WARN)
		lafe_errc(1, 0, "Requested compression not available");
	r = archive_write_set_format_by_name(cpio->archive, cpio->format);
	if (r != ARCHIVE_OK)
		lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
	archive_write_set_bytes_per_block(cpio->archive, cpio->bytes_per_block);
	cpio->linkresolver = archive_entry_linkresolver_new();
	archive_entry_linkresolver_set_strategy(cpio->linkresolver,
	    archive_format(cpio->archive));

	/*
	 * The main loop:  Copy each file into the output archive.
	 */
	r = archive_write_open_file(cpio->archive, cpio->filename);
	if (r != ARCHIVE_OK)
		lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));
	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);

	/*
	 * The hardlink detection may have queued up a couple of entries
	 * that can now be flushed.
	 */
	entry = NULL;
	archive_entry_linkify(cpio->linkresolver, &entry, &spare);
	while (entry != NULL) {
		entry_to_archive(cpio, entry);
		archive_entry_free(entry);
		entry = NULL;
		archive_entry_linkify(cpio->linkresolver, &entry, &spare);
	}

	r = archive_write_close(cpio->archive);
	if (r != ARCHIVE_OK)
		lafe_errc(1, 0, "%s", archive_error_string(cpio->archive));

	if (!cpio->quiet) {
		int64_t blocks =
			(archive_position_uncompressed(cpio->archive) + 511)
			/ 512;
		fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
		    blocks == 1 ? "block" : "blocks");
	}
	archive_write_finish(cpio->archive);
}
コード例 #17
0
/*
 * Set the locale and write a pathname containing invalid characters.
 * This should work; the underlying implementation should automatically
 * fall back to storing the pathname in binary.
 */
static void
test_pax_filename_encoding_2(void)
{
	char filename[] = "abc\314\214mno\374xyz";
	struct archive *a;
	struct archive_entry *entry;
	char buff[65536];
	char longname[] = "abc\314\214mno\374xyz"
	    "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
	    "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
	    "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
	    "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
	    "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
	    "/abc\314\214mno\374xyz/abcdefghijklmnopqrstuvwxyz"
	    ;
	size_t used;

	/*
	 * We need a starting locale which has invalid sequences.
	 * en_US.UTF-8 seems to be commonly supported.
	 */
	/* If it doesn't exist, just warn and return. */
	if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) {
		skipping("invalid encoding tests require a suitable locale;"
		    " en_US.UTF-8 not available on this system");
		return;
	}

	assert((a = archive_write_new()) != NULL);
	assertEqualIntA(a, 0, archive_write_set_format_pax(a));
	assertEqualIntA(a, 0, archive_write_add_filter_none(a));
	assertEqualIntA(a, 0, archive_write_set_bytes_per_block(a, 0));
	assertEqualInt(0,
	    archive_write_open_memory(a, buff, sizeof(buff), &used));

	assert((entry = archive_entry_new()) != NULL);
	/* Set pathname, gname, uname, hardlink to nonconvertible values. */
	archive_entry_copy_pathname(entry, filename);
	archive_entry_copy_gname(entry, filename);
	archive_entry_copy_uname(entry, filename);
	archive_entry_copy_hardlink(entry, filename);
	archive_entry_set_filetype(entry, AE_IFREG);
	failure("This should generate a warning for nonconvertible names.");
	assertEqualInt(ARCHIVE_WARN, archive_write_header(a, entry));
	archive_entry_free(entry);

	assert((entry = archive_entry_new()) != NULL);
	/* Set path, gname, uname, and symlink to nonconvertible values. */
	archive_entry_copy_pathname(entry, filename);
	archive_entry_copy_gname(entry, filename);
	archive_entry_copy_uname(entry, filename);
	archive_entry_copy_symlink(entry, filename);
	archive_entry_set_filetype(entry, AE_IFLNK);
	failure("This should generate a warning for nonconvertible names.");
	assertEqualInt(ARCHIVE_WARN, archive_write_header(a, entry));
	archive_entry_free(entry);

	assert((entry = archive_entry_new()) != NULL);
	/* Set pathname to a very long nonconvertible value. */
	archive_entry_copy_pathname(entry, longname);
	archive_entry_set_filetype(entry, AE_IFREG);
	failure("This should generate a warning for nonconvertible names.");
	assertEqualInt(ARCHIVE_WARN, archive_write_header(a, entry));
	archive_entry_free(entry);

	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));

	/*
	 * Now read the entries back.
	 */

	assert((a = archive_read_new()) != NULL);
	assertEqualInt(0, archive_read_support_format_tar(a));
	assertEqualInt(0, archive_read_open_memory(a, buff, used));

	assertEqualInt(0, archive_read_next_header(a, &entry));
	assertEqualString(filename, archive_entry_pathname(entry));
	assertEqualString(filename, archive_entry_gname(entry));
	assertEqualString(filename, archive_entry_uname(entry));
	assertEqualString(filename, archive_entry_hardlink(entry));

	assertEqualInt(0, archive_read_next_header(a, &entry));
	assertEqualString(filename, archive_entry_pathname(entry));
	assertEqualString(filename, archive_entry_gname(entry));
	assertEqualString(filename, archive_entry_uname(entry));
	assertEqualString(filename, archive_entry_symlink(entry));

	assertEqualInt(0, archive_read_next_header(a, &entry));
	assertEqualString(longname, archive_entry_pathname(entry));

	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
コード例 #18
0
/* ArchiveWriter::__construct {{{
 *
*/
ZEND_METHOD(ArchiveWriter, __construct)
{
	archive_file_t *arch = NULL;
	int resource_id;
	zval *this = getThis();
	const char *error_string = NULL;
	char *filename;
	long error_num, filename_len, result, format=0, compression=0;
	zend_error_handling error_handling;

	zend_replace_error_handling(EH_THROW, ce_ArchiveException, &error_handling TSRMLS_CC);

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &filename, &filename_len, &format, &compression) == FAILURE) {
		zend_restore_error_handling(&error_handling TSRMLS_CC);
		return;
	}

#if PHP_API_VERSION < 20100412
	if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
		zend_restore_error_handling(&error_handling TSRMLS_CC);
		return;
	}
#endif

	if (php_check_open_basedir(filename TSRMLS_CC)) {
		zend_restore_error_handling(&error_handling TSRMLS_CC);
		return;
	}

	arch = (archive_file_t *) emalloc(sizeof(archive_file_t));

	arch->stream = NULL;

	ALLOC_HASHTABLE(arch->entries);
	zend_hash_init(arch->entries, 10, NULL, _archive_entries_hash_dtor, 0);

	arch->mode = PHP_ARCHIVE_WRITE_MODE;
	arch->buf = emalloc(PHP_ARCHIVE_BUF_LEN + 1);
	arch->filename = estrndup(filename, filename_len);
	arch->arch = archive_write_new();

	switch (compression) {
		case PHP_ARCHIVE_COMPRESSION_GZIP:
			if (archive_write_add_filter_gzip(arch->arch) != ARCHIVE_OK) {
				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Gzip compression is not supported in this build");
				zend_restore_error_handling(&error_handling TSRMLS_CC);
				return;
			}
			break;

		case PHP_ARCHIVE_COMPRESSION_BZIP2:
			if (archive_write_add_filter_bzip2(arch->arch) != ARCHIVE_OK) {
				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bzip2 compression is not supported in this build");
				zend_restore_error_handling(&error_handling TSRMLS_CC);
				return;
			}
			break;
		case 0: /* default value */
		case PHP_ARCHIVE_COMPRESSION_NONE:
			/* always supported */
			break;
		default:
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported compression type %ld", compression);
			zend_restore_error_handling(&error_handling TSRMLS_CC);
			return;
			break;
	}

	switch (format) {
		case 0: /* default value */
		case PHP_ARCHIVE_FORMAT_TAR:
		case PHP_ARCHIVE_FORMAT_PAX_RESTRICTED:
			archive_write_set_format_pax_restricted(arch->arch);
			break;
		case PHP_ARCHIVE_FORMAT_PAX:
			archive_write_set_format_pax(arch->arch);
			break;
		case PHP_ARCHIVE_FORMAT_CPIO:
			archive_write_set_format_cpio(arch->arch);
			break;
		case PHP_ARCHIVE_FORMAT_SHAR:
			archive_write_set_format_shar(arch->arch);
			break;
		case PHP_ARCHIVE_FORMAT_USTAR:
			archive_write_set_format_ustar(arch->arch);
			break;
		default:
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported archive format: %ld", format);
			zend_restore_error_handling(&error_handling TSRMLS_CC);
			return;
			break;
	}

	archive_write_set_bytes_per_block(arch->arch, DEFAULT_BYTES_PER_BLOCK);
	result = archive_write_open(arch->arch, arch, _archive_open_clbk, _archive_write_clbk, _archive_close_clbk);
	/* do not pad the last block */
	archive_write_set_bytes_in_last_block(arch->arch, 1);

	if (result) {
		error_num = archive_errno(arch->arch);
		error_string = archive_error_string(arch->arch);
		efree(arch->filename);
		efree(arch->buf);
		efree(arch);
		if (error_num && error_string) {
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to open file %s for writing: error #%ld, %s", filename, error_num, error_string);
		}
		else {
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to open file %s for writing: unknown error %ld", filename, result);
		}
		zend_restore_error_handling(&error_handling TSRMLS_CC);
		return;
	}

	resource_id = zend_list_insert(arch,le_archive);
	add_property_resource(this, "fd", resource_id);

	zend_restore_error_handling(&error_handling TSRMLS_CC);
	return;
}
コード例 #19
0
ファイル: write.c プロジェクト: kamilWLca/brix
void
tar_mode_c(struct bsdtar *bsdtar)
{
	struct archive *a;
	int r;

	if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL)
		lafe_errc(1, 0, "no files or directories specified");

	a = archive_write_new();

	/* Support any format that the library supports. */
	if (bsdtar->create_format == NULL) {
		r = archive_write_set_format_pax_restricted(a);
		bsdtar->create_format = "pax restricted";
	} else {
		r = archive_write_set_format_by_name(a, bsdtar->create_format);
	}
	if (r != ARCHIVE_OK) {
		fprintf(stderr, "Can't use format %s: %s\n",
		    bsdtar->create_format,
		    archive_error_string(a));
		usage();
	}

	archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block);
	archive_write_set_bytes_in_last_block(a, bsdtar->bytes_in_last_block);

	if (bsdtar->compress_program) {
		archive_write_set_compression_program(a, bsdtar->compress_program);
	} else {
		switch (bsdtar->create_compression) {
		case 0:
			r = ARCHIVE_OK;
			break;
		case 'j': case 'y':
			r = archive_write_set_compression_bzip2(a);
			break;
		case 'J':
			r = archive_write_set_compression_xz(a);
			break;
		case OPTION_LZIP:
			r = archive_write_set_compression_lzip(a);
			break;
		case OPTION_LZMA:
			r = archive_write_set_compression_lzma(a);
			break;
		case 'z':
			r = archive_write_set_compression_gzip(a);
			break;
		case 'Z':
			r = archive_write_set_compression_compress(a);
			break;
		default:
			lafe_errc(1, 0,
			    "Unrecognized compression option -%c",
			    bsdtar->create_compression);
		}
		if (r != ARCHIVE_OK) {
			lafe_errc(1, 0,
			    "Unsupported compression option -%c",
			    bsdtar->create_compression);
		}
	}

	if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options))
		lafe_errc(1, 0, "%s", archive_error_string(a));
	if (ARCHIVE_OK != archive_write_open_file(a, bsdtar->filename))
		lafe_errc(1, 0, "%s", archive_error_string(a));
	write_archive(a, bsdtar);
}
コード例 #20
0
ファイル: test_ustar_filenames.c プロジェクト: coyizumi/cs111
static void
test_filename(const char *prefix, int dlen, int flen)
{
	char buff[8192];
	char filename[400];
	char dirname[400];
	struct archive_entry *ae;
	struct archive *a;
	size_t used;
	int separator = 0;
	int i = 0;

	if (prefix != NULL) {
		strcpy(filename, prefix);
		i = (int)strlen(prefix);
	}
	if (dlen > 0) {
		for (; i < dlen; i++)
			filename[i] = 'a';
		filename[i++] = '/';
		separator = 1;
	}
	for (; i < dlen + flen + separator; i++)
		filename[i] = 'b';
	filename[i] = '\0';

	strcpy(dirname, filename);

	/* Create a new archive in memory. */
	assert((a = archive_write_new()) != NULL);
	assertA(0 == archive_write_set_format_ustar(a));
	assertA(0 == archive_write_add_filter_none(a));
	assertA(0 == archive_write_set_bytes_per_block(a,0));
	assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

	/*
	 * Write a file to it.
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_copy_pathname(ae, filename);
	archive_entry_set_mode(ae, S_IFREG | 0755);
	failure("dlen=%d, flen=%d", dlen, flen);
	if (flen > 100) {
		assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
	} else {
		assertEqualIntA(a, 0, archive_write_header(a, ae));
	}
	archive_entry_free(ae);

	/*
	 * Write a dir to it (without trailing '/').
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_copy_pathname(ae, dirname);
	archive_entry_set_mode(ae, S_IFDIR | 0755);
	failure("dlen=%d, flen=%d", dlen, flen);
	if (flen >= 100) {
		assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
	} else {
		assertEqualIntA(a, 0, archive_write_header(a, ae));
	}
	archive_entry_free(ae);

	/* Tar adds a '/' to directory names. */
	strcat(dirname, "/");

	/*
	 * Write a dir to it (with trailing '/').
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_copy_pathname(ae, dirname);
	archive_entry_set_mode(ae, S_IFDIR | 0755);
	failure("dlen=%d, flen=%d", dlen, flen);
	if (flen >= 100) {
		assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
	} else {
		assertEqualIntA(a, 0, archive_write_header(a, ae));
	}
	archive_entry_free(ae);

	/* Close out the archive. */
	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
	assertEqualInt(ARCHIVE_OK, archive_write_free(a));

	/*
	 * Now, read the data back.
	 */
	assert((a = archive_read_new()) != NULL);
	assertA(0 == archive_read_support_format_all(a));
	assertA(0 == archive_read_support_filter_all(a));
	assertA(0 == archive_read_open_memory(a, buff, used));

	if (flen <= 100) {
		/* Read the file and check the filename. */
		assertA(0 == archive_read_next_header(a, &ae));
		failure("dlen=%d, flen=%d", dlen, flen);
		assertEqualString(filename, archive_entry_pathname(ae));
		assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));
	}

	/*
	 * Read the two dirs and check the names.
	 *
	 * Both dirs should read back with the same name, since
	 * tar should add a trailing '/' to any dir that doesn't
	 * already have one.
	 */
	if (flen <= 99) {
		assertA(0 == archive_read_next_header(a, &ae));
		assert((S_IFDIR | 0755) == archive_entry_mode(ae));
		failure("dlen=%d, flen=%d", dlen, flen);
		assertEqualString(dirname, archive_entry_pathname(ae));
	}

	if (flen <= 99) {
		assertA(0 == archive_read_next_header(a, &ae));
		assert((S_IFDIR | 0755) == archive_entry_mode(ae));
		assertEqualString(dirname, archive_entry_pathname(ae));
	}

	/* Verify the end of the archive. */
	failure("This fails if entries were written that should not have been written.  dlen=%d, flen=%d", dlen, flen);
	assertEqualInt(1, archive_read_next_header(a, &ae));
	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
コード例 #21
0
static int
create_iso_image(unsigned char *buff, size_t buffsize, size_t *used,
    const char *opt)
{
	struct archive *a;
	int i, l, fcnt;
	const int lens[] = {
	    0, 1, 3, 5, 7, 8, 9, 29, 30, 31, 32,
		62, 63, 64, 65, 101, 102, 103, 104,
	    191, 192, 193, 194, 204, 205, 206, 207, 208,
		252, 253, 254, 255,
	    -1 };
	char fname1[256];
	char fname2[256];
	char sym1[2];
	char sym128[129];
	char sym255[256];

	/* ISO9660 format: Create a new archive in memory. */
	assert((a = archive_write_new()) != NULL);
	assertA(0 == archive_write_set_format_iso9660(a));
	assertA(0 == archive_write_add_filter_none(a));
	assertA(0 == archive_write_set_option(a, NULL, "pad", NULL));
	if (opt)
		assertA(0 == archive_write_set_options(a, opt));
	assertA(0 == archive_write_set_bytes_per_block(a, 1));
	assertA(0 == archive_write_set_bytes_in_last_block(a, 1));
	assertA(0 == archive_write_open_memory(a, buff, buffsize, used));

	sym1[0] = 'x';
	sym1[1] = '\0';
	for (i = 0; i < (int)sizeof(sym128)-2; i++)
		sym128[i] = 'a';
	sym128[sizeof(sym128)-2] = 'x';
	sym128[sizeof(sym128)-1] = '\0';
	for (i = 0; i < (int)sizeof(sym255)-2; i++)
		sym255[i] = 'a';
	sym255[sizeof(sym255)-2] = 'x';
	sym255[sizeof(sym255)-1] = '\0';

	fcnt = 0;
	for (i = 0; lens[i] >= 0; i++) {
		for (l = 0; l < lens[i]; l++) {
			fname1[l] = 'a';
			fname2[l] = 'A';
		}
		if (l > 0) {
			fname1[l] = '\0';
			fname2[l] = '\0';
			add_entry(a, fname1, NULL);
			add_entry(a, fname2, sym1);
			fcnt += 2;
		}
		if (l < 254) {
			fname1[l] = '.';
			fname1[l+1] = 'c';
			fname1[l+2] = '\0';
			fname2[l] = '.';
			fname2[l+1] = 'C';
			fname2[l+2] = '\0';
			add_entry(a, fname1, sym128);
			add_entry(a, fname2, sym255);
			fcnt += 2;
		}
		if (l < 252) {
			fname1[l] = '.';
			fname1[l+1] = 'p';
			fname1[l+2] = 'n';
			fname1[l+3] = 'g';
			fname1[l+4] = '\0';
			fname2[l] = '.';
			fname2[l+1] = 'P';
			fname2[l+2] = 'N';
			fname2[l+3] = 'G';
			fname2[l+4] = '\0';
			add_entry(a, fname1, NULL);
			add_entry(a, fname2, sym1);
			fcnt += 2;
		}
		if (l < 251) {
			fname1[l] = '.';
			fname1[l+1] = 'j';
			fname1[l+2] = 'p';
			fname1[l+3] = 'e';
			fname1[l+4] = 'g';
			fname1[l+5] = '\0';
			fname2[l] = '.';
			fname2[l+1] = 'J';
			fname2[l+2] = 'P';
			fname2[l+3] = 'E';
			fname2[l+4] = 'G';
			fname2[l+5] = '\0';
			add_entry(a, fname1, sym128);
			add_entry(a, fname2, sym255);
			fcnt += 2;
		}
	}

	/* Close out the archive. */
	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
	assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a));

	return (fcnt);
}