server: handle pcre2 now returning -1 for "no match"
[rb-79.git] / preconditions.c
blob1ed0ec8c5a171adfb6ebad525f82447439ff8dc0
1 /*
2 * Copyright (c) 2017-2020, 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
33 try_get_all_lock_files(size_t num_boards)
35 for (size_t j = 0; j < num_boards; ++j) {
36 if (lock_acquire(j) < 0) {
37 return -1;
41 return 0;
44 /* Try and release all lock files, in order */
45 static int
46 try_drop_all_lock_files(size_t num_boards)
48 for (size_t j = 0; j < num_boards; ++j) {
49 lock_release(j);
52 return 0;
55 /* Make sure we can write to the directory where all the www files will be */
56 static int
57 try_write_work_dir(const char *work_dir)
59 int ret = -1;
61 /* First, the directories should be there */
62 if (mkdir(work_dir, 0755) < 0) {
63 if (errno != EEXIST) {
64 PERROR_MESSAGE("mkdir");
65 ERROR_MESSAGE("Cannot create directory %s", work_dir);
66 goto done;
70 ret = 0;
71 done:
73 return ret;
76 /* Make sure we can write to the directory where all the www files will be */
77 static int
78 try_write_www_dir(const struct board *boards, size_t boards_num, const
79 char *static_www_folder)
81 int ret = -1;
82 size_t len = 0;
83 char *path = 0;
84 FILE *f = 0;
86 /* First, the directories should be there */
87 for (size_t j = 0; j < boards_num; ++j) {
88 len = snprintf(0, 0, "%s/%s", static_www_folder,
89 boards[j].name);
91 if (len + 1 < len) {
92 ERROR_MESSAGE("overflow");
93 goto done;
96 if (!(path = malloc(len + 1))) {
97 PERROR_MESSAGE("malloc");
98 goto done;
101 sprintf(path, "%s/%s", static_www_folder, boards[j].name);
103 if (mkdir(path, 0755) < 0) {
104 if (errno != EEXIST) {
105 PERROR_MESSAGE("mkdir");
106 ERROR_MESSAGE("Cannot create directory %s",
107 path);
108 goto done;
112 free(path);
113 path = 0;
116 /* The /recent page */
117 len = snprintf(0, 0, "%s/recent", static_www_folder);
119 if (len + 1 < len) {
120 ERROR_MESSAGE("overflow");
121 goto done;
124 if (!(path = malloc(len + 1))) {
125 PERROR_MESSAGE("malloc");
126 goto done;
129 sprintf(path, "%s/recent", static_www_folder);
131 if (mkdir(path, 0755) < 0) {
132 if (errno != EEXIST) {
133 PERROR_MESSAGE("mkdir");
134 ERROR_MESSAGE("Cannot create directory %s", path);
135 goto done;
139 free(path);
140 path = 0;
142 /* Now, the src/ and res/ dirs should be there */
143 for (size_t j = 0; j < boards_num; ++j) {
144 len = snprintf(0, 0, "%s/%s/src", static_www_folder,
145 boards[j].name);
147 if (len + 1 < len) {
148 ERROR_MESSAGE("overflow");
149 goto done;
152 if (!(path = malloc(len + 1))) {
153 PERROR_MESSAGE("malloc");
154 goto done;
157 sprintf(path, "%s/%s/src", static_www_folder, boards[j].name);
159 if (mkdir(path, 0755) < 0) {
160 if (errno != EEXIST) {
161 PERROR_MESSAGE("mkdir");
162 ERROR_MESSAGE("Cannot create directory %s",
163 path);
164 goto done;
168 sprintf(path, "%s/%s/res", static_www_folder, boards[j].name);
170 if (mkdir(path, 0755) < 0) {
171 if (errno != EEXIST) {
172 PERROR_MESSAGE("mkdir");
173 ERROR_MESSAGE("Cannot create directory %s",
174 path);
175 goto done;
179 free(path);
180 path = 0;
183 /* Now, we need to be able to write there */
184 for (size_t j = 0; j < boards_num; ++j) {
185 f = 0;
186 len = snprintf(0, 0, "%s/%s/src/a", static_www_folder,
187 boards[j].name);
189 if (len + 1 < len) {
190 ERROR_MESSAGE("overflow");
191 goto done;
194 if (!(path = malloc(len + 1))) {
195 PERROR_MESSAGE("malloc");
196 goto done;
199 sprintf(path, "%s/%s/src/a", static_www_folder, boards[j].name);
201 if (!(f = fopen(path, "a"))) {
202 PERROR_MESSAGE("fopen");
203 ERROR_MESSAGE("Cannot create dummy file %s", path);
204 goto done;
207 if (fclose(f)) {
208 PERROR_MESSAGE("fclose");
209 ERROR_MESSAGE("Cannot close dummy file %s", path);
210 goto done;
213 unlink(path);
214 sprintf(path, "%s/%s/res/a", static_www_folder, boards[j].name);
216 if (!(f = fopen(path, "a"))) {
217 PERROR_MESSAGE("fopen");
218 ERROR_MESSAGE("Cannot create dummy file %s", path);
219 goto done;
222 if (fclose(f)) {
223 PERROR_MESSAGE("fclose");
224 ERROR_MESSAGE("Cannot close dummy file %s", path);
225 goto done;
228 unlink(path);
229 free(path);
230 path = 0;
233 len = snprintf(0, 0, "%s/recent/a", static_www_folder);
235 if (len + 1 < len) {
236 ERROR_MESSAGE("overflow");
237 goto done;
240 if (!(path = malloc(len + 1))) {
241 PERROR_MESSAGE("malloc");
242 goto done;
245 sprintf(path, "%s/recent/a", static_www_folder);
247 if (!(f = fopen(path, "a"))) {
248 PERROR_MESSAGE("fopen");
249 ERROR_MESSAGE("Cannot create dummy file %s", path);
250 goto done;
253 if (fclose(f)) {
254 PERROR_MESSAGE("fclose");
255 ERROR_MESSAGE("Cannot close dummy file %s", path);
256 goto done;
259 unlink(path);
260 ret = 0;
261 done:
262 free(path);
264 return ret;
268 * Returns < 0 in case something isn't set up right
270 * Preconditions:
272 * - conf is correctly set up.
274 * Postconditions (success):
276 * - The ZZZ_setup() functions in other files have all been called,
277 * and all returned successfully.
280 preconditions_check(const struct configuration *conf)
282 int ret = -1;
283 size_t j = 0;
284 uintmax_t max_size = (size_t) -1;
286 for (j = 0; j < conf->filetypes_num; ++j) {
287 const struct filetype *f = &conf->filetypes[j];
289 if (f->thumb_creation_command &&
290 f->static_thumbnail) {
291 ERROR_MESSAGE("Filetype for %s cannot have both "
292 "thumb_creation_command and static_thumbnail",
293 f->mime_type);
294 goto done;
297 if (!f->thumb_creation_command &&
298 !f->static_thumbnail) {
299 ERROR_MESSAGE("Filetype for %s must have one of "
300 "thumb_creation_command or static_thumbnail",
301 f->mime_type);
302 goto done;
306 for (j = 0; j < conf->boards_num; ++j) {
307 const struct board *b = &conf->boards[j];
309 if (!b->num_pages) {
310 ERROR_MESSAGE("Board /%s/'s num_pages must be positive",
311 b->name);
312 goto done;
315 if (!b->threads_per_page) {
316 ERROR_MESSAGE("Board /%s/'s threads_per_page must be "
317 "positive", b->name);
318 goto done;
321 if (b->num_pages * b->threads_per_page > max_size) {
322 ERROR_MESSAGE("Board /%s/'s threads cannot be "
323 "fit in memory", b->name);
324 goto done;
327 if (!strcmp(b->name, "recent")) {
328 ERROR_MESSAGE("The board name /recent/ is reserved");
329 goto done;
333 if (try_write_work_dir(conf->work_path) < 0) {
334 goto done;
337 if (setup_multipart() < 0) {
338 goto done;
341 if (setup_sanitize_comment(conf) < 0) {
342 goto done;
345 if (setup_sanitize_file(conf) < 0) {
346 goto done;
349 if (setup_tripcodes(conf) < 0) {
350 goto done;
353 if (setup_locks(conf) < 0) {
354 goto done;
357 if (setup_write_thread(conf) < 0) {
358 goto done;
361 if (try_get_all_lock_files(conf->boards_num) < 0) {
362 goto done;
365 /* Since we have the lock files now, we need not fear races */
366 if (setup_dbs(conf) < 0) {
367 goto done;
370 if (try_write_www_dir(conf->boards, conf->boards_num,
371 conf->static_www_folder) < 0) {
372 goto done;
375 ret = 0;
376 done:
378 if (try_drop_all_lock_files(conf->boards_num) < 0) {
379 ret = -1;
382 return ret;