Items will only be overwritten if date > mtime.
[agg.git] / src / fs.c
blob7fae1acbb41978089140a1379ecaa7d8380c5218
1 /* agg - the news aggregator
2 * Copyright (C) 2011 Andreas Waidler <arandes@programmers.at>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 #define _XOPEN_SOURCE
17 #include <sys/time.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <assert.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <fcntl.h>
25 #include <time.h>
26 #include "config.h"
27 #include "bool.h"
28 #include "fail.h"
29 #include "fs.h"
31 char feed_title[TEXT_BUFFER_SIZE] = { 0 };
32 time_t feed_date = 0;
33 time_t feed_date_new = 0;
35 char item_title[TEXT_BUFFER_SIZE] = { 0 };
36 char item_link [TEXT_BUFFER_SIZE] = { 0 };
37 char item_desc [TEXT_BUFFER_SIZE] = { 0 };
38 time_t item_date = 0;
40 void fs_buffer(char* dest, const char* src, size_t size)
42 assert(dest);
43 assert(src);
44 assert(size);
46 strncpy(dest, src, size);
48 /* Destination is not null-terminated iff
49 * strlen(src) >= size. */
50 if (dest[size - 1] != '\0') {
51 dest[size - 4] = '.';
52 dest[size - 3] = '.';
53 dest[size - 2] = '.';
54 dest[size - 1] = '\0';
57 assert(strlen(dest) < size);
60 void sanitize(char* str)
62 char* evil;
63 while ((evil = strchr(str, '/'))) *evil = '\\';
66 void set_item_date(const char* date)
68 struct tm t;
70 assert(!item_date);
72 assert(strptime(date, "%a, %d %b %Y %T %z", &t));
73 item_date = mktime(&t);
74 assert(item_date != -1);
77 void set_item_link(const char* link)
79 assert(!item_link[0]);
80 fs_buffer(item_link, link, TEXT_BUFFER_SIZE);
83 void set_item_desc(const char* desc)
85 assert(!item_desc[0]);
86 fs_buffer(item_desc, desc, TEXT_BUFFER_SIZE);
89 void set_item_title(const char* title)
91 assert(!item_title[0]);
92 fs_buffer(item_title, title, TEXT_BUFFER_SIZE);
95 const char* get_item_title()
97 return item_title;
100 void feed_open(const char* title)
102 struct stat st;
104 if (feed_title[0]) {
105 /* Feed contained title twice. The
106 * directory may just have been created.
107 * Deletion may lead to loss of previous
108 * mtime. We don't care; that feed is
109 * fucked up anyways. */
110 chdir("..");
111 rmdir(feed_title);
112 fail(111);
115 fs_buffer(feed_title, title, TEXT_BUFFER_SIZE);
116 sanitize(feed_title);
118 if (!stat(feed_title, &st)) feed_date = st.st_mtime;
119 mkdir(feed_title, 0755);
120 assert(!chdir(feed_title));
125 void feed_flush()
127 struct timeval times[2];
128 times[0].tv_sec = feed_date_new;
129 times[0].tv_usec = 0;
130 times[1].tv_sec = feed_date_new;
131 times[1].tv_usec = 0;
133 if (!feed_title[0]) return;
135 assert(!chdir(".."));
136 assert(!utimes(feed_title, times));
137 feed_title[0] = '\0';
141 void fs_set(const char* name, const char* value)
143 FILE* f;
145 assert(name);
146 assert(value);
148 /* Only write if attribute has a value. */
149 if (value[0]) {
150 assert(f = fopen(name, "w"));
151 fprintf(f, "%s", value);
152 fclose(f);
156 void item_flush()
158 struct timeval times[2];
159 struct stat st;
160 char buf[FILE_NAME_LENGTH + 1] = { 0 };
161 const char* name_src;
162 assert(feed_title[0]);
164 /* snip: from set_item_date */
165 /* assert(item_title[0]); */
166 /*if (item_date > 0 && item_date <= feed_date) {
167 printf("No new feeds assumed.\n");
168 fail(0);
169 } else */if (item_date > feed_date_new) {
170 feed_date_new = item_date;
172 /* snap */
174 if (item_date == 0 || item_date > feed_date) {
175 name_src = item_title[0] ? item_title : item_desc;
176 assert(name_src[0]);
177 fs_buffer(buf, name_src, FILE_NAME_LENGTH + 1);
178 sanitize(buf);
180 if (mkdir(buf, 0755)) {
181 assert(errno == EEXIST);
183 stat(buf, &st);
184 if (st.st_mtime >= item_date) return;
187 assert(chdir(buf) == 0);
188 fs_set("title", item_title);
189 fs_set("desc", item_desc);
190 fs_set("link", item_link);
191 assert(chdir("..") == 0);
193 /* FIXME: item date might not have been set. */
195 times[0].tv_sec = item_date;
196 times[0].tv_usec = 0;
197 times[1].tv_sec = item_date;
198 times[1].tv_usec = 0;
200 assert(!utimes(buf, times));
203 item_title[0] = 0;
204 item_desc[0] = 0;
205 item_link[0] = 0;
206 item_date = 0;