From 50fb3adf7a670c1a711d15805b6957da45d3725f Mon Sep 17 00:00:00 2001
From: Maxime Bizon <mbizon@freebox.fr>
Date: Mon, 30 Sep 2024 17:10:37 +0200
Subject: [PATCH] libexif: add support to read exif data from fd

---
 libexif/exif-data.c   | 14 ++++++++++++++
 libexif/exif-data.h   |  8 ++++++++
 libexif/exif-loader.c | 19 +++++++++++++++++++
 libexif/exif-loader.h |  8 ++++++++
 libexif/libexif.sym   |  2 ++
 5 files changed, 51 insertions(+)

diff --git a/libexif/exif-data.c b/libexif/exif-data.c
index 023aaaa..7399478 100644
--- a/libexif/exif-data.c
+++ b/libexif/exif-data.c
@@ -1085,6 +1085,20 @@ exif_data_new_from_file (const char *path)
 	return (edata);
 }
 
+ExifData *
+exif_data_new_from_fd (int fd)
+{
+	ExifData *edata;
+	ExifLoader *loader;
+
+	loader = exif_loader_new ();
+	exif_loader_write_fd (loader, fd);
+	edata = exif_loader_get_data (loader);
+	exif_loader_unref (loader);
+
+	return (edata);
+}
+
 void
 exif_data_ref (ExifData *data)
 {
diff --git a/libexif/exif-data.h b/libexif/exif-data.h
index c60371c..c53bcaa 100644
--- a/libexif/exif-data.h
+++ b/libexif/exif-data.h
@@ -83,6 +83,14 @@ ExifData *exif_data_new_mem       (ExifMem *);
  */
 ExifData *exif_data_new_from_file (const char *path);
 
+/*! Allocate a new #ExifData and load EXIF data from a JPEG file.
+ * Uses an #ExifLoader internally to do the loading.
+ *
+ * \param[in] fd file description
+ * \return allocated #ExifData, or NULL on error
+ */
+ExifData *exif_data_new_from_fd (int fd);
+
 /*! Allocate a new #ExifData and load EXIF data from a memory buffer.
  *
  * \param[in] data pointer to raw JPEG or EXIF data
diff --git a/libexif/exif-loader.c b/libexif/exif-loader.c
index ad4ae96..7256ee5 100644
--- a/libexif/exif-loader.c
+++ b/libexif/exif-loader.c
@@ -28,6 +28,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
+#include <unistd.h>
 
 #undef JPEG_MARKER_DCT
 #define JPEG_MARKER_DCT  0xc0
@@ -139,6 +140,24 @@ exif_loader_write_file (ExifLoader *l, const char *path)
 	fclose (f);
 }
 
+void
+exif_loader_write_fd (ExifLoader *l, int fd)
+{
+	ssize_t size;
+	unsigned char data[1024];
+
+	if (!l || fd < 0)
+		return;
+
+	while (1) {
+		size = read (fd, data, sizeof (data));
+		if (size <= 0)
+			break;
+		if (!exif_loader_write (l, data, size))
+			break;
+      }
+}
+
 static unsigned int
 exif_loader_copy (ExifLoader *eld, unsigned char *buf, unsigned int len)
 {
diff --git a/libexif/exif-loader.h b/libexif/exif-loader.h
index 581a925..a20a65a 100644
--- a/libexif/exif-loader.h
+++ b/libexif/exif-loader.h
@@ -68,6 +68,14 @@ void        exif_loader_unref   (ExifLoader *loader);
  */
 void        exif_loader_write_file (ExifLoader *loader, const char *fname);
 
+/*! Load a file into the given #ExifLoader from the file descriptor.
+ * The relevant data is copied in raw form into the #ExifLoader.
+ *
+ * \param[in] loader loader to write to
+ * \param[in] fd file descriptor
+ */
+void        exif_loader_write_fd (ExifLoader *loader, int fd);
+
 /*! Load a buffer into the #ExifLoader from a memory buffer.
  * The relevant data is copied in raw form into the #ExifLoader.
  *
diff --git a/libexif/libexif.sym b/libexif/libexif.sym
index f1d77cf..b94dbe9 100644
--- a/libexif/libexif.sym
+++ b/libexif/libexif.sym
@@ -26,6 +26,7 @@ exif_data_log
 exif_data_new
 exif_data_new_from_data
 exif_data_new_from_file
+exif_data_new_from_fd
 exif_data_new_mem
 exif_data_option_get_description
 exif_data_option_get_name
@@ -62,6 +63,7 @@ exif_loader_ref
 exif_loader_reset
 exif_loader_unref
 exif_loader_write
+exif_loader_write_fd
 exif_loader_write_file
 exif_log
 exif_log_code_get_message
-- 
2.34.1

