For Programmers: Free Programming Magazines  


Home > Archive > Unix Programming > May 2004 > Determine if open(2) created or opened (again)









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Determine if open(2) created or opened (again)
Michael B Allen

2004-05-23, 1:31 am

Some time ago I asked if there was a way to open a file and know if it
was actually created or if it was just opened. Someone posted a fairly
reasonable answer but strangely I can't find it in google groups.

Anyway, I've implemented what I recall about the answer but perhaps
someone confirm or provide a better solution? I've tested this to some
extent and it appears to work correctly.

Thanks,
Mike

int
opencre(const char *pathname, int flags, mode_t mode, int *cre)
{
int max = 3; /* maximum attempts to open */

if ((flags & O_CREAT) == 0) { /* bypass special procedure */
if (open(pathname, flags, mode) == -1) {
return -1;
}
*cre = 0;
return 0;
}
while (max--) {
/* fail if not exists */
if (open(pathname, flags & ~(O_CREAT | O_EXCL)) != -1) {
*cre = 0;
return 0;
} else if (errno != ENOENT) {
return -1;
}
/* fail if exits */
if (open(pathname, flags | O_EXCL, mode) != -1) {
*cre = 1;
return 0;
} else if (errno != EEXIST) {
return -1;
}
}

errno = EACCES;
return -1;
}
Juha Laiho

2004-05-23, 7:35 am

Michael B Allen <mba2000@ioplex.com> said:
>Some time ago I asked if there was a way to open a file and know if it
>was actually created or if it was just opened. Someone posted a fairly
>reasonable answer but strangely I can't find it in google groups.


Hmm.. that's an answer I'd like to see, as I think this is not possible.

>Anyway, I've implemented what I recall about the answer but perhaps
>someone confirm or provide a better solution? I've tested this to some
>extent and it appears to work correctly.


Hm. At least this causes a resource leak in form of file descriptors
(it doesn't return the fd returned by open(), so the file cannot be
closed, or accessed in any way). So, instead of returning '0' from this
function, you must store and return the real return value from the
call to "open".

In practice the code might work for most cases, but still it contains
the exact race condition that makes this functionality impossible.

Consider another piece of code that runs concurrently with this
one, and somehow manages to keep synchronous with this code.

First iteration of the while loop ("OC" = opencre; "X" = "other" code):
X: make sure file does not exist
OC: goes through the first "if" struture within the while loop
X: creates file
OC: goes through the second "if" structure within the while loop
.... and continue similarly through the remaining iterations through
the while loop, thus falling off to the "errno=EACCESS".

You can reduce the possibility of this race condition in practical
situations by increasing the "max" value, but the theoretical race
condition will always remain, because there is no atomic way to
open/create a file and return whether the file was created or merely
opened.



>int
>opencre(const char *pathname, int flags, mode_t mode, int *cre)
>{
> int max = 3; /* maximum attempts to open */
>
> if ((flags & O_CREAT) == 0) { /* bypass special procedure */
> if (open(pathname, flags, mode) == -1) {
> return -1;
> }
> *cre = 0;
> return 0;
> }
> while (max--) {
> /* fail if not exists */
> if (open(pathname, flags & ~(O_CREAT | O_EXCL)) != -1) {
> *cre = 0;
> return 0;
> } else if (errno != ENOENT) {
> return -1;
> }
> /* fail if exits */
> if (open(pathname, flags | O_EXCL, mode) != -1) {
> *cre = 1;
> return 0;
> } else if (errno != EEXIST) {
> return -1;
> }
> }
>
> errno = EACCES;
> return -1;
>}


--
Wolf a.k.a. Juha Laiho Espoo, Finland
(GC 3.0) GIT d- s+: a C++ ULSH++++$ P++@ L+++ E- W+$@ N++ !K w !O !M V
PS(+) PE Y+ PGP(+) t- 5 !X R !tv b+ !DI D G e+ h---- r+++ y++++
"...cancel my subscription to the resurrection!" (Jim Morrison)
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com