Welcome to little lamb

Code » qmdoc » commit 38aa9d1

Switch read/write CSS files to skalibs..

author Olivier Brunel
2022-12-26 15:26:25 UTC
committer Olivier Brunel
2022-12-26 15:26:25 UTC
parent a137a251ce0d53ad92a9a967ea12436d781402fe

Switch read/write CSS files to skalibs..

..which required to add some openat function lacking in skalibs. This
won't stay like this, but for now let's just cram all that in here.

Makefile +4 -0
djbunix2.h +15 -0
main.c +27 -75
openat3.c +11 -0
openat4.c +11 -0
openat_append.c +8 -0
openat_create.c +8 -0
openat_excl.c +8 -0
openat_read.c +8 -0
openat_readb.c +15 -0
openat_trunc.c +8 -0
openat_write.c +8 -0
openatb_read.c +8 -0

diff --git a/Makefile b/Makefile
index c83bc74..d970d9e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,8 @@
 SRCS = main.c output.c md4c.c
+
+SRCS += openat3.c openat4.c openat_append.c openatb_read.c openat_create.c \
+		openat_excl.c openat_readb.c openat_read.c openat_trunc.c openat_write.c
+
 OBJS = $(SRCS:.c=.o)
 DEPS = $(SRCS:.c=.d)
 
diff --git a/djbunix2.h b/djbunix2.h
new file mode 100644
index 0000000..9c38ab3
--- /dev/null
+++ b/djbunix2.h
@@ -0,0 +1,15 @@
+#ifndef DJBUNIX2_H
+#define DJBUNIX2_H
+
+int openat3(int fd, const char *file, unsigned int flags);
+int openat4(int fd, const char *file, unsigned int flags, unsigned int mode);
+int openat_read(int fd, const char *file);
+int openatb_read(int fd, const char *file);
+int openat_readb(int fd, const char *file);
+int openat_excl(int fd, const char *file);
+int openat_append(int fd, const char *file);
+int openat_create(int fd, const char *file);
+int openat_trunc(int fd, const char *file);
+int openat_write(int fd, const char *file);
+
+#endif /* DJBUNIX2_H */
diff --git a/main.c b/main.c
index c59bab1..6523780 100644
--- a/main.c
+++ b/main.c
@@ -10,9 +10,11 @@
 #include <errno.h>
 #include <skalibs/strerr2.h>
 #include <skalibs/buffer.h>
+#include <skalibs/djbunix.h>
 #include <err.h>
 #include "qmdoc.h"
 #include "output.h"
+#include "djbunix2.h"
 #include "md4c.h"
 
 const char *PROG = "qmdoc";
