Exemplo n.º 1
0
_WCRTLINK FILE *tmpfile( void )         /* create a temporary file */
{
    char    tmpfnext;
    int     fd;
    FILE    *fp;
    char    name[L_tmpnam];
    char    *ptr;

    ptr = __tmpdir( name );
    strcpy( ptr, _TMPFNAME );
    for( tmpfnext = 'a'; ; tmpfnext++ ) {
        ptr[_TMPFCHAR] = tmpfnext;
        fd = open( name, O_RDWR | O_CREAT | O_EXCL | O_TEMP, 0666 );
        if( fd != -1 ) break;
        if( errno != EEXIST ) return( NULL );
        if( tmpfnext == 'z' ) tmpfnext = 'A' - 1;
        if( tmpfnext == 'Z' ) return( NULL );
    }
    fp = fdopen( fd, "wb+" );
    if( fp != NULL ) {
        /* fp->_flag |= _TMPFIL;
           -- Don't turn the TMPFIL bit on... we're going to
              remove the filename from the file system right away.
              This is allowed under POSIX. The file will be deleted
              as soon as it's closed */
        _FP_TMPFCHAR(fp) = tmpfnext;
    } else {
        close( fd );
    }
    remove( name );
    return( fp );
}
Exemplo n.º 2
0
void __RmTmpFile( FILE *fp )
{
    char    name[PATH_MAX + _TMPFNAME_LENGTH + 1]; /* 02-aug-90 */

    __MkTmpFile( name, _FP_TMPFCHAR(fp) );
    remove( name );
}
Exemplo n.º 3
0
_WCRTLINK FILE *tmpfile( void )         /* create a temporary file */
{
    int         hdl;
    int         old_errno;
    int         our_errno;
    char        suffix1;
    char        suffix2;
    FILE        *fp;
    char        name1[PATH_MAX + _TMPFNAME_LENGTH + 1];
    char        name2[PATH_MAX + _TMPFNAME_LENGTH + 1];

    old_errno = _RWD_errno;
    suffix1 = 0;
    for( ;; ) {
        // Part I
        for( ;; ) {
            __MkTmpFile( name1, suffix1 );
            // if a file by this name does not exist
            if( access( name1, F_OK ) != 0 ) {

                // then let's try to create it
                hdl = sopen( name1, OPEN_MODE, OPENMODE_DENY_COMPAT, PMODE );

                // if we created it then continue with part II
                if( hdl != -1 )
                    break;
                _RWD_errno = EAGAIN;
            }
            suffix1++;
            // give up after _TMP_INIT_CHAR tries  JBS 99/10/26
            if( suffix1 >= _TMP_INIT_CHAR ) return NULL;
        }
        close( hdl );

        // Part II
        /* we now have a empty file. Let's try to rename it
           rename should be an atomic operation in the operating system
           so if it succeeds we can be sure no one else has this file.
           Consider the following sequence:

           task1: access x.y => file does not exist
           task2: access x.y => file does not exist
           task1: fopen  x.y => succeeds
           task2: fopen  x.y => succeeds (now have both tasks with x.y open)
           task1: rename x.y to y.y => succeeds, can use this file
           task2: rename x.y to y.y => fails (because x.y no longer exists)
           task2: start over again to get a new file name
           task2: succeeds second time around since no more race condition
                  with task1.
         */
        suffix2 = _RWD_tmpfnext;    // only one of these per process
        for( ;; ) {
            if( suffix2 == suffix1 ) {
                suffix2++;
            }
            __MkTmpFile( name2, suffix2 );

            if( rename( name1, name2 ) == 0 ) { // if rename worked

                // The file is now ours. Let's try to open it.
                fp = fopen( name2, "wb+" );
                if( fp != NULL ) {
                    fp->_flag |= _TMPFIL;
                    _FP_TMPFCHAR(fp) = suffix2;
                    _RWD_errno = old_errno;
                    return( fp );
                }
                // We couldn't open it, probably because we have run out of handles.
                // Remove the renamed file.
                our_errno = _RWD_errno;
                remove( name2 );
                _RWD_errno = our_errno;
                return( NULL );
            }
            // The rename didn't work or we couldn't open the renamed file.
            // One of two possibilities:
            // (1) The "to" name already exists.
            // (2) Another process renamed it away from us.

            // Check for case (2).
            // Quit if "from" file is gone and start over.
            if( access( name1, F_OK ) != 0 ) break;

            // Must be case (1). Try another "to" name.
            ++suffix2;
            if( suffix2 == 0 ) {
                suffix2 = _TMP_INIT_CHAR;
            }
            _RWD_tmpfnext = suffix2;    // update for all processes
        }
    }
}