Пример #1
0
static int ar_entry_ctime(lua_State *L) {
    struct archive_entry* self = *ar_entry_check(L, 1);
    int is_set;
    int num_results;
    if ( NULL == self ) return 0;

    is_set = ( lua_gettop(L) >= 2 );
    num_results = 0;
    if ( archive_entry_ctime_is_set(self) ) {
        num_results = 2;
        lua_pushnumber(L, archive_entry_ctime(self));
        lua_pushnumber(L, archive_entry_ctime_nsec(self));
    }
    if ( is_set ) {
        if ( lua_isnil(L, 2) ) {
            archive_entry_unset_ctime(self);
        } else if ( lua_istable(L, 2) ) {
            lua_rawgeti(L, 2, 1);
            lua_rawgeti(L, 2, 2);
            archive_entry_set_ctime(self,
                                    lua_tonumber(L, -2),
                                    lua_tonumber(L, -1));
        } else {
            archive_entry_set_ctime(self,
                                    lua_tonumber(L, 2),
                                    lua_tonumber(L, 3));
        }
    }
    return num_results;
}
Пример #2
0
int createArchiveofFilesPC(char** files, unsigned long * size,
		unsigned int fileCount, const char* filename, const char* tarHostDir) {
	unsigned int ctr = 0;
	struct timespec ts;
	struct archive_entry* entry;
	struct archive* archive = archive_write_new();
	int dirlen = strlen(tarHostDir);
	if ((archive_write_set_compression_gzip(archive) != ARCHIVE_OK)
			|| (archive_write_set_format_ustar(archive) != ARCHIVE_OK)
			|| (archive_write_open_filename(archive, filename) != ARCHIVE_OK)) {
		printf("%s\n", archive_error_string(archive));
		return -1;
	}
	int tarHostDirLen = strlen(tarHostDir);
	for (ctr = 0; ctr < fileCount; ctr++) {
		entry = archive_entry_new();
		clock_gettime(CLOCK_REALTIME, &ts);

		//Set entry to be stored under the tarHostDir directory
		const char* path = files[ctr];
		int pathlength = dirlen + strlen(path) + 2; //One for / and the other for '\0'
		char newPath[pathlength];
		if(tarHostDirLen>0)
			snprintf(newPath, pathlength, "%s/%s", tarHostDir, boost::filesystem::path(path).filename().c_str());
		else
			snprintf(newPath, pathlength, "%s", boost::filesystem::path(path).filename().c_str());
		archive_entry_set_pathname(entry, newPath);
		archive_entry_set_size(entry, size[ctr]);
		archive_entry_set_filetype(entry, AE_IFREG);
		archive_entry_set_perm(entry, 0444);
		archive_entry_set_atime(entry, ts.tv_sec, ts.tv_nsec);
		archive_entry_set_birthtime(entry, ts.tv_sec, ts.tv_nsec);
		archive_entry_set_ctime(entry, ts.tv_sec, ts.tv_nsec);
		archive_entry_set_mtime(entry, ts.tv_sec, ts.tv_nsec);

		int rc = archive_write_header(archive, entry);
		char *contents = new char[size[ctr]+1];
		FILE* fp = fopen(files[ctr],"rb");
		fread((void *)contents, size[ctr], 1, fp);
		fclose(fp);
		archive_write_data(archive, contents, size[ctr]);
		archive_entry_free(entry);
		entry = NULL;
		delete[] contents;
		if (ARCHIVE_OK != rc) {
			printf("%s\n", archive_error_string(archive));
			return -1;
		}
	}
	archive_write_finish(archive);
}
/*
 * Check that an ISO 9660 image is correctly created.
 */
