diff options
| author | Yaroslav de la Peña Smirnov <yps@yaroslavps.com> | 2021-11-09 20:47:16 +0300 | 
|---|---|---|
| committer | Yaroslav de la Peña Smirnov <yps@yaroslavps.com> | 2021-11-09 20:47:16 +0300 | 
| commit | e2a71b0366aa80a7cf131fdbde6012671493d364 (patch) | |
| tree | a5a60dbb56043af72c600bff992b863b4f821ede | |
| parent | abbee959bf5c87a8b2ad0b2d55d9ddb955147892 (diff) | |
| download | revela-e2a71b0366aa80a7cf131fdbde6012671493d364.tar.gz revela-e2a71b0366aa80a7cf131fdbde6012671493d364.zip | |
Copy/sync static files
| -rw-r--r-- | README.md | 1 | ||||
| -rw-r--r-- | include/fs.h | 13 | ||||
| -rw-r--r-- | src/fs.c | 88 | ||||
| -rw-r--r-- | src/site.c | 10 | 
4 files changed, 109 insertions, 3 deletions
| @@ -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 @@ -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; +} @@ -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;  } | 
