mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
common: Add an info callback to dotlock.
* common/dotlock.h (enum dotlock_reasons): New. (DOTLOCK_PREPARE_CREATE): New flag. * common/dotlock.c (struct dotlock_handle): Add info_cb and info_cb_value. (dotlock_create): Support the new flag. (dotlock_finish_create): New. (read_lockfile): Silence in case of ENOENT. (dotlock_set_info_cb): New. Use callback after all error and info messages. (dotlock_take_unix, dotlock_take_w32): Allow termination by callback.
This commit is contained in:
parent
f57717bf23
commit
937aeb1904
152
common/dotlock.c
152
common/dotlock.c
@ -396,6 +396,13 @@ struct dotlock_handle
|
|||||||
|
|
||||||
int extra_fd; /* A place for the caller to store an FD. */
|
int extra_fd; /* A place for the caller to store an FD. */
|
||||||
|
|
||||||
|
/* An optional info callback - see dotlock_set_info_cb. */
|
||||||
|
int (*info_cb)(dotlock_t, void *,
|
||||||
|
enum dotlock_reasons reason,
|
||||||
|
const char *,...);
|
||||||
|
void *info_cb_value;
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_DOSISH_SYSTEM
|
#ifdef HAVE_DOSISH_SYSTEM
|
||||||
HANDLE lockhd; /* The W32 handle of the lock file. */
|
HANDLE lockhd; /* The W32 handle of the lock file. */
|
||||||
#else /*!HAVE_DOSISH_SYSTEM */
|
#else /*!HAVE_DOSISH_SYSTEM */
|
||||||
@ -545,8 +552,15 @@ read_lockfile (dotlock_t h, int *same_node, int *r_fd)
|
|||||||
if ( (fd = open (h->lockname, O_RDONLY)) == -1 )
|
if ( (fd = open (h->lockname, O_RDONLY)) == -1 )
|
||||||
{
|
{
|
||||||
int e = errno;
|
int e = errno;
|
||||||
|
if (errno != ENOENT)
|
||||||
|
{
|
||||||
my_info_2 ("error opening lockfile '%s': %s\n",
|
my_info_2 ("error opening lockfile '%s': %s\n",
|
||||||
h->lockname, strerror(errno) );
|
h->lockname, strerror(errno) );
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
|
||||||
|
"error opening lockfile '%s': %s\n",
|
||||||
|
h->lockname, strerror (errno) );
|
||||||
|
}
|
||||||
if (buffer != buffer_space)
|
if (buffer != buffer_space)
|
||||||
xfree (buffer);
|
xfree (buffer);
|
||||||
my_set_errno (e); /* Need to return ERRNO here. */
|
my_set_errno (e); /* Need to return ERRNO here. */
|
||||||
@ -564,6 +578,10 @@ read_lockfile (dotlock_t h, int *same_node, int *r_fd)
|
|||||||
{
|
{
|
||||||
int e = errno;
|
int e = errno;
|
||||||
my_info_1 ("error reading lockfile '%s'\n", h->lockname );
|
my_info_1 ("error reading lockfile '%s'\n", h->lockname );
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
|
||||||
|
"error reading lockfile '%s': %s\n",
|
||||||
|
h->lockname, strerror (errno) );
|
||||||
close (fd);
|
close (fd);
|
||||||
if (buffer != buffer_space)
|
if (buffer != buffer_space)
|
||||||
xfree (buffer);
|
xfree (buffer);
|
||||||
@ -583,6 +601,9 @@ read_lockfile (dotlock_t h, int *same_node, int *r_fd)
|
|||||||
if (nread < 11)
|
if (nread < 11)
|
||||||
{
|
{
|
||||||
my_info_1 ("invalid size of lockfile '%s'\n", h->lockname);
|
my_info_1 ("invalid size of lockfile '%s'\n", h->lockname);
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_INV_FILE,
|
||||||
|
"invalid size of lockfile '%s'\n", h->lockname);
|
||||||
if (buffer != buffer_space)
|
if (buffer != buffer_space)
|
||||||
xfree (buffer);
|
xfree (buffer);
|
||||||
my_set_errno (EINVAL);
|
my_set_errno (EINVAL);
|
||||||
@ -594,6 +615,9 @@ read_lockfile (dotlock_t h, int *same_node, int *r_fd)
|
|||||||
|| !pid )
|
|| !pid )
|
||||||
{
|
{
|
||||||
my_error_2 ("invalid pid %d in lockfile '%s'\n", pid, h->lockname);
|
my_error_2 ("invalid pid %d in lockfile '%s'\n", pid, h->lockname);
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_INV_FILE,
|
||||||
|
"invalid pid %d in lockfile '%s'\n", pid, h->lockname);
|
||||||
if (buffer != buffer_space)
|
if (buffer != buffer_space)
|
||||||
xfree (buffer);
|
xfree (buffer);
|
||||||
my_set_errno (EINVAL);
|
my_set_errno (EINVAL);
|
||||||
@ -722,6 +746,10 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
|
|||||||
UNLOCK_all_lockfiles ();
|
UNLOCK_all_lockfiles ();
|
||||||
my_error_2 (_("failed to create temporary file '%s': %s\n"),
|
my_error_2 (_("failed to create temporary file '%s': %s\n"),
|
||||||
h->tname, strerror (errno));
|
h->tname, strerror (errno));
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_WAITING,
|
||||||
|
_("failed to create temporary file '%s': %s\n"),
|
||||||
|
h->tname, strerror (errno));
|
||||||
xfree (h->tname);
|
xfree (h->tname);
|
||||||
xfree (h);
|
xfree (h);
|
||||||
my_set_errno (saveerrno);
|
my_set_errno (saveerrno);
|
||||||
@ -755,6 +783,10 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
|
|||||||
int saveerrno = errno;
|
int saveerrno = errno;
|
||||||
my_error_2 ("can't check whether hardlinks are supported for '%s': %s\n"
|
my_error_2 ("can't check whether hardlinks are supported for '%s': %s\n"
|
||||||
, h->tname, strerror (saveerrno));
|
, h->tname, strerror (saveerrno));
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_CONFIG_TEST,
|
||||||
|
"can't check whether hardlinks are supported for '%s': %s\n"
|
||||||
|
, h->tname, strerror (saveerrno));
|
||||||
my_set_errno (saveerrno);
|
my_set_errno (saveerrno);
|
||||||
}
|
}
|
||||||
goto write_failed;
|
goto write_failed;
|
||||||
@ -783,6 +815,11 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
|
|||||||
all_lockfiles = h->next;
|
all_lockfiles = h->next;
|
||||||
UNLOCK_all_lockfiles ();
|
UNLOCK_all_lockfiles ();
|
||||||
my_error_2 (_("error writing to '%s': %s\n"), h->tname, strerror (errno));
|
my_error_2 (_("error writing to '%s': %s\n"), h->tname, strerror (errno));
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
|
||||||
|
_("error writing to '%s': %s\n"),
|
||||||
|
h->tname, strerror (errno));
|
||||||
|
|
||||||
if ( fd != -1 )
|
if ( fd != -1 )
|
||||||
close (fd);
|
close (fd);
|
||||||
unlink (h->tname);
|
unlink (h->tname);
|
||||||
@ -849,6 +886,10 @@ dotlock_create_w32 (dotlock_t h, const char *file_to_lock)
|
|||||||
all_lockfiles = h->next;
|
all_lockfiles = h->next;
|
||||||
UNLOCK_all_lockfiles ();
|
UNLOCK_all_lockfiles ();
|
||||||
my_error_2 (_("can't create '%s': %s\n"), h->lockname, w32_strerror (-1));
|
my_error_2 (_("can't create '%s': %s\n"), h->lockname, w32_strerror (-1));
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
|
||||||
|
_("can't create '%s': %s\n"),
|
||||||
|
h->lockname, w32_strerror (-1));
|
||||||
xfree (h->lockname);
|
xfree (h->lockname);
|
||||||
xfree (h);
|
xfree (h);
|
||||||
my_set_errno (saveerrno);
|
my_set_errno (saveerrno);
|
||||||
@ -873,7 +914,10 @@ dotlock_create_w32 (dotlock_t h, const char *file_to_lock)
|
|||||||
POSIX systems a temporary file ".#lk.<hostname>.pid[.threadid] is
|
POSIX systems a temporary file ".#lk.<hostname>.pid[.threadid] is
|
||||||
used.
|
used.
|
||||||
|
|
||||||
FLAGS must be 0.
|
The only defined FLAG bit is DOTLOCK_PREPARE_CREATE, which only
|
||||||
|
allocates the handle and requires a further call to
|
||||||
|
dotlock_finish_create. This can be used to set a callback between
|
||||||
|
these calls.
|
||||||
|
|
||||||
The function returns an new handle which needs to be released using
|
The function returns an new handle which needs to be released using
|
||||||
destroy_dotlock but gets also released at the termination of the
|
destroy_dotlock but gets also released at the termination of the
|
||||||
@ -895,7 +939,7 @@ dotlock_create (const char *file_to_lock, unsigned int flags)
|
|||||||
if ( !file_to_lock )
|
if ( !file_to_lock )
|
||||||
return NULL; /* Only initialization was requested. */
|
return NULL; /* Only initialization was requested. */
|
||||||
|
|
||||||
if (flags)
|
if ((flags & ~DOTLOCK_PREPARE_CREATE))
|
||||||
{
|
{
|
||||||
my_set_errno (EINVAL);
|
my_set_errno (EINVAL);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -916,6 +960,24 @@ dotlock_create (const char *file_to_lock, unsigned int flags)
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((flags & DOTLOCK_PREPARE_CREATE))
|
||||||
|
return h;
|
||||||
|
else
|
||||||
|
return dotlock_finish_create (h, file_to_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This function may be used along with dotlock_create (file_name,
|
||||||
|
* DOTLOCK_PREPARE_CREATE) to finish the creation call. The given
|
||||||
|
* filename shall be the same as passed to dotlock_create. On success
|
||||||
|
* the same handle H is returned, on error NULL is returned and H is
|
||||||
|
* released. */
|
||||||
|
dotlock_t
|
||||||
|
dotlock_finish_create (dotlock_t h, const char *file_to_lock)
|
||||||
|
{
|
||||||
|
if (!h || !file_to_lock)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
#ifdef HAVE_DOSISH_SYSTEM
|
#ifdef HAVE_DOSISH_SYSTEM
|
||||||
return dotlock_create_w32 (h, file_to_lock);
|
return dotlock_create_w32 (h, file_to_lock);
|
||||||
#else /*!HAVE_DOSISH_SYSTEM */
|
#else /*!HAVE_DOSISH_SYSTEM */
|
||||||
@ -942,6 +1004,24 @@ dotlock_get_fd (dotlock_t h)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Set a callback function for info diagnostics. The callback
|
||||||
|
* function CB is called with the handle, the opaque value OPAQUE, a
|
||||||
|
* reason code, and a format string with its arguments. The callback
|
||||||
|
* shall return 0 to continue operation or true in which case the
|
||||||
|
* current function will be terminated with an error. */
|
||||||
|
void
|
||||||
|
dotlock_set_info_cb (dotlock_t h,
|
||||||
|
int (*cb)(dotlock_t, void *,
|
||||||
|
enum dotlock_reasons reason,
|
||||||
|
const char *,...),
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
h->info_cb = cb;
|
||||||
|
h->info_cb_value = opaque;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_POSIX_SYSTEM
|
#ifdef HAVE_POSIX_SYSTEM
|
||||||
/* Unix specific code of destroy_dotlock. */
|
/* Unix specific code of destroy_dotlock. */
|
||||||
@ -1090,6 +1170,10 @@ dotlock_take_unix (dotlock_t h, long timeout)
|
|||||||
saveerrno = errno;
|
saveerrno = errno;
|
||||||
my_error_2 ("lock not made: open(O_EXCL) of '%s' failed: %s\n",
|
my_error_2 ("lock not made: open(O_EXCL) of '%s' failed: %s\n",
|
||||||
h->lockname, strerror (saveerrno));
|
h->lockname, strerror (saveerrno));
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
|
||||||
|
"lock not made: open(O_EXCL) of '%s' failed: %s\n",
|
||||||
|
h->lockname, strerror (saveerrno));
|
||||||
my_set_errno (saveerrno);
|
my_set_errno (saveerrno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1111,6 +1195,10 @@ dotlock_take_unix (dotlock_t h, long timeout)
|
|||||||
saveerrno = errno;
|
saveerrno = errno;
|
||||||
my_error_2 ("lock not made: writing to '%s' failed: %s\n",
|
my_error_2 ("lock not made: writing to '%s' failed: %s\n",
|
||||||
h->lockname, strerror (errno));
|
h->lockname, strerror (errno));
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
|
||||||
|
"lock not made: writing to '%s' failed: %s\n",
|
||||||
|
h->lockname, strerror (errno));
|
||||||
close (fd);
|
close (fd);
|
||||||
unlink (h->lockname);
|
unlink (h->lockname);
|
||||||
my_set_errno (saveerrno);
|
my_set_errno (saveerrno);
|
||||||
@ -1129,6 +1217,10 @@ dotlock_take_unix (dotlock_t h, long timeout)
|
|||||||
saveerrno = errno;
|
saveerrno = errno;
|
||||||
my_error_1 ("lock not made: Oops: stat of tmp file failed: %s\n",
|
my_error_1 ("lock not made: Oops: stat of tmp file failed: %s\n",
|
||||||
strerror (errno));
|
strerror (errno));
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
|
||||||
|
"lock not made: Oops: stat of tmp file failed: %s\n",
|
||||||
|
strerror (errno));
|
||||||
/* In theory this might be a severe error: It is possible
|
/* In theory this might be a severe error: It is possible
|
||||||
that link succeeded but stat failed due to changed
|
that link succeeded but stat failed due to changed
|
||||||
permissions. We can't do anything about it, though. */
|
permissions. We can't do anything about it, though. */
|
||||||
@ -1150,6 +1242,9 @@ dotlock_take_unix (dotlock_t h, long timeout)
|
|||||||
{
|
{
|
||||||
saveerrno = errno;
|
saveerrno = errno;
|
||||||
my_info_0 ("cannot read lockfile\n");
|
my_info_0 ("cannot read lockfile\n");
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
|
||||||
|
"cannot read lockfile\n");
|
||||||
my_set_errno (saveerrno);
|
my_set_errno (saveerrno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1158,8 +1253,8 @@ dotlock_take_unix (dotlock_t h, long timeout)
|
|||||||
}
|
}
|
||||||
else if ( (pid == getpid() && same_node)
|
else if ( (pid == getpid() && same_node)
|
||||||
|| (same_node && kill (pid, 0) && errno == ESRCH) )
|
|| (same_node && kill (pid, 0) && errno == ESRCH) )
|
||||||
/* Stale lockfile is detected. */
|
|
||||||
{
|
{
|
||||||
|
/* Stale lockfile is detected. */
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
|
||||||
/* Check if it's unlocked during examining the lockfile. */
|
/* Check if it's unlocked during examining the lockfile. */
|
||||||
@ -1202,6 +1297,9 @@ dotlock_take_unix (dotlock_t h, long timeout)
|
|||||||
unlink (h->lockname);
|
unlink (h->lockname);
|
||||||
my_info_1 (_("removing stale lockfile (created by %d)\n"), pid);
|
my_info_1 (_("removing stale lockfile (created by %d)\n"), pid);
|
||||||
close (fd);
|
close (fd);
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_STALE_REMOVED,
|
||||||
|
_("removing stale lockfile (created by %d)\n"), pid);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1228,6 +1326,15 @@ dotlock_take_unix (dotlock_t h, long timeout)
|
|||||||
sumtime = 0;
|
sumtime = 0;
|
||||||
my_info_3 (_("waiting for lock (held by %d%s) %s...\n"),
|
my_info_3 (_("waiting for lock (held by %d%s) %s...\n"),
|
||||||
pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
|
pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
|
||||||
|
if (h->info_cb
|
||||||
|
&& h->info_cb (h, h->info_cb_value, DOTLOCK_WAITING,
|
||||||
|
_("waiting for lock (held by %d%s) %s...\n"),
|
||||||
|
pid, maybe_dead,
|
||||||
|
maybe_deadlock(h)? _("(deadlock?) "):""))
|
||||||
|
{
|
||||||
|
my_set_errno (ECANCELED);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tv.tv_sec = wtimereal / 1000;
|
tv.tv_sec = wtimereal / 1000;
|
||||||
@ -1268,7 +1375,11 @@ dotlock_take_w32 (dotlock_t h, long timeout)
|
|||||||
{
|
{
|
||||||
my_error_2 (_("lock '%s' not made: %s\n"),
|
my_error_2 (_("lock '%s' not made: %s\n"),
|
||||||
h->lockname, w32_strerror (w32err));
|
h->lockname, w32_strerror (w32err));
|
||||||
my_set_errno (map_w32_to_errno (w32err));
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
|
||||||
|
_("lock '%s' not made: %s\n"),
|
||||||
|
h->lockname, w32_strerror (w32err));
|
||||||
|
_set_errno (map_w32_to_errno (w32err));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1281,7 +1392,16 @@ dotlock_take_w32 (dotlock_t h, long timeout)
|
|||||||
timedout = 1; /* remember. */
|
timedout = 1; /* remember. */
|
||||||
|
|
||||||
if (wtime >= 800)
|
if (wtime >= 800)
|
||||||
|
{
|
||||||
my_info_1 (_("waiting for lock %s...\n"), h->lockname);
|
my_info_1 (_("waiting for lock %s...\n"), h->lockname);
|
||||||
|
if (h->info_cb
|
||||||
|
&& h->info_cb (h, h->info_cb_value, DOTLOCK_WAITING,
|
||||||
|
_("waiting for lock %s...\n"), h->lockname))
|
||||||
|
{
|
||||||
|
my_set_errno (ECANCELED);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Sleep (wtimereal);
|
Sleep (wtimereal);
|
||||||
goto again;
|
goto again;
|
||||||
@ -1334,12 +1454,18 @@ dotlock_release_unix (dotlock_t h)
|
|||||||
{
|
{
|
||||||
saveerrno = errno;
|
saveerrno = errno;
|
||||||
my_error_0 ("release_dotlock: lockfile error\n");
|
my_error_0 ("release_dotlock: lockfile error\n");
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
|
||||||
|
"release_dotlock: lockfile error\n");
|
||||||
my_set_errno (saveerrno);
|
my_set_errno (saveerrno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ( pid != getpid() || !same_node )
|
if ( pid != getpid() || !same_node )
|
||||||
{
|
{
|
||||||
my_error_1 ("release_dotlock: not our lock (pid=%d)\n", pid);
|
my_error_1 ("release_dotlock: not our lock (pid=%d)\n", pid);
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_CONFLICT,
|
||||||
|
"release_dotlock: not our lock (pid=%d)\n", pid);
|
||||||
my_set_errno (EACCES);
|
my_set_errno (EACCES);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1349,6 +1475,10 @@ dotlock_release_unix (dotlock_t h)
|
|||||||
saveerrno = errno;
|
saveerrno = errno;
|
||||||
my_error_1 ("release_dotlock: error removing lockfile '%s'\n",
|
my_error_1 ("release_dotlock: error removing lockfile '%s'\n",
|
||||||
h->lockname);
|
h->lockname);
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
|
||||||
|
"release_dotlock: error removing lockfile '%s'\n",
|
||||||
|
h->lockname);
|
||||||
my_set_errno (saveerrno);
|
my_set_errno (saveerrno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1369,10 +1499,15 @@ dotlock_release_w32 (dotlock_t h)
|
|||||||
memset (&ovl, 0, sizeof ovl);
|
memset (&ovl, 0, sizeof ovl);
|
||||||
if (!UnlockFileEx (h->lockhd, 0, 1, 0, &ovl))
|
if (!UnlockFileEx (h->lockhd, 0, 1, 0, &ovl))
|
||||||
{
|
{
|
||||||
int saveerrno = map_w32_to_errno (GetLastError ());
|
int ec = (int)GetLastError ();
|
||||||
|
|
||||||
my_error_2 ("release_dotlock: error removing lockfile '%s': %s\n",
|
my_error_2 ("release_dotlock: error removing lockfile '%s': %s\n",
|
||||||
h->lockname, w32_strerror (-1));
|
h->lockname, w32_strerror (ec));
|
||||||
my_set_errno (saveerrno);
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_FILE_ERROR,
|
||||||
|
"release_dotlock: error removing lockfile '%s': %s\n",
|
||||||
|
h->lockname, w32_strerror (ec));
|
||||||
|
my_set_errno (map_w32_to_errno (ec));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1403,6 +1538,9 @@ dotlock_release (dotlock_t h)
|
|||||||
if ( !h->locked )
|
if ( !h->locked )
|
||||||
{
|
{
|
||||||
my_debug_1 ("Oops, '%s' is not locked\n", h->lockname);
|
my_debug_1 ("Oops, '%s' is not locked\n", h->lockname);
|
||||||
|
if (h->info_cb)
|
||||||
|
h->info_cb (h, h->info_cb_value, DOTLOCK_NOT_LOCKED,
|
||||||
|
"Oops, '%s' is not locked\n", h->lockname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,12 +97,32 @@ extern "C"
|
|||||||
struct dotlock_handle;
|
struct dotlock_handle;
|
||||||
typedef struct dotlock_handle *dotlock_t;
|
typedef struct dotlock_handle *dotlock_t;
|
||||||
|
|
||||||
|
enum dotlock_reasons
|
||||||
|
{
|
||||||
|
DOTLOCK_CONFIG_TEST, /* Can't check system - function terminates. */
|
||||||
|
DOTLOCK_FILE_ERROR, /* General file error - function terminates. */
|
||||||
|
DOTLOCK_INV_FILE, /* Invalid file - function terminates. */
|
||||||
|
DOTLOCK_CONFLICT, /* Something is wrong - function terminates. */
|
||||||
|
DOTLOCK_NOT_LOCKED, /* Not locked - No action required. */
|
||||||
|
DOTLOCK_STALE_REMOVED, /* Stale lock file was removed - retrying. */
|
||||||
|
DOTLOCK_WAITING /* Waiting for the lock - may be terminated. */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DOTLOCK_PREPARE_CREATE (1<<5) /* Require dotlock_finish_create. */
|
||||||
|
|
||||||
void dotlock_disable (void);
|
void dotlock_disable (void);
|
||||||
dotlock_t dotlock_create (const char *file_to_lock, unsigned int flags);
|
dotlock_t dotlock_create (const char *file_to_lock, unsigned int flags);
|
||||||
|
dotlock_t dotlock_finish_create (dotlock_t h, const char *file_to_lock);
|
||||||
void dotlock_set_fd (dotlock_t h, int fd);
|
void dotlock_set_fd (dotlock_t h, int fd);
|
||||||
int dotlock_get_fd (dotlock_t h);
|
int dotlock_get_fd (dotlock_t h);
|
||||||
|
void dotlock_set_info_cb (dotlock_t h,
|
||||||
|
int (*cb)(dotlock_t, void *,
|
||||||
|
enum dotlock_reasons reason,
|
||||||
|
const char *,...),
|
||||||
|
void *opaque);
|
||||||
void dotlock_destroy (dotlock_t h);
|
void dotlock_destroy (dotlock_t h);
|
||||||
int dotlock_take (dotlock_t h, long timeout);
|
int dotlock_take (dotlock_t h, long timeout);
|
||||||
|
int dotlock_is_locked (dotlock_t h);
|
||||||
int dotlock_release (dotlock_t h);
|
int dotlock_release (dotlock_t h);
|
||||||
void dotlock_remove_lockfiles (void);
|
void dotlock_remove_lockfiles (void);
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
|
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
w32_strerror (int ec)
|
w32_strerror (int ec)
|
||||||
{
|
{
|
||||||
@ -174,6 +175,11 @@ strconcat (const char *s1, ...)
|
|||||||
|
|
||||||
#define PGM "t-dotlock"
|
#define PGM "t-dotlock"
|
||||||
|
|
||||||
|
static int opt_silent;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
#ifndef HAVE_W32_SYSTEM
|
||||||
static volatile int ctrl_c_pending_flag;
|
static volatile int ctrl_c_pending_flag;
|
||||||
static void
|
static void
|
||||||
@ -217,6 +223,9 @@ inf (const char *format, ...)
|
|||||||
{
|
{
|
||||||
va_list arg_ptr;
|
va_list arg_ptr;
|
||||||
|
|
||||||
|
if (opt_silent)
|
||||||
|
return;
|
||||||
|
|
||||||
va_start (arg_ptr, format);
|
va_start (arg_ptr, format);
|
||||||
fprintf (stderr, PGM "[%lu]: ", (unsigned long)getpid ());
|
fprintf (stderr, PGM "[%lu]: ", (unsigned long)getpid ());
|
||||||
vfprintf (stderr, format, arg_ptr);
|
vfprintf (stderr, format, arg_ptr);
|
||||||
@ -225,15 +234,35 @@ inf (const char *format, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
lock_info_cb (dotlock_t h, void *opaque, enum dotlock_reasons reason,
|
||||||
|
const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list arg_ptr;
|
||||||
|
|
||||||
|
va_start (arg_ptr, format);
|
||||||
|
fprintf (stderr, PGM "[%lu]: info_cb: reason %d, ",
|
||||||
|
(unsigned long)getpid (), (int)reason);
|
||||||
|
vfprintf (stderr, format, arg_ptr);
|
||||||
|
va_end (arg_ptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lock_and_unlock (const char *fname)
|
lock_and_unlock (const char *fname)
|
||||||
{
|
{
|
||||||
dotlock_t h;
|
dotlock_t h;
|
||||||
unsigned long usec;
|
unsigned long usec;
|
||||||
|
|
||||||
h = dotlock_create (fname, 0);
|
h = dotlock_create (fname, DOTLOCK_PREPARE_CREATE);
|
||||||
if (!h)
|
if (!h)
|
||||||
die ("error creating lock file for '%s': %s", fname, strerror (errno));
|
die ("error creating lock file for '%s': %s", fname, strerror (errno));
|
||||||
|
dotlock_set_info_cb (h, lock_info_cb, NULL);
|
||||||
|
h = dotlock_finish_create (h, fname);
|
||||||
|
if (!h)
|
||||||
|
die ("error finishing lock file creation for '%s': %s",
|
||||||
|
fname, strerror (errno));
|
||||||
inf ("lock created");
|
inf ("lock created");
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -270,6 +299,11 @@ main (int argc, char **argv)
|
|||||||
ctrl_c_pending_flag = 1;
|
ctrl_c_pending_flag = 1;
|
||||||
argc--;
|
argc--;
|
||||||
}
|
}
|
||||||
|
if (argc > 1 && !strcmp (argv[1], "--silent"))
|
||||||
|
{
|
||||||
|
opt_silent = 1;
|
||||||
|
argc--;
|
||||||
|
}
|
||||||
|
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
fname = argv[argc-1];
|
fname = argv[argc-1];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user