summaryrefslogtreecommitdiff
path: root/open-vm-tools/vgauth/common/VGAuthUtil.c
blob: b4d132bb20d9c4cc0ac9a3b7a632c7fe7ca16d99 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
/*********************************************************
 * Copyright (C) 2011-2015 VMware, Inc. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation version 2.1 and no later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
 *
 *********************************************************/

/**
 * @file VGAuthUtil.c --
 *
 *       utility functions.
 */
#include <stdlib.h>

#include <glib.h>
#include <glib/gstdio.h>

#include "VGAuthBasicDefs.h"
#include "VGAuthLog.h"
#include "VGAuthUtil.h"

#ifdef _WIN32
#include <windows.h>
#endif


/*
 ******************************************************************************
 * HangThread --                                                         */ /**
 *
 * Hang the current thread.
 * Debug function to help diagnose IPC issues and unit tests such as pipe full.
 *
 * @param[in]   func       The function name
 * @param[in]   file       The file name
 * @param[in]   line       The line number
 *
 ******************************************************************************
 */

void HangThread(const char *func,
                const char *file,
                unsigned line)
{
   LogDebug(func, file, line, "Hang the calling thread");

   do {
      g_usleep(1000 * G_USEC_PER_SEC);
   } while (TRUE);
}


#ifdef _WIN32
/*
 ******************************************************************************
 * Convert_Utf8ToUtf16 --                                                */ /**
 *
 * Convert a NULL terminated UTF8 string to a NULL terminiated UTF16 string
 * Log an error if the conversion fails.
 *
 * @param[in]   func       The function name
 * @param[in]   file       The file name
 * @param[in]   line       The line number
 * @param[in]   str        The input NULL terminated UTF8 string
 *
 * @return a utf16 string result
 *
 ******************************************************************************
 */

gunichar2 *
Convert_Utf8ToUtf16(const char *func,
                    const char *file,
                    unsigned line,
                    const gchar *str)
{
   glong nRead = 0;
   glong nWritten = 0;
   GError *pError = NULL;
   gunichar2 *result = g_utf8_to_utf16(str, -1, &nRead, &nWritten, &pError);

   if (!result) {
      LogWarning(func, file, line, "g_utf8_to_utf16() failed, %s, "
                 "read %d byte(s), written %d wchar(s)", pError->message,
                 (int)nRead, (int)nWritten);
      g_clear_error(&pError);
   }

   return result;
}


/*
 ******************************************************************************
 * Convert_Utf16ToUtf8 --                                                */ /**
 *
 * Convert a NULL terminated UTF16 string to a NULL terminated UTF8 string
 * Log an error if the conversion fails.
 *
 * @param[in]   func       The function name
 * @param[in]   file       The file name
 * @param[in]   line       The line number
 * @param[in]   str        The input NULL terminated UTF16 string
 *
 * @return a utf8 string result
 *
 ******************************************************************************
 */

gchar *
Convert_Utf16ToUtf8(const char *func,
                    const char *file,
                    unsigned line,
                    const gunichar2 *str)
{
   glong nRead = 0;
   glong nWritten = 0;
   GError *pError = NULL;
   gchar *result = g_utf16_to_utf8(str, -1, &nRead, &nWritten, &pError);

   if (!result) {
      LogWarning(func, file, line, "g_utf16_to_utf8() failed, %s, "
                 "read %d wchar(s), written %d byte(s)", pError->message,
                 (int)nRead, (int)nWritten);
      g_clear_error(&pError);
   }

   return result;
}


/*
 ******************************************************************************
 * Convert_TextToUnsignedInt32 --                                        */ /**
 *
 * Convert a NULL terminated ascii string to a unsigned 32bit number
 * Log an error if the conversion fails
 *
 * @param[in]   func       The function name
 * @param[in]   file       The file name
 * @param[in]   line       The line number
 * @param[in]   str        The input NULL terminated ascii string
 * @param[out]  result     The converted unsigned 32bit value
 *
 * @return TRUE on sucess, FALSE otherwise
 *
 ******************************************************************************
 */

