aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYaroslav de la Peña Smirnov <yps@yaroslavps.com>2021-11-09 20:47:16 +0300
committerYaroslav de la Peña Smirnov <yps@yaroslavps.com>2021-11-09 20:47:16 +0300
commite2a71b0366aa80a7cf131fdbde6012671493d364 (patch)
treea5a60dbb56043af72c600bff992b863b4f821ede
parentabbee959bf5c87a8b2ad0b2d55d9ddb955147892 (diff)
downloadrevela-e2a71b0366aa80a7cf131fdbde6012671493d364.tar.gz
revela-e2a71b0366aa80a7cf131fdbde6012671493d364.zip
Copy/sync static files
-rw-r--r--README.md1
-rw-r--r--include/fs.h13
-rw-r--r--src/fs.c88
-rw-r--r--src/site.c10
4 files changed, 109 insertions, 3 deletions
diff --git a/README.md b/README.md
index c5cb8d1..d0f1a8f 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,6 @@ DEBUG=1 make
## TODO:
-* Copy CSS and static files
* Fix template generation on outdated html files. Right now if, for example, a
new image was added, the templates for the next and prev images, and the album
are not updated accordingly.
diff --git a/include/fs.h b/include/fs.h
index 015214a..973d585 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -37,7 +37,18 @@ const char *delext(const char *restrict basename, char *restrict dest, size_t n)
*/
int file_is_uptodate(const char *path, const struct timespec *srcmtim);
-/* Sets access and modification times to the time passed */
+/*
+ * Sets access and modification times to the time passed.
+ */
void setdatetime(const char *path, const struct timespec *mtim);
+/*
+ * Copies file(s) truncating and overwritting the file(s) in the destination
+ * path if they exist and are not a directory, or creating them if they don't
+ * exist. If srcpath is a directory, copies all files within that directory
+ * recursively. Only copies the regular files that already exist if their
+ * timestamps do not match.
+ */
+bool filesync(const char *restrict srcpath, const char *restrict dstpath);
+
#endif
diff --git a/src/fs.c b/src/fs.c
index e4a6d7b..a1b5626 100644
--- a/src/fs.c
+++ b/src/fs.c
@@ -6,12 +6,19 @@
#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
+#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <limits.h>
+#include <dirent.h>
#include <string.h>
#include <strings.h>
#include <sys/stat.h>
+#ifdef __linux__
+#include <sys/sendfile.h>
+#endif
+
+#define BUFSIZE 8192
#define CONTENTDIR "content"
#define DEFAULTALBUM "unorganized"
@@ -142,3 +149,84 @@ setdatetime(const char *path, const struct timespec *mtim)
log_printl_errno(LOG_ERROR, "Warning: couldn't set times of %s", path);
}
}
+
+bool
+filesync(const char *restrict srcpath, const char *restrict dstpath)
+{
+ int fdsrc;
+ struct stat stsrc;
+
+ fdsrc = open(srcpath, O_RDONLY);
+ if (fdsrc < 0) return false;
+ if (fstat(fdsrc, &stsrc)) goto dir_error;
+
+ if (S_ISDIR(stsrc.st_mode)) {
+ if (mkdir(dstpath, 0755)) {
+ if (errno != EEXIST) goto dir_error;
+ if (stat(dstpath, &stsrc)) goto dir_error;
+ if (!S_ISDIR(stsrc.st_mode)){
+ errno = ENOTDIR;
+ goto dir_error;
+ }
+ }
+ DIR *dir = fdopendir(fdsrc);
+ if (dir == NULL) goto dir_error;
+ struct dirent *ent;
+ while ((ent = readdir(dir))) {
+ if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
+ continue;
+ }
+ char entsrc[PATH_MAX], entdst[PATH_MAX];
+ sprintf(entsrc, "%s/%s", srcpath, ent->d_name);
+ sprintf(entdst, "%s/%s", dstpath, ent->d_name);
+ if (filesync(entsrc, entdst)) {
+ closedir(dir);
+ goto dir_error;
+ }
+ }
+ closedir(dir);
+
+ goto dir_success;
+ }
+
+ int fddst, uptodate;
+ if ((uptodate = file_is_uptodate(dstpath, &stsrc.st_mtim)) > 0) {
+ goto dir_success;
+ } else if (uptodate < 0) {
+ goto dir_error;
+ }
+ fddst = open(dstpath, O_CREAT | O_WRONLY | O_TRUNC, 0644);
+ if (fddst < 0) goto dir_error;
+
+#ifdef __linux__
+ ssize_t nwrote = sendfile(fddst, fdsrc, NULL, stsrc.st_size);
+ if (nwrote != stsrc.st_size) goto copy_error;
+#else
+ char buf[BUFSIZE];
+ ssize_t nread;
+
+ while ((nread = read(fdsrc, buf, BUFSIZE)) > 0) {
+ ssize_t nwrote = write(fddst, buf, nread);
+ if (nread != nwrote) goto copy_error;
+ }
+ if (nread < 0) goto copy_error;
+#endif
+
+ struct timespec tms[] = {
+ { .tv_sec = stsrc.st_mtim.tv_sec, .tv_nsec = stsrc.st_mtim.tv_nsec },
+ { .tv_sec = stsrc.st_mtim.tv_sec, .tv_nsec = stsrc.st_mtim.tv_nsec },
+ };
+ futimens(fddst, tms);
+
+ log_printl(LOG_DETAIL, "Copied %s", srcpath);
+
+ close(fddst);
+dir_success:
+ close(fdsrc);
+ return true;
+copy_error:
+ close(fddst);
+dir_error:
+ close(fdsrc);
+ return false;
+}
diff --git a/src/site.c b/src/site.c
index e96c52c..5fa40c4 100644
--- a/src/site.c
+++ b/src/site.c
@@ -197,8 +197,16 @@ bool
site_build(struct site *site)
{
struct stat dstat;
+ char staticp[PATH_MAX];
+
if (!nmkdir(site->output_dir, &dstat, false)) return false;
+ joinpathb(staticp, site->root_dir, STATICDIR);
+ if (!filesync(staticp, site->output_dir) && errno != ENOENT) {
+ log_printl_errno(LOG_FATAL, "Can't copy static files");
+ return false;
+ }
+
if (chdir(site->output_dir)) {
log_printl_errno(LOG_FATAL, "Can't change to directory %s",
site->output_dir);
@@ -210,7 +218,7 @@ site_build(struct site *site)
if (!bstree_inorder_walk(site->albums->root, albums_walk, (void *)site)) {
return false;
}
- /* TODO: static files and css */
+
chdir(site->root_dir);
return true;
}