void GuiZipper::packageSingleFile(const char *absFilename, const char *filename, struct archive *a, bool binary) throw (ZipperException*) { struct stat st; char buff[8192]; int fd; stat(absFilename, &st); struct archive_entry *entry = archive_entry_new(); archive_entry_copy_stat(entry, &st); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_pathname(entry, filename); archive_entry_set_perm(entry, 0644); int r = archive_write_header(a, entry); checkForErrors("Error writing header", a, r); int flags = O_RDONLY; #ifdef __WIN32__ if (binary) { flags |= O_BINARY; } #endif fd = open(absFilename, flags); ssize_t len = read(fd, buff, sizeof(buff)); while (len > 0) { archive_write_data(a, buff, len); len = read(fd, buff, sizeof(buff)); } close(fd); archive_entry_free(entry); }
void write_archive(const char *outname, const char **filename) { struct mydata *mydata = malloc(sizeof(struct mydata)); struct archive *a; struct archive_entry *entry; struct stat st; char buff[8192]; int len; int fd; a = archive_write_new(); mydata->name = outname; archive_write_set_compression_gzip(a); archive_write_set_format_ustar(a); archive_write_open(a, mydata, myopen, mywrite, myclose); while (*filename) { stat(*filename, &st); entry = archive_entry_new(); archive_entry_copy_stat(entry, &st); archive_entry_set_pathname(entry, *filename); archive_entry_set_size(entry, st.st_size); archive_clear_error(a); archive_write_header(a, entry); fd = open(*filename, O_RDONLY); len = read(fd, buff, sizeof(buff)); while ( len > 0 ) { archive_write_data(a, buff, len); len = read(fd, buff, sizeof(buff)); } archive_entry_free(entry); filename++; } archive_write_finish(a); }
static void DTAR_write_header(struct archive* ar, uint64_t idx, uint64_t offset) { /* allocate and entry for this item */ struct archive_entry* entry = archive_entry_new(); /* get file name for this item */ /* fill up entry, FIXME: the uglyness of removing leading slash */ const char* fname = mfu_flist_file_get_name(DTAR_flist, idx); archive_entry_copy_pathname(entry, &fname[1]); if (DTAR_user_opts.preserve) { struct archive* source = archive_read_disk_new(); archive_read_disk_set_standard_lookup(source); int fd = open(fname, O_RDONLY); if (archive_read_disk_entry_from_file(source, entry, fd, NULL) != ARCHIVE_OK) { MFU_LOG(MFU_LOG_ERR, "archive_read_disk_entry_from_file(): %s", archive_error_string(ar)); } archive_read_free(source); close(fd); } else { /* TODO: read stat info from mfu_flist */ struct stat stbuf; mfu_lstat(fname, &stbuf); archive_entry_copy_stat(entry, &stbuf); /* set user name of owner */ const char* uname = mfu_flist_file_get_username(DTAR_flist, idx); archive_entry_set_uname(entry, uname); /* set group name */ const char* gname = mfu_flist_file_get_groupname(DTAR_flist, idx); archive_entry_set_gname(entry, gname); } /* TODO: Seems to be a bug here potentially leading to corrupted * archive files. archive_write_free also writes two blocks of * NULL bytes at the end of an archive file, however, each rank * will have a different view of the length of the file, so one * rank may write its NULL blocks over top of the actual data * written by another rank */ /* write entry info to archive */ struct archive* dest = archive_write_new(); archive_write_set_format_pax(dest); if (archive_write_open_fd(dest, DTAR_writer.fd_tar) != ARCHIVE_OK) { MFU_LOG(MFU_LOG_ERR, "archive_write_open_fd(): %s", archive_error_string(ar)); } /* seek to offset in tar archive for this file */ lseek(DTAR_writer.fd_tar, offset, SEEK_SET); /* write header for this item */ if (archive_write_header(dest, entry) != ARCHIVE_OK) { MFU_LOG(MFU_LOG_ERR, "archive_write_header(): %s", archive_error_string(ar)); } archive_entry_free(entry); archive_write_free(dest); }
int add_dir(struct archive *archive, const char * path) { struct stat st; struct archive_entry *entry; int8_t rc = EXIT_FAILURE; /* initialize struct stat for directories from root */ if (stat("/", &st) < 0) { perror("stat() failed"); goto out; } if ((entry = archive_entry_new()) == NULL) { fprintf(stderr, "archive_entry_new() failed"); goto out; } archive_entry_set_pathname(entry, path); archive_entry_set_filetype(entry, AE_IFDIR); archive_entry_copy_stat(entry, &st); if (archive_write_header(archive, entry) != ARCHIVE_OK) { fprintf(stderr, "archive_write_header() failed"); goto out; } archive_entry_free(entry); rc = EXIT_SUCCESS; out: return rc; }
int packing_append_file(struct packing *pack, const char *filepath, const char *newpath) { int fd; int len; char linkdest[MAXPATHLEN]; char buf[BUFSIZ]; int retcode = EPKG_OK; struct stat st; archive_entry_clear(pack->entry); archive_entry_copy_sourcepath(pack->entry, filepath); retcode = archive_read_disk_entry_from_file(pack->aread, pack->entry, -1, NULL); if (retcode != ARCHIVE_OK) { pkg_emit_event(PKG_EVENT_ARCHIVE_ERROR, /*argc*/2, filepath, pack->aread); retcode = EPKG_FATAL; goto cleanup; } retcode = EPKG_OK; lstat(filepath, &st); archive_entry_copy_stat(pack->entry, &st); if (S_ISLNK(st.st_mode)) { bzero(linkdest, MAXPATHLEN); readlink(filepath, linkdest, MAXPATHLEN); archive_entry_set_symlink(pack->entry, linkdest); } if (newpath != NULL) archive_entry_set_pathname(pack->entry, newpath); if (archive_entry_filetype(pack->entry) != AE_IFREG) { archive_entry_set_size(pack->entry, 0); } archive_write_header(pack->awrite, pack->entry); if (archive_entry_size(pack->entry) > 0) { if ((fd = open(filepath, O_RDONLY)) < 0) { pkg_emit_event(PKG_EVENT_IO_ERROR, /*argc*/3, "open", filepath, strerror(errno)); retcode = EPKG_FATAL; goto cleanup; } while ((len = read(fd, buf, sizeof(buf))) > 0 ) archive_write_data(pack->awrite, buf, len); close(fd); } cleanup: archive_entry_clear(pack->entry); return (retcode); }
void Entry::copy_stat_helper(const char *filename) { struct stat sb; if(lstat(filename, &sb) == -1) { std::string error_msg = strerror(errno); throw Error(error_msg); } archive_entry_copy_stat(_entry, &sb); }
static void write_normal_file(const char *name, struct archive *archive, struct archive_entry_linkresolver *resolver, const char *owner, const char *group) { char buf[16384]; ssize_t buf_len; struct archive_entry *entry, *sparse_entry; struct stat st; if (lstat(name, &st) == -1) err(2, "lstat failed for file %s", name); entry = archive_entry_new(); archive_entry_set_pathname(entry, name); archive_entry_copy_stat(entry, &st); if (owner != NULL) { uid_t uid; archive_entry_set_uname(entry, owner); if (uid_from_user(owner, &uid) == -1) errx(2, "user %s unknown", owner); archive_entry_set_uid(entry, uid); } else { archive_entry_set_uname(entry, user_from_uid(st.st_uid, 1)); } if (group != NULL) { gid_t gid; archive_entry_set_gname(entry, group); if (gid_from_group(group, &gid) == -1) errx(2, "group %s unknown", group); archive_entry_set_gid(entry, gid); } else { archive_entry_set_gname(entry, group_from_gid(st.st_gid, 1)); } if ((st.st_mode & S_IFMT) == S_IFLNK) { buf_len = readlink(name, buf, sizeof buf); if (buf_len < 0) err(2, "cannot read symlink %s", name); buf[buf_len] = '\0'; archive_entry_set_symlink(entry, buf); } archive_entry_linkify(resolver, &entry, &sparse_entry); if (entry != NULL) write_entry(archive, entry); if (sparse_entry != NULL) write_entry(archive, sparse_entry); }
/* * Write a file to the archive. We have special handling for symbolic links. */ static int shar_write_entry(struct archive *a, const char *pathname, const char *accpath, const struct stat *st) { struct archive_entry *entry; int fd = -1; int ret = ARCHIVE_OK; assert(a != NULL); assert(pathname != NULL); assert(accpath != NULL); assert(st != NULL); entry = archive_entry_new(); if (S_ISREG(st->st_mode) && st->st_size > 0) { /* regular file */ if ((fd = open(accpath, O_RDONLY)) == -1) { warn("%s", accpath); ret = ARCHIVE_WARN; goto out; } } else if (S_ISLNK(st->st_mode)) { /* symbolic link */ char lnkbuff[PATH_MAX + 1]; int lnklen; if ((lnklen = readlink(accpath, lnkbuff, PATH_MAX)) == -1) { warn("%s", accpath); ret = ARCHIVE_WARN; goto out; } lnkbuff[lnklen] = '\0'; archive_entry_set_symlink(entry, lnkbuff); } archive_entry_copy_stat(entry, st); archive_entry_set_pathname(entry, pathname); if (!S_ISREG(st->st_mode) || st->st_size == 0) archive_entry_set_size(entry, 0); if (archive_write_header(a, entry) != ARCHIVE_OK) { warnx("%s: %s", pathname, archive_error_string(a)); ret = ARCHIVE_WARN; goto out; } if (fd >= 0) { if ((ret = shar_write_entry_data(a, fd)) != ARCHIVE_OK) warnx("%s: %s", accpath, archive_error_string(a)); } out: archive_entry_free(entry); if (fd >= 0) close(fd); return (ret); }
int ar_entry(lua_State *L) { struct archive_entry** self_ref = (struct archive_entry**) lua_newuserdata(L, sizeof(struct archive_entry*)); // ..., {ud} *self_ref = NULL; luaL_getmetatable(L, AR_ENTRY); // ..., {ud}, {meta} lua_setmetatable(L, -2); // ..., {ud} __ref_count++; *self_ref = archive_entry_new(); if ( lua_istable(L, 1) ) { int mt; // If given a sourcepath, copy stat buffer from there: lua_pushliteral(L, "sourcepath"); // ..., {ud}, "sourcepath" lua_rawget(L, 1); // ..., {ud}, src if ( lua_isstring(L, -1) ) { struct stat sb; #ifdef _MSC_VER stat(lua_tostring(L, -1), &sb); #else lstat(lua_tostring(L, -1), &sb); #endif archive_entry_copy_stat(*self_ref, &sb); } else { // Give a reasonable default mode: archive_entry_set_mode(*self_ref, S_IFREG); } lua_pop(L, 1); // ... {ud} /* XXX: optimized away by assert */ mt = lua_getmetatable(L, -1); // ..., {ud}, {meta} assert(mt != 0); // Iterate over the table and call the method with that name lua_pushnil(L); // ..., {ud}, {meta}, nil while (lua_next(L, 1) != 0) { // ..., {ud}, {meta}, key, value lua_pushvalue(L, -2); // ..., {ud}, {meta}, key, value, key lua_gettable(L, -4); // ..., {ud}, {meta}, key, value, func if ( lua_isnil(L, -1) ) { err("InvalidArgument: '%s' is not a valid field", lua_tostring(L, -3)); } lua_pushvalue(L, -5); // ..., {ud}, {meta}, key, value, func, {ud} lua_pushvalue(L, -3); // ..., {ud}, {meta}, key, value, func, {ud}, value lua_call(L, 2, 0); // ..., {ud}, {meta}, key, value lua_pop(L, 1); // ..., {ud}, {meta}, key } // ..., {ud}, {meta} lua_pop(L, 1); } return 1; }
void DTAR_write_header(struct archive *ar, uint64_t idx, uint64_t offset) { const char * fname = mfu_flist_file_get_name(DTAR_flist, idx); /* fill up entry, FIXME: the uglyness of removing leading slash */ struct archive_entry *entry = archive_entry_new(); archive_entry_copy_pathname(entry, &fname[1]); if (DTAR_user_opts.preserve) { struct archive * source = archive_read_disk_new(); archive_read_disk_set_standard_lookup(source); int fd = open(fname, O_RDONLY); if (archive_read_disk_entry_from_file(source, entry, fd, NULL) != ARCHIVE_OK) { MFU_LOG(MFU_LOG_ERR, "archive_read_disk_entry_from_file(): %s", archive_error_string(ar)); } archive_read_free(source); } else { /* read stat info from mfu_flist */ struct stat stbuf; mfu_lstat(fname, &stbuf); archive_entry_copy_stat(entry, &stbuf); const char* uname = mfu_flist_file_get_username(DTAR_flist, idx); archive_entry_set_uname(entry, uname); const char* gname = mfu_flist_file_get_groupname(DTAR_flist, idx); archive_entry_set_gname(entry, gname); } /* write entry info to archive */ struct archive* dest = archive_write_new(); archive_write_set_format_pax(dest); if (archive_write_open_fd(dest, DTAR_writer.fd_tar) != ARCHIVE_OK) { MFU_LOG(MFU_LOG_ERR, "archive_write_open_fd(): %s", archive_error_string(ar)); } lseek64(DTAR_writer.fd_tar, offset, SEEK_SET); if (archive_write_header(dest, entry) != ARCHIVE_OK) { MFU_LOG(MFU_LOG_ERR, "archive_write_header(): %s", archive_error_string(ar)); } archive_entry_free(entry); archive_write_free(dest); }
static void write_meta_file(struct memory_file *file, struct archive *archive) { struct archive_entry *entry; entry = archive_entry_new(); archive_entry_set_pathname(entry, file->name); archive_entry_copy_stat(entry, &file->st); archive_entry_set_uname(entry, file->owner); archive_entry_set_gname(entry, file->group); if (archive_write_header(archive, entry)) errx(2, "cannot write to archive: %s", archive_error_string(archive)); archive_write_data(archive, file->data, file->len); archive_entry_free(entry); }
static int set_timefilter_stat(struct archive_match *a, int timetype, struct stat *st) { struct archive_entry *ae; time_t ctime_sec, mtime_sec; long ctime_ns, mtime_ns; ae = archive_entry_new(); if (ae == NULL) return (error_nomem(a)); archive_entry_copy_stat(ae, st); ctime_sec = archive_entry_ctime(ae); ctime_ns = archive_entry_ctime_nsec(ae); mtime_sec = archive_entry_mtime(ae); mtime_ns = archive_entry_mtime_nsec(ae); archive_entry_free(ae); return set_timefilter(a, timetype, mtime_sec, mtime_ns, ctime_sec, ctime_ns); }
static int append_path_recursively(const char *pathname, struct archive *a) { int error = 0; struct archive_entry *entry = archive_entry_new(); archive_entry_set_pathname(entry, pathname); struct stat st; stat(pathname, &st); archive_entry_copy_stat(entry, &st); // if we want to add uname/gname, we should do something like: // archive_entry_copy_uname(entry, uname); // archive_entry_copy_gname(entry, gname); archive_write_header(a, entry); int fd = open(pathname, O_RDONLY); ssize_t amt = 0; static char buffer[16*1024]; while ((amt = read(fd, buffer, sizeof(buffer))) > 0) { archive_write_data(a, buffer, amt); } close(fd); archive_entry_free(entry); if (S_ISLNK(st.st_mode)) { } // don't recurse into symbolic link dirs else if (S_ISDIR(st.st_mode)) { DIR *dir = opendir(pathname); struct dirent *dirent = NULL; while ((dirent = readdir(dir))) { if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) { continue; } char *subpath = NULL; asprintf(&subpath, "%s/%s", pathname, dirent->d_name); error = append_path_recursively(subpath, a); free(subpath); if (error != 0) { break; } } } return error; }
void archive_add(char* from, char* to){ struct archive_entry *entry; char buff[8192]; int len; int fd; struct stat s; if(stat(from, &s)==-1) show_errno(); entry = archive_entry_new(); // Note 2 archive_entry_set_pathname(entry, to); archive_entry_copy_stat(entry,&s); archive_write_header(g_archive, entry); fd = open(from, O_RDONLY); len = read(fd, buff, sizeof(buff)); while ( len > 0 ) { archive_write_data(g_archive, buff, len); len = read(fd, buff, sizeof(buff)); } close(fd); archive_entry_free(entry); }
int archive_read_disk_entry_from_file(struct archive *_a, struct archive_entry *entry, int fd, const struct stat *st) { struct archive_read_disk *a = (struct archive_read_disk *)_a; const char *path, *name; struct stat s; int initial_fd = fd; int r, r1; archive_clear_error(_a); path = archive_entry_sourcepath(entry); if (path == NULL) path = archive_entry_pathname(entry); if (a->tree == NULL) { if (st == NULL) { #if HAVE_FSTAT if (fd >= 0) { if (fstat(fd, &s) != 0) { archive_set_error(&a->archive, errno, "Can't fstat"); return (ARCHIVE_FAILED); } } else #endif #if HAVE_LSTAT if (!a->follow_symlinks) { if (lstat(path, &s) != 0) { archive_set_error(&a->archive, errno, "Can't lstat %s", path); return (ARCHIVE_FAILED); } } else #endif if (stat(path, &s) != 0) { archive_set_error(&a->archive, errno, "Can't stat %s", path); return (ARCHIVE_FAILED); } st = &s; } archive_entry_copy_stat(entry, st); } /* Lookup uname/gname */ name = archive_read_disk_uname(_a, archive_entry_uid(entry)); if (name != NULL) archive_entry_copy_uname(entry, name); name = archive_read_disk_gname(_a, archive_entry_gid(entry)); if (name != NULL) archive_entry_copy_gname(entry, name); #ifdef HAVE_STRUCT_STAT_ST_FLAGS /* On FreeBSD, we get flags for free with the stat. */ /* TODO: Does this belong in copy_stat()? */ if (st->st_flags != 0) archive_entry_set_fflags(entry, st->st_flags, 0); #endif #if defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) /* Linux requires an extra ioctl to pull the flags. Although * this is an extra step, it has a nice side-effect: We get an * open file descriptor which we can use in the subsequent lookups. */ if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) { if (fd < 0) { if (a->tree != NULL) fd = a->open_on_current_dir(a->tree, path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); else fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); __archive_ensure_cloexec_flag(fd); } if (fd >= 0) { int stflags; r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags); if (r == 0 && stflags != 0) archive_entry_set_fflags(entry, stflags, 0); } } #endif #if defined(HAVE_READLINK) || defined(HAVE_READLINKAT) if (S_ISLNK(st->st_mode)) { size_t linkbuffer_len = st->st_size + 1; char *linkbuffer; int lnklen; linkbuffer = malloc(linkbuffer_len); if (linkbuffer == NULL) { archive_set_error(&a->archive, ENOMEM, "Couldn't read link data"); return (ARCHIVE_FAILED); } if (a->tree != NULL) { #ifdef HAVE_READLINKAT lnklen = readlinkat(a->tree_current_dir_fd(a->tree), path, linkbuffer, linkbuffer_len); #else if (a->tree_enter_working_dir(a->tree) != 0) { archive_set_error(&a->archive, errno, "Couldn't read link data"); free(linkbuffer); return (ARCHIVE_FAILED); } lnklen = readlink(path, linkbuffer, linkbuffer_len); #endif /* HAVE_READLINKAT */ } else lnklen = readlink(path, linkbuffer, linkbuffer_len); if (lnklen < 0) { archive_set_error(&a->archive, errno, "Couldn't read link data"); free(linkbuffer); return (ARCHIVE_FAILED); } linkbuffer[lnklen] = 0; archive_entry_set_symlink(entry, linkbuffer); free(linkbuffer); } #endif /* HAVE_READLINK || HAVE_READLINKAT */ r = setup_acls(a, entry, &fd); r1 = setup_xattrs(a, entry, &fd); if (r1 < r) r = r1; if (a->enable_copyfile) { r1 = setup_mac_metadata(a, entry, &fd); if (r1 < r) r = r1; } r1 = setup_sparse(a, entry, &fd); if (r1 < r) r = r1; /* If we opened the file earlier in this function, close it. */ if (initial_fd != fd) close(fd); return (r); }
/* ArchiveWriter::addEntry {{{ * */ ZEND_METHOD(ArchiveWriter, addEntry) { zval *this = getThis(); zval *entry_obj; archive_file_t *arch; archive_entry_t *entry, *entry_copy; char *pathname; int pathname_len; const struct stat *stat_sb; 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, "o", &entry_obj) == FAILURE) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (!_archive_get_fd(this, &arch TSRMLS_CC)) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (!instanceof_function(Z_OBJCE_P(entry_obj), ce_ArchiveEntry TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "An instance of ArchiveEntry is required"); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (!_archive_get_entry_struct(entry_obj, &entry TSRMLS_CC)) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } pathname = entry->filename; pathname_len = strlen(pathname); _archive_normalize_path(&pathname, &pathname_len); if (pathname_len == 0 || pathname[0] == '\0') { /* user is probably trying to add "./", "/", ".." or ".", ignoring it silently */ zend_restore_error_handling(&error_handling TSRMLS_CC); RETURN_TRUE; } /* copy entry.. */ entry_copy = emalloc(sizeof(archive_entry_t)); memcpy(entry_copy, entry, sizeof(archive_entry_t)); entry_copy->entry = archive_entry_new(); entry_copy->filename = estrdup(entry->filename); entry_copy->data = NULL; entry_copy->data_len = 0; archive_entry_copy_pathname(entry_copy->entry, pathname); stat_sb = archive_entry_stat(entry->entry); archive_entry_copy_stat(entry_copy->entry, stat_sb); /* ..and add it to the hash */ zend_hash_update(arch->entries, pathname, pathname_len + 1, &entry_copy, sizeof(archive_entry_t), NULL); zend_restore_error_handling(&error_handling TSRMLS_CC); RETURN_TRUE; }
/* * This is used by both out mode (to copy objects from disk into * an archive) and pass mode (to copy objects from disk to * an archive_write_disk "archive"). */ static int file_to_archive(struct cpio *cpio, const char *srcpath) { struct stat st; const char *destpath; struct archive_entry *entry, *spare; size_t len; const char *p; #if !defined(_WIN32) || defined(__CYGWIN__) int lnklen; #endif int r; /* * Create an archive_entry describing the source file. * * XXX TODO: rework to use archive_read_disk_entry_from_file() */ entry = archive_entry_new(); if (entry == NULL) cpio_errc(1, 0, "Couldn't allocate entry"); archive_entry_copy_sourcepath(entry, srcpath); /* Get stat information. */ if (cpio->option_follow_links) r = stat(srcpath, &st); else r = lstat(srcpath, &st); if (r != 0) { cpio_warnc(errno, "Couldn't stat \"%s\"", srcpath); archive_entry_free(entry); return (0); } if (cpio->uid_override >= 0) st.st_uid = cpio->uid_override; if (cpio->gid_override >= 0) st.st_gid = cpio->uid_override; archive_entry_copy_stat(entry, &st); #if !defined(_WIN32) || defined(__CYGWIN__) /* If its a symlink, pull the target. */ if (S_ISLNK(st.st_mode)) { lnklen = readlink(srcpath, cpio->buff, cpio->buff_size); if (lnklen < 0) { cpio_warnc(errno, "%s: Couldn't read symbolic link", srcpath); archive_entry_free(entry); return (0); } cpio->buff[lnklen] = 0; archive_entry_set_symlink(entry, cpio->buff); } #endif /* * Generate a destination path for this entry. * "destination path" is the name to which it will be copied in * pass mode or the name that will go into the archive in * output mode. */ destpath = srcpath; if (cpio->destdir) { len = strlen(cpio->destdir) + strlen(srcpath) + 8; if (len >= cpio->pass_destpath_alloc) { while (len >= cpio->pass_destpath_alloc) { cpio->pass_destpath_alloc += 512; cpio->pass_destpath_alloc *= 2; } free(cpio->pass_destpath); cpio->pass_destpath = malloc(cpio->pass_destpath_alloc); if (cpio->pass_destpath == NULL) cpio_errc(1, ENOMEM, "Can't allocate path buffer"); } strcpy(cpio->pass_destpath, cpio->destdir); p = srcpath; while (p[0] == '/') ++p; strcat(cpio->pass_destpath, p); destpath = cpio->pass_destpath; } if (cpio->option_rename) destpath = cpio_rename(destpath); if (destpath == NULL) return (0); archive_entry_copy_pathname(entry, destpath); /* * If we're trying to preserve hardlinks, match them here. */ spare = NULL; if (cpio->linkresolver != NULL && !S_ISDIR(st.st_mode)) { archive_entry_linkify(cpio->linkresolver, &entry, &spare); } if (entry != NULL) { r = entry_to_archive(cpio, entry); archive_entry_free(entry); } if (spare != NULL) { if (r == 0) r = entry_to_archive(cpio, spare); archive_entry_free(spare); } return (r); }
void pkg_sign_gpg(const char *name, const char *output) { struct archive *pkg; struct archive_entry *entry, *hash_entry, *sign_entry; int fd; struct stat sb; char *hash_file, *signature_file, *tmp, *pkgname, hash[SHA512_DIGEST_STRING_LENGTH]; unsigned char block[65536]; off_t i, size; size_t block_len, signature_len; if ((fd = open(name, O_RDONLY)) == -1) err(EXIT_FAILURE, "Cannot open binary package %s", name); if (fstat(fd, &sb) == -1) err(EXIT_FAILURE, "Cannot stat %s", name); entry = archive_entry_new(); archive_entry_copy_stat(entry, &sb); pkgname = extract_pkgname(fd); hash_file = xasprintf(hash_template, pkgname, (long long)archive_entry_size(entry)); free(pkgname); for (i = 0; i < archive_entry_size(entry); i += block_len) { if (i + (off_t)sizeof(block) < archive_entry_size(entry)) block_len = sizeof(block); else block_len = archive_entry_size(entry) % sizeof(block); if (read(fd, block, block_len) != (ssize_t)block_len) err(2, "short read"); hash_block(block, block_len, hash); tmp = xasprintf("%s%s\n", hash_file, hash); free(hash_file); hash_file = tmp; } tmp = xasprintf("%s%s", hash_file, hash_trailer); free(hash_file); hash_file = tmp; if (detached_gpg_sign(hash_file, strlen(hash_file), &signature_file, &signature_len, gpg_keyring_sign, gpg_sign_as)) err(EXIT_FAILURE, "Cannot sign hash file"); lseek(fd, 0, SEEK_SET); sign_entry = archive_entry_clone(entry); hash_entry = archive_entry_clone(entry); pkgname = strrchr(name, '/'); archive_entry_set_pathname(entry, pkgname != NULL ? pkgname + 1 : name); archive_entry_set_pathname(hash_entry, HASH_FNAME); archive_entry_set_pathname(sign_entry, GPG_SIGNATURE_FNAME); archive_entry_set_size(hash_entry, strlen(hash_file)); archive_entry_set_size(sign_entry, signature_len); pkg = archive_write_new(); archive_write_set_compression_none(pkg); archive_write_set_format_ar_bsd(pkg); archive_write_open_filename(pkg, output); archive_write_header(pkg, hash_entry); archive_write_data(pkg, hash_file, strlen(hash_file)); archive_write_finish_entry(pkg); archive_entry_free(hash_entry); archive_write_header(pkg, sign_entry); archive_write_data(pkg, signature_file, signature_len); archive_write_finish_entry(pkg); archive_entry_free(sign_entry); size = archive_entry_size(entry); archive_write_header(pkg, entry); for (i = 0; i < size; i += block_len) { if (i + (off_t)sizeof(block) < size) block_len = sizeof(block); else block_len = size % sizeof(block); if (read(fd, block, block_len) != (ssize_t)block_len) err(2, "short read"); archive_write_data(pkg, block, block_len); } archive_write_finish_entry(pkg); archive_entry_free(entry); archive_write_finish(pkg); close(fd); exit(0); }
const gchar* archive_create(const char* archive_name, GSList* files, COMPRESS_METHOD method, ARCHIVE_FORMAT format) { struct archive* arch; struct archive_entry* entry; char* buf = NULL; ssize_t len; int fd; struct stat st; struct file_info* file; gchar* filename = NULL; gchar* msg = NULL; #ifndef _TEST gint num = 0; gint total = g_slist_length (files); #endif g_return_val_if_fail(files != NULL, "No files for archiving"); debug_print("File: %s\n", archive_name); arch = archive_write_new(); switch (method) { case ZIP: if (archive_write_set_compression_gzip(arch) != ARCHIVE_OK) return archive_error_string(arch); break; case BZIP2: if (archive_write_set_compression_bzip2(arch) != ARCHIVE_OK) return archive_error_string(arch); break; #if NEW_ARCHIVE_API case COMPRESS: if (archive_write_set_compression_compress(arch) != ARCHIVE_OK) return archive_error_string(arch); break; #endif case NO_COMPRESS: if (archive_write_set_compression_none(arch) != ARCHIVE_OK) return archive_error_string(arch); break; } switch (format) { case TAR: if (archive_write_set_format_ustar(arch) != ARCHIVE_OK) return archive_error_string(arch); break; case SHAR: if (archive_write_set_format_shar(arch) != ARCHIVE_OK) return archive_error_string(arch); break; case PAX: if (archive_write_set_format_pax(arch) != ARCHIVE_OK) return archive_error_string(arch); break; case CPIO: if (archive_write_set_format_cpio(arch) != ARCHIVE_OK) return archive_error_string(arch); break; case NO_FORMAT: return "Missing archive format"; } if (archive_write_open_file(arch, archive_name) != ARCHIVE_OK) return archive_error_string(arch); while (files && ! stop_action) { #ifndef _TEST set_progress_print_all(num++, total, 30); #endif file = (struct file_info *) files->data; if (!file) continue; filename = get_full_path(file); /* libarchive will crash if instructed to add archive to it self */ if (g_utf8_collate(archive_name, filename) == 0) { buf = NULL; buf = g_strdup_printf( "%s: Not dumping to %s", archive_name, filename); g_warning("%s\n", buf); #ifndef _TEST debug_print("%s\n", buf); #endif g_free(buf); } else { #ifndef _TEST debug_print("Adding: %s\n", filename); msg = g_strdup_printf("%s", filename); set_progress_file_label(msg); g_free(msg); #endif entry = archive_entry_new(); lstat(filename, &st); if ((fd = open(filename, O_RDONLY)) == -1) { perror("open file"); } else { archive_entry_copy_stat(entry, &st); archive_entry_set_pathname(entry, filename); if (S_ISLNK(st.st_mode)) { buf = NULL; buf = malloc(PATH_MAX + 1); if ((len = readlink(filename, buf, PATH_MAX)) < 0) perror("error in readlink"); else buf[len] = '\0'; archive_entry_set_symlink(entry, buf); g_free(buf); archive_entry_set_size(entry, 0); archive_write_header(arch, entry); } else { if (archive_write_header(arch, entry) != ARCHIVE_OK) g_warning("%s", archive_error_string(arch)); buf = NULL; buf = malloc(READ_BLOCK_SIZE); len = read(fd, buf, READ_BLOCK_SIZE); while (len > 0) { if (archive_write_data(arch, buf, len) == -1) g_warning("%s", archive_error_string(arch)); memset(buf, 0, READ_BLOCK_SIZE); len = read(fd, buf, READ_BLOCK_SIZE); } g_free(buf); } close(fd); archive_entry_free(entry); } } g_free(filename); files = g_slist_next(files); } #ifndef _TEST if (stop_action) unlink(archive_name); stop_action = FALSE; #endif archive_write_close(arch); archive_write_finish(arch); return NULL; }
int archive_read_disk_entry_from_file(struct archive *_a, struct archive_entry *entry, int fd, const struct stat *st) { struct archive_read_disk *a = (struct archive_read_disk *)_a; const char *path, *name; struct stat s; int initial_fd = fd; int r, r1; archive_clear_error(_a); path = archive_entry_sourcepath(entry); if (path == NULL) path = archive_entry_pathname(entry); #ifdef EXT2_IOC_GETFLAGS /* Linux requires an extra ioctl to pull the flags. Although * this is an extra step, it has a nice side-effect: We get an * open file descriptor which we can use in the subsequent lookups. */ if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) { if (fd < 0) fd = open(pathname, O_RDONLY | O_NONBLOCK | O_BINARY); if (fd >= 0) { unsigned long stflags; int r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags); if (r == 0 && stflags != 0) archive_entry_set_fflags(entry, stflags, 0); } } #endif if (st == NULL) { /* TODO: On Windows, use GetFileInfoByHandle() here. * Using Windows stat() call is badly broken, but * even the stat() wrapper has problems because * 'struct stat' is broken on Windows. */ #if HAVE_FSTAT if (fd >= 0) { if (fstat(fd, &s) != 0) { archive_set_error(&a->archive, errno, "Can't fstat"); return (ARCHIVE_FAILED); } } else #endif #if HAVE_LSTAT if (!a->follow_symlinks) { if (lstat(path, &s) != 0) { archive_set_error(&a->archive, errno, "Can't lstat %s", path); return (ARCHIVE_FAILED); } } else #endif if (stat(path, &s) != 0) { archive_set_error(&a->archive, errno, "Can't stat %s", path); return (ARCHIVE_FAILED); } st = &s; } archive_entry_copy_stat(entry, st); /* Lookup uname/gname */ name = archive_read_disk_uname(_a, archive_entry_uid(entry)); if (name != NULL) archive_entry_copy_uname(entry, name); name = archive_read_disk_gname(_a, archive_entry_gid(entry)); if (name != NULL) archive_entry_copy_gname(entry, name); #ifdef HAVE_STRUCT_STAT_ST_FLAGS /* On FreeBSD, we get flags for free with the stat. */ /* TODO: Does this belong in copy_stat()? */ if (st->st_flags != 0) archive_entry_set_fflags(entry, st->st_flags, 0); #endif #ifdef HAVE_READLINK if (S_ISLNK(st->st_mode)) { char linkbuffer[PATH_MAX + 1]; int lnklen = readlink(path, linkbuffer, PATH_MAX); if (lnklen < 0) { archive_set_error(&a->archive, errno, "Couldn't read link data"); return (ARCHIVE_FAILED); } linkbuffer[lnklen] = 0; archive_entry_set_symlink(entry, linkbuffer); } #endif r = setup_acls_posix1e(a, entry, fd); r1 = setup_xattrs(a, entry, fd); if (r1 < r) r = r1; /* If we opened the file earlier in this function, close it. */ if (initial_fd != fd) close(fd); return (r); }
int powaur_backup(alpm_list_t *targets) { int ret = 0; char localdb[PATH_MAX]; struct archive *a; struct archive_entry *entry; struct stat st; char cwd[PATH_MAX]; char backup_dest[PATH_MAX]; char backup[MINI_BUFSZ]; time_t time_now; struct tm tm_st; if (targets != NULL && alpm_list_count(targets) != 1) { pw_fprintf(PW_LOG_ERROR, stderr, "-B only takes 1 argument.\n"); return -1; } a = archive_write_new(); if (!a) { return error(PW_ERR_ARCHIVE_CREATE); } archive_write_set_compression_bzip2(a); archive_write_set_format_pax_restricted(a); /* Filename = pacman-YYYY-MM-DD_HHhMM.tar.bz2 */ time(&time_now); localtime_r(&time_now, &tm_st); strftime(backup, MINI_BUFSZ, "pacman-%Y-%m-%d_%Hh%M.tar.bz2", &tm_st); if (!getcwd(cwd, PATH_MAX)) { error(PW_ERR_GETCWD); ret = -1; goto cleanup; } /* Get full path */ if (targets) { snprintf(backup_dest, PATH_MAX, "%s/%s", targets->data, backup); } else { snprintf(backup_dest, PATH_MAX, "%s/%s", cwd, backup); } if (archive_write_open_filename(a, backup_dest) != ARCHIVE_OK) { PW_SETERRNO(PW_ERR_ARCHIVE_OPEN); ret = -1; goto cleanup; } if (ret = chdir(pacman_dbpath)) { error(PW_ERR_CHDIR, pacman_dbpath); goto restore_cwd; } /* Create entry for the current directory. */ entry = archive_entry_new(); if (!entry) { error(PW_ERR_ARCHIVE_ENTRY); goto restore_cwd; } snprintf(localdb, PATH_MAX, "%s", "local"); if (ret = stat(localdb, &st)) { error(PW_ERR_STAT, localdb); goto free_entry; } archive_entry_set_pathname(entry, localdb); archive_entry_copy_stat(entry, &st); archive_write_header(a, entry); pw_printf(PW_LOG_INFO, "Saving pacman database in %s\n", backup_dest); ret = write_dir_archive(localdb, a); if (!ret) { pw_printf(PW_LOG_INFO, "Pacman database successfully saved in %s\n", backup_dest); } else { pw_fprintf(PW_LOG_ERROR, stderr, "Pacman database not saved.\n"); } free_entry: archive_entry_free(entry); restore_cwd: if (chdir(cwd)) { PW_SETERRNO(PW_ERR_RESTORECWD); ret = -1; } cleanup: archive_write_finish(a); return ret; }
/* Writes a directory to an archive */ static int write_dir_archive(char *dirname, struct archive *a) { int ret = 0; struct archive_entry *entry; struct dirent *dir_entry; DIR *dirp; struct stat st; char filename[PATH_MAX]; char buf[PATH_MAX]; int fd; ssize_t bytesread; dirp = opendir(dirname); if (!dirp) { return error(PW_ERR_OPENDIR); } while (dir_entry = readdir(dirp)) { if (!strcmp(dir_entry->d_name, ".") || !strcmp(dir_entry->d_name, "..")) { continue; } snprintf(filename, PATH_MAX, "%s/%s", dirname, dir_entry->d_name); if (stat(filename, &st)) { pw_fprintf(PW_LOG_ERROR, stderr, "%s: Failed to stat file %s\n", __func__, filename); ret = -1; goto free_entry; } entry = archive_entry_new(); if (!entry) { pw_fprintf(PW_LOG_ERROR, stderr, "%s: Failed to create new entry\n", __func__); ret = -1; goto free_entry; } archive_entry_set_pathname(entry, filename); archive_entry_copy_stat(entry, &st); archive_write_header(a, entry); if (st.st_mode & S_IFDIR) { /* Directory entry. NOTE: Recursion * I don't really like recursion but there doesn't seem to be * a more elegant way out. */ snprintf(filename, PATH_MAX, "%s/%s", dirname, dir_entry->d_name); if (ret = write_dir_archive(filename, a)) { goto free_entry; } } else { fd = open(filename, O_RDONLY); if (fd < 0) { pw_fprintf(PW_LOG_ERROR, stderr, "Cannot open %s\n", filename); goto free_entry; } while (bytesread = read(fd, buf, PATH_MAX)) { archive_write_data(a, buf, bytesread); } close(fd); } free_entry: archive_entry_free(entry); entry = NULL; } closedir(dirp); return ret; }