diff options
Diffstat (limited to 'index_gmi.c')
-rw-r--r-- | index_gmi.c | 185 |
1 files changed, 185 insertions, 0 deletions
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 <sys/types.h> +#include <sys/stat.h> + +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <gemtext.h> + +#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; +} |