open () on Win95 directories

Pierre A. Humblet
Tue Sep 17 18:41:00 GMT 2002

At 08:18 PM 9/17/2002 -0500, Gary R. Van Sickle wrote:
>Hehehehe, I was just about to hit send on a reply to your original email
on this
>Pierre!  It wasn't going to have a nice patch attached though.  Thanks for
>tracking this down and fixing it.

This problem is fixed, but there is another one! Solving the other one
would best
be done with the help of the mutt developer and integrated in the main release
(same for the fopen( ,"b"), by the way, he shouldn't object).

The problem is that hard links are not implemented on FAT, and dotlock.c
on the hardlink count. You will see that it will timeout.
However there is NO NEED to look at the hardlink count when the link succeeds
(only when it fails, which can happen because of NFS problems even though the
actual link succeeded on the remote machine), because when it succeeds the
MUST be 2.
This is how exim does it, not because of Win95 but for efficiency sake. 
Below I cut and pasted a relevant part of appendfile.c that explains the

By the way, exim uses both fcntl and dotlock by default (can be changed from
exim.conf), so mutt could interoperate with exim with fcntl only.


  if (ob->use_lockfile)
    lockname = string_sprintf("%s.lock", filename);
    hitchname = string_sprintf( "%s.%s.%08x.%08x", lockname, primary_hostname,
      (unsigned int)(time(NULL)), (unsigned int)getpid());

    DEBUG(D_transport) debug_printf("lock name: %s\nhitch name: %s\n",

    /* Lock file creation retry loop */

    for (i = 0; i < ob->lock_retries; sleep(ob->lock_interval), i++)
      int rc;
      hd = Uopen(hitchname, O_WRONLY | O_CREAT | O_EXCL, ob->lockfile_mode);

      if (hd < 0)
        addr->basic_errno = errno;
        addr->message =
          string_sprintf("creating lock file hitching post %s "
            "(euid=%ld egid=%ld)", hitchname, (long int)geteuid(),
            (long int)getegid());
        return FALSE;

      /* Attempt to hitch the hitching post to the lock file. If link()
      succeeds (the common case, we hope) all is well. Otherwise, fstat the
      file, and get rid of the hitching post. If the number of links was 2,
      the link was created, despite the failure of link(). If the hitch was
      not successful, try again, having unlinked the lock file if it is too

      There's a version of Linux (2.0.27) which doesn't update its local cache
      of the inode after link() by default - which many think is a bug - but
      if the link succeeds, this code will be OK. It just won't work in the
      case when link() fails after having actually created the link. The Linux
      NFS person is fixing this; a temporary patch is available if anyone is
      sufficiently worried. */

      if ((rc = Ulink(hitchname, lockname)) != 0) fstat(hd, &statbuf);
      if (rc != 0 && statbuf.st_nlink != 2)
        if (ob->lockfile_timeout > 0 && Ustat(lockname, &statbuf) == 0 &&
            time(NULL) - statbuf.st_ctime > ob->lockfile_timeout)
          DEBUG(D_transport) debug_printf("unlinking timed-out lock file\n");
        DEBUG(D_transport) debug_printf("link of hitching post failed -

      DEBUG(D_transport) debug_printf("lock file created\n");

    /* Check for too many tries at creating the lock file */

    if (i >= ob->lock_retries)
      addr->basic_errno = ERRNO_LOCKFAILED;
      addr->message = string_sprintf("failed to lock mailbox %s (lock file)",
      return FALSE;

More information about the Cygwin-patches mailing list