~jscott/pdfpartition

79dc45121451340c38ba01b2182d58c484d21fa0 — John Scott 5 months ago d3f6e4e
Use poppler_document_new_from_file()

Initially motivated by finding that the version of Poppler
packaged for Cygwin doesn't yet have poppler_document_new_from_fd(),
I've come to discover that this is actually slightly cleaner.
2 files changed, 42 insertions(+), 49 deletions(-)

M main.c
M meson.build
M main.c => main.c +41 -46
@@ 14,6 14,31 @@
#include <sys/stat.h>
#include <unistd.h>

static int asprintf(char *str[restrict static 1], const char fmt[restrict static 1], ...) {
	FILE *const memstream = open_memstream(str, &(size_t){0});
	if(!memstream) {
		return -1;
	}

	va_list list;
	va_start(list, fmt);
	int n = vfprintf(memstream, fmt, list);
	va_end(list);
	if(n < 0) {
		const int save = errno;
		if(fclose(memstream) != EOF) {
			free(*str);
		}
		errno = save;
		return n;
	}

	if(fclose(memstream) == EOF) {
		return -1;
	}
	return n;
}

G_GNUC_ALLOC_SIZE2(2, 3) G_GNUC_WARN_UNUSED_RESULT
static void *reallocarray(void *p, size_t m, size_t n) {
	if(n && m > SIZE_MAX / n) {


@@ 50,45 75,25 @@ int main(int argc, char *argv[static argc+1]) {
		exit(EXIT_FAILURE);
	}

	const int fileone = open(argv[0], O_RDONLY);
	if(fileone == -1) {
		fprintf(stderr, "Failed to open %s: %s\n", argv[0], strerror(errno));
		exit(EXIT_FAILURE);
	}
	/* Before handing these file descriptors over to Poppler, we
	 * are required to check that they correspond to regular files. */
	struct stat st;
	if(fstat(fileone, &st) == -1) {
		fprintf(stderr, "Failed to get information on %s: %s\n", argv[0], strerror(errno));
		goto endfileone;
	}
	if(!S_ISREG(st.st_mode)) {
		fprintf(stderr, "%s is not a regular file\n", argv[0]);
		goto endfileone;
	}

	const int filetwo = open(argv[1], O_RDONLY);
	if(filetwo == -1) {
		fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno));
		goto endfileone;
	}
	if(fstat(filetwo, &st) == -1) {
		fprintf(stderr, "Failed to get information on %s: %s\n", argv[1], strerror(errno));
		goto endfiletwo;
	char *urione, *uritwo;
	if(asprintf(&urione, "file://%s", argv[0]) < 0) {
		perror("Failed to construct URI");
		exit(EXIT_FAILURE);
	}
	if(!S_ISREG(st.st_mode)) {
		fprintf(stderr, "%s is not a regular file\n", argv[1]);
		goto endfiletwo;
	if(asprintf(&uritwo, "file://%s", argv[1]) < 0) {
		perror("Failed to construct URI");
		goto endurione;
	}

	GError *err = NULL;
	PopplerDocument *const docone = poppler_document_new_from_fd(fileone, NULL, &err);
	PopplerDocument *const docone = poppler_document_new_from_file(urione, NULL, &err);
	if(!docone) {
		fprintf(stderr, "Failed to read %s: %s\n", argv[0], err->message);
		g_error_free(err);
		goto endfiletwo;
		goto enduritwo;
	}
	PopplerDocument *const doctwo = poppler_document_new_from_fd(filetwo, NULL, &err);
	PopplerDocument *const doctwo = poppler_document_new_from_file(uritwo, NULL, &err);
	if(!doctwo) {
		fprintf(stderr, "Failed to read %s: %s\n", argv[1], err->message);
		g_error_free(err);


@@ 170,14 175,8 @@ int main(int argc, char *argv[static argc+1]) {
	free(maindocpages);
	g_object_unref(doctwo);
	g_object_unref(docone);
	if(close(filetwo) == -1) {
		fprintf(stderr, "Failed to close %s: %s\n", argv[1], strerror(errno));
		goto endfileone;
	}
	if(close(fileone) == -1) {
		fprintf(stderr, "Failed to close %s: %s\n", argv[0], strerror(errno));
		exit(EXIT_FAILURE);
	}
	free(uritwo);
	free(urione);
	exit(EXIT_SUCCESS);

endcontext:


@@ 192,13 191,9 @@ enddoctwo:
	g_object_unref(doctwo);
enddocone:
	g_object_unref(docone);
endfiletwo:
	if(close(filetwo) == -1) {
		fprintf(stderr, "Failed to close %s: %s\n", argv[1], strerror(errno));
	}
endfileone:
	if(close(fileone) == -1) {
		fprintf(stderr, "Failed to close %s: %s\n", argv[0], strerror(errno));
	}
enduritwo:
	free(uritwo);
endurione:
	free(urione);
	exit(EXIT_FAILURE);
}

M meson.build => meson.build +1 -3
@@ 15,10 15,8 @@ if not cc.compiles('''
endif

posix = ['-D_POSIX_C_SOURCE=200809L']
assert(cc.has_function('fstat', args: posix, prefix: '#include <sys/stat.h>'))
assert(cc.has_type('struct stat', args: posix, prefix: '#include <sys/stat.h>'))
assert(cc.has_function('getopt', args: posix, prefix: '#include <unistd.h>'))
assert(cc.has_function('open', args: posix, prefix: '#include <fcntl.h>'))
assert(cc.has_function('open_memstream', args: posix, prefix: '#include <stdio.h>'))

cairo = dependency('cairo-pdf')
if not cc.compiles('''