Пример #1
0
/* Destroy the locck handle H and release the lock.  */
void
dotlock_destroy (dotlock_t h)
{
  dotlock_t hprev, htmp;

  if ( !h )
    return;

  /* First remove the handle from our global list of all locks. */
  LOCK_all_lockfiles ();
  for (hprev=NULL, htmp=all_lockfiles; htmp; hprev=htmp, htmp=htmp->next)
    if (htmp == h)
      {
        if (hprev)
          hprev->next = htmp->next;
        else
          all_lockfiles = htmp->next;
        h->next = NULL;
        break;
      }
  UNLOCK_all_lockfiles ();

  /* Then destroy the lock. */
  if (!h->disable)
    {
#ifdef HAVE_DOSISH_SYSTEM
      dotlock_destroy_w32 (h);
#else /* !HAVE_DOSISH_SYSTEM */
      dotlock_destroy_unix (h);
#endif /* HAVE_DOSISH_SYSTEM */
      jnlib_free (h->lockname);
    }
  jnlib_free(h);
}
Пример #2
0
/* Locking core for Windows.  This version does not need a temporary
   file but uses the plain lock file along with record locking.  We
   create this file here so that we later only need to do the file
   locking.  For error reporting it is useful to keep the name of the
   file in the handle.  */
static dotlock_t
dotlock_create_w32 (dotlock_t h, const char *file_to_lock)
{
  LOCK_all_lockfiles ();
  h->next = all_lockfiles;
  all_lockfiles = h;

  h->lockname = jnlib_malloc ( strlen (file_to_lock) + 6 );
  if (!h->lockname)
    {
      all_lockfiles = h->next;
      UNLOCK_all_lockfiles ();
      jnlib_free (h);
      return NULL;
    }
  strcpy (stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock");

  /* If would be nice if we would use the FILE_FLAG_DELETE_ON_CLOSE
     along with FILE_SHARE_DELETE but that does not work due to a race
     condition: Despite the OPEN_ALWAYS flag CreateFile may return an
     error and we can't reliable create/open the lock file unless we
     would wait here until it works - however there are other valid
     reasons why a lock file can't be created and thus the process
     would not stop as expected but spin until Windows crashes.  Our
     solution is to keep the lock file open; that does not harm. */
  {
#ifdef HAVE_W32CE_SYSTEM
    wchar_t *wname = utf8_to_wchar (h->lockname);

    if (wname)
      h->lockhd = CreateFile (wname,
                              GENERIC_READ|GENERIC_WRITE,
                              FILE_SHARE_READ|FILE_SHARE_WRITE,
                              NULL, OPEN_ALWAYS, 0, NULL);
    else
      h->lockhd = INVALID_HANDLE_VALUE;
    jnlib_free (wname);
#else
    h->lockhd = CreateFile (h->lockname,
                            GENERIC_READ|GENERIC_WRITE,
                            FILE_SHARE_READ|FILE_SHARE_WRITE,
                            NULL, OPEN_ALWAYS, 0, NULL);
#endif
  }
  if (h->lockhd == INVALID_HANDLE_VALUE)
    {
      all_lockfiles = h->next;
      UNLOCK_all_lockfiles ();
      my_error_2 (_("can't create `%s': %s\n"), h->lockname, w32_strerror (-1));
      jnlib_free (h->lockname);
      jnlib_free (h);
      return NULL;
    }
  return h;
}
Пример #3
0
static int
use_hardlinks_p (const char *tname)
{
  char *lname;
  struct stat sb;
  unsigned int nlink;
  int res;

  if (stat (tname, &sb))
    return -1;
  nlink = (unsigned int)sb.st_nlink;

  lname = jnlib_malloc (strlen (tname) + 1 + 1);
  if (!lname)
    return -1;
  strcpy (lname, tname);
  strcat (lname, "x");

  link (tname, lname);

  if (stat (tname, &sb))
    res = -1;  /* Ooops.  */
  else if (sb.st_nlink == nlink + 1)
    res = 0;   /* Yeah, hardlinks are supported.  */
  else
    res = 1;   /* No hardlink support.  */

  unlink (lname);
  jnlib_free (lname);
  return res;
}
Пример #4
0
/* Unix specific code of destroy_dotlock.  */
static void
dotlock_destroy_unix (dotlock_t h)
{
  if (h->locked && h->lockname)
    unlink (h->lockname);
  if (h->tname && !h->use_o_excl)
    unlink (h->tname);
  jnlib_free (h->tname);
}
Пример #5
0
static int
fun_closer (void *cookie_arg)
{
  struct fun_cookie_s *cookie = cookie_arg;

  if (cookie->fd != -1 && cookie->fd != 2)
    close (cookie->fd);
  jnlib_free (cookie);
  log_socket = -1;
  return 0;
}
Пример #6
0
/* Check whether the files NAME1 and NAME2 are identical.  This is for
   example achieved by comparing the inode numbers of the files.  */
int
same_file_p (const char *name1, const char *name2)
{
  int yes;

  /* First try a shortcut.  */
  if (!compare_filenames (name1, name2))
    yes = 1;
  else
    {
#ifdef HAVE_W32_SYSTEM
      HANDLE file1, file2;
      BY_HANDLE_FILE_INFORMATION info1, info2;

#ifdef HAVE_W32CE_SYSTEM
      {
        wchar_t *wname = utf8_to_wchar (name1);
        if (wname)
          file1 = CreateFile (wname, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
        else
          file1 = INVALID_HANDLE_VALUE;
        jnlib_free (wname);
      }
#else
      file1 = CreateFile (name1, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
#endif
      if (file1 == INVALID_HANDLE_VALUE)
        yes = 0; /* If we can't open the file, it is not the same.  */
      else
        {
#ifdef HAVE_W32CE_SYSTEM
          {
            wchar_t *wname = utf8_to_wchar (name2);
            if (wname)
              file2 = CreateFile (wname, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
            else
              file2 = INVALID_HANDLE_VALUE;
            jnlib_free (wname);
          }
#else
          file2 = CreateFile (name2, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
#endif
          if (file2 == INVALID_HANDLE_VALUE)
            yes = 0; /* If we can't open the file, it is not the same.  */
          else
            {
              yes = (GetFileInformationByHandle (file1, &info1)
                     && GetFileInformationByHandle (file2, &info2)
                     && info1.dwVolumeSerialNumber==info2.dwVolumeSerialNumber
                     && info1.nFileIndexHigh == info2.nFileIndexHigh
                     && info1.nFileIndexLow == info2.nFileIndexLow);
              CloseHandle (file2);
            }
          CloseHandle (file1);
        }
#else /*!HAVE_W32_SYSTEM*/
      struct stat info1, info2;

      yes = (!stat (name1, &info1) && !stat (name2, &info2)
             && info1.st_dev == info2.st_dev && info1.st_ino == info2.st_ino);
#endif /*!HAVE_W32_SYSTEM*/
    }
  return yes;
}
Пример #7
0
/* Because we can't use our jnlib_free macro in inline functions we
   provide this wrapper.  */
void
_jnlib_free (void *p)
{
  if (p)
    jnlib_free (p);
}
Пример #8
0
/* Locking core for Unix.  It used a temporary file and the link
   system call to make locking an atomic operation. */
static dotlock_t
dotlock_create_unix (dotlock_t h, const char *file_to_lock)
{
  int  fd = -1;
  char pidstr[16];
  const char *nodename;
  const char *dirpart;
  int dirpartlen;
  struct utsname utsbuf;
  size_t tnamelen;

  snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid() );

  /* Create a temporary file. */
  if ( uname ( &utsbuf ) )
    nodename = "unknown";
  else
    nodename = utsbuf.nodename;

  if ( !(dirpart = strrchr (file_to_lock, DIRSEP_C)) )
    {
      dirpart = EXTSEP_S;
      dirpartlen = 1;
    }
  else
    {
      dirpartlen = dirpart - file_to_lock;
      dirpart = file_to_lock;
    }

  LOCK_all_lockfiles ();
  h->next = all_lockfiles;
  all_lockfiles = h;

  tnamelen = dirpartlen + 6 + 30 + strlen(nodename) + 10 + 1;
  h->tname = jnlib_malloc (tnamelen + 1);
  if (!h->tname)
    {
      all_lockfiles = h->next;
      UNLOCK_all_lockfiles ();
      jnlib_free (h);
      return NULL;
    }
  h->nodename_len = strlen (nodename);

  snprintf (h->tname, tnamelen, "%.*s/.#lk%p.", dirpartlen, dirpart, h );
  h->nodename_off = strlen (h->tname);
  snprintf (h->tname+h->nodename_off, tnamelen - h->nodename_off,
           "%s.%d", nodename, (int)getpid ());

  do
    {
      jnlib_set_errno (0);
      fd = open (h->tname, O_WRONLY|O_CREAT|O_EXCL,
                 S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
    }
  while (fd == -1 && errno == EINTR);

  if ( fd == -1 )
    {
      all_lockfiles = h->next;
      UNLOCK_all_lockfiles ();
      my_error_2 (_("failed to create temporary file `%s': %s\n"),
                  h->tname, strerror(errno));
      jnlib_free (h->tname);
      jnlib_free (h);
      return NULL;
    }
  if ( write (fd, pidstr, 11 ) != 11 )
    goto write_failed;
  if ( write (fd, nodename, strlen (nodename) ) != strlen (nodename) )
    goto write_failed;
  if ( write (fd, "\n", 1 ) != 1 )
    goto write_failed;
  if ( close (fd) )
    goto write_failed;

  /* Check whether we support hard links.  */
  switch (use_hardlinks_p (h->tname))
    {
    case 0: /* Yes.  */
      break;
    case 1: /* No.  */
      unlink (h->tname);
      h->use_o_excl = 1;
      break;
    default:
      my_error_2 ("can't check whether hardlinks are supported for `%s': %s\n",
                  h->tname, strerror(errno));
      goto write_failed;
    }

  h->lockname = jnlib_malloc (strlen (file_to_lock) + 6 );
  if (!h->lockname)
    {
      all_lockfiles = h->next;
      UNLOCK_all_lockfiles ();
      unlink (h->tname);
      jnlib_free (h->tname);
      jnlib_free (h);
      return NULL;
    }
  strcpy (stpcpy (h->lockname, file_to_lock), EXTSEP_S "lock");
  UNLOCK_all_lockfiles ();
  if (h->use_o_excl)
    my_debug_1 ("locking for `%s' done via O_EXCL\n", h->lockname);

  return h;

 write_failed:
  all_lockfiles = h->next;
  UNLOCK_all_lockfiles ();
  my_error_2 (_("error writing to `%s': %s\n"), h->tname, strerror (errno));
  close (fd);
  unlink (h->tname);
  jnlib_free (h->tname);
  jnlib_free (h);
  return NULL;
}
Пример #9
0
static int
read_lockfile (dotlock_t h, int *same_node )
{
  char buffer_space[10+1+70+1]; /* 70 is just an estimated value; node
                                   names are usually shorter. */
  int fd;
  int pid = -1;
  char *buffer, *p;
  size_t expected_len;
  int res, nread;

  *same_node = 0;
  expected_len = 10 + 1 + h->nodename_len + 1;
  if ( expected_len >= sizeof buffer_space)
    {
      buffer = jnlib_malloc (expected_len);
      if (!buffer)
        return -1;
    }
  else
    buffer = buffer_space;

  if ( (fd = open (h->lockname, O_RDONLY)) == -1 )
    {
      int e = errno;
      my_info_2 ("error opening lockfile `%s': %s\n",
                 h->lockname, strerror(errno) );
      if (buffer != buffer_space)
        jnlib_free (buffer);
      jnlib_set_errno (e); /* Need to return ERRNO here. */
      return -1;
    }

  p = buffer;
  nread = 0;
  do
    {
      res = read (fd, p, expected_len - nread);
      if (res == -1 && errno == EINTR)
        continue;
      if (res < 0)
        {
          my_info_1 ("error reading lockfile `%s'\n", h->lockname );
          close (fd);
          if (buffer != buffer_space)
            jnlib_free (buffer);
          jnlib_set_errno (0); /* Do not return an inappropriate ERRNO. */
          return -1;
        }
      p += res;
      nread += res;
    }
  while (res && nread != expected_len);
  close(fd);

  if (nread < 11)
    {
      my_info_1 ("invalid size of lockfile `%s'\n", h->lockname);
      if (buffer != buffer_space)
        jnlib_free (buffer);
      jnlib_set_errno (0); /* Better don't return an inappropriate ERRNO. */
      return -1;
    }

  if (buffer[10] != '\n'
      || (buffer[10] = 0, pid = atoi (buffer)) == -1
      || !pid )
    {
      my_error_2 ("invalid pid %d in lockfile `%s'\n", pid, h->lockname);
      if (buffer != buffer_space)
        jnlib_free (buffer);
      jnlib_set_errno (0);
      return -1;
    }

  if (nread == expected_len
      && !memcmp (h->tname+h->nodename_off, buffer+11, h->nodename_len)
      && buffer[11+h->nodename_len] == '\n')
    *same_node = 1;

  if (buffer != buffer_space)
    jnlib_free (buffer);
  return pid;
}