+ __try
+ {
+ oflag &= (O_CREAT | O_EXCL);
+
+ again:
+ if (oflag & O_CREAT)
+ {
+ va_start (ap, oflag); /* init ap to final named argument */
+ mode = va_arg (ap, mode_t) & ~S_IXUSR;
+ value = va_arg (ap, unsigned int);
+ va_end (ap);
+
+ /* Open and specify O_EXCL and user-execute */
+ fd = open (semname, oflag | O_EXCL | O_RDWR | O_CLOEXEC,
+ mode | S_IXUSR);
+ if (fd < 0)
+ {
+ if (errno == EEXIST && (oflag & O_EXCL) == 0)
+ goto exists; /* already exists, OK */
+ return SEM_FAILED;
+ }
+ created = 1;
+ /* First one to create the file initializes it. */
+ NtAllocateLocallyUniqueId (&sf.luid);
+ sf.value = value;
+ sf.hash = hash_path_name (0, semname);
+ if (write (fd, &sf, sizeof sf) != sizeof sf)
+ __leave;
+ sem = semaphore::open (sf.hash, sf.luid, fd, oflag, mode, value,
+ wasopen);
+ if (sem == SEM_FAILED)
+ __leave;
+ /* Initialization complete, turn off user-execute bit */
+ if (fchmod (fd, mode) == -1)
+ __leave;
+ /* Don't close (fd); */
+ return sem;
+ }
+
+ exists:
+ /* Open the file and fetch the semaphore name. */
+ if ((fd = open (semname, O_RDWR | O_CLOEXEC)) < 0)
+ {
+ if (errno == ENOENT && (oflag & O_CREAT))
+ goto again;
+ __leave;
+ }
+ /* Make certain initialization is complete */
+ for (i = 0; i < MAX_TRIES; i++)
+ {
+ if (stat64 (semname, &statbuff) == -1)
+ {
+ if (errno == ENOENT && (oflag & O_CREAT))
+ {
+ close (fd);
+ fd = -1;
+ goto again;
+ }
+ __leave;
+ }
+ if ((statbuff.st_mode & S_IXUSR) == 0)
+ break;
+ sleep (1);
+ }
+ if (i == MAX_TRIES)
+ {
+ set_errno (ETIMEDOUT);
+ __leave;
+ }
+ if (file.lock (fd, sizeof sf))
+ __leave;
+ if (read (fd, &sf, sizeof sf) != sizeof sf)
+ __leave;
+ sem = semaphore::open (sf.hash, sf.luid, fd, oflag, mode, sf.value,
+ wasopen);
+ file.unlock (fd);
+ if (sem == SEM_FAILED)
+ __leave;
+ /* If wasopen is set, the semaphore was already opened and we already have
+ an open file descriptor pointing to the file. This means, we have to
+ close the file descriptor created in this call. It won't be stored
+ anywhere anyway. */
+ if (wasopen)
+ close (fd);
+ return sem;
+ }
+ __except (EFAULT) {}
+ __endtry
+ /* Don't let following function calls change errno */
+ save_errno save;
+
+ if (fd >= 0)
+ file.unlock (fd);
+ if (created)
+ unlink (semname);
+ if (sem != SEM_FAILED)
+ semaphore::close (sem);
+ if (fd >= 0)
+ close (fd);
+ return SEM_FAILED;
+}
+
+extern "C" off_t lseek64 (int, off_t, int);
+
+int
+_sem_close (sem_t *sem, bool do_close)
+{
+ sem_finfo sf;
+ int fd, ret = -1;
+ ipc_flock file;
+
+ if (semaphore::getinternal (sem, &fd, &sf.hash, &sf.luid, &sf.value) == -1)