summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/ntdb/open.c53
1 files changed, 30 insertions, 23 deletions
diff --git a/lib/ntdb/open.c b/lib/ntdb/open.c
index 28aff0a2ea..8dce4ce6f2 100644
--- a/lib/ntdb/open.c
+++ b/lib/ntdb/open.c
@@ -508,48 +508,55 @@ _PUBLIC_ struct ntdb_context *ntdb_open(const char *name, int ntdb_flags,
ntdb->file = find_file(st.st_dev, st.st_ino);
if (!ntdb->file) {
- int fd;
+ ecode = ntdb_new_file(ntdb);
+ if (ecode != NTDB_SUCCESS) {
+ goto fail;
+ }
- if ((fd = open(name, open_flags, mode)) == -1) {
+ /* Set this now, as ntdb_nest_lock examines it. */
+ ntdb->file->map_size = 0;
+
+ if ((ntdb->file->fd = open(name, open_flags, mode)) == -1) {
/* errno set by open(2) */
saved_errno = errno;
ntdb_logerr(ntdb, NTDB_ERR_IO, NTDB_LOG_ERROR,
"ntdb_open: could not open file %s: %s",
name, strerror(errno));
+
+ goto fail_errno;
+ }
+
+ /* ensure there is only one process initialising at once:
+ * do it immediately to reduce the create/openlock race. */
+ ecode = ntdb_lock_open(ntdb, openlock,
+ NTDB_LOCK_WAIT|NTDB_LOCK_NOCHECK);
+ if (ecode != NTDB_SUCCESS) {
+ saved_errno = errno;
goto fail_errno;
}
/* on exec, don't inherit the fd */
- v = fcntl(fd, F_GETFD, 0);
- fcntl(fd, F_SETFD, v | FD_CLOEXEC);
+ v = fcntl(ntdb->file->fd, F_GETFD, 0);
+ fcntl(ntdb->file->fd, F_SETFD, v | FD_CLOEXEC);
- if (fstat(fd, &st) == -1) {
+ if (fstat(ntdb->file->fd, &st) == -1) {
saved_errno = errno;
ntdb_logerr(ntdb, NTDB_ERR_IO, NTDB_LOG_ERROR,
"ntdb_open: could not stat open %s: %s",
name, strerror(errno));
- close(fd);
goto fail_errno;
}
- ecode = ntdb_new_file(ntdb);
- if (ecode != NTDB_SUCCESS) {
- close(fd);
- goto fail;
- }
-
- ntdb->file->fd = fd;
ntdb->file->device = st.st_dev;
ntdb->file->inode = st.st_ino;
- ntdb->file->map_ptr = NULL;
- ntdb->file->map_size = 0;
- }
-
- /* ensure there is only one process initialising at once */
- ecode = ntdb_lock_open(ntdb, openlock, NTDB_LOCK_WAIT|NTDB_LOCK_NOCHECK);
- if (ecode != NTDB_SUCCESS) {
- saved_errno = errno;
- goto fail_errno;
+ } else {
+ /* ensure there is only one process initialising at once */
+ ecode = ntdb_lock_open(ntdb, openlock,
+ NTDB_LOCK_WAIT|NTDB_LOCK_NOCHECK);
+ if (ecode != NTDB_SUCCESS) {
+ saved_errno = errno;
+ goto fail_errno;
+ }
}
/* call their open hook if they gave us one. */
@@ -696,7 +703,7 @@ fail_errno:
} else
ntdb_munmap(ntdb->file);
}
- if (close(ntdb->file->fd) != 0)
+ if (ntdb->file->fd != -1 && close(ntdb->file->fd) != 0)
ntdb_logerr(ntdb, NTDB_ERR_IO, NTDB_LOG_ERROR,
"ntdb_open: failed to close ntdb fd"
" on error: %s", strerror(errno));