ReactOS 0.4.16-dev-979-g79f281e
mktemp.cpp
Go to the documentation of this file.
1//
2// mktemp.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Defines _tmktemp() and _tmktemp_s(), which create unique file names.
7//
10#include <mbctype.h>
11#include <process.h>
12#include <stddef.h>
13#include <stdio.h>
14
15
16
17// These functions test whether we should continue scanning for X's.
18static bool common_mktemp_s_continue(char const* const string, char const* const current) throw()
19{
20 return !_ismbstrail(
21 reinterpret_cast<unsigned char const*>(string),
22 reinterpret_cast<unsigned char const*>(current));
23}
24
25static bool common_mktemp_s_continue(wchar_t const* const, wchar_t const* const) throw()
26{
27 return true;
28}
29
30
31
32// Creates a unique file name given a template string of the form "fnamXXXXXX".
33// The "XXXXXX" sequence is replaced by a letter and the five-digit thread
34// identifier.
35//
36// The template string is modified in-place. Returns 0 on success; returns an
37// errno error code on failure.
38template <typename Character>
39_Success_(return == 0)
40static errno_t __cdecl common_mktemp_s(
41 _Inout_updates_z_(buffer_size_in_chars) Character* const template_string,
42 size_t const buffer_size_in_chars
44{
45 typedef __crt_char_traits<Character> traits;
46
47 _VALIDATE_RETURN_ERRCODE(template_string != nullptr && buffer_size_in_chars > 0, EINVAL);
48
49 size_t const template_string_length = traits::tcsnlen(template_string, buffer_size_in_chars);
50 if (template_string_length >= buffer_size_in_chars)
51 {
52 _RESET_STRING(template_string, buffer_size_in_chars);
53 _RETURN_DEST_NOT_NULL_TERMINATED(template_string, buffer_size_in_chars);
54 }
55 _FILL_STRING(template_string, buffer_size_in_chars, template_string_length + 1);
56
57 if(template_string_length < 6 || buffer_size_in_chars <= template_string_length)
58 {
59 _RESET_STRING(template_string, buffer_size_in_chars);
60 _VALIDATE_RETURN_ERRCODE(("Incorrect Input for mktemp", 0), EINVAL);
61 }
62
63 // The Win32 thread identifier is unique across all threads in all processes.
64 // Note, however, that unlike *NIX process identifiers, which are not reused
65 // until all values up to 32K have been used, Win32 thread identifiers are
66 // frequenty reused and usually have small numbers.
67 unsigned number = GetCurrentThreadId();
68
69 // 'string' points to the null-terminator:
70 Character* string = template_string + template_string_length;
71
72 size_t template_length = 0;
73
74 // Replace the last five 'X' characters with the number:
75 while (--string >= template_string
76 && common_mktemp_s_continue(template_string, string)
77 && *string == 'X'
78 && template_length < 5)
79 {
80 ++template_length;
81 *string = static_cast<Character>((number % 10) + '0');
82 number /= 10;
83 }
84
85 // Too few X's?
86 if (*string != 'X' || template_length < 5)
87 {
88 _RESET_STRING(template_string, buffer_size_in_chars);
89 _VALIDATE_RETURN_ERRCODE(("Incorrect Input for mktemp", 0), EINVAL);
90 }
91
92 // Finally, add the letter:
93 Character letter = 'a';
94
95 *string = letter++;
96
97 errno_t const saved_errno = errno;
98 errno = 0;
99
100 // Test each letter, from a-z, until we find a name that is not yet used:
101 while (traits::taccess_s(template_string, 0) == 0)
102 {
103 if (letter == 'z' + 1)
104 {
105 _RESET_STRING(template_string, buffer_size_in_chars);
106 errno = EEXIST;
107 return errno;
108 }
109
110 *string = letter++;
111 errno = 0;
112 }
113
114 // Restore the old value of errno and return success:
115 errno = saved_errno;
116 return 0;
117}
118
120 char* const template_string,
121 size_t const buffer_size_in_chars
122 )
123{
124 return common_mktemp_s(template_string, buffer_size_in_chars);
125}
126
128 wchar_t* const template_string,
129 size_t const buffer_size_in_chars
130 )
131{
132 return common_mktemp_s(template_string, buffer_size_in_chars);
133}
134
135
136
137// Creates a unique file name given a template string of the form "fnamXXXXXX".
138// The "XXXXXX" sequence is replaced by a letter and the five-digit thread
139// identifier. The template string is modified in-place.
140//
141// On success, returns the pointer to the modified template string. On failure,
142// nullptr is returned (e.g. if the template string is malformed or there are no
143// more unique names).
144template <typename Character>
145static Character* __cdecl common_mktemp(
146 Character* const template_string
147 ) throw()
148{
149 typedef __crt_char_traits<Character> traits;
150
151 _VALIDATE_RETURN(template_string != nullptr, EINVAL, nullptr);
152
153 errno_t const result = common_mktemp_s(
154 template_string,
155 static_cast<size_t>(traits::tcslen(template_string) + 1));
156
157 return result == 0 ? template_string : nullptr;
158}
159
160extern "C" char* __cdecl _mktemp(char* const template_string)
161{
162 return common_mktemp(template_string);
163}
164
165extern "C" wchar_t* __cdecl _wmktemp(wchar_t* const template_string)
166{
167 return common_mktemp(template_string);
168}
#define EEXIST
Definition: acclib.h:88
#define EINVAL
Definition: acclib.h:90
#define __cdecl
Definition: accygwin.h:79
#define _RETURN_DEST_NOT_NULL_TERMINATED(_String, _Size)
#define _FILL_STRING
#define _RESET_STRING(_String, _Size)
#define _VALIDATE_RETURN(expr, errorcode, retexpr)
_wmktemp
Definition: corecrt_wio.h:154
GLuint64EXT * result
Definition: glext.h:11304
#define _VALIDATE_RETURN_ERRCODE(expr, errorcode)
errno_t __cdecl _wmktemp_s(wchar_t *const template_string, size_t const buffer_size_in_chars)
Definition: mktemp.cpp:127
static bool common_mktemp_s_continue(char const *const string, char const *const current)
Definition: mktemp.cpp:18
char *__cdecl _mktemp(char *const template_string)
Definition: mktemp.cpp:160
errno_t __cdecl _mktemp_s(char *const template_string, size_t const buffer_size_in_chars)
Definition: mktemp.cpp:119
size_t const buffer_size_in_chars throw()
Definition: mktemp.cpp:43
static Character *__cdecl common_mktemp(Character *const template_string)
Definition: mktemp.cpp:145
struct task_struct * current
Definition: linux.c:32
static unsigned int number
Definition: dsound.c:1479
int __cdecl _ismbstrail(const unsigned char *start, const unsigned char *str)
Definition: ismbtrl.c:32
#define _Success_(c)
Definition: no_sal2.h:84
#define _Inout_updates_z_(s)
Definition: no_sal2.h:186
#define errno
Definition: errno.h:18
int errno_t
Definition: corecrt.h:615
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
#define const
Definition: zconf.h:233