예제 #1
0
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);
}
예제 #2
0
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);
}
예제 #3
0
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);
}
예제 #4
0
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;
}
예제 #5
0
파일: packing.c 프로젝트: philpep/pkgng
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);
}
예제 #6
0
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);
}
예제 #7
0
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);
}
예제 #8
0
파일: shar.c 프로젝트: Bebere/libarchive
/*
 * 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);
}
예제 #9
0
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;
}
예제 #10
0
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);

}
예제 #11
0
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);
}
예제 #12
0
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);
}
예제 #13
0
파일: archiving.c 프로젝트: alist/Greenwich
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;
}
예제 #14
0
파일: archive.c 프로젝트: nishidy/cpee
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;
}
예제 #17
0
파일: cpio.c 프로젝트: marccodes/lfl
/*
 * 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);
}
예제 #18
0
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);
}
예제 #19
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);
}
예제 #21
0
파일: util.c 프로젝트: Berticus/powaur
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;
}
예제 #22
0
파일: util.c 프로젝트: Berticus/powaur
/* 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;
}