[evince/wip/chpe/load-fd: 2/5] libdocument: Add API to create EvDocument from file descriptor




commit 4bcc5d196cdc505a7fef524d7b73321fcddb5444
Author: Christian Persch <chpe src gnome org>
Date:   Wed Dec 1 21:25:02 2021 +0100

    libdocument: Add API to create EvDocument from file descriptor
    
    Add new EvDocumentClass vfunc load_fd to load the document from
    a file descriptor.

 .../libdocument/libevdocument-sections.txt         |  2 +
 libdocument/ev-document-factory.c                  | 64 ++++++++++++++-
 libdocument/ev-document-factory.h                  |  9 ++-
 libdocument/ev-document.c                          | 93 +++++++++++++++++++++-
 libdocument/ev-document.h                          | 12 ++-
 5 files changed, 173 insertions(+), 7 deletions(-)
---
diff --git a/help/reference/libdocument/libevdocument-sections.txt 
b/help/reference/libdocument/libevdocument-sections.txt
index 01211405b..795c947de 100644
--- a/help/reference/libdocument/libevdocument-sections.txt
+++ b/help/reference/libdocument/libevdocument-sections.txt
@@ -368,6 +368,7 @@ ev_document_get_backend_info
 ev_document_load
 ev_document_load_stream
 ev_document_load_gfile
+ev_document_load_fd
 ev_document_save
 ev_document_get_n_pages
 ev_document_get_page
@@ -775,6 +776,7 @@ ev_document_fonts_get_type
 ev_document_factory_get_document
 ev_document_factory_get_document_for_gfile
 ev_document_factory_get_document_for_stream
+ev_document_factory_get_document_for_fd
 ev_document_factory_add_filters
 </SECTION>
 
