int mail_index_lock_fd(struct mail_index *index, const char *path, int fd, int lock_type, unsigned int timeout_secs, struct file_lock **lock_r) { if (fd == -1) { i_assert(MAIL_INDEX_IS_IN_MEMORY(index)); return 1; } return file_wait_lock(fd, path, lock_type, index->lock_method, timeout_secs, lock_r); }
static int squat_uidlist_lock(struct squat_uidlist *uidlist) { int ret; for (;;) { i_assert(uidlist->fd != -1); i_assert(uidlist->file_lock == NULL); i_assert(uidlist->dotlock == NULL); if (uidlist->trie->lock_method != FILE_LOCK_METHOD_DOTLOCK) { ret = file_wait_lock(uidlist->fd, uidlist->path, F_WRLCK, uidlist->trie->lock_method, SQUAT_TRIE_LOCK_TIMEOUT, &uidlist->file_lock); } else { ret = file_dotlock_create(&uidlist->trie->dotlock_set, uidlist->path, 0, &uidlist->dotlock); } if (ret == 0) { i_error("squat uidlist %s: Locking timed out", uidlist->path); return 0; } if (ret < 0) return -1; ret = squat_uidlist_is_file_stale(uidlist); if (ret == 0) break; if (uidlist->file_lock != NULL) file_unlock(&uidlist->file_lock); else file_dotlock_delete(&uidlist->dotlock); if (ret < 0) return -1; squat_uidlist_close(uidlist); uidlist->fd = squat_trie_create_fd(uidlist->trie, uidlist->path, 0); if (uidlist->fd == -1) return -1; } return 1; }
int file_try_lock(int fd, const char *path, int lock_type, enum file_lock_method lock_method, struct file_lock **lock_r) { return file_wait_lock(fd, path, lock_type, lock_method, 0, lock_r); }
static void ssl_params_if_unchanged(const char *path, time_t mtime, unsigned int ssl_dh_parameters_length ATTR_UNUSED) { const char *temp_path, *error; struct file_lock *lock; struct stat st, st2; mode_t old_mask; int fd, ret; buffer_t *buf; #ifdef HAVE_SETPRIORITY if (setpriority(PRIO_PROCESS, 0, SSL_PARAMS_PRIORITY) < 0) i_error("setpriority(%d) failed: %m", SSL_PARAMS_PRIORITY); #endif temp_path = t_strconcat(path, ".tmp", NULL); old_mask = umask(0); fd = open(temp_path, O_WRONLY | O_CREAT, 0644); umask(old_mask); if (fd == -1) i_fatal("creat(%s) failed: %m", temp_path); /* If multiple dovecot instances are running, only one of them needs to regenerate this file. */ ret = file_wait_lock(fd, temp_path, F_WRLCK, FILE_LOCK_METHOD_FCNTL, SSL_BUILD_PARAM_TIMEOUT_SECS, &lock); if (ret < 0) i_fatal("file_try_lock(%s) failed: %m", temp_path); if (ret == 0) { /* someone else is writing this */ i_fatal("Timeout while waiting for %s generation to complete", path); } /* make sure the .tmp file is still the one we created */ if (fstat(fd, &st) < 0) i_fatal("fstat(%s) failed: %m", temp_path); if (stat(temp_path, &st2) < 0) { if (errno != ENOENT) i_fatal("stat(%s) failed: %m", temp_path); st2.st_ino = st.st_ino+1; } if (st.st_ino != st2.st_ino) { /* nope. so someone else just generated the file. */ i_close_fd(&fd); return; } /* check that the parameters file is still the same */ if (stat(path, &st) == 0) { if (st.st_mtime != mtime) { i_close_fd(&fd); return; } } else if (errno != ENOENT) i_fatal("stat(%s) failed: %m", path); /* ok, we really want to generate it. */ if (ftruncate(fd, 0) < 0) i_fatal("ftruncate(%s) failed: %m", temp_path); i_info("Generating SSL parameters"); buf = buffer_create_dynamic(pool_datastack_create(), 1024); if (ssl_iostream_generate_params(buf, ssl_dh_parameters_length, &error) < 0) { i_fatal("ssl_iostream_generate_params(%u) failed: %s", ssl_dh_parameters_length, error); } if (write_full(fd, buf->data, buf->used) < 0) i_fatal("write(%s) failed: %m", temp_path); if (rename(temp_path, path) < 0) i_fatal("rename(%s, %s) failed: %m", temp_path, path); if (close(fd) < 0) i_fatal("close(%s) failed: %m", temp_path); file_lock_free(&lock); i_info("SSL parameters regeneration completed"); }