/* try_file_lock (LOCKING, FD, TYPE) returns true if the locking
operation failed and recovery needs to be performed.
- (file_lock_restore (LOCKING) still needs to be called.)
file_unlock (FD) removes the lock (which must have been
- acquired).
-
- file_lock_restore (LOCKING) is needed to clean up in both
- cases. */
-
-struct file_locking
-{
- struct sigaction old_action;
- unsigned int old_timeout;
-};
+ successfully acquired). */
static bool
-try_file_lock (struct file_locking *locking, int fd, int type)
+try_file_lock (int fd, int type)
{
/* Cancel any existing alarm. */
- locking->old_timeout = alarm (0);
+ int old_timeout = alarm (0);
/* Establish signal handler. */
+ struct sigaction old_action;
struct sigaction action;
action.sa_handler = timeout_handler;
__sigemptyset (&action.sa_mask);
action.sa_flags = 0;
- __sigaction (SIGALRM, &action, &locking->old_action);
+ __sigaction (SIGALRM, &action, &old_action);
alarm (TIMEOUT);
.l_type = type,
fl.l_whence = SEEK_SET,
};
- return __fcntl64_nocancel (fd, F_SETLKW, &fl) < 0;
+
+ bool status = __fcntl64_nocancel (fd, F_SETLKW, &fl) < 0;
+ int saved_errno = errno;
+
+ /* Reset the signal handler and alarm. We must reset the alarm
+ before resetting the handler so our alarm does not generate a
+ spurious SIGALRM seen by the user. However, we cannot just set
+ the user's old alarm before restoring the handler, because then
+ it's possible our handler could catch the user alarm's SIGARLM and
+ then the user would never see the signal he expected. */
+ alarm (0);
+ __sigaction (SIGALRM, &old_action, NULL);
+ if (old_timeout != 0)
+ alarm (old_timeout);
+
+ __set_errno (saved_errno);
+ return status;
}
static void
__fcntl64_nocancel (fd, F_SETLKW, &fl);
}
-static void
-file_lock_restore (struct file_locking *locking)
-{
- /* Reset the signal handler and alarm. We must reset the alarm
- before resetting the handler so our alarm does not generate a
- spurious SIGALRM seen by the user. However, we cannot just set
- the user's old alarm before restoring the handler, because then
- it's possible our handler could catch the user alarm's SIGARLM
- and then the user would never see the signal he expected. */
- alarm (0);
- __sigaction (SIGALRM, &locking->old_action, NULL);
- if (locking->old_timeout != 0)
- alarm (locking->old_timeout);
-}
-
#ifndef TRANSFORM_UTMP_FILE_NAME
# define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name)
#endif
return -1;
}
- struct file_locking fl;
- if (try_file_lock (&fl, file_fd, F_RDLCK))
+ if (try_file_lock (file_fd, F_RDLCK))
nbytes = 0;
else
{
nbytes = __read_nocancel (file_fd, &last_entry, sizeof (struct utmp));
file_unlock (file_fd);
}
- file_lock_restore (&fl);
if (nbytes != sizeof (struct utmp))
{
{
int result = -1;
- struct file_locking fl;
- if (try_file_lock (&fl, file_fd, F_RDLCK))
+ if (try_file_lock (file_fd, F_RDLCK))
{
*lock_failed = true;
- file_lock_restore (&fl);
return -1;
}
unlock_return:
file_unlock (file_fd);
- file_lock_restore (&fl);
return result;
}
return -1;
}
- struct file_locking fl;
- if (try_file_lock (&fl, file_fd, F_RDLCK))
+ if (try_file_lock (file_fd, F_RDLCK))
{
*result = NULL;
- file_lock_restore (&fl);
return -1;
}
unlock_return:
file_unlock (file_fd);
- file_lock_restore (&fl);
return ((*result == NULL) ? -1 : 0);
}
}
}
- struct file_locking fl;
- if (try_file_lock (&fl, file_fd, F_WRLCK))
- {
- file_lock_restore (&fl);
- return NULL;
- }
+ if (try_file_lock (file_fd, F_WRLCK))
+ return NULL;
if (found < 0)
{
unlock_return:
file_unlock (file_fd);
- file_lock_restore (&fl);
return pbuf;
}
if (fd < 0)
return -1;
- struct file_locking fl;
- if (try_file_lock (&fl, fd, F_WRLCK))
+ if (try_file_lock (fd, F_WRLCK))
{
- file_lock_restore (&fl);
__close_nocancel_nostatus (fd);
return -1;
}
unlock_return:
file_unlock (fd);
- file_lock_restore (&fl);
/* Close WTMP file. */
__close_nocancel_nostatus (fd);