From b9b2ae68e26ef1b1b033d4231f8d7e53244cebff Mon Sep 17 00:00:00 2001 From: Ali Fardan Date: Wed, 4 Nov 2020 09:53:05 +0300 Subject: implement gemtext index generator --- .gitignore | 1 + Makefile | 2 +- gemlog.h | 3 + index_gmi.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 13 ++++- 5 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 index_gmi.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..34e3a08 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +blog diff --git a/Makefile b/Makefile index 100e062..9036784 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ OUT = gemlog PREFIX = /usr -OBJS = gemlog.o html.o free.o main.o strlcpy.o strlcat.o +OBJS = gemlog.o html.o index_gmi.o free.o main.o strlcpy.o strlcat.o MANPAGES = all: $(OUT) diff --git a/gemlog.h b/gemlog.h index e74058b..e9cefa0 100644 --- a/gemlog.h +++ b/gemlog.h @@ -20,6 +20,9 @@ struct gemlog_entry **gemlog_readdir(const char *); /* html.c */ int gemlog_write_html(struct gemlog_entry **, const char *); +/* index_gmi.c */ +int gemlog_write_index(struct gemlog_entry **, const char *); + /* free.c */ void gemlog_entry_free(struct gemlog_entry *); void gemlog_entry_list_free(struct gemlog_entry **); diff --git a/index_gmi.c b/index_gmi.c new file mode 100644 index 0000000..7f16a42 --- /dev/null +++ b/index_gmi.c @@ -0,0 +1,185 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "gemlog.h" + +static int +find_latest_year(struct gemlog_entry **feed) +{ + int i; + int ret; + + ret = 0; + for (i = 0; feed[i] != NULL; i++) { + if (feed[i]->date.tm_year > ret) + ret = feed[i]->date.tm_year; + } + return ret; +} + +static int +find_latest_month(struct gemlog_entry **feed, int year) +{ + int i; + int ret; + + ret = 0; + for (i = 0; feed[i] != NULL; i++) { + if (feed[i]->date.tm_year == year) { + if (feed[i]->date.tm_mon > ret) + ret = feed[i]->date.tm_mon; + } + } + return ret; +} + +static int +find_latest_day(struct gemlog_entry **feed, int year, int month) +{ + int i; + int ret; + + ret = 0; + for (i = 0; feed[i] != NULL; i++) { + if (feed[i]->date.tm_year == year && feed[i]->date.tm_mon == month) { + if (feed[i]->date.tm_mday > ret) + ret = feed[i]->date.tm_mday; + } + } + return ret; +} + +static int +find_latest_hour(struct gemlog_entry **feed, int year, int month, int day) +{ + int i; + int ret; + + ret = 0; + for (i = 0; feed[i] != NULL; i++) { + if (feed[i]->date.tm_year == year && feed[i]->date.tm_mon == month && feed[i]->date.tm_mday == day) { + if (feed[i]->date.tm_hour > ret) + ret = feed[i]->date.tm_hour; + } + } + return ret; +} + +static int +gemlog_write_index_hour(struct gemlog_entry **feed, int fd, int year, int month, int day, int hour) +{ + int i; + int labellen; + char *labelbuf; + char timestamp[11]; /* 1990-01-01\0 */ + char pathbuf[PATH_MAX+1]; + struct gemtext *out; + + labellen = 0; + + for (i = 0; feed[i] != NULL; i++) { + if (feed[i]->date.tm_year == year + && feed[i]->date.tm_mon == month + && feed[i]->date.tm_mday == day + && feed[i]->date.tm_hour == hour) { + strftime(timestamp, sizeof(timestamp), "%F", &(feed[i]->date)); + labellen += strlen(timestamp); + labellen += 2; /* ": " */ + labellen += strlen(feed[i]->title); + labelbuf = malloc(labellen+1); + if (labelbuf == NULL) + return -1; + strlcpy(labelbuf, timestamp, labellen+1); + strlcat(labelbuf, ": ", labellen+1); + strlcat(labelbuf, feed[i]->title, labellen+1); + snprintf(pathbuf, sizeof(pathbuf), "%d/%d/%d/%d/%s", year+1900, month+1, day, hour, GEMLOG_CONTENT_FILENAME); + out = gemtext_link_new(pathbuf, labelbuf); + free(labelbuf); + if (out == NULL) + return -1; + if (gemtext_encode_fd(out, fd) == -1) { + gemtext_free(out); + return -1; + } + gemtext_free(out); + if (write(fd, "\n", strlen("\n")) == -1) + return -1; + } + } + + return 0; +} + +static int +gemlog_write_index_day(struct gemlog_entry **feed, int fd, int year, int month, int day) +{ + int hour; + + for (hour = find_latest_hour(feed, year, month, day); hour != 0; hour--) { + if (gemlog_write_index_hour(feed, fd, year, month, day, hour) == -1) + return -1; + } + + return 0; +} + +static int +gemlog_write_index_month(struct gemlog_entry **feed, int fd, int year, int month) +{ + int day; + + for (day = find_latest_day(feed, year, month); day != 0; day--) { + if (gemlog_write_index_day(feed, fd, year, month, day) == -1) + return -1; + } + + return 0; +} + +static int +gemlog_write_index_year(struct gemlog_entry **feed, int fd, int year) +{ + int month; + + for (month = find_latest_month(feed, year); month != 0; month--) { + if (gemlog_write_index_month(feed, fd, year, month) == -1) + return -1; + } + + return 0; +} + +int +gemlog_write_index(struct gemlog_entry **feed, const char *path) +{ + int year; + int fd; + + fd = open(path, O_WRONLY|O_CREAT|O_TRUNC); + if (fd == -1) + return -1; + if (chmod(path, 0644) == -1) { + close(fd); + return -1; + } + + for (year = find_latest_year(feed); year != 0; year--) { + if (gemlog_write_index_year(feed, fd, year) == -1) { + close(fd); + return -1; + } + } + + close(fd); + return 0; +} diff --git a/main.c b/main.c index 713fcae..fd0c64a 100644 --- a/main.c +++ b/main.c @@ -25,12 +25,14 @@ main(int argc, char *argv[]) struct gemlog_entry **log; char *aflag; char *hflag; + char *iflag; int ch; aflag = NULL; hflag = NULL; + iflag = NULL; - while ((ch = getopt(argc, argv, "a:h:")) != -1) { + while ((ch = getopt(argc, argv, "a:h:i:")) != -1) { switch (ch) { case 'a': aflag = optarg; @@ -38,6 +40,9 @@ main(int argc, char *argv[]) case 'h': hflag = optarg; break; + case 'i': + iflag = optarg; + break; default: fprintf(stderr, "Usage: %s [-a file] [-h path] path\n", argv[0]); return 1; @@ -53,7 +58,7 @@ main(int argc, char *argv[]) if (log == NULL) err(1, "gemlog_readdir"); - if (!aflag && !hflag) + if (!aflag && !hflag && !iflag) _print_gemlog(log); // if (aflag) { @@ -64,6 +69,10 @@ main(int argc, char *argv[]) if (gemlog_write_html(log, hflag) == -1) err(1, "gemlog_write_html"); } + if (iflag) { + if (gemlog_write_index(log, iflag) == -1) + err(1, "gemlog_write_index"); + } gemlog_entry_list_free(log); return 0; -- cgit 1.4.1-2-gfad0