home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Windows Gam…ming Gurus (2nd Edition)
/
Disc2.iso
/
vc98
/
crt
/
src
/
tmpfile.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-17
|
16KB
|
621 lines
/***
*tmpfile.c - create unique file name or file
*
* Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines tmpnam() and tmpfile().
*
*******************************************************************************/
#ifdef _WIN32
#include <cruntime.h>
#include <errno.h>
#include <process.h>
#include <fcntl.h>
#include <io.h>
#include <mtdll.h>
#include <share.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <file2.h>
#include <internal.h>
#include <tchar.h>
#include <dbgint.h>
/*
* Buffers used by tmpnam() and tmpfile() to build filenames.
*/
static _TSCHAR namebuf0[L_tmpnam] = { 0 }; /* used by tmpnam() */
static _TSCHAR namebuf1[L_tmpnam] = { 0 }; /* used by tmpfile() */
/*
* Initializing function for namebuf0 and namebuf1.
*/
#ifdef _UNICODE
static void __cdecl winit_namebuf(int);
#else /* _UNICODE */
static void __cdecl init_namebuf(int);
#endif /* _UNICODE */
/*
* Generator function that produces temporary filenames
*/
#ifdef _UNICODE
static int __cdecl wgenfname(wchar_t *);
#else /* _UNICODE */
static int __cdecl genfname(char *);
#endif /* _UNICODE */
/***
*_TSCHAR *tmpnam(_TSCHAR *s) - generate temp file name
*
*Purpose:
* Creates a file name that is unique in the directory specified by
* _P_tmpdir in stdio.h. Places file name in string passed by user or
* in static mem if pass NULL.
*
*Entry:
* _TSCHAR *s - ptr to place to put temp name
*
*Exit:
* returns pointer to constructed file name (s or address of static mem)
* returns NULL if fails
*
*Exceptions:
*
*******************************************************************************/
_TSCHAR * __cdecl _ttmpnam (
_TSCHAR *s
)
{
#ifdef _MT
_ptiddata ptd;
#endif /* _MT */
_mlock(_TMPNAM_LOCK);
/*
* Initialize namebuf0, if needed. Otherwise, call genfname() to
* generate the next filename.
*/
if ( *namebuf0 == 0 ) {
#ifdef _UNICODE
winit_namebuf(0);
#else /* _UNICODE */
init_namebuf(0);
#endif /* _UNICODE */
}
#ifdef _UNICODE
else if ( wgenfname(namebuf0) )
#else /* _UNICODE */
else if ( genfname(namebuf0) )
#endif /* _UNICODE */
goto tmpnam_err;
/*
* Generate a filename that doesn't already exist.
*/
while ( _taccess(namebuf0, 0) == 0 )
#ifdef _UNICODE
if ( wgenfname(namebuf0) )
#else /* _UNICODE */
if ( genfname(namebuf0) )
#endif /* _UNICODE */
goto tmpnam_err;
/*
* Filename has successfully been generated.
*/
if ( s == NULL )
#ifdef _MT
{
/*
* Use a per-thread buffer to hold the generated file name.
* If there isn't one, and one cannot be created, just use
* namebuf0.
*/
ptd = _getptd();
#ifdef _UNICODE
if ( (ptd->_wnamebuf0 != NULL) || ((ptd->_wnamebuf0 =
_malloc_crt(L_tmpnam * sizeof(wchar_t))) != NULL) )
{
s = ptd->_wnamebuf0;
wcscpy(s, namebuf0);
}
#else /* _UNICODE */
if ( (ptd->_namebuf0 != NULL) || ((ptd->_namebuf0 =
_malloc_crt(L_tmpnam)) != NULL) )
{
s = ptd->_namebuf0;
strcpy(s, namebuf0);
}
#endif /* _UNICODE */
else
s = namebuf0;
}
#else /* _MT */
s = namebuf0;
#endif /* _MT */
else
_tcscpy(s, namebuf0);
_munlock(_TMPNAM_LOCK);
return s;
/*
* Error return path. All errors exit through here.
*/
tmpnam_err:
_munlock(_TMPNAM_LOCK);
return NULL;
}
#ifndef _UNICODE
/***
*FILE *tmpfile() - create a temporary file
*
*Purpose:
* Creates a temporary file with the file mode "w+b". The file
* will be automatically deleted when closed or the program terminates
* normally.
*
*Entry:
* None.
*
*Exit:
* Returns stream pointer to opened file.
* Returns NULL if fails
*
*Exceptions:
*
*******************************************************************************/
FILE * __cdecl tmpfile (
void
)
{
FILE *stream;
int fh;
_mlock(_TMPNAM_LOCK);
/*
* Initialize namebuf1, if needed. Otherwise, call genfname() to
* generate the next filename.
*/
if ( *namebuf1 == 0 ) {
init_namebuf(1);
}
else if ( genfname(namebuf1) )
goto tmpfile_err0;
/*
* Get a free stream.
*
* Note: In multi-thread models, the stream obtained below is locked!
*/
if ( (stream = _getstream()) == NULL )
goto tmpfile_err0;
/*
* Create a temporary file.
*
* Note: The loop below will only create a new file. It will NOT
* open and truncate an existing file. Either behavior is probably
* legal under ANSI (4.9.4.3 says tmpfile "creates" the file, but
* also says it is opened with mode "wb+"). However, the behavior
* implemented below is compatible with prior versions of MS-C and
* makes error checking easier.
*/
while ( ((fh = _sopen(namebuf1,
_O_CREAT | _O_EXCL | _O_RDWR | _O_BINARY |
_O_TEMPORARY,
_SH_DENYNO,
_S_IREAD | _S_IWRITE
))
== -1) && (errno == EEXIST) )
if ( genfname(namebuf1) )
break;
/*
* Check that the loop above did indeed create a temporary
* file.
*/
if ( fh == -1 )
goto tmpfile_err1;
/*
* Initialize stream
*/
#ifdef _DEBUG
if ( (stream->_tmpfname = _malloc_crt( (_tcslen( namebuf1 ) + 1) *
sizeof(_TSCHAR) )) == NULL )
#else /* _DEBUG */
if ( (stream->_tmpfname = _tcsdup( namebuf1 )) == NULL )
#endif /* _DEBUG */
{
/* close the file, then branch to error handling */
_close(fh);
goto tmpfile_err1;
}
#ifdef _DEBUG
_tcscpy( stream->_tmpfname, namebuf1 );
#endif /* _DEBUG */
stream->_cnt = 0;
stream->_base = stream->_ptr = NULL;
stream->_flag = _commode | _IORW;
stream->_file = fh;
_unlock_str(stream);
_munlock(_TMPNAM_LOCK);
return stream;
/*
* Error return. All errors paths branch to one of the two
* labels below.
*/
tmpfile_err1:
_unlock_str(stream);
tmpfile_err0:
_munlock(_TMPNAM_LOCK);
return NULL;
}
#endif /* _UNICODE */
/***
*static void init_namebuf(flag) - initializes the namebuf arrays
*
*Purpose:
* Called once each for namebuf0 and namebuf1, to initialize
* them.
*
*Entry:
* int flag - flag set to 0 if namebuf0 is to be initialized,
* non-zero (1) if namebuf1 is to be initialized.
*Exit:
*
*Exceptions:
*
*******************************************************************************/
#ifdef _UNICODE
static void __cdecl winit_namebuf(
#else /* _UNICODE */
static void __cdecl init_namebuf(
#endif /* _UNICODE */
int flag
)
{
_TSCHAR *p, *q;
if ( flag == 0 )
p = namebuf0;
else
p = namebuf1;
/*
* Put in the path prefix. Make sure it ends with a slash or
* backslash character.
*/
#ifdef _UNICODE
wcscpy(p, _wP_tmpdir);
#else /* _UNICODE */
strcpy(p, _P_tmpdir);
#endif /* _UNICODE */
q = p + sizeof(_P_tmpdir) - 1; /* same as p + _tcslen(p) */
if ( (*(q - 1) != _T('\\')) && (*(q - 1) != _T('/')) )
*(q++) = _T('\\');
/*
* Append the leading character of the filename.
*/
if ( flag )
/* for tmpfile() */
*(q++) = _T('t');
else
/* for tmpnam() */
*(q++) = _T('s');
/*
* Append the process id, encoded in base 32. Note this makes
* p back into a string again (i.e., terminated by a '\0').
*/
_ultot((unsigned long)_getpid(), q, 32);
_tcscat(p, _T("."));
}
/***
*static int genfname(_TSCHAR *fname) -
*
*Purpose:
*
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
#ifdef _UNICODE
static int __cdecl wgenfname (
#else /* _UNICODE */
static int __cdecl genfname (
#endif /* _UNICODE */
_TSCHAR *fname
)
{
_TSCHAR *p;
_TSCHAR pext[4];
unsigned long extnum;
p = _tcsrchr(fname, _T('.'));
p++;
if ( (extnum = _tcstoul(p, NULL, 32) + 1) >= (unsigned long)TMP_MAX )
return -1;
_tcscpy(p, _ultot(extnum, pext, 32));
return 0;
}
#if !defined (_UNICODE) && !defined (CRTDLL)
/***
*void __inc_tmpoff(void) - force external reference for _tmpoff
*
*Purpose:
* Forces an external reference to be generate for _tmpoff, which is
* is defined in cinittmp.obj. This has the forces cinittmp.obj to be
* pulled in, making a call to rmtmp part of the termination.
*
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
extern int _tmpoff;
void __inc_tmpoff(
void
)
{
_tmpoff++;
}
#endif /* !defined (_UNICODE) && !defined (CRTDLL) */
#else /* _WIN32 */
#if defined (_M_MPPC) || defined (_M_M68K)
#include <cruntime.h>
#include <stdio.h>
#include <share.h>
#include <stdlib.h>
#include <file2.h>
#include <io.h>
#include <malloc.h>
#include <errno.h>
#include <internal.h>
#include <string.h>
#include <dbgint.h>
#include <macos\osutils.h>
#include <macos\files.h>
#include <macos\errors.h>
#include <macos\gestalte.h>
#include <macos\traps.h>
#include <macos\toolutil.h>
#include <macos\folders.h>
static char namebuf[L_tmpnam]; /* internal static buffer for tmpnam */
/***
*char *tmpnam(s) - generate temp file name
*
*Purpose:
* Creates a file name that is unique in the directory specified by
* _P_tmpdir in stdio.h. Places file name in string passed by user or
* in static mem if pass NULL.
*
*Entry:
* char *s - ptr to place to put temp name
*
*Exit:
* returns pointer to constructed file name (s or address of static mem)
* returns NULL if fails
*
*Exceptions:
*
*******************************************************************************/
char * __cdecl tmpnam (
REG1 char *s
)
{
int olderrno;
unsigned int first;
OSErr osErr;
short foundVRefNum;
long foundDirID;
HParamBlockRec hparamBlock;
CInfoPBRec cinfoPB;
char *ptmp;
Str255 st, st2;
int fwrapped;
/* use internal buffer if user didn't provide one */
if (s == NULL)
s = namebuf;
/* construct base name */
*s = '\0';
/*decide if we are in system 7.0 or earlier version*/
/*if system 7.0, put in temp file folder, otherwise*/
/*put in system folder*/
hparamBlock.volumeParam.ioNamePtr = &st2[0];
hparamBlock.volumeParam.ioVRefNum = 0;
hparamBlock.volumeParam.ioVolIndex = 1;
osErr = PBHGetVInfoSync(&hparamBlock);
if (osErr)
{
return NULL;
}
if (__TrapFromGestalt(gestaltFindFolderAttr, gestaltFindFolderPresent))
{
osErr = FindFolder((unsigned short)kOnSystemDisk, (OSType)kTemporaryFolderType, (Boolean)kCreateFolder,
&foundVRefNum, &foundDirID);
if (osErr)
{
return NULL;
}
}
else /* put into system folder */
{
foundVRefNum = hparamBlock.volumeParam.ioVRefNum;
foundDirID = hparamBlock.volumeParam.ioVFndrInfo[0];
if (!foundDirID)
{
return NULL;
}
}
/* get full pathname -- folder name to put tmp file*/
cinfoPB.dirInfo.ioVRefNum = foundVRefNum;
cinfoPB.dirInfo.ioDrDirID = foundDirID;
cinfoPB.dirInfo.ioFDirIndex = -1; /*use ioDirID only*/
cinfoPB.dirInfo.ioNamePtr = &st[0];
osErr = PBGetCatInfoSync(&cinfoPB);
if (osErr)
{
return NULL;
}
else
{
_p2cstr(st); /* dir name system folder or temp items */
_p2cstr(st2); /* volume name */
strcpy(s, st2);
strcat(s, ":");
strcat(s, st);
}
/* Loop until a non-existent filename is found */
strcat(s, ":");
ptmp = s + strlen(s);
olderrno = errno;
first = _tmpoff;
fwrapped = 0;
do {
if (_tmpoff > TMP_MAX )
{
if (!fwrapped)
{
_tmpoff = 1;
fwrapped = 1;
}
else
{
return (NULL);
}
}
_itoa( _tmpoff, ptmp, 10 );
_tmpoff++;
errno = 0;
}
while ( ( _access( s, 0 ) == 0 ) || ( errno == EACCES ) );
errno = olderrno;
return( s );
}
/***
*FILE *tmpfile() - create a temporary file
*
*Purpose:
* Creates a temporary file with the file mode "w+b". The file
* will be automatically deleted when closed or the program terminates
* normally.
*
*Entry:
* None.
*
*Exit:
* Returns stream pointer to opened file.
* Returns NULL if fails
*
*Exceptions:
*
*******************************************************************************/
FILE * __cdecl tmpfile (
void
)
{
char name[ L_tmpnam ];
char *ptr;
FILE *stream;
int tmpnum;
FILE *retval;
/* Call tmpnam() to generate the filename. Save the _tmpoff value. */
ptr = name;
ptr = tmpnam( ptr );
tmpnum = _tmpoff - 1;
/* Now get a free stream and open the file. */
if ((stream = _getstream()) == NULL)
return(NULL);
retval = _openfile(name,"w+b",_SH_DENYNO,stream);
if (retval != NULL)
#ifdef _DEBUG
if ( (stream->_tmpfname = _malloc_crt( strlen(ptr) + 1 ))
!= NULL )
strcpy(stream->_tmpfname, ptr);
#else /* _DEBUG */
stream->_tmpfname = _strdup(ptr); /* store _tmpoff value */
#endif /* _DEBUG */
return(retval);
}
#endif /* defined (_M_MPPC) || defined (_M_M68K) */
#endif /* _WIN32 */