aboutsummaryrefslogtreecommitdiffstats
path: root/libskrift_open_font_fd.c
diff options
context:
space:
mode:
Diffstat (limited to 'libskrift_open_font_fd.c')
-rw-r--r--libskrift_open_font_fd.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/libskrift_open_font_fd.c b/libskrift_open_font_fd.c
new file mode 100644
index 0000000..c00422e
--- /dev/null
+++ b/libskrift_open_font_fd.c
@@ -0,0 +1,59 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+int
+libskrift_open_font_fd(LIBSKRIFT_FONT **fontp, int fd)
+{
+ int saved_errno;
+ struct stat st;
+ char *mem = NULL, *new;
+ size_t size = 0, off = 0;
+ int mmapped = 0;
+ ssize_t r;
+
+ saved_errno = errno;
+ if (fstat(fd, &st) < 0 || !st.st_size || !S_ISREG(st.st_mode)) {
+ for (;;) {
+ if (off + 2048 > size) {
+ size += 8192;
+ new = realloc(mem, size);
+ if (!new) {
+ free(mem);
+ return -1;
+ }
+ mem = new;
+ }
+ r = read(fd, &mem[off], size - off);
+ if (r <= 0) {
+ if (!r)
+ break;
+ free(mem);
+ return -1;
+ }
+ off += (size_t)r;
+ }
+ size = off;
+ new = realloc(mem, size);
+ if (new)
+ mem = new;
+ errno = saved_errno;
+ } else {
+ mem = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ size = (size_t)st.st_size;
+ mmapped = 1;
+ }
+
+ if (libskrift_open_font_mem(fontp, mem, size)) {
+ if (mmapped)
+ munmap(mem, size);
+ else
+ free(mem);
+ return -1;
+ }
+
+ (*fontp)->memory_free = mmapped ? NULL : mem;
+ (*fontp)->memory_unmap = mmapped ? mem : NULL;
+ (*fontp)->memory_size = size;
+
+ return 0;
+}