static void
add_entry(struct archive *a, const char *fname, const char *sym)
{
	struct archive_entry *ae;

	assert((ae = archive_entry_new()) != NULL);
	archive_entry_set_birthtime(ae, 2, 20);
	archive_entry_set_atime(ae, 3, 30);
	archive_entry_set_ctime(ae, 4, 40);
	archive_entry_set_mtime(ae, 5, 50);
	archive_entry_copy_pathname(ae, fname);
	if (sym != NULL)
		archive_entry_set_symlink(ae, sym);
	archive_entry_set_mode(ae, S_IFREG | 0555);
	archive_entry_set_size(ae, 0);
	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
	archive_entry_free(ae);
}
Пример #4
0
int createArchiveofFiles(char** files, unsigned long * size,
		unsigned int fileCount, const char* filename) {
	unsigned int ctr = 0;
	struct timespec ts;
	struct archive_entry* entry;
	struct archive* archive = archive_write_new();
	if ((archive_write_set_compression_gzip(archive) != ARCHIVE_OK)
			|| (archive_write_set_format_ustar(archive) != ARCHIVE_OK)
			|| (archive_write_open_filename(archive, filename) != ARCHIVE_OK)) {
		printf("%s\n", archive_error_string(archive));
		return -1;
	}
	for (ctr = 0; ctr < fileCount; ctr++) {
		entry = archive_entry_new();
		clock_gettime(CLOCK_REALTIME, &ts);

		archive_entry_set_pathname(entry, files[ctr]);
		archive_entry_set_size(entry, size[ctr]);
		archive_entry_set_filetype(entry, AE_IFREG);
		archive_entry_set_perm(entry, 0444);
		archive_entry_set_atime(entry, ts.tv_sec, ts.tv_nsec);
		archive_entry_set_birthtime(entry, ts.tv_sec, ts.tv_nsec);
		archive_entry_set_ctime(entry, ts.tv_sec, ts.tv_nsec);
		archive_entry_set_mtime(entry, ts.tv_sec, ts.tv_nsec);

		int rc = archive_write_header(archive, entry);
		char *contents = new char[size[ctr]+1];
		FILE* fp = fopen(files[ctr],"rb");
		fread((void *)contents, size[ctr], 1, fp);
		fclose(fp);
		archive_write_data(archive, contents, size[ctr]);
		archive_entry_free(entry);
		entry = NULL;
		delete[] contents;
		if (ARCHIVE_OK != rc) {
			printf("%s\n", archive_error_string(archive));
			return -1;
		}
	}
	archive_write_finish(archive);
}
Пример #5
0
static void record_entry(db_writer_t *writer, const char *root, const char *entry)
{
    time_t now = time(NULL);
    char entry_path[PATH_MAX];

    snprintf(entry_path, PATH_MAX, "%s/%s", root, entry);
    archive_entry_set_pathname(writer->entry, entry_path);
    archive_entry_set_filetype(writer->entry, AE_IFREG);
    archive_entry_set_size(writer->entry, writer->buf.len);

    archive_entry_set_perm(writer->entry, 0644);
    archive_entry_set_ctime(writer->entry, now, 0);
    archive_entry_set_mtime(writer->entry, now, 0);
    archive_entry_set_atime(writer->entry, now, 0);

    archive_write_header(writer->archive, writer->entry);
    archive_write_data(writer->archive, writer->buf.data, writer->buf.len);

    archive_entry_clear(writer->entry);
    buffer_clear(&writer->buf);
}
Пример #6
0
int
xbps_archive_append_buf(struct archive *ar, const void *buf, const size_t buflen,
	const char *fname, const mode_t mode, const char *uname, const char *gname)
{
	struct archive_entry *entry;
	time_t tm;

	assert(ar);
	assert(buf);
	assert(fname);
	assert(uname);
	assert(gname);

	tm = time(NULL);
	entry = archive_entry_new();
	assert(entry);

	archive_entry_set_filetype(entry, AE_IFREG);
	archive_entry_set_perm(entry, mode);
	archive_entry_set_uname(entry, uname);
	archive_entry_set_gname(entry, gname);
	archive_entry_set_pathname(entry, fname);
	archive_entry_set_size(entry, buflen);
	archive_entry_set_atime(entry, tm, 0);
	archive_entry_set_mtime(entry, tm, 0);
	archive_entry_set_ctime(entry, tm, 0);

	if (archive_write_header(ar, entry) != ARCHIVE_OK) {
		archive_entry_free(entry);
		return archive_errno(ar);
	}
	if (archive_write_data(ar, buf, buflen) != ARCHIVE_OK) {
		archive_entry_free(entry);
		return archive_errno(ar);
	}
	archive_write_finish_entry(ar);
	archive_entry_free(entry);

	return 0;
}
void
archive_entry_copy_bhfi(struct archive_entry *entry,
			BY_HANDLE_FILE_INFORMATION *bhfi)
{
	time_t secs;
	long nsecs;

	fileTimeToUtc(&bhfi->ftLastAccessTime, &secs, &nsecs);
	archive_entry_set_atime(entry, secs, nsecs);
	fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs);
	archive_entry_set_mtime(entry, secs, nsecs);
	fileTimeToUtc(&bhfi->ftCreationTime, &secs, &nsecs);
	archive_entry_set_birthtime(entry, secs, nsecs);
	archive_entry_set_ctime(entry, secs, nsecs);
	archive_entry_set_dev(entry, bhfi->dwVolumeSerialNumber);
	archive_entry_set_ino64(entry, (((int64_t)bhfi->nFileIndexHigh) << 32)
		+ bhfi->nFileIndexLow);
	archive_entry_set_nlink(entry, bhfi->nNumberOfLinks);
	archive_entry_set_size(entry, (((int64_t)bhfi->nFileSizeHigh) << 32)
		+ bhfi->nFileSizeLow);
	/* archive_entry_set_mode(entry, st->st_mode); */
}
Пример #8
0
void
archive_entry_copy_stat(struct archive_entry *entry, const struct stat *st)
{
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
	archive_entry_set_atime(entry, st->st_atime, st->st_atimespec.tv_nsec);
	archive_entry_set_ctime(entry, st->st_ctime, st->st_ctimespec.tv_nsec);
	archive_entry_set_mtime(entry, st->st_mtime, st->st_mtimespec.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
	archive_entry_set_atime(entry, st->st_atime, st->st_atim.tv_nsec);
	archive_entry_set_ctime(entry, st->st_ctime, st->st_ctim.tv_nsec);
	archive_entry_set_mtime(entry, st->st_mtime, st->st_mtim.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIME_N
	archive_entry_set_atime(entry, st->st_atime, st->st_atime_n);
	archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_n);
	archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_n);
#elif HAVE_STRUCT_STAT_ST_UMTIME
	archive_entry_set_atime(entry, st->st_atime, st->st_uatime * 1000);
	archive_entry_set_ctime(entry, st->st_ctime, st->st_uctime * 1000);
	archive_entry_set_mtime(entry, st->st_mtime, st->st_umtime * 1000);
#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
	archive_entry_set_atime(entry, st->st_atime, st->st_atime_usec * 1000);
	archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_usec * 1000);
	archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_usec * 1000);
