Re: Determine if open(2) created or opened (again)

From: Juha Laiho (Juha.Laiho_at_iki.fi)
Date: 05/23/04


Date: Sun, 23 May 2004 10:52:02 GMT

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)


Relevant Pages

  • Re: Batch file and MFC (Properly Terminating Application)
    ... I never worked with MFC before and I wanted a response ... at it and then make corrections-that is, practice, practice and ... that processes user inputsuch as clicking of Exit Button. ... I give user a few seconds for each input via a while loop where I call ...
    (microsoft.public.vc.mfc)
  • Re: strlen(), K+1: clarification
    ... )> And if Clive used an invariant in a for loop, well, what's wrong with ... a for loop. ... It IS good practice. ... of the terminating value is automatically hoisted out of the loop ...
    (comp.programming)
  • Re: Perform Thru/Go to vs. Perform - Compile Speed
    ... various fields and possibilities but no necessity to loop or jump out of line. ... As a maintenance programmer by trade ... The people who never use THRU because disaster can happen if there's an extra label ... there are quite correct in their practice. ...
    (comp.lang.cobol)
  • Re: strlen(), K+1: clarification
    ... )> And if Clive used an invariant in a for loop, well, what's wrong with ... a for loop. ... It IS good practice. ... of the terminating value is automatically hoisted out of the loop ...
    (comp.programming)

Loading