gboolean
Convert_TextToUnsignedInt32(const char *func,
                            const char *file,
                            unsigned line,
                            const char *str,
                            unsigned int *result)
{
   /*
    * On 32/64bit Windows, sizeof(unsigned long) = sizeof(unsigned int) = 4
    * On 32bit Linux, sizeof(unsigned long) = sizeof(unsigned int) = 4
    * On 64bit Linux, sizeof(unsigned long) = 8, sizeof(unsigned int) = 4
    */
   unsigned long value;
   char *stopChar;

   value = strtoul(str, &stopChar, 10);
   if (value == 0 || value == ULONG_MAX) {
      LogErrorPosix(func, file, line, "strtoul(%s) failed", str);
      return FALSE;
   }

#ifndef _WIN32
   if (!Check_Is32bitNumber((size_t)value)) {
      LogWarning(func, file, line, "Convert to uint32 overflowed, input = %s",
                 str);
      return FALSE;
   }
#endif

   *result = (unsigned int)value;

   return TRUE;
}


/*
 ******************************************************************************
 * Check_Is32bitNumber --                                               */ /**
 *
 * Check if the number is a 32bit number
 *
 * @param[in]   number     The number to check
 *
 * @note   size_t is 64bit on a 64bit system, and 32bit on a 32bit system
 *
 * @return TRUE if the number is a 32bit number, FALSE otherwise.
 *
 ******************************************************************************
 */

gboolean
Check_Is32bitNumber(size_t number)
{
   unsigned long long number64 = (unsigned long long)number;

   /*
    * Cast to 64bit to shift 32bit
    * Otherwise, the C compiler warns and generates no-op code
    */
   number64 >>=32;

   return (number64 == 0);
}


/*
 ******************************************************************************
 * Convert_UnsignedInt32ToText --                                       */ /**
 *
 * Convert a unsigned 32bit number to its text representation
 * Log an error if the conversion fails
 *
 * @param[in]   number       The number to convert
 *
 * @return   the result ascii string
 *
 ******************************************************************************
 */

gchar *
Convert_UnsignedInt32ToText(unsigned int number)
{
   return g_strdup_printf("%d", number);
}
#endif  // #ifdef _WIN32


/*
 ******************************************************************************
 * Util_CheckExpiration --                                               */ /**
 *
 * Checks whether, given a start time and duration, the current time is
 * passed that duration.
 *
 * @param[in]  start     The start time.
 * @param[in]  duration  The timeout in seconds.
 *
 * @return  TRUE if the current time is passed the duration or FALSE otherwise.
 *
 ******************************************************************************
 */

gboolean
Util_CheckExpiration(const GTimeVal *start,
                     unsigned int duration)
{
   GTimeVal now;
   GTimeVal expire;

   /*
    * XXX blech.  Move to GDateTime as soon as the toolchain glib
    * supports it (version 2.26).
    */
   g_get_current_time(&now);
   expire = *start;

   expire.tv_sec += duration;

   /*
    * We don't need the precision, so just ignore micros.
    */
   return now.tv_sec > expire.tv_sec;
}


/*
 ******************************************************************************
 * Util_Assert --                                                        */ /**
 *
 * Asserts after spewing some location data.
 *
 * @param[in]  cond      The assertion cause.
 * @param[in]  file      The file.
 * @param[in]  lineNum   The line number.
 *
 ******************************************************************************
 */

void
Util_Assert(const char *cond,
            const char *file,
            int lineNum)
{
   g_warning("Assertion '%s' failed at %s:%d\n", cond, file, lineNum);
#ifdef _WIN32
#ifdef VMX86_DEBUG
   DebugBreak();
#endif
#endif
   g_assert(0);
}