* sem_open.c (sem_open): Fix handling of O_CREAT without O_EXCL.
This commit is contained in:
Ulrich Drepper 2003-02-25 06:19:22 +00:00
parent 80d807799f
commit 3857ca787c
2 changed files with 46 additions and 42 deletions

View File

@ -1,5 +1,7 @@
2003-02-24 Ulrich Drepper <drepper@redhat.com> 2003-02-24 Ulrich Drepper <drepper@redhat.com>
* sem_open.c (sem_open): Fix handling of O_CREAT without O_EXCL.
* tst-cond2.c: Fix sychronization with child. * tst-cond2.c: Fix sychronization with child.
* tst-rwlock8.c (reader_thread): Remove unused variable. * tst-rwlock8.c (reader_thread): Remove unused variable.

View File

@ -126,7 +126,7 @@ sem_t *
sem_open (const char *name, int oflag, ...) sem_open (const char *name, int oflag, ...)
{ {
char *finalname; char *finalname;
size_t namelen; size_t namelen = SEM_FAILED;
sem_t *result; sem_t *result;
int fd; int fd;
@ -158,19 +158,24 @@ sem_open (const char *name, int oflag, ...)
name, namelen + 1); name, namelen + 1);
/* If the semaphore object has to exist simply open it. */ /* If the semaphore object has to exist simply open it. */
if ((oflag & O_CREAT) == 0) if ((oflag & O_CREAT) == 0 || (oflag & O_EXCL) == 0)
{ {
fd = __libc_open (finalname, oflag | O_NOFOLLOW); try_again:
fd = __libc_open (finalname,
(oflag & ~(O_CREAT|O_ACCMODE)) | O_NOFOLLOW | O_RDWR);
if (fd == -1) if (fd == -1)
/* Return. errno is already set. */ {
return SEM_FAILED; /* If we are supposed to create the file try this next. */
if ((oflag & O_CREAT) != 0)
goto try_create;
/* Map the sem_t structure from the file. */ /* Return. errno is already set. */
result = (sem_t *) mmap (NULL, sizeof (sem_t), PROT_READ | PROT_WRITE, }
MAP_SHARED, fd, 0); else
if (MAP_FAILED != (void *) SEM_FAILED && result == MAP_FAILED) /* Map the sem_t structure from the file. */
result = SEM_FAILED; result = (sem_t *) mmap (NULL, sizeof (sem_t), PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
} }
else else
{ {
@ -181,6 +186,7 @@ sem_open (const char *name, int oflag, ...)
unsigned int value; unsigned int value;
va_list ap; va_list ap;
try_create:
va_start (ap, oflag); va_start (ap, oflag);
mode = va_arg (ap, mode_t); mode = va_arg (ap, mode_t);
@ -213,46 +219,42 @@ sem_open (const char *name, int oflag, ...)
sizeof (sem_t) - sizeof (struct sem)); sizeof (sem_t) - sizeof (struct sem));
if (TEMP_FAILURE_RETRY (__libc_write (fd, &initsem, sizeof (sem_t))) if (TEMP_FAILURE_RETRY (__libc_write (fd, &initsem, sizeof (sem_t)))
!= sizeof (sem_t) == sizeof (sem_t)
/* Adjust the permission. */ /* Adjust the permission. */
|| fchmod (fd, mode) != 0) && fchmod (fd, mode) == 0
/* Map the sem_t structure from the file. */
&& (result = (sem_t *) mmap (NULL, sizeof (sem_t),
PROT_READ | PROT_WRITE, MAP_SHARED,
fd, 0)) != MAP_FAILED)
{ {
unlink_return: /* Create the file. Don't overwrite an existing file. */
unlink (tmpfname); if (link (tmpfname, finalname) != 0)
return SEM_FAILED;
}
/* Map the sem_t structure from the file. */
result = (sem_t *) mmap (NULL, sizeof (sem_t), PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (result == MAP_FAILED)
goto unlink_return;
/* Create or overwrite the file. Depending on what is wanted we
use rename or link. */
if ((oflag & O_EXCL) == 0)
{
/* An existing file gets overwritten. */
if (rename (tmpfname, finalname) != 0)
{ {
unmap_unlink_return: /* Remove the file. */
munmap (result, sizeof (sem_t)); unlink (tmpfname);
goto unlink_return;
/* Undo the mapping. */
(void) munmap (result, sizeof (sem_t));
/* Reinitialize 'result'. */
result = SEM_FAILED;
/* This failed. If O_EXCL is not set and the problem was
that the file exists, try again. */
if ((oflag & O_EXCL) == 0 && errno == EEXIST)
goto try_again;
} }
} }
else
{
/* Don't overwrite an existing file. */
if (link (tmpfname, finalname) != 0)
goto unmap_unlink_return;
/* This went well. Now remove the temporary name. This /* Now remove the temporary name. This should never fail. If
should never fail. If it fails we leak a file name. it fails we leak a file name. Better fix the kernel. */
Better fix the kernel. */ (void) unlink (tmpfname);
(void) unlink (tmpfname);
}
} }
/* Map the mmap error to the error we need. */
if (MAP_FAILED != (void *) SEM_FAILED && result == MAP_FAILED)
result = SEM_FAILED;
/* We don't need the file descriptor anymore. */ /* We don't need the file descriptor anymore. */
__libc_close (fd); __libc_close (fd);