/*** *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 * . * 03-26-90 GJF Added #include . * 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 #include #include #include #include #include #include #include #include #include #include #ifdef _MBCS #include #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_ */