#else
	archive_entry_set_atime(entry, st->st_atime, 0);
	archive_entry_set_ctime(entry, st->st_ctime, 0);
	archive_entry_set_mtime(entry, st->st_mtime, 0);
#endif
#if HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
	archive_entry_set_birthtime(entry, st->st_birthtime, st->st_birthtimespec.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_BIRTHTIME
	archive_entry_set_birthtime(entry, st->st_birthtime, 0);
#else
	archive_entry_unset_birthtime(entry);
#endif
	archive_entry_set_dev(entry, st->st_dev);
	archive_entry_set_gid(entry, st->st_gid);
	archive_entry_set_uid(entry, st->st_uid);
	archive_entry_set_ino(entry, st->st_ino);
	archive_entry_set_nlink(entry, st->st_nlink);
	archive_entry_set_rdev(entry, st->st_rdev);
	archive_entry_set_size(entry, st->st_size);
	archive_entry_set_mode(entry, st->st_mode);
}
Пример #9
0
void
archive_entry_unset_ctime(struct archive_entry *entry)
{
	archive_entry_set_ctime(entry, 0, 0);
	entry->ae_set &= ~AE_SET_CTIME;
}
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);
}
Пример #11
0
	void TarUtils::write(std::ostream &output, const io::ObservedFile &root, const std::set<ObservedFile> &files_to_send)
	{
		bool processed = false;

		//create new archive, set format to tar, use callbacks (above this method)
		struct archive *a;
		a = archive_write_new();
		archive_write_set_format_ustar(a);
		archive_write_open(a, &output, &__tar_utils_open_callback, &__tar_utils_write_callback, &__tar_utils_close_callback);

		for(std::set<ObservedFile>::const_iterator of_iter = files_to_send.begin(); of_iter != files_to_send.end(); ++of_iter)
		{
			const ObservedFile &of = (*of_iter);
			const ibrcommon::File &file = of.getFile();

			struct archive_entry *entry;
			entry = archive_entry_new();
			archive_entry_set_size(entry, file.size());

			if(file.isDirectory())
			{
				archive_entry_set_filetype(entry, AE_IFDIR);
				archive_entry_set_perm(entry, 0755);
			}
			else
			{
				archive_entry_set_filetype(entry, AE_IFREG);
				archive_entry_set_perm(entry, 0644);
			}

			archive_entry_set_pathname(entry, rel_filename(root, of).c_str());

			//set timestamps
			struct timespec ts;
			clock_gettime(CLOCK_REALTIME, &ts);
			archive_entry_set_atime(entry, ts.tv_sec, ts.tv_nsec); //accesstime
			archive_entry_set_birthtime(entry, ts.tv_sec, ts.tv_nsec); //creationtime
			archive_entry_set_ctime(entry, ts.tv_sec, ts.tv_nsec); //time, inode changed
			archive_entry_set_mtime(entry, ts.tv_sec, ts.tv_nsec); //modification time

			archive_write_header(a, entry);

			try {
#ifdef HAVE_LIBTFFS
				//read file on vfat-image
				try {
					const FATFile &ffile = dynamic_cast<const FATFile&>(file);
					processed = true;

					// get image reader
					const FatImageReader &reader = ffile.getReader();

					// open fat file
					io::FatImageReader::FileHandle fh = reader.open(ffile);

					char buff[BUFF_SIZE];
					ssize_t ret = 0;
					size_t len = 0;

					// read file
					len = fh.read((unsigned char*)&buff, BUFF_SIZE);

					//write buffer to archive
					while (len > 0)
					{
						if( (ret = archive_write_data(a, buff, len)) < 0)
						{
							IBRCOMMON_LOGGER_TAG("TarUtils", error) << "archive_write_data failed" << IBRCOMMON_LOGGER_ENDL;
							break;
						}

						// read next chunk
						len = fh.read((unsigned char*)&buff, BUFF_SIZE);
					}
				} catch (const std::bad_cast&) { };
#endif

				if (!processed)
				{
					char buff[BUFF_SIZE];
					ssize_t ret = 0;

					// open file for reading
					std::ifstream fs(file.getPath().c_str());

					// write buffer to archive
					while (fs.good())
					{
						// read bytes
						fs.read(buff, BUFF_SIZE);

						// write bytes to archive
						if( (ret = archive_write_data(a, buff, fs.gcount())) < 0)
						{
							IBRCOMMON_LOGGER_TAG("TarUtils", error) << "archive write failed" << IBRCOMMON_LOGGER_ENDL;
							break;
						}
					}
				}
			} catch (const ibrcommon::IOException &e) {
				// write failed
				IBRCOMMON_LOGGER_TAG("TarUtils", error) << "archive write failed: " << e.what() << IBRCOMMON_LOGGER_ENDL;

				archive_entry_free(entry);
				archive_write_close(a);
				archive_write_free(a);

				throw;
			}

			archive_entry_free(entry);
		}
		archive_write_close(a);
		archive_write_free(a);
	}
