Back to index

glibc  2.9
Defines | Functions | Variables
lckpwdf.c File Reference
#include <fcntl.h>
#include <bits/libc-lock.h>
#include <shadow.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <sys/file.h>
#include <kernel-features.h>

Go to the source code of this file.

Defines

#define PWD_LOCKFILE   "/etc/.pwd.lock"
#define TIMEOUT   15 /* sec */
#define RETURN_CLOSE_FD(code)
#define RETURN_RESTORE_HANDLER(code)
#define RETURN_CLEAR_ALARM(code)

Functions

 __libc_lock_define_initialized (static, lock)
 weak_alias (__lckpwdf, lckpwdf)
 weak_alias (__ulckpwdf, ulckpwdf)

Variables

static int lock_fd = -1

Define Documentation

#define PWD_LOCKFILE   "/etc/.pwd.lock"

Definition at line 33 of file lckpwdf.c.

#define RETURN_CLEAR_ALARM (   code)
Value:
do {                                                                 \
    /* Clear alarm.  */                                                     \
    alarm (0);                                                              \
    /* Restore old set of handled signals.  We don't need to know           \
       about the current one.*/                                             \
    __sigprocmask (SIG_SETMASK, &saved_set, NULL);                          \
    RETURN_RESTORE_HANDLER (code);                                   \
  } while (0)
#define RETURN_CLOSE_FD (   code)
Value:
do {                                                                 \
    if ((code) < 0 && lock_fd >= 0)                                         \
      {                                                                     \
       __close (lock_fd);                                            \
       lock_fd = -1;                                                 \
      }                                                                     \
    __libc_lock_unlock (lock);                                              \
    return (code);                                                   \
  } while (0)
#define RETURN_RESTORE_HANDLER (   code)
Value:
do {                                                                 \
    /* Restore old action handler for alarm.  We don't need to know         \
       about the current one.  */                                    \
    __sigaction (SIGALRM, &saved_act, NULL);                                \
    RETURN_CLOSE_FD (code);                                          \
  } while (0)
#define TIMEOUT   15 /* sec */

Definition at line 37 of file lckpwdf.c.


Function Documentation

__libc_lock_define_initialized ( static  ,
lock   
)

Definition at line 44 of file lckpwdf.c.

     {                                                               \
    if ((code) < 0 && lock_fd >= 0)                                         \
      {                                                                     \
       __close (lock_fd);                                            \
       lock_fd = -1;                                                 \
      }                                                                     \
    __libc_lock_unlock (lock);                                              \
    return (code);                                                   \
  } while (0)

#define RETURN_RESTORE_HANDLER(code)                                        \
  do {                                                               \
    /* Restore old action handler for alarm.  We don't need to know         \
       about the current one.  */                                    \
    __sigaction (SIGALRM, &saved_act, NULL);                                \
    RETURN_CLOSE_FD (code);                                          \
  } while (0)

#define RETURN_CLEAR_ALARM(code)                                     \
  do {                                                               \
    /* Clear alarm.  */                                                     \
    alarm (0);                                                              \
    /* Restore old set of handled signals.  We don't need to know           \
       about the current one.*/                                             \
    __sigprocmask (SIG_SETMASK, &saved_set, NULL);                          \
    RETURN_RESTORE_HANDLER (code);                                   \
  } while (0)


int
__lckpwdf (void)
{
  int flags;
  sigset_t saved_set;                     /* Saved set of caught signals.  */
  struct sigaction saved_act;             /* Saved signal action.  */
  sigset_t new_set;                /* New set of caught signals.  */
  struct sigaction new_act;        /* New signal action.  */
  struct flock fl;                 /* Information struct for locking.  */
  int result;

  if (lock_fd != -1)
    /* Still locked by own process.  */
    return -1;

  /* Prevent problems caused by multiple threads.  */
  __libc_lock_lock (lock);

  int oflags = O_WRONLY | O_CREAT;
#ifdef O_CLOEXEC
  oflags |= O_CLOEXEC;
#endif
  lock_fd = __open (PWD_LOCKFILE, oflags, 0600);
  if (lock_fd == -1)
    /* Cannot create lock file.  */
    RETURN_CLOSE_FD (-1);

#ifndef __ASSUME_O_CLOEXEC
# ifdef O_CLOEXEC
  if (__have_o_cloexec <= 0)
# endif
    {
      /* Make sure file gets correctly closed when process finished.  */
      flags = __fcntl (lock_fd, F_GETFD, 0);
      if (flags == -1)
       /* Cannot get file flags.  */
       RETURN_CLOSE_FD (-1);
# ifdef O_CLOEXEC
      if (__have_o_cloexec == 0)
       __have_o_cloexec = (flags & FD_CLOEXEC) == 0 ? -1 : 1;
      if (__have_o_cloexec < 0)
# endif
       {
         flags |= FD_CLOEXEC;             /* Close on exit.  */
         if (__fcntl (lock_fd, F_SETFD, flags) < 0)
           /* Cannot set new flags.  */
           RETURN_CLOSE_FD (-1);
       }
    }
#endif

  /* Now we have to get exclusive write access.  Since multiple
     process could try this we won't stop when it first fails.
     Instead we set a timeout for the system call.  Once the timer
     expires it is likely that there are some problems which cannot be
     resolved by waiting.

     It is important that we don't change the signal state.  We must
     restore the old signal behaviour.  */
  memset (&new_act, '\0', sizeof (struct sigaction));
  new_act.sa_handler = noop_handler;
  __sigfillset (&new_act.sa_mask);
  new_act.sa_flags = 0ul;

  /* Install new action handler for alarm and save old.  */
  if (__sigaction (SIGALRM, &new_act, &saved_act) < 0)
    /* Cannot install signal handler.  */
    RETURN_CLOSE_FD (-1);

  /* Now make sure the alarm signal is not blocked.  */
  __sigemptyset (&new_set);
  __sigaddset (&new_set, SIGALRM);
  if (__sigprocmask (SIG_UNBLOCK, &new_set, &saved_set) < 0)
    RETURN_RESTORE_HANDLER (-1);

  /* Start timer.  If we cannot get the lock in the specified time we
     get a signal.  */
  alarm (TIMEOUT);

  /* Try to get the lock.  */
  memset (&fl, '\0', sizeof (struct flock));
  fl.l_type = F_WRLCK;
  fl.l_whence = SEEK_SET;
  result = __fcntl (lock_fd, F_SETLKW, &fl);

Here is the call graph for this function:

Definition at line 168 of file lckpwdf.c.

{
  int result;

  if (lock_fd == -1)
    /* There is no lock set.  */
    result = -1;
  else
    {
      /* Prevent problems caused by multiple threads.  */
      __libc_lock_lock (lock);

      result = __close (lock_fd);

      /* Mark descriptor as unused.  */
      lock_fd = -1;

      /* Clear mutex.  */
      __libc_lock_unlock (lock);
    }

Definition at line 195 of file lckpwdf.c.

{

Variable Documentation

int lock_fd = -1 [static]

Definition at line 41 of file lckpwdf.c.