misc: update copyright years
[rb-79.git] / preconditions.c
blobfbd1779d736dec1d05d118152674d82ee2170a93
1 /*
2 * Copyright (c) 2017-2018, De Rais <derais@cock.li>
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
18 #include <errno.h>
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <time.h>
26 #include <unistd.h>
28 #include "macros.h"
29 #include "rb79.h"
31 /* Try and acquire all lock files, in order */
32 static int try_get_all_lock_files(size_t num_boards)
34 for (size_t j = 0; j < num_boards; ++j) {
35 if (lock_acquire(j) < 0) {
36 return -1;
40 return 0;
43 /* Try and release all lock files, in order */
44 static int try_drop_all_lock_files(size_t num_boards)
46 for (size_t j = 0; j < num_boards; ++j) {
47 lock_release(j);
50 return 0;
53 /* Make sure we can write to the directory where all the www files will be */
54 static int try_write_work_dir(const char *work_dir)
56 int ret = -1;
58 /* First, the directories should be there */
59 if (mkdir(work_dir, 0755) < 0) {
60 if (errno != EEXIST) {
61 PERROR_MESSAGE("mkdir");
62 ERROR_MESSAGE("Cannot create directory %s", work_dir);
63 goto done;
67 ret = 0;
68 done:
70 return ret;
73 /* Make sure we can write to the directory where all the www files will be */
74 static int try_write_www_dir(const struct board *boards, size_t boards_num,
75 const char *static_www_folder)
77 int ret = -1;
78 size_t len = 0;
79 char *path = 0;
80 FILE *f = 0;
82 /* First, the directories should be there */
83 for (size_t j = 0; j < boards_num; ++j) {
84 len = snprintf(0, 0, "%s/%s", static_www_folder,
85 boards[j].name);
87 if (len + 1 < len) {
88 ERROR_MESSAGE("overflow");
89 goto done;
92 if (!(path = malloc(len + 1))) {
93 PERROR_MESSAGE("malloc");
94 goto done;
97 sprintf(path, "%s/%s", static_www_folder, boards[j].name);
99 if (mkdir(path, 0755) < 0) {
100 if (errno != EEXIST) {
101 PERROR_MESSAGE("mkdir");
102 ERROR_MESSAGE("Cannot create directory %s",
103 path);
104 goto done;
108 free(path);
109 path = 0;
112 /* The /recent page */
113 len = snprintf(0, 0, "%s/recent", static_www_folder);
115 if (len + 1 < len) {
116 ERROR_MESSAGE("overflow");
117 goto done;
120 if (!(path = malloc(len + 1))) {
121 PERROR_MESSAGE("malloc");
122 goto done;
125 sprintf(path, "%s/recent", static_www_folder);
127 if (mkdir(path, 0755) < 0) {
128 if (errno != EEXIST) {
129 PERROR_MESSAGE("mkdir");
130 ERROR_MESSAGE("Cannot create directory %s", path);
131 goto done;
135 free(path);
136 path = 0;
138 /* Now, the src/ and res/ dirs should be there */
139 for (size_t j = 0; j < boards_num; ++j) {
140 len = snprintf(0, 0, "%s/%s/src", static_www_folder,
141 boards[j].name);
143 if (len + 1 < len) {
144 ERROR_MESSAGE("overflow");
145 goto done;
148 if (!(path = malloc(len + 1))) {
149 PERROR_MESSAGE("malloc");
150 goto done;
153 sprintf(path, "%s/%s/src", static_www_folder, boards[j].name);
155 if (mkdir(path, 0755) < 0) {
156 if (errno != EEXIST) {
157 PERROR_MESSAGE("mkdir");
158 ERROR_MESSAGE("Cannot create directory %s",
159 path);
160 goto done;
164 sprintf(path, "%s/%s/res", static_www_folder, boards[j].name);
166 if (mkdir(path, 0755) < 0) {
167 if (errno != EEXIST) {
168 PERROR_MESSAGE("mkdir");
169 ERROR_MESSAGE("Cannot create directory %s",
170 path);
171 goto done;
175 free(path);
176 path = 0;
179 /* Now, we need to be able to write there */
180 for (size_t j = 0; j < boards_num; ++j) {
181 f = 0;
182 len = snprintf(0, 0, "%s/%s/src/a", static_www_folder,
183 boards[j].name);
185 if (len + 1 < len) {
186 ERROR_MESSAGE("overflow");
187 goto done;
190 if (!(path = malloc(len + 1))) {
191 PERROR_MESSAGE("malloc");
192 goto done;
195 sprintf(path, "%s/%s/src/a", static_www_folder, boards[j].name);
197 if (!(f = fopen(path, "a"))) {
198 PERROR_MESSAGE("fopen");
199 ERROR_MESSAGE("Cannot create dummy file %s", path);
200 goto done;
203 if (fclose(f)) {
204 PERROR_MESSAGE("fclose");
205 ERROR_MESSAGE("Cannot close dummy file %s", path);
206 goto done;
209 unlink(path);
210 sprintf(path, "%s/%s/res/a", static_www_folder, boards[j].name);
212 if (!(f = fopen(path, "a"))) {
213 PERROR_MESSAGE("fopen");
214 ERROR_MESSAGE("Cannot create dummy file %s", path);
215 goto done;
218 if (fclose(f)) {
219 PERROR_MESSAGE("fclose");
220 ERROR_MESSAGE("Cannot close dummy file %s", path);
221 goto done;
224 unlink(path);
225 free(path);
226 path = 0;
229 len = snprintf(0, 0, "%s/recent/a", static_www_folder);
231 if (len + 1 < len) {
232 ERROR_MESSAGE("overflow");
233 goto done;
236 if (!(path = malloc(len + 1))) {
237 PERROR_MESSAGE("malloc");
238 goto done;
241 sprintf(path, "%s/recent/a", static_www_folder);
243 if (!(f = fopen(path, "a"))) {
244 PERROR_MESSAGE("fopen");
245 ERROR_MESSAGE("Cannot create dummy file %s", path);
246 goto done;
249 if (fclose(f)) {
250 PERROR_MESSAGE("fclose");
251 ERROR_MESSAGE("Cannot close dummy file %s", path);
252 goto done;
255 unlink(path);
256 ret = 0;
257 done:
258 free(path);
260 return ret;
264 * Returns < 0 in case something isn't set up right
266 * Preconditions:
268 * - conf is correctly set up.
270 * Postconditions (success):
272 * - The ZZZ_setup() functions in other files have all been called,
273 * and all returned successfully.
275 int preconditions_check(const struct configuration *conf)
277 int ret = -1;
278 size_t j = 0;
279 uintmax_t max_size = (size_t) -1;
281 for (j = 0; j < conf->filetypes_num; ++j) {
282 const struct filetype *f = &conf->filetypes[j];
284 if (f->thumb_creation_command &&
285 f->static_thumbnail) {
286 ERROR_MESSAGE("Filetype for %s cannot have both "
287 "thumb_creation_command and static_thumbnail",
288 f->mime_type);
289 goto done;
292 if (!f->thumb_creation_command &&
293 !f->static_thumbnail) {
294 ERROR_MESSAGE("Filetype for %s must have one of "
295 "thumb_creation_command or static_thumbnail",
296 f->mime_type);
297 goto done;
301 for (j = 0; j < conf->boards_num; ++j) {
302 const struct board *b = &conf->boards[j];
304 if (!b->num_pages) {
305 ERROR_MESSAGE("Board /%s/'s num_pages must be positive",
306 b->name);
307 goto done;
310 if (!b->threads_per_page) {
311 ERROR_MESSAGE("Board /%s/'s threads_per_page must be "
312 "positive", b->name);
313 goto done;
316 if (b->num_pages * b->threads_per_page > max_size) {
317 ERROR_MESSAGE("Board /%s/'s threads cannot be "
318 "fit in memory", b->name);
319 goto done;
322 if (!strcmp(b->name, "recent")) {
323 ERROR_MESSAGE("The board name /recent/ is reserved");
324 goto done;
328 if (try_write_work_dir(conf->work_path) < 0) {
329 goto done;
332 if (setup_multipart() < 0) {
333 goto done;
336 if (setup_sanitize_comment(conf) < 0) {
337 goto done;
340 if (setup_sanitize_file(conf) < 0) {
341 goto done;
344 if (setup_tripcodes(conf) < 0) {
345 goto done;
348 if (setup_locks(conf) < 0) {
349 goto done;
352 if (setup_write_thread(conf) < 0) {
353 goto done;
356 if (try_get_all_lock_files(conf->boards_num) < 0) {
357 goto done;
360 /* Since we have the lock files now, we need not fear races */
361 if (setup_dbs(conf) < 0) {
362 goto done;
365 if (try_write_www_dir(conf->boards, conf->boards_num,
366 conf->static_www_folder) < 0) {
367 goto done;
370 ret = 0;
371 done:
373 if (try_drop_all_lock_files(conf->boards_num) < 0) {
374 ret = -1;
377 return ret;