diff options
Diffstat (limited to 'libskrift_open_font_fd.c')
-rw-r--r-- | libskrift_open_font_fd.c | 59 |
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; +} |