@@ -40,7 +42,7 @@ enum {
 };
 static struct css {
     const char *file;
-    char *buf;
+    off_t offset;
 } css[NB_CSS] = {
     { "struct.css" },
     { "common.css" },
@@ -56,6 +58,7 @@ struct page {
 struct ctx {
     int options;
     FILE *out;
+    stralloc sa_css;
     struct css *css;
     struct page *pages;
     int nb_pages;
@@ -191,7 +194,7 @@ enter_block(MD_BLOCKTYPE type, void *details, void *ctx_)
                 if (ctx->options & OPT_INLINE_CSS) {
                     for (int i = 0; i < NB_CSS; ++i) {
                         if (raw_str(f, "<style>") < 0
-                                || raw_str(f, ctx->css[i].buf) < 0
+                                || raw_str(f, ctx->sa_css.s + ctx->css[i].offset) < 0
                                 || raw_str(f, "</style>") < 0)
                             return ERR_IO;
                     }
@@ -633,67 +636,6 @@ convert_file(const char *file, struct ctx *ctx)
     return 0;
 }
 
-static int
-load_file(const char *file, char **dst)
-{
-    int fd = open(file, O_RDONLY | O_CLOEXEC | O_NONBLOCK);
-    if (fd < 0) ret(ERR_IO, "cannot open '%s'", file);
-
-    struct stat st;
-    if (fstat(fd, &st) < 0) {
-        warn("cannot stat '%s'", file);
-        close(fd);
-        return ERR_IO;
-    }
-
-    FILE *f = fdopen(fd, "re");
-    if (!f) {
-        warn("cannot open '%s'", file);
-        close(fd);
-        return ERR_IO;
-    }
-
-    *dst = malloc(st.st_size + 1);
-    if (!*dst) {
-        warn("cannot load '%s'", file);
-        fclose(f);
-        return ERR_MEM;
-    }
-
-    if (fread(*dst, 1, st.st_size, f) != st.st_size) {
-        free(*dst);
-        fclose(f);
-        retx(ERR_IO, "cannot read '%s'", file);
-    }
-    (*dst)[st.st_size] = 0;
-
-    fclose(f);
-    return 0;
-}
-
-static int
-write_file(int fdp, const char *path, const char *file, const char *data)
-{
-    int fd = openat(fdp, file, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC | O_NONBLOCK, 0644);
-    if (fd < 0) ret(ERR_IO, "cannot create '%s/%s'", path, file);
-
-    FILE *f = fdopen(fd, "w");
-    if (!f) {
-        warn("cannot open '%s/%s'", path, file);
-        close(fd);
-        return ERR_IO;
-    }
-
-    size_t dlen = strlen(data);
-    if (fwrite(data, 1, dlen, f) != dlen) {
-        fclose(f);
-        retx(ERR_IO, "cannot write '%s/%s'", path, file);
-    }
-
-    fclose(f);
-    return 0;
-}
-
 static int
 load_page_from_file(const char *file, struct page *page)
 {
@@ -822,26 +764,36 @@ main (int argc, char *argv[])
         }
     }
 
+    struct ctx ctx = {
+        .options = options,
+        .sa_css = STRALLOC_ZERO,
+        .css = css,
+        .pages = pages,
+        .nb_pages = sizeof(pages) / sizeof(*pages),
+    };
+
     if (!(options & OPT_NO_CSS)) {
         outs((options & OPT_INLINE_CSS) ? "Loading" : "Copying");
         outse(" CSS files...");
         for (int i = 0; i < NB_CSS; ++i) {
-            r = load_file(css[i].file, &css[i].buf);
-            if (r < 0) return -r;
-            if (!(options & OPT_INLINE_CSS)) {
-                r = write_file(fddest, destdir, css[i].file, css[i].buf);
-                if (r < 0) return -r;
+            if ((options & OPT_INLINE_CSS)) {
+                css[i].offset = ctx.sa_css.len;
+                if (!openreadfileclose(css[i].file, &ctx.sa_css, 0))
+                    strerr_diefu3sys(ERR_IO, "load CSS from '", css[i].file, "'");
+            } else {
+                int from, to;
+                from = open_read(css[i].file);
+                if (from < 0) strerr_diefu3sys(ERR_IO, "open '", css[i].file, "'");
+                to = openat_excl(fddest, css[i].file);
+                if (to < 0) strerr_diefu5sys(ERR_IO, "create '", destdir, "/", css[i].file, "'");
+                if (fd_cat(from, to) < 0)
+                    strerr_diefu5sys(ERR_IO, "copy CSS to '", destdir, "/", css[i].file, "'");
+                fd_close(from);
+                fd_close(to);
             }
         }
     }
 
-    struct ctx ctx = {
-        .options = options,
-        .css = css,
-        .pages = pages,
-        .nb_pages = sizeof(pages) / sizeof(*pages),
-    };
-
     for (int i = optind; i < argc; ++i) {
         const char *sce = argv[i];
         size_t scelen = strlen(sce);
diff --git a/openat3.c b/openat3.c
new file mode 100644
index 0000000..d54b385
--- /dev/null
+++ b/openat3.c
@@ -0,0 +1,11 @@
+#include <fcntl.h>
+#include <errno.h>
+
+int
+openat3(int fd, const char *file, unsigned int flags)
+{
+    int r;
+    do r = openat(fd, file, flags);
+    while ((r < 0 && errno == EINTR));
+    return r;
+}
diff --git a/openat4.c b/openat4.c
new file mode 100644
index 0000000..61c5100
--- /dev/null
+++ b/openat4.c
@@ -0,0 +1,11 @@
+#include <fcntl.h>
+#include <errno.h>
+
+int
+openat4(int fd, const char *file, unsigned int flags, unsigned int mode)
+{
+    int r;
+    do r = openat(fd, file, flags, mode);
+    while ((r < 0 && errno == EINTR));
+    return r;
+}
diff --git a/openat_append.c b/openat_append.c
new file mode 100644
index 0000000..5ea9cab
--- /dev/null
+++ b/openat_append.c
@@ -0,0 +1,8 @@
+#include <fcntl.h>
+#include "djbunix2.h"
+
+int
+openat_append(int fd, const char *file)
+{
+    return openat4(fd, file, O_WRONLY | O_CREAT | O_APPEND | O_NONBLOCK, 0666);
+}
diff --git a/openat_create.c b/openat_create.c
new file mode 100644
index 0000000..09a75e1
--- /dev/null
+++ b/openat_create.c
@@ -0,0 +1,8 @@
+#include <fcntl.h>
+#include "djbunix2.h"
+
+int
+openat_create(int fd, const char *file)
+{
+    return openat4(fd, file, O_WRONLY | O_CREAT | O_NONBLOCK, 0666);
+}
diff --git a/openat_excl.c b/openat_excl.c
new file mode 100644
index 0000000..32ecfb5
--- /dev/null
+++ b/openat_excl.c
@@ -0,0 +1,8 @@
+#include <fcntl.h>
+#include "djbunix2.h"
+
+int
+openat_excl(int fd, const char *file)
+{
+    return openat4(fd, file, O_WRONLY | O_CREAT | O_EXCL | O_NONBLOCK, 0666);
+}
diff --git a/openat_read.c b/openat_read.c
new file mode 100644
index 0000000..528a38b
--- /dev/null
+++ b/openat_read.c
@@ -0,0 +1,8 @@
+#include <fcntl.h>
+#include "djbunix2.h"
+
+int
+openat_read(int fd, const char *file)
+{
+    return openat3(fd, file, O_RDONLY | O_NONBLOCK);
+}
diff --git a/openat_readb.c b/openat_readb.c
new file mode 100644
index 0000000..45539ea
--- /dev/null
+++ b/openat_readb.c
@@ -0,0 +1,15 @@
+#include <skalibs/djbunix.h>
+#include <fcntl.h>
+#include "djbunix2.h"
+
+int
+openat_readb(int fd, const char *file)
+{
+    int ffd = openat_read(fd, file);
+    if (ffd < 0) return -1;
+    if (ndelay_off(ffd) < 0) {
+        fd_close(ffd);
+        return -1;
+    }
+    return ffd;
+}
diff --git a/openat_trunc.c b/openat_trunc.c
new file mode 100644
index 0000000..8efc820
--- /dev/null
+++ b/openat_trunc.c
@@ -0,0 +1,8 @@
+#include <fcntl.h>
+#include "djbunix2.h"
+
+int
+openat_trunc(int fd, const char *file)
+{
+    return openat4(fd, file, O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, 0666);
+}
diff --git a/openat_write.c b/openat_write.c
new file mode 100644
index 0000000..df6ae80
--- /dev/null
+++ b/openat_write.c
@@ -0,0 +1,8 @@
+#include <fcntl.h>
+#include "djbunix2.h"
+
+int
+openat_write(int fd, const char *file)
+{
+    return openat3(fd, file, O_WRONLY | O_NONBLOCK);
+}
diff --git a/openatb_read.c b/openatb_read.c
new file mode 100644
index 0000000..ce8d5a5
--- /dev/null
+++ b/openatb_read.c
@@ -0,0 +1,8 @@
+#include <fcntl.h>
+#include "djbunix2.h"
+
+int
+openatb_read(int fd, const char *file)
+{
+    return openat3(fd, file, O_RDONLY);
+}