static int
archive_read_format_iso9660_read_header(struct archive_read *a,
    struct archive_entry *entry)
{
	struct iso9660 *iso9660;
	struct file_info *file;
	ssize_t bytes_read;
	int r;

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

	if (!a->archive.archive_format) {
		a->archive.archive_format = ARCHIVE_FORMAT_ISO9660;
		a->archive.archive_format_name = "ISO9660";
	}

	/* Get the next entry that appears after the current offset. */
	r = next_entry_seek(a, iso9660, &file);
	if (r != ARCHIVE_OK)
		return (r);

	iso9660->entry_bytes_remaining = file->size;
	iso9660->entry_sparse_offset = 0; /* Offset for sparse-file-aware clients. */

	/* Set up the entry structure with information about this entry. */
	archive_entry_set_mode(entry, file->mode);
	archive_entry_set_uid(entry, file->uid);
	archive_entry_set_gid(entry, file->gid);
	archive_entry_set_nlink(entry, file->nlinks);
	archive_entry_set_ino(entry, file->inode);
	archive_entry_set_mtime(entry, file->mtime, 0);
	archive_entry_set_ctime(entry, file->ctime, 0);
	archive_entry_set_atime(entry, file->atime, 0);
	archive_entry_set_size(entry, iso9660->entry_bytes_remaining);
	archive_string_empty(&iso9660->pathname);
	archive_entry_set_pathname(entry,
	    build_pathname(&iso9660->pathname, file));
	if (file->symlink.s != NULL)
		archive_entry_copy_symlink(entry, file->symlink.s);

	/* If this entry points to the same data as the previous
	 * entry, convert this into a hardlink to that entry.
	 * But don't bother for zero-length files. */
	if (file->offset == iso9660->previous_offset
	    && file->size == iso9660->previous_size
	    && file->size > 0) {
		archive_entry_set_hardlink(entry,
		    iso9660->previous_pathname.s);
		iso9660->entry_bytes_remaining = 0;
		iso9660->entry_sparse_offset = 0;
		release_file(iso9660, file);
		return (ARCHIVE_OK);
	}

