checks if the SCB file exists, creates a new one in case it doesn't. */
| 187 | |
| 188 | /* checks if the SCB file exists, creates a new one in case it doesn't. */ |
| 189 | static void maybe_create_new_scb(struct plugin *p, |
| 190 | struct modern_scb_chan **channels) |
| 191 | { |
| 192 | |
| 193 | /* Note that this is opened for write-only, even though the permissions |
| 194 | * are set to read-only. That's perfectly valid! */ |
| 195 | int fd = open(FILENAME, O_CREAT|O_EXCL|O_WRONLY, 0400); |
| 196 | if (fd < 0) { |
| 197 | /* Don't do anything if the file already exists. */ |
| 198 | if (errno == EEXIST) |
| 199 | return; |
| 200 | plugin_err(p, "creating: %s", strerror(errno)); |
| 201 | } |
| 202 | |
| 203 | /* Comes here only if the file haven't existed before */ |
| 204 | unlink_noerr(FILENAME); |
| 205 | |
| 206 | /* This couldn't give EEXIST because we call unlink_noerr("scb.tmp") |
| 207 | * in INIT */ |
| 208 | fd = open("scb.tmp", O_CREAT|O_EXCL|O_WRONLY, 0400); |
| 209 | if (fd < 0) |
| 210 | plugin_err(p, "Opening: %s", strerror(errno)); |
| 211 | |
| 212 | plugin_log(p, LOG_INFORM, "Creating Emergency Recovery"); |
| 213 | |
| 214 | write_scb(p, fd, channels); |
| 215 | |
| 216 | /* fsync (mostly!) ensures that the file has reached the disk. */ |
| 217 | if (fsync(fd) != 0) { |
| 218 | unlink_noerr("scb.tmp"); |
| 219 | plugin_err(p, "fsync : %s", strerror(errno)); |
| 220 | } |
| 221 | |
| 222 | /* This should never fail if fsync succeeded. But paranoia good, and |
| 223 | * bugs exist. */ |
| 224 | if (close(fd) != 0) { |
| 225 | unlink_noerr("scb.tmp"); |
| 226 | plugin_err(p, "closing: %s", strerror(errno)); |
| 227 | } |
| 228 | |
| 229 | /* We actually need to sync the *directory itself* to make sure the |
| 230 | * file exists! You're only allowed to open directories read-only in |
| 231 | * modern Unix though. */ |
| 232 | fd = open(".", O_RDONLY); |
| 233 | if (fd < 0) |
| 234 | plugin_err(p, "Opening: %s", strerror(errno)); |
| 235 | |
| 236 | if (fsync(fd) != 0) { |
| 237 | unlink_noerr("scb.tmp"); |
| 238 | plugin_err(p, "closing: %s", strerror(errno)); |
| 239 | } |
| 240 | |
| 241 | /* This will never fail, if fsync worked! */ |
| 242 | close(fd); |
| 243 | |
| 244 | /* This will update the scb file */ |
| 245 | rename("scb.tmp", FILENAME); |
| 246 | } |
no test coverage detected