home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / mktemp.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  6KB  |  229 lines

  1. /***
  2. *mktemp.c - create a unique file name
  3. *
  4. *       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines _mktemp() - create a unique file name
  8. *
  9. *******************************************************************************/
  10.  
  11. #ifndef _MAC
  12.  
  13.  
  14. #include <cruntime.h>
  15. #include <stdio.h>
  16. #include <io.h>
  17. #include <process.h>
  18. #include <errno.h>
  19. #include <dbgint.h>
  20. #include <stddef.h>
  21. #ifdef _MBCS
  22. #include <mbctype.h>
  23. #include <mbdata.h>
  24. #endif  /* _MBCS */
  25. #include <tchar.h>
  26.  
  27. /***
  28. *_TSCHAR *_mktemp(template) - create a unique file name
  29. *
  30. *Purpose:
  31. *       given a template of the form "fnamXXXXXX", insert number on end
  32. *       of template, insert unique letter if needed until unique filename
  33. *       found or run out of letters.  The number is generated from the Win32
  34. *       Process ID for single-thread libraries, or the Win32 Thread ID for
  35. *       multi-thread libraries.
  36. *
  37. *Entry:
  38. *       _TSCHAR *template - template of form "fnamXXXXXX"
  39. *
  40. *Exit:
  41. *       return pointer to modifed template
  42. *       returns NULL if template malformed or no more unique names
  43. *
  44. *Exceptions:
  45. *
  46. *******************************************************************************/
  47.  
  48. _TSCHAR * __cdecl _tmktemp (
  49.         _TSCHAR *template
  50.         )
  51. {
  52.         _TSCHAR *string = template;
  53.         unsigned number;
  54.         int letter = _T('a');
  55.         int xcount = 0;
  56.         int olderrno;
  57.  
  58.         _ASSERTE(template != NULL);
  59.         _ASSERTE(*template != _T('\0'));
  60.  
  61.         /*
  62.          * The Process ID is not a good choice in multi-threaded programs
  63.          * because of the likelihood that two threads might call mktemp()
  64.          * almost simultaneously, thus getting the same temporary name.
  65.          * Instead, the Win32 Thread ID is used, because it is unique across
  66.          * all threads in all processes currently running.
  67.          *
  68.          * Note, however, that unlike *NIX process IDs, which are not re-used
  69.          * until all values up to 32K have been used, Win32 process IDs are
  70.          * re-used and tend to always be relatively small numbers.  Same for
  71.          * thread IDs.
  72.          */
  73. #ifdef _MT
  74.         number = __threadid();
  75. #else  /* _MT */
  76.         number = _getpid();
  77. #endif  /* _MT */
  78.  
  79.         while (*string)
  80.                 string++;
  81.  
  82.         /* replace last five X's */
  83. #ifdef _MBCS
  84.         while ((--string>=template) && (!_ismbstrail(template,string))
  85.                 && (*string == 'X') && xcount < 5)
  86. #else  /* _MBCS */
  87.         while (*--string == _T('X') && xcount < 5)
  88. #endif  /* _MBCS */
  89.         {
  90.                 xcount++;
  91.                 *string = (_TSCHAR)((number % 10) + '0');
  92.                 number /= 10;
  93.         }
  94.  
  95.         /* too few X's ? */
  96.         if (*string != _T('X') || xcount < 5)
  97.                 return(NULL);
  98.  
  99.         /* set first X */
  100.         *string = letter++;
  101.  
  102.         olderrno = errno;       /* save current errno */
  103.         errno = 0;              /* make sure errno isn't EACCESS */
  104.  
  105.         /* check all the files 'a'-'z' */
  106.         while ((_taccess(template,0) == 0) || (errno == EACCES))
  107.         /* while file exists */
  108.         {
  109.                 errno = 0;
  110.                 if (letter == _T('z') + 1) {
  111.                         errno = olderrno;
  112.                         return(NULL);
  113.                 }
  114.  
  115.                 *string = (_TSCHAR)letter++;
  116.         }
  117.  
  118.         errno = olderrno;
  119.         return(template);
  120. }
  121.  
  122.  
  123. #else  /* _MAC */
  124.  
  125.  
  126. #include <cruntime.h>
  127. #include <internal.h>
  128. #include <stdio.h>
  129. #include <io.h>
  130. #include <errno.h>
  131. #include <dbgint.h>
  132. #include <stddef.h>
  133. #include <macos\errors.h>
  134. #include <macos\processe.h>
  135. #include <macos\gestalte.h>
  136. #include <macos\osutils.h>
  137. #include <macos\traps.h>
  138. #include <macos\toolutil.h>
  139. #ifdef _MBCS
  140. #include <mbctype.h>
  141. #include <mbdata.h>
  142. int __isdbcscode(const char *, const char *);     /* defined in fullpath.c */
  143. #endif  /* _MBCS */
  144.  
  145. /***
  146. *char *_mktemp(template) - create a unique file name
  147. *
  148. *Purpose:
  149. *       given a template of the form "fnamXXXXXX", insert number on end
  150. *       of template, insert unique letter if needed until unique filename
  151. *       found or run out of letters
  152. *
  153. *Entry:
  154. *       char *template - template of form "fnamXXXXXX"
  155. *
  156. *Exit:
  157. *       return pointer to modifed template
  158. *       returns NULL if template malformed or no more unique names
  159. *
  160. *Exceptions:
  161. *
  162. *******************************************************************************/
  163.  
  164.  
  165. char * __cdecl _mktemp (
  166.         char *template
  167.         )
  168. {
  169.         char *string = template;
  170.         unsigned number;
  171.         int letter = 'a';
  172.         int xcount = 0;
  173.         int olderrno;
  174.         ProcessSerialNumber psn;
  175.  
  176.         _ASSERTE(template != NULL);
  177.         _ASSERTE(*template != '\0');
  178.  
  179.         if (__TrapFromGestalt(gestaltOSAttr, gestaltLaunchControl))
  180.         {
  181.                 GetCurrentProcess(&psn);
  182.                 number = (unsigned) psn.lowLongOfPSN;
  183.         }
  184.         else
  185.         {
  186.                 /*LATER -- how to get multifinder process id*/
  187.                 number = 1;
  188.         }
  189.  
  190.         while (*string)
  191.                 string++;
  192.  
  193. #ifndef _MBCS
  194.         while (*--string == 'X')
  195. #else  /* _MBCS */
  196.         while ((string>template) && (!__isdbcscode(template,string-1))
  197.                 && (*--string == 'X'))
  198. #endif  /* _MBCS */
  199.         {
  200.                 xcount++;
  201.                 *string = (char)((number % 10) + '0');
  202.                 number /= 10;
  203.         }
  204.  
  205.         if (*++string == '\0' || xcount != 6 )
  206.                 return(NULL);
  207.  
  208.         olderrno = errno;       /* save current errno */
  209.         errno = 0;              /* make sure errno isn't EACCESS */
  210.  
  211.         while ((_access(template,0) == 0) || (errno == EACCES))
  212.         /* while file exists */
  213.         {
  214.                 errno = 0;
  215.                 if (letter == 'z'+1) {
  216.                         errno = olderrno;
  217.                         return(NULL);
  218.                 }
  219.  
  220.                 *string = (char)letter++;
  221.         }
  222.  
  223.         errno = olderrno;
  224.         return(template);
  225. }
  226.  
  227.  
  228. #endif  /* _MAC */
  229.