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; }
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); }
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); }
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); }
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); */ }
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); }
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); }
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); }
/* * 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); }
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); }