	/* If the offset is before our current position, we can't
	 * seek backwards to extract it, so issue a warning. */
	if (file->offset < iso9660->current_position) {
		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
		    "Ignoring out-of-order file");
		iso9660->entry_bytes_remaining = 0;
		iso9660->entry_sparse_offset = 0;
		release_file(iso9660, file);
		return (ARCHIVE_WARN);
	}

	iso9660->previous_size = file->size;
	iso9660->previous_offset = file->offset;
	archive_strcpy(&iso9660->previous_pathname, iso9660->pathname.s);

	/* If this is a directory, read in all of the entries right now. */
	if (archive_entry_filetype(entry) == AE_IFDIR) {
		while (iso9660->entry_bytes_remaining > 0) {
			const void *block;
			const unsigned char *p;
			ssize_t step = iso9660->logical_block_size;
			if (step > iso9660->entry_bytes_remaining)
				step = iso9660->entry_bytes_remaining;
			bytes_read = (a->decompressor->read_ahead)(a, &block, step);
			if (bytes_read < step) {
				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
	    "Failed to read full block when scanning ISO9660 directory list");
				release_file(iso9660, file);
				return (ARCHIVE_FATAL);
			}
			if (bytes_read > step)
				bytes_read = step;
			(a->decompressor->consume)(a, bytes_read);
			iso9660->current_position += bytes_read;
			iso9660->entry_bytes_remaining -= bytes_read;
			for (p = (const unsigned char *)block;
			     *p != 0 && p < (const unsigned char *)block + bytes_read;
			     p += *p) {
				struct file_info *child;

				/* Skip '.' entry. */
				if (*(p + DR_name_len_offset) == 1
				    && *(p + DR_name_offset) == '\0')
					continue;
				/* Skip '..' entry. */
				if (*(p + DR_name_len_offset) == 1
				    && *(p + DR_name_offset) == '\001')
					continue;
				child = parse_file_info(iso9660, file, p);
				add_entry(iso9660, child);
				if (iso9660->seenRockridge) {
					a->archive.archive_format =
					    ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
					a->archive.archive_format_name =
					    "ISO9660 with Rockridge extensions";
				}
			}
		}
	}

	release_file(iso9660, file);
	return (ARCHIVE_OK);
}
static int
_warc_rdhdr(struct archive_read *a, struct archive_entry *entry)
{
#define HDR_PROBE_LEN		(12U)
	struct warc_s *w = a->format->data;
	unsigned int ver;
	const char *buf;
	ssize_t nrd;
	const char *eoh;
	/* for the file name, saves some strndup()'ing */
	warc_string_t fnam;
	/* warc record type, not that we really use it a lot */
	warc_type_t ftyp;
	/* content-length+error monad */
	ssize_t cntlen;
	/* record time is the WARC-Date time we reinterpret it as ctime */
	time_t rtime;
	/* mtime is the Last-Modified time which will be the entry's mtime */
	time_t mtime;

start_over:
	/* just use read_ahead() they keep track of unconsumed
	 * bits and bobs for us; no need to put an extra shift in
	 * and reproduce that functionality here */
	buf = __archive_read_ahead(a, HDR_PROBE_LEN, &nrd);

	if (nrd < 0) {
		/* no good */
		archive_set_error(
			&a->archive, ARCHIVE_ERRNO_MISC,
			"Bad record header");
		return (ARCHIVE_FATAL);
	} else if (buf == NULL) {
		/* there should be room for at least WARC/bla\r\n
		 * must be EOF therefore */
		return (ARCHIVE_EOF);
	}
 	/* looks good so far, try and find the end of the header now */
	eoh = _warc_find_eoh(buf, nrd);
	if (eoh == NULL) {
		/* still no good, the header end might be beyond the
		 * probe we've requested, but then again who'd cram
		 * so much stuff into the header *and* be 28500-compliant */
		archive_set_error(
			&a->archive, ARCHIVE_ERRNO_MISC,
			"Bad record header");
		return (ARCHIVE_FATAL);
	} else if ((ver = _warc_rdver(buf, eoh - buf)) > 10000U) {
		/* nawww, I wish they promised backward compatibility
		 * anyhoo, in their infinite wisdom the 28500 guys might
		 * come up with something we can't possibly handle so
		 * best end things here */
		archive_set_error(
			&a->archive, ARCHIVE_ERRNO_MISC,
			"Unsupported record version");
		return (ARCHIVE_FATAL);
	} else if ((cntlen = _warc_rdlen(buf, eoh - buf)) < 0) {
		/* nightmare!  the specs say content-length is mandatory
		 * so I don't feel overly bad stopping the reader here */
		archive_set_error(
			&a->archive, EINVAL,
			"Bad content length");
		return (ARCHIVE_FATAL);
	} else if ((rtime = _warc_rdrtm(buf, eoh - buf)) == (time_t)-1) {
		/* record time is mandatory as per WARC/1.0,
		 * so just barf here, fast and loud */
		archive_set_error(
			&a->archive, EINVAL,
			"Bad record time");
		return (ARCHIVE_FATAL);
	}

	/* let the world know we're a WARC archive */
	a->archive.archive_format = ARCHIVE_FORMAT_WARC;
	if (ver != w->pver) {
		/* stringify this entry's version */
		archive_string_sprintf(&w->sver,
			"WARC/%u.%u", ver / 10000, ver % 10000);
		/* remember the version */
		w->pver = ver;
	}
	/* start off with the type */
	ftyp = _warc_rdtyp(buf, eoh - buf);
	/* and let future calls know about the content */
	w->cntlen = cntlen;
	w->cntoff = 0U;
	mtime = 0;/* Avoid compiling error on some platform. */

	switch (ftyp) {
	case WT_RSRC:
	case WT_RSP:
		/* only try and read the filename in the cases that are
		 * guaranteed to have one */
		fnam = _warc_rduri(buf, eoh - buf);
		/* check the last character in the URI to avoid creating
		 * directory endpoints as files, see Todo above */
		if (fnam.len == 0 || fnam.str[fnam.len - 1] == '/') {
			/* break here for now */
			fnam.len = 0U;
			fnam.str = NULL;
			break;
		}
		/* bang to our string pool, so we save a
		 * malloc()+free() roundtrip */
		if (fnam.len + 1U > w->pool.len) {
			w->pool.len = ((fnam.len + 64U) / 64U) * 64U;
			w->pool.str = realloc(w->pool.str, w->pool.len);
		}
		memcpy(w->pool.str, fnam.str, fnam.len);
		w->pool.str[fnam.len] = '\0';
		/* let noone else know about the pool, it's a secret, shhh */
		fnam.str = w->pool.str;

		/* snarf mtime or deduce from rtime
		 * this is a custom header added by our writer, it's quite
		 * hard to believe anyone else would go through with it
		 * (apart from being part of some http responses of course) */
		if ((mtime = _warc_rdmtm(buf, eoh - buf)) == (time_t)-1) {
			mtime = rtime;
		}
		break;
	default:
		fnam.len = 0U;
		fnam.str = NULL;
		break;
	}

	/* now eat some of those delicious buffer bits */
	__archive_read_consume(a, eoh - buf);

	switch (ftyp) {
	case WT_RSRC:
	case WT_RSP:
		if (fnam.len > 0U) {
			/* populate entry object */
			archive_entry_set_filetype(entry, AE_IFREG);
			archive_entry_copy_pathname(entry, fnam.str);
			archive_entry_set_size(entry, cntlen);
			archive_entry_set_perm(entry, 0644);
			/* rtime is the new ctime, mtime stays mtime */
			archive_entry_set_ctime(entry, rtime, 0L);
			archive_entry_set_mtime(entry, mtime, 0L);
			break;
		}
		/* FALLTHROUGH */
	default:
		/* consume the content and start over */
		_warc_skip(a);
		goto start_over;
	}
	return (ARCHIVE_OK);
}
static void
test_format_by_name(const char *format_name, const char *compression_type,
    int format_id, int dot_stored, const void *image, size_t image_size)
{
	struct archive_entry *ae;
	struct archive *a;
	size_t used;
	size_t buffsize = 1024 * 1024;
	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);
	r = archive_write_set_format_by_name(a, format_name);
	if (r == ARCHIVE_WARN) {
		skipping("%s format not fully supported on this platform",
		   compression_type);
		assertEqualInt(ARCHIVE_OK, archive_write_free(a));
		free(buff);
		return;
	}
	assertEqualIntA(a, ARCHIVE_OK, r);
	if (compression_type != NULL &&
	    ARCHIVE_OK != archive_write_set_format_option(a, format_name,
	    "compression", compression_type)) {
		skipping("%s writing not fully supported on this platform",
		   compression_type);
		assertEqualInt(ARCHIVE_OK, archive_write_free(a));
		free(buff);
		return;
	}
	assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a));
	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));

	if (image && image_size > 0) {
		assertEqualMem(buff, image, image_size);
	}
	if (format_id > 0) {
		/*
		 * Now, read the data back.
		 */
		/* With the test memory reader -- seeking mode. */
		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,
		    read_open_memory_seek(a, buff, used, 7));

		if (dot_stored & 1) {
			assertEqualIntA(a, ARCHIVE_OK,
			    archive_read_next_header(a, &ae));
			assertEqualString(".", archive_entry_pathname(ae));
			assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
		}
		/*
		 * Read and verify the file.
		 */
		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
		assertEqualInt(1, archive_entry_mtime(ae));
		if (dot_stored & 2) {
			assertEqualString("./file", archive_entry_pathname(ae));
		} else {
			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, ARCHIVE_FILTER_NONE,
		    archive_filter_code(a, 0));
		assertEqualIntA(a, format_id, archive_format(a));

		assertEqualInt(ARCHIVE_OK, archive_read_close(a));
		assertEqualInt(ARCHIVE_OK, archive_read_free(a));
	}
	free(buff);
}
Пример #15
0
/*
 * Test writing an empty file.
 */