diff --git a/libdocument/ev-document-factory.c b/libdocument/ev-document-factory.c
index ffe180caf..c0718fd9b 100644
--- a/libdocument/ev-document-factory.c
+++ b/libdocument/ev-document-factory.c
@@ -1,6 +1,6 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
 /*
- *  Copyright (C) 2005, Red Hat, Inc. 
+ *  Copyright (C) 2005, Red Hat, Inc.
+ *  Copyright © 2018 Christian Persch
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -540,6 +540,66 @@ ev_document_factory_get_document_for_stream (GInputStream *stream,
         return document;
 }
 
+/**
+ * ev_document_factory_get_document_for_fd:
+ * @stream: a file descriptor
+ * @mime_type: the mime type
+ * @flags: flags from #EvDocumentLoadFlags
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: (allow-none): a #GError location to store an error, or %NULL
+ *
+ * Synchronously creates a #EvDocument for the document from @fd using the backend
+ * for loading documents of type @mime_type; or, if the backend does not support
+ * loading from file descriptors, or an error occurred on opening the document,
+ * returns %NULL and fills in @error.
+ * If the document is encrypted, it is returned but also @error is set to
+ * %EV_DOCUMENT_ERROR_ENCRYPTED.
+ *
+ * If the mime type cannot be inferred from the file descriptor, and @mime_type is %NULL,
+ * an error is returned.
+ *
+ * Note that this function takes ownership of @fd; you must not ever
+ * operate on it again. It will be closed automatically if the document
+ * is destroyed, or if this function returns %NULL.
+ *
+ * Returns: (transfer full): a new #EvDocument, or %NULL
+ *
+ * Since: 42.0
+ */
+EvDocument*
+ev_document_factory_get_document_for_fd (int fd,
+                                         const char *mime_type,
+                                         EvDocumentLoadFlags flags,
+                                         GCancellable *cancellable,
+                                         GError **error)
+{
+        EvDocument *document;
+
+        g_return_val_if_fail (fd != -1, NULL);
+        g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+        if (mime_type == NULL) {
+                g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                                     "Cannot query mime type from file descriptor");
+                close (fd);
+                return NULL;
+        }
+
+        document = ev_document_factory_new_document_for_mime_type (mime_type, error);
+        if (document == NULL) {
+                close (fd);
+                return NULL;
+        }
+
+        if (!ev_document_load_fd (document, fd, flags, cancellable, error)) {
+                /* fd is now consumed */
+                g_object_unref (document);
+                return NULL;
+        }
+
+        return document;
+}
+
 static void
 file_filter_add_mime_types (EvBackendInfo *info, GtkFileFilter *filter)
 {
diff --git a/libdocument/ev-document-factory.h b/libdocument/ev-document-factory.h
index a071a4179..a771346c5 100644
--- a/libdocument/ev-document-factory.h
+++ b/libdocument/ev-document-factory.h
@@ -1,6 +1,5 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
 /*
- *  Copyright (C) 2005, Red Hat, Inc. 
+ *  Copyright (C) 2005, Red Hat, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -51,6 +50,12 @@ EvDocument* ev_document_factory_get_document_for_stream (GInputStream *stream,
                                                          EvDocumentLoadFlags flags,
                                                          GCancellable *cancellable,
                                                          GError **error);
+EV_PUBLIC
+EvDocument* ev_document_factory_get_document_for_fd (int fd,
+                                                     const char *mime_type,
+                                                     EvDocumentLoadFlags flags,
+                                                     GCancellable *cancellable,
+                                                     GError **error);
 
 EV_PUBLIC
 void       ev_document_factory_add_filters  (GtkWidget *chooser, EvDocument *document);
diff --git a/libdocument/ev-document.c b/libdocument/ev-document.c
index 1be739c9b..cfb843384 100644
--- a/libdocument/ev-document.c
+++ b/libdocument/ev-document.c
@@ -1,7 +1,7 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
 /*
  *  Copyright (C) 2009 Carlos Garcia Campos
  *  Copyright (C) 2004 Marco Pesenti Gritti
+ *  Copyright © 2018 Christian Persch
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,6 +23,9 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
 
 #include "ev-document.h"
 #include "ev-document-misc.h"
@@ -563,6 +566,92 @@ ev_document_load_gfile (EvDocument         *document,
         return TRUE;
 }
 
+/**
+ * ev_document_load_fd:
+ * @document: a #EvDocument
+ * @fd: a file descriptor
+ * @flags: flags from #EvDocumentLoadFlags
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: (allow-none): a #GError location to store an error, or %NULL
+ *
+ * Synchronously loads the document from @fd, which must refer to
+ * a regular file.
+ *
+ * Note that this function takes ownership of @fd; you must not ever
+ * operate on it again. It will be closed automatically if the document
+ * is destroyed, or if this function returns %NULL.
+ *
+ * See ev_document_load() for more information.
+ *
+ * Returns: %TRUE if loading succeeded, or %FALSE on error with @error filled in
+ *
+ * Since: 42.0
+ */
+gboolean
+ev_document_load_fd (EvDocument         *document,
+                     int                 fd,
+                     EvDocumentLoadFlags flags,
+                     GCancellable       *cancellable,
+                     GError            **error)
+{
+        EvDocumentClass *klass;
+       struct stat statbuf;
+       int fd_flags;
+
+        g_return_val_if_fail (EV_IS_DOCUMENT (document), FALSE);
+        g_return_val_if_fail (fd != -1, FALSE);
+        g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+        g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+        klass = EV_DOCUMENT_GET_CLASS (document);
+        if (!klass->load_fd) {
+                g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                                     "Backend does not support loading from file descriptor");
+                close (fd);
+                return FALSE;
+        }
+
+       if (fstat(fd, &statbuf) == -1 ||
+           (fd_flags = fcntl (fd, F_GETFL, &flags)) == -1) {
+               int errsv = errno;
+               g_set_error_literal(error, G_FILE_ERROR,
+                                   g_file_error_from_errno(errsv),
+                                   g_strerror(errsv));
+                close (fd);
+               return FALSE;
+       }
+
+       if (!S_ISREG(statbuf.st_mode)) {
+               g_set_error_literal(error, G_FILE_ERROR, G_FILE_ERROR_BADF,
+                                   "Not a regular file.");
+                close (fd);
+               return FALSE;
+       }
+
+       switch (fd_flags & O_ACCMODE) {
+       case O_RDONLY:
+       case O_RDWR:
+               break;
+       case O_WRONLY:
+       default:
+               g_set_error_literal(error, G_FILE_ERROR, G_FILE_ERROR_BADF,
+                                   "Not a readable file descriptor.");
+                close (fd);
+               return FALSE;
+       }
+
+        if (!klass->load_fd (document, fd, flags, cancellable, error))
+                return FALSE;
+
+       document->priv->info = _ev_document_get_info (document);
+       document->priv->n_pages = _ev_document_get_n_pages (document);
+
+        if (!(flags & EV_DOCUMENT_LOAD_FLAG_NO_CACHE))
+                ev_document_setup_cache (document);
+
+        return TRUE;
+}
+
 /**
  * ev_document_save:
  * @document: a #EvDocument
@@ -570,7 +659,7 @@ ev_document_load_gfile (EvDocument         *document,
  * @error: a #GError location to store an error, or %NULL
  *
  * Saves @document to @uri.
- * 
+ *
  * Returns: %TRUE on success, or %FALSE on error with @error filled in
  */
 gboolean
diff --git a/libdocument/ev-document.h b/libdocument/ev-document.h
index 6bce0ada8..d19543237 100644
--- a/libdocument/ev-document.h
+++ b/libdocument/ev-document.h
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
 /*
  *  Copyright (C) 2009 Carlos Garcia Campos
  *  Copyright (C) 2000-2003 Marco Pesenti Gritti
@@ -130,6 +129,11 @@ struct _EvDocumentClass
                                                     GError             **error);
        cairo_surface_t * (* get_thumbnail_surface) (EvDocument          *document,
                                                     EvRenderContext     *rc);
+        gboolean          (* load_fd)               (EvDocument          *document,
+                                                    int                  fd,
+                                                    EvDocumentLoadFlags  flags,
+                                                    GCancellable        *cancellable,
+                                                    GError             **error);
 };
 
 EV_PUBLIC
@@ -189,6 +193,12 @@ gboolean         ev_document_load_gfile           (EvDocument         *document,
                                                    GCancellable       *cancellable,
                                                    GError            **error);
 EV_PUBLIC
+gboolean         ev_document_load_fd              (EvDocument         *document,
+                                                   int                 fd,
+                                                   EvDocumentLoadFlags flags,
+                                                   GCancellable       *cancellable,
+                                                   GError            **error);
+EV_PUBLIC
 gboolean         ev_document_save                 (EvDocument      *document,
                                                   const char      *uri,
                                                   GError         **error);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]