userscript: make "No. 123" links smarter
[rb-79.git] / locks.c
blobfd7a44e57460aec873e82c5170de724f5226539d
1 /*
2 * Copyright (c) 2017, 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 <fcntl.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <sys/stat.h>
24 #include <time.h>
25 #include <unistd.h>
27 #include "macros.h"
28 #include "rb79.h"
30 static int *lock_table = 0;
31 static size_t lock_table_len = 0;
34 * Set up the lock files and make sure we can connect to them.
36 * Preconditions:
38 * - setup_locks() was not invoked more recently than clean_locks().
40 * Postconditions (success):
42 * - Any other function in this file may be safely called.
44 int setup_locks(const struct configuration *conf)
46 int ret = -1;
47 char *path = 0;
48 size_t len = 0;
50 if (lock_table) {
51 return 0;
54 if (!(lock_table = calloc(conf->boards_num, sizeof *lock_table))) {
55 PERROR_MESSAGE("malloc");
56 ERROR_MESSAGE("Cannot set up locks");
57 goto done;
60 for (size_t j = 0; j < conf->boards_num; ++j) {
61 lock_table[j] = -1;
64 for (size_t j = 0; j < conf->boards_num; ++j) {
65 len = snprintf(0, 0, "%s/lock_board_%s", conf->work_path,
66 conf->boards[j].name);
68 if (len + 1 < len) {
69 ERROR_MESSAGE("overflow");
70 goto done;
73 if (!(path = malloc(len + 1))) {
74 PERROR_MESSAGE("malloc");
75 goto done;
78 sprintf(path, "%s/lock_board_%s", conf->work_path,
79 conf->boards[j].name);
81 if (!(lock_table[j] = open(path, O_RDWR | O_CREAT, 0700))) {
82 PERROR_MESSAGE("open");
83 ERROR_MESSAGE("Cannot open or create lock file %s",
84 path);
85 goto done;
88 free(path);
89 path = 0;
92 ret = 0;
93 lock_table_len = conf->boards_num;
94 done:
95 free(path);
97 return ret;
101 * Get a lock for a board
103 * Preconditions:
105 * - board_idx represents a board.
107 * - The lock for board_idx is not held in this program.
109 * Postconditions (success):
111 * - The lock for board_idx is now held by this program.
113 int lock_acquire(size_t board_idx)
115 int ret = -1;
117 if (!lock_table ||
118 lock_table[board_idx] < 0) {
119 ERROR_MESSAGE("lock_table isn't set up yet");
120 goto done;
123 if (lockf(lock_table[board_idx], F_LOCK, 0) < 0) {
124 PERROR_MESSAGE("lockf");
125 ERROR_MESSAGE("Cannot lock board %zu", board_idx);
126 goto done;
129 ret = 0;
130 done:
132 return ret;
136 * Release a lock for a board
138 * Preconditions:
140 * - board_idx represents a board.
142 * - The lock for board_idx is held in this program.
144 * Postconditions (success):
146 * - The lock for board_idx is now not held by this program.
148 int lock_release(size_t board_idx)
150 if (!lock_table ||
151 lock_table[board_idx] < 0) {
152 return 0;
155 if (lockf(lock_table[board_idx], F_ULOCK, 0) < 0) {
156 PERROR_MESSAGE("lockf");
157 ERROR_MESSAGE("Cannot release lock for board %zu", board_idx);
159 return -1;
162 return 0;
166 * Clean up any memory from this file
168 * Postconditions (success):
170 * - Valgrind won't report any memory leaks from this file.
172 * - setup_locks() can be safely called again.
174 int clean_locks(void)
176 if (!lock_table) {
177 return 0;
180 for (size_t j = 0; j < lock_table_len; ++j) {
181 lock_release(j);
182 close(lock_table[j]);
185 free(lock_table);
186 lock_table = 0;
188 return 0;