static void
test_only_empty_file(void)
{
	struct archive *a;
	struct archive_entry *ae;
	size_t buffsize = 1000;
	char *buff;
	size_t used;

	buff = malloc(buffsize);

	/* Create a new archive in memory. */
	assert((a = archive_write_new()) != NULL);
	assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_7zip(a));
	assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a));
	assertEqualIntA(a, ARCHIVE_OK,
	    archive_write_open_memory(a, buff, buffsize, &used));

	/*
	 * Write an empty 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_set_atime(ae, 2, 20);
	assertEqualInt(2, archive_entry_atime(ae));
	assertEqualInt(20, archive_entry_atime_nsec(ae));
	archive_entry_set_ctime(ae, 0, 100);
	assertEqualInt(0, archive_entry_ctime(ae));
	assertEqualInt(100, archive_entry_ctime_nsec(ae));
	archive_entry_copy_pathname(ae, "empty");
	assertEqualString("empty", archive_entry_pathname(ae));
	archive_entry_set_mode(ae, AE_IFREG | 0755);
	assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));

	assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae));
	archive_entry_free(ae);

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

	/* Verify the archive file size. */
	assertEqualInt(102, used);

	/* Verify the initial header. */
	assertEqualMem(buff,
		"\x37\x7a\xbc\xaf\x27\x1c\x00\x03"
		"\x00\x5b\x58\x25\x00\x00\x00\x00"
		"\x00\x00\x00\x00\x46\x00\x00\x00"
		"\x00\x00\x00\x00\x8f\xce\x1d\xf3", 32);

	/*
	 * Now, read the data back.
	 */
	/* With the test memory reader -- seeking mode. */
	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, read_open_memory_seek(a, buff, used, 7));

	/*
	 * Read and verify an empty file.
	 */
	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
	assertEqualInt(1, archive_entry_mtime(ae));
	assertEqualInt(0, archive_entry_mtime_nsec(ae));
	assertEqualInt(2, archive_entry_atime(ae));
	assertEqualInt(0, archive_entry_atime_nsec(ae));
	assertEqualInt(0, archive_entry_ctime(ae));
	assertEqualInt(100, archive_entry_ctime_nsec(ae));
	assertEqualString("empty", archive_entry_pathname(ae));
	assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae));
	assertEqualInt(0, 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, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
	assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a));

	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));

	free(buff);
}
Пример #16
0
int
packing_append_file_attr(struct packing *pack, const char *filepath,
    const char *newpath, const char *uname, const char *gname, mode_t perm,
    u_long fflags)
{
	int fd;
	int retcode = EPKG_OK;
	int ret;
	time_t source_time;
	struct stat st;
	struct archive_entry *entry, *sparse_entry;
	bool unset_timestamp;
	const char *source_date_epoch;
	char buf[32768];
	int len;

	entry = archive_entry_new();
	archive_entry_copy_sourcepath(entry, filepath);

	pkg_debug(2, "Packing file '%s'", filepath);

	if (lstat(filepath, &st) != 0) {
		pkg_emit_errno("lstat", filepath);
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	ret = archive_read_disk_entry_from_file(pack->aread, entry, -1,
			&st);
	if (ret != ARCHIVE_OK) {
		pkg_emit_error("%s: %s", filepath,
				archive_error_string(pack->aread));
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	if (newpath != NULL)
		archive_entry_set_pathname(entry, newpath);

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

	if (uname != NULL && uname[0] != '\0') {
		archive_entry_set_uname(entry, uname);
	}

	if (gname != NULL && gname[0] != '\0') {
		archive_entry_set_gname(entry, gname);
	}

	if (fflags > 0)
		archive_entry_set_fflags(entry, fflags, 0);

	if (perm != 0)
		archive_entry_set_perm(entry, perm);

	unset_timestamp = pkg_object_bool(pkg_config_get("UNSET_TIMESTAMP"));

	if (unset_timestamp) {
		archive_entry_unset_atime(entry);
		archive_entry_unset_ctime(entry);
		archive_entry_unset_mtime(entry);
		archive_entry_unset_birthtime(entry);
	}

	if ((source_date_epoch = getenv("SOURCE_DATE_EPOCH")) != NULL) {
		if (source_date_epoch[strspn(source_date_epoch, "0123456789")] != '\0') {
			pkg_emit_error("Bad environment variable "
			    "SOURCE_DATE_EPOCH: %s", source_date_epoch);
			retcode = EPKG_FATAL;
			goto cleanup;
		}
		source_time = strtoll(source_date_epoch, NULL, 10);
		archive_entry_set_atime(entry, source_time, 0);
		archive_entry_set_ctime(entry, source_time, 0);
		archive_entry_set_mtime(entry, source_time, 0);
		archive_entry_set_birthtime(entry, source_time, 0);
	}

	archive_entry_linkify(pack->resolver, &entry, &sparse_entry);

	if (sparse_entry != NULL && entry == NULL)
		entry = sparse_entry;

	archive_write_header(pack->awrite, entry);

	if (archive_entry_size(entry) <= 0)
		goto cleanup;

	if ((fd = open(filepath, O_RDONLY)) < 0) {
		pkg_emit_errno("open", filepath);
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	while ((len = read(fd, buf, sizeof(buf))) > 0) {
		if (archive_write_data(pack->awrite, buf, len) == -1) {
			pkg_emit_errno("archive_write_data", "archive write error");
			retcode = EPKG_FATAL;
			break;
		}
	}

	if (len == -1) {
		pkg_emit_errno("read", "file read error");
		retcode = EPKG_FATAL;
	}
	close(fd);

cleanup:
	archive_entry_free(entry);
	return (retcode);
}
int
zip_read_file_header(struct archive_read *a, struct archive_entry *entry,
    struct zip *zip)
{
	const struct zip_file_header *p;
	const void *h;

	if ((p = __archive_read_ahead(a, sizeof *p)) == NULL) {
		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
		    "Truncated ZIP file header");
		return (ARCHIVE_FATAL);
	}

	zip->version = p->version[0];
	zip->system = p->version[1];
	zip->flags = archive_le16dec(p->flags);
	zip->compression = archive_le16dec(p->compression);
	if (zip->compression <
	    sizeof(compression_names)/sizeof(compression_names[0]))
		zip->compression_name = compression_names[zip->compression];
	else
		zip->compression_name = "??";
	zip->mtime = zip_time(p->timedate);
	zip->ctime = 0;
	zip->atime = 0;
	zip->mode = 0;
	zip->uid = 0;
	zip->gid = 0;
	zip->crc32 = archive_le32dec(p->crc32);
	zip->filename_length = archive_le16dec(p->filename_length);
	zip->extra_length = archive_le16dec(p->extra_length);
	zip->uncompressed_size = archive_le32dec(p->uncompressed_size);
	zip->compressed_size = archive_le32dec(p->compressed_size);

	(a->decompressor->consume)(a, sizeof(struct zip_file_header));


	/* Read the filename. */
	if ((h = __archive_read_ahead(a, zip->filename_length)) == NULL) {
		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
		    "Truncated ZIP file header");
		return (ARCHIVE_FATAL);
	}
	if (archive_string_ensure(&zip->pathname, zip->filename_length) == NULL)
		__archive_errx(1, "Out of memory");
	archive_strncpy(&zip->pathname, h, zip->filename_length);
	(a->decompressor->consume)(a, zip->filename_length);
	archive_entry_set_pathname(entry, zip->pathname.s);

	if (zip->pathname.s[archive_strlen(&zip->pathname) - 1] == '/')
		zip->mode = AE_IFDIR | 0777;
	else
		zip->mode = AE_IFREG | 0777;

	/* Read the extra data. */
	if ((h = __archive_read_ahead(a, zip->extra_length)) == NULL) {
		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
		    "Truncated ZIP file header");
		return (ARCHIVE_FATAL);
	}
	process_extra(h, zip);
	(a->decompressor->consume)(a, zip->extra_length);

	/* Populate some additional entry fields: */
	archive_entry_set_mode(entry, zip->mode);
	archive_entry_set_uid(entry, zip->uid);
	archive_entry_set_gid(entry, zip->gid);
	archive_entry_set_mtime(entry, zip->mtime, 0);
	archive_entry_set_ctime(entry, zip->ctime, 0);
	archive_entry_set_atime(entry, zip->atime, 0);
	archive_entry_set_size(entry, zip->uncompressed_size);

	zip->entry_bytes_remaining = zip->compressed_size;
	zip->entry_offset = 0;

	/* If there's no body, force read_data() to return EOF immediately. */
	if (0 == (zip->flags & ZIP_LENGTH_AT_END)
	    && zip->entry_bytes_remaining < 1)
		zip->end_of_entry = 1;

	/* Set up a more descriptive format name. */
	sprintf(zip->format_name, "ZIP %d.%d (%s)",
	    zip->version / 10, zip->version % 10,
	    zip->compression_name);
	a->archive.archive_format_name = zip->format_name;

	return (ARCHIVE_OK);
}