📄 tmpfile.c
字号:
}
else if ( genfname(tmpfile_buf, _countof(tmpfile_buf), _TMP_MAX_S) )
goto tmpfile_err;
/*
* Get a free stream.
*
* Note: In multi-thread models, the stream obtained below is locked!
*/
if ( (stream = _getstream()) == NULL ) {
retval = EMFILE;
goto tmpfile_err;
}
stream_lock_held = 1;
/*
* 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.
*/
save_errno = errno;
errno = 0;
while ( (_sopen_s(&fh, tmpfile_buf,
_O_CREAT | _O_EXCL | _O_RDWR | _O_BINARY |
_O_TEMPORARY,
shflag,
_S_IREAD | _S_IWRITE
) == EEXIST) )
{
if ( genfname(tmpfile_buf, _countof(tmpfile_buf), _TMP_MAX_S) )
break;
}
if(errno == 0)
{
errno = save_errno;
}
/*
* Check that the loop above did indeed create a temporary
* file.
*/
if ( fh == -1 )
goto tmpfile_err;
/*
* Initialize stream
*/
#ifdef _DEBUG
if ( (stream->_tmpfname = _calloc_crt( (_tcslen( tmpfile_buf ) + 1), sizeof(_TSCHAR) )) == NULL )
#else /* _DEBUG */
if ( (stream->_tmpfname = _tcsdup( tmpfile_buf )) == NULL )
#endif /* _DEBUG */
{
/* close the file, then branch to error handling */
_close(fh);
goto tmpfile_err;
}
#ifdef _DEBUG
_ERRCHECK(_tcscpy_s( stream->_tmpfname, _tcslen( tmpfile_buf ) + 1, tmpfile_buf ));
#endif /* _DEBUG */
stream->_cnt = 0;
stream->_base = stream->_ptr = NULL;
stream->_flag = _commode | _IORW;
stream->_file = fh;
*pFile = stream;
/*
* All errors branch to the label below.
*/
tmpfile_err:;
}
__finally {
if ( stream_lock_held )
_unlock_str(stream);
_munlock(_TMPNAM_LOCK);
}
if (retval != 0)
{
errno = retval;
}
return retval ;
}
/***
*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 * fp = NULL;
_tmpfile_helper(&fp, _SH_DENYNO);
return fp;
}
/***
*errno_t *tmpfile_s - 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. Similiar to tmpfile, except that it opens the tmpfile in
* _SH_DENYRW share mode.
*
*Entry:
* FILE ** pFile - in param to fill the FILE * to.
*
*Exit:
* returns 0 on success & sets pfile
* returns errno_t on failure.
* On success, fills in the FILE pointer into the in param.
*
*Exceptions:
*
*******************************************************************************/
errno_t __cdecl tmpfile_s (FILE ** pFile)
{
return _tmpfile_helper(pFile, _SH_DENYRW);
}
#endif /* _UNICODE */
/***
*static void init_namebuf(flag) - initializes the namebuf arrays
*
*Purpose:
* Called once each for tmpnam_buf and tmpfile_buf, to initialize
* them.
*
*Entry:
* int flag - flag set to 0 if tmpnam_buf is to be initialized,
* set to 1 if tmpfile_buf is to be initialized.
* set to 2 if tmpnam_s_buf 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;
size_t size = 0;
switch(flag)
{
case 0 :
p = tmpnam_buf;
size = _countof(tmpnam_buf);
break;
case 1 :
p = tmpfile_buf;
size = _countof(tmpfile_buf);
break;
case 2 :
p = tmpnam_s_buf;
size = _countof(tmpnam_s_buf);
break;
}
/*
* Put in the path prefix. Make sure it ends with a slash or
* backslash character.
*/
#ifdef _UNICODE
_ERRCHECK(wcscpy_s(p, size, _wP_tmpdir));
#else /* _UNICODE */
_ERRCHECK(strcpy_s(p, size, _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 == _TMPFILE_BUFFER )
/* for tmpfile() */
*(q++) = _T('t');
else
/* for tmpnam() & _tmpnam_s */
*(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').
*/
_ERRCHECK(_ultot_s((unsigned long)_getpid(), q, size - (q - p), 32));
_ERRCHECK(_tcscat_s(p, size, _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, size_t fnameSize, unsigned long tmp_max
)
{
_TSCHAR *p;
_TSCHAR pext[8]; // 7 positions for base 32 ulong + null terminator
unsigned long extnum;
p = _tcsrchr(fname, _T('.'));
p++;
_VALIDATE_RETURN_NOERRNO(p >= fname && fnameSize > (size_t)(p-fname), -1);
if ( (extnum = _tcstoul(p, NULL, 32) + 1) >= tmp_max )
return -1;
_ERRCHECK(_ultot_s(extnum, pext, _countof(pext), 32));
_ERRCHECK(_tcscpy_s(p, fnameSize - (p - fname), pext));
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) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -