diff options
Diffstat (limited to 'private/crt32/stdio/tempnam.c')
-rw-r--r-- | private/crt32/stdio/tempnam.c | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/private/crt32/stdio/tempnam.c b/private/crt32/stdio/tempnam.c new file mode 100644 index 000000000..4539ba870 --- /dev/null +++ b/private/crt32/stdio/tempnam.c @@ -0,0 +1,262 @@ +/*** +*tempnam.c - generate unique file name +* +* Copyright (c) 1986-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* +*Revision History: +* ??-??-?? TC initial version +* 04-17-86 JMB changed directory of last resort from \tmp to tmp. +* eliminated use of L_tmpnam (it was incoorectly defined +* in stdio.h and should not be used in tempnam; see +* System V definition of tempnam. +* 04-23-86 TC changed last try directory from tmp to current directory +* 04-29-86 JMB bug fix: pfxlength was being set from strlen(pfx) +* even if pfx was NULL. Fixed to set pfxlength to zero +* if pfx is NULL, strlen(pfx) otherwise. +* 05-28-86 TC changed stat's to access's, and optimized code a bit +* 12-01-86 JMB added support for Kanji file names until KANJI switch +* 12-15-86 JMB free malloced memory if (++_tmpoff == first) +* 07-15-87 JCR Re-init _tempoff based on length of pfx (fixes infinate +* loop bug; also, tempnam() now uses _tempoff instead of +* _tmpoff (used by tmpnam()). +* 10-16-87 JCR Fixed bug in _tempoff re-init code if pfx is NULL. +* 11-09-87 JCR Multi-thread version +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 05-27-88 PHG Merged DLL and normal versions +* 06-09-89 GJF Propagated MT's change of 05-17-89 (Kanji) +* 02-16-90 GJF Fixed copyright and indents +* 03-19-90 GJF Replaced _LOAD_DS and _CALLTYPE1 and added #include +* <cruntime.h>. +* 03-26-90 GJF Added #include <io.h>. +* 08-13-90 SBM Compiles cleanly with -W3, replaced explicit register +* declarations by REGn references +* 10-03-90 GJF New-style function declarator. +* 01-21-91 GJF ANSI naming. +* 08-19-91 JCR Allow quotes in TMP variable path +* 08-27-91 JCR ANSI naming +* 08-25-92 GJF Don't build for POSIX. +* 11-30-92 KRS Generalize KANJI support to MBCS. Port 16-bit bug fix. +* +*******************************************************************************/ + +#ifndef _POSIX_ + +#include <cruntime.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <io.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <malloc.h> +#include <string.h> +#include <internal.h> +#include <os2dll.h> + +#ifdef _MBCS +#include <mbstring.h> +#endif + +static char * _stripquote (char *); + +/*** +*char *_tempnam(dir, prefix) - create unique file name +* +*Purpose: +* Create a file name that is unique in the specified directory. +* The semantics of directory specification is as follows: +* Use the directory specified by the TMP environment variable +* if that exists, else use the dir argument if non-NULL, else +* use _P_tmpdir if that directory exists, else use the current +* working directory), else return NULL. +* +*Entry: +* char *dir - directory to be used for temp file if TMP env var +* not set +* char *prefix - user provided prefix for temp file name +* +*Exit: +* returns ptr to constructed file name if successful +* returns NULL if unsuccessful +* +*Exceptions: +* +*******************************************************************************/ + +char * _CALLTYPE1 _tempnam ( + char *dir, + char *pfx + ) +{ + REG1 char *ptr; + REG2 unsigned int pfxlength=0; + char *s; + char *pfin; + unsigned int first; + char * qptr = NULL; /* ptr to TMP path with quotes stripped out */ + + /* try TMP path */ + if ( ( ptr = getenv( "TMP" ) ) && ( _access( ptr, 0 ) != -1 ) ) + dir = ptr; + + /* try stripping quotes out of TMP path */ + else if ( (ptr != NULL) && (qptr = _stripquote(ptr)) && + (_access(qptr, 0) != -1 ) ) + dir = qptr; + + /* TMP path not available, use alternatives */ + else if (!( dir != NULL && ( _access( dir, 0 ) != -1 ) ) ) + /* do not "simplify" this depends on side effects!! */ + { + free(qptr); /* free buffer, if non-NULL */ + if ( _access( _P_tmpdir, 0 ) != -1 ) + dir = _P_tmpdir; + else + dir = "."; + } + + + if (pfx) + pfxlength = strlen(pfx); + if ( ( s = malloc(strlen(dir) + pfxlength + 8 ) ) == NULL ) + /* the 8 above allows for a backslash, 6 char temp string and + a null terminator */ + { + goto done2; + } + *s = '\0'; + strcat( s, dir ); + pfin = &(dir[ strlen( dir ) - 1 ]); +#ifdef _MBCS + if (*pfin == '\\') { + if (pfin != _mbsrchr(dir,'\\')) + /* *pfin is second byte of a double-byte char */ + strcat( s, "\\" ); + } + else if (*pfin != '/') + strcat( s, "\\" ); +#else + if ( ( *pfin != '\\' ) && ( *pfin != '/' ) ) + { + strcat( s, "\\" ); + } +#endif + if ( pfx != NULL ) + { + strcat( s, pfx ); + } + ptr = &s[strlen( s )]; + + /* + Re-initialize _tempoff if necessary. If we don't re-init _tempoff, we + can get into an infinate loop (e.g., (a) _tempoff is a big number on + entry, (b) prefix is a long string (e.g., 8 chars) and all tempfiles + with that prefix exist, (c) _tempoff will never equal first and we'll + loop forever). + + [NOTE: To avoid a conflict that causes the same bug as that discussed + above, _tempnam() uses _tempoff; tmpnam() uses _tmpoff] + */ + + _mlock(_TMPNAM_LOCK); /* Lock access to _old_pfxlen and _tempoff */ + + if (_old_pfxlen < pfxlength) + _tempoff = 1; + _old_pfxlen = pfxlength; + + first = _tempoff; + + do { + if ( ++_tempoff == first ) { + free(s); + s = NULL; + goto done1; + } + _itoa( _tempoff, ptr, 10 ); + if ( strlen( ptr ) + pfxlength > 8 ) + { + *ptr = '\0'; + _tempoff = 0; + } + } + while ( (_access( s, 0 ) == 0 ) || (errno == EACCES) ); + + + /* Common return */ +done1: + _munlock(_TMPNAM_LOCK); /* release tempnam lock */ +done2: + free(qptr); /* free temp ptr, if non-NULL */ + return(s); +} + + + +/*** +*_stripquote() - Strip quotes out of a string +* +*Purpose: +* This routine strips quotes out of a string. This is necessary +* in the case where a file/path name has embedded quotes (i.e., +* new file system.) +* +* For example, +* c:\tmp\"a b c"\d --> c:\tmp\a b d\d +* +* NOTE: This routine makes a copy of the string since it may be +* passed a pointer to an environment variable that shouldn't be +* changed. It is up to the caller to free up the memory (if the +* return value is non-NULL). +* +*Entry: +* char * ptr = pointer to string +* +*Exit: +* char * ptr = pointer to copy of string with quotes gone. +* NULL = no quotes in string. +* +*Exceptions: +* +*******************************************************************************/ + +char * _stripquote (src) +char * src; +{ + char * dst; + char * ret; + unsigned int q = 0; + + + /* get a buffer for the new string */ + + if ((dst = malloc(strlen(src)+1)) == NULL) + return(NULL); + + /* copy the string stripping out the quotes */ + + ret = dst; /* save base ptr */ + + while (*src) { + + if (*src == '\"') { + src++; q++; + } + else + *dst++ = *src++; + } + + if (q) { + *dst = '\0'; /* final nul */ + return(ret); + } + else { + free(ret); + return(NULL); + } + +} + + +#endif /* _POSIX_ */ |