Subversion Repositories DevTools

Rev

Blame | Last modification | View Log | RSS feed

/***************************************************************************
* Module name   : mktemp.c
* Module type   : CMDFILE source file
* Environment(s): n/a
*
* Description:
*
    Build 'binary' temp file ...
*
* Version   Who      Date        Description
            APY      12/99       Created
            APY      07//2001    WIN32 support
*
* $Source: /cvsroot/device/DEVL/UTILS/CMDFILE/mktemp.c,v $            
* $Revision: 1.1 $ $Date: 2002/08/02 06:49:28 $ $State: Exp $ 
* $Author: adamy $ $Locker:  $
*.........................................................................*/

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if defined(MSDOS)
#include <process.h>                            /* getpid() */
#endif
#if defined(WIN32)
#include <process.h>
#include <windows.h>
#endif
#include <errno.h>
#include "unistd.h"

#if defined(WIN32)
#define DISABLE_HARD_ERRORS     SetErrorMode (0);
#define ENABLE_HARD_ERRORS      SetErrorMode (SEM_FAILCRITICALERRORS | \
                                        SEM_NOOPENFILEERRORBOX);
#else
#define DISABLE_HARD_ERRORS
#define ENABLE_HARD_ERRORS
#endif


static int
_gettemp(char *path, register int *fd)
{
        register char *start, *trv;
        struct stat sbuf;
        unsigned pid;
        int rc;
        char c;

        pid = (unsigned)getpid();
        for (trv = path; *trv; ++trv);          /* extra X's get set to 0's */
        while (*--trv == 'X' && trv >= path) {
                *trv = (pid % 10) + '0';
                pid /= 10;
        }

        /*
         * check the target directory; if you have six X's and it
         * doesn't exist this runs for a *very* long time.
         */
        for (start = trv + 1;; --trv) {
                if (trv <= path)
                        break;
                if ((c = *trv) == '/' || c == '\\') {
                        *trv = '\0';
                        if (trv[-1] == ':') {
                                *trv = c;
                                break;
                        }
                        DISABLE_HARD_ERRORS
                        rc = stat(path, &sbuf);
                        ENABLE_HARD_ERRORS
                        if (rc)
                                return(0);
                        if (!(sbuf.st_mode & S_IFDIR)) {
                                errno = ENOTDIR;
                                return(0);
                        }
                        *trv = c;
                        break;
                }
        }

        for (;;) {
                if (fd) {
                        if ((*fd =
#if defined(MSDOS) || defined(WIN32)
                            open(path, O_CREAT|O_EXCL|O_RDWR|O_BINARY, 0600)) >= 0)
#else
                            open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
#endif
                                return(1);
                        if (errno != EEXIST)
                                return(0);
                }
                else
                {
                    DISABLE_HARD_ERRORS
                    rc = stat(path, &sbuf);
                    ENABLE_HARD_ERRORS
                    if (rc)
                    {
#ifndef ENMFILE
                        return(((errno == ENOENT)) ? 1 : 0);
#else
                        return(((errno == ENOENT) || (errno == ENMFILE)) ? 1 : 0);
#endif
                    }
                }

                /* tricky little algorithm for backward compatibility */
                for (trv = start;;) {
                        if (*trv == '\0')       /* EOS */
                                return(0);
                        if (*trv == 'z')
                                *trv++ = 'a';
                        else {
                                if (isdigit(*trv))
                                        *trv = 'a';
                                else
                                        ++*trv;
                                break;
                        }
                }
        }
        /*NOTREACHED*/
}


int
mkstemp(char *path)
{
        int fd;

        return (_gettemp(path, &fd) ? fd : -1);
}