]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * The contents of this file are subject to the Mozilla Public | |
3 | * License Version 1.1 (the "License"); you may not use this file | |
4 | * except in compliance with the License. You may obtain a copy of | |
5 | * the License at http://www.mozilla.org/MPL/ | |
6 | * | |
7 | * Software distributed under the License is distributed on an "AS | |
8 | * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | |
9 | * implied. See the License for the specific language governing | |
10 | * rights and limitations under the License. | |
11 | * | |
12 | * The Original Code is the Netscape security libraries. | |
13 | * | |
14 | * The Initial Developer of the Original Code is Netscape | |
15 | * Communications Corporation. Portions created by Netscape are | |
16 | * Copyright (C) 1994-2000 Netscape Communications Corporation. All | |
17 | * Rights Reserved. | |
18 | * | |
19 | * Contributor(s): | |
20 | * | |
21 | * Alternatively, the contents of this file may be used under the | |
22 | * terms of the GNU General Public License Version 2 or later (the | |
23 | * "GPL"), in which case the provisions of the GPL are applicable | |
24 | * instead of those above. If you wish to allow use of your | |
25 | * version of this file only under the terms of the GPL and not to | |
26 | * allow others to use your version of this file under the MPL, | |
27 | * indicate your decision by deleting the provisions above and | |
28 | * replace them with the notice and other provisions required by | |
29 | * the GPL. If you do not delete the provisions above, a recipient | |
30 | * may use your version of this file under either the MPL or the | |
31 | * GPL. | |
32 | */ | |
33 | ||
34 | /* | |
35 | * secport.c - portability interfaces for security libraries | |
36 | * | |
37 | * This file abstracts out libc functionality that libsec depends on | |
38 | * | |
39 | * NOTE - These are not public interfaces | |
40 | * | |
41 | * $Id: secport.c,v 1.5 2004/10/27 20:36:36 dmitch Exp $ | |
42 | */ | |
43 | ||
44 | #include "seccomon.h" | |
45 | #include "prmem.h" | |
46 | #include "prerror.h" | |
47 | #include "plarena.h" | |
48 | #include "secerr.h" | |
49 | #include "prmon.h" | |
50 | #include "nsslocks.h" | |
51 | #include "secport.h" | |
52 | #include "prvrsion.h" | |
53 | #include "prenv.h" | |
54 | ||
55 | #ifdef DEBUG | |
56 | //#define THREADMARK | |
57 | #endif /* DEBUG */ | |
58 | ||
59 | #ifdef THREADMARK | |
60 | #include "prthread.h" | |
61 | #endif /* THREADMARK */ | |
62 | ||
63 | #if defined(XP_UNIX) || defined(XP_MAC) || defined(XP_OS2) || defined(XP_BEOS) | |
64 | #include <stdlib.h> | |
65 | #else | |
66 | #include "wtypes.h" | |
67 | #endif | |
68 | ||
69 | #define SET_ERROR_CODE /* place holder for code to set PR error code. */ | |
70 | ||
71 | #ifdef THREADMARK | |
72 | typedef struct threadmark_mark_str { | |
73 | struct threadmark_mark_str *next; | |
74 | void *mark; | |
75 | } threadmark_mark; | |
76 | ||
77 | #endif /* THREADMARK */ | |
78 | ||
79 | /* The value of this magic must change each time PORTArenaPool changes. */ | |
80 | #define ARENAPOOL_MAGIC 0xB8AC9BDF | |
81 | ||
82 | /* enable/disable mutex in PORTArenaPool */ | |
83 | #define ARENA_POOL_LOCK 0 | |
84 | ||
85 | typedef struct PORTArenaPool_str { | |
86 | PLArenaPool arena; | |
87 | PRUint32 magic; | |
88 | #if ARENA_POOL_LOCK | |
89 | PRLock * lock; | |
90 | #endif | |
91 | #ifdef THREADMARK | |
92 | PRThread *marking_thread; | |
93 | threadmark_mark *first_mark; | |
94 | #endif | |
95 | } PORTArenaPool; | |
96 | ||
97 | ||
98 | /* count of allocation failures. */ | |
99 | unsigned long port_allocFailures; | |
100 | ||
101 | #ifndef __APPLE__ | |
102 | /* locations for registering Unicode conversion functions. | |
103 | * XXX is this the appropriate location? or should they be | |
104 | * moved to client/server specific locations? | |
105 | */ | |
106 | PORTCharConversionFunc ucs4Utf8ConvertFunc; | |
107 | PORTCharConversionFunc ucs2Utf8ConvertFunc; | |
108 | PORTCharConversionWSwapFunc ucs2AsciiConvertFunc; | |
109 | #endif /* __APPLE__ */ | |
110 | ||
60c433a9 A |
111 | /* NSPR memory allocation functions (PR_Malloc, PR_Calloc, and PR_Realloc) |
112 | * use the PRUint32 type for the size parameter. Before we pass a size_t or | |
113 | * unsigned long size to these functions, we need to ensure it is <= half of | |
114 | * the maximum PRUint32 value to avoid truncation and catch a negative size. | |
115 | */ | |
116 | #define MAX_SIZE (PR_UINT32_MAX >> 1) | |
117 | ||
b1ab9ed8 A |
118 | void * |
119 | PORT_Alloc(size_t bytes) | |
120 | { | |
60c433a9 | 121 | void *rv = NULL; |
b1ab9ed8 | 122 | |
60c433a9 A |
123 | if (bytes <= MAX_SIZE) { |
124 | /* Always allocate a non-zero amount of bytes */ | |
125 | rv = PR_Malloc(bytes ? bytes : 1); | |
126 | } | |
b1ab9ed8 A |
127 | if (!rv) { |
128 | ++port_allocFailures; | |
129 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
130 | } | |
131 | return rv; | |
132 | } | |
133 | ||
134 | void * | |
135 | PORT_Realloc(void *oldptr, size_t bytes) | |
136 | { | |
60c433a9 | 137 | void *rv = NULL; |
b1ab9ed8 | 138 | |
60c433a9 A |
139 | if (bytes <= MAX_SIZE) { |
140 | rv = PR_Realloc(oldptr, bytes); | |
141 | } | |
b1ab9ed8 A |
142 | if (!rv) { |
143 | ++port_allocFailures; | |
144 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
145 | } | |
146 | return rv; | |
147 | } | |
148 | ||
149 | void * | |
150 | PORT_ZAlloc(size_t bytes) | |
151 | { | |
60c433a9 | 152 | void *rv = NULL; |
b1ab9ed8 | 153 | |
60c433a9 A |
154 | if (bytes <= MAX_SIZE) { |
155 | /* Always allocate a non-zero amount of bytes */ | |
156 | rv = PR_Calloc(1, bytes ? bytes : 1); | |
157 | } | |
b1ab9ed8 A |
158 | if (!rv) { |
159 | ++port_allocFailures; | |
160 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
161 | } | |
162 | return rv; | |
163 | } | |
164 | ||
165 | void | |
166 | PORT_Free(void *ptr) | |
167 | { | |
168 | if (ptr) { | |
169 | PR_Free(ptr); | |
170 | } | |
171 | } | |
172 | ||
173 | void | |
174 | PORT_ZFree(void *ptr, size_t len) | |
175 | { | |
176 | if (ptr) { | |
177 | memset(ptr, 0, len); | |
178 | PR_Free(ptr); | |
179 | } | |
180 | } | |
181 | ||
182 | char * | |
183 | PORT_Strdup(const char *str) | |
184 | { | |
185 | size_t len = PORT_Strlen(str)+1; | |
186 | char *newstr; | |
187 | ||
188 | newstr = (char *)PORT_Alloc(len); | |
189 | if (newstr) { | |
190 | PORT_Memcpy(newstr, str, len); | |
191 | } | |
192 | return newstr; | |
193 | } | |
194 | ||
195 | void | |
196 | PORT_SetError(int value) | |
197 | { | |
198 | PR_SetError(value, 0); | |
199 | return; | |
200 | } | |
201 | ||
202 | int | |
203 | PORT_GetError(void) | |
204 | { | |
205 | return(PR_GetError()); | |
206 | } | |
207 | ||
208 | /********************* Arena code follows *****************************/ | |
209 | ||
210 | PLArenaPool * | |
211 | PORT_NewArena(unsigned long chunksize) | |
212 | { | |
213 | PORTArenaPool *pool; | |
214 | ||
60c433a9 A |
215 | if (chunksize > MAX_SIZE) { |
216 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
217 | return NULL; | |
218 | } | |
b1ab9ed8 A |
219 | pool = PORT_ZNew(PORTArenaPool); |
220 | if (!pool) { | |
221 | return NULL; | |
222 | } | |
223 | pool->magic = ARENAPOOL_MAGIC; | |
224 | #if ARENA_POOL_LOCK | |
225 | pool->lock = PZ_NewLock(nssILockArena); | |
226 | if (!pool->lock) { | |
227 | ++port_allocFailures; | |
228 | PORT_Free(pool); | |
229 | return NULL; | |
230 | } | |
231 | #endif | |
60c433a9 | 232 | PL_InitArenaPool(&pool->arena, "security", (PRUint32)chunksize, sizeof(double)); |
b1ab9ed8 A |
233 | return(&pool->arena); |
234 | } | |
235 | ||
236 | void * | |
237 | PORT_ArenaAlloc(PLArenaPool *arena, size_t size) | |
238 | { | |
60c433a9 | 239 | void *p = NULL; |
b1ab9ed8 A |
240 | |
241 | PORTArenaPool *pool = (PORTArenaPool *)arena; | |
242 | ||
60c433a9 A |
243 | if (size <= 0) { |
244 | size = 1; | |
245 | } | |
b1ab9ed8 | 246 | |
60c433a9 A |
247 | if (size > MAX_SIZE) { |
248 | /* you lose. */ | |
249 | } else | |
b1ab9ed8 A |
250 | /* Is it one of ours? Assume so and check the magic */ |
251 | if (ARENAPOOL_MAGIC == pool->magic ) { | |
252 | #if ARENA_POOL_LOCK | |
253 | PZ_Lock(pool->lock); | |
254 | #ifdef THREADMARK | |
255 | /* Most likely one of ours. Is there a thread id? */ | |
256 | if (pool->marking_thread && | |
257 | pool->marking_thread != PR_GetCurrentThread() ) { | |
258 | /* Another thread holds a mark in this arena */ | |
259 | PZ_Unlock(pool->lock); | |
260 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
261 | PORT_Assert(0); | |
262 | return NULL; | |
263 | } /* tid != null */ | |
264 | #endif /* THREADMARK */ | |
265 | #endif /* ARENA_POOL_LOCK */ | |
266 | PL_ARENA_ALLOCATE(p, arena, (PRUint32)size); | |
267 | #if ARENA_POOL_LOCK | |
268 | PZ_Unlock(pool->lock); | |
269 | #endif | |
270 | } else { | |
271 | PL_ARENA_ALLOCATE(p, arena, (PRUint32)size); | |
272 | } | |
273 | ||
274 | if (!p) { | |
275 | ++port_allocFailures; | |
276 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
277 | } | |
278 | ||
279 | return(p); | |
280 | } | |
281 | ||
282 | void * | |
283 | PORT_ArenaZAlloc(PLArenaPool *arena, size_t size) | |
284 | { | |
60c433a9 A |
285 | void *p; |
286 | ||
287 | if (size <= 0) | |
288 | size = 1; | |
289 | ||
290 | p = PORT_ArenaAlloc(arena, size); | |
b1ab9ed8 A |
291 | |
292 | if (p) { | |
293 | PORT_Memset(p, 0, size); | |
294 | } | |
295 | ||
296 | return(p); | |
297 | } | |
298 | ||
60c433a9 A |
299 | /* |
300 | * If zero is true, zeroize the arena memory before freeing it. | |
301 | */ | |
b1ab9ed8 A |
302 | void |
303 | PORT_FreeArena(PLArenaPool *arena, PRBool zero) | |
304 | { | |
305 | PORTArenaPool *pool = (PORTArenaPool *)arena; | |
306 | #if ARENA_POOL_LOCK | |
307 | PRLock * lock = (PRLock *)0; | |
308 | #endif | |
309 | size_t len = sizeof *arena; | |
310 | extern const PRVersionDescription * libVersionPoint(void); | |
311 | #ifndef __APPLE__ | |
312 | static const PRVersionDescription * pvd; | |
313 | #endif | |
314 | static PRBool doFreeArenaPool = PR_FALSE; | |
315 | ||
316 | if (ARENAPOOL_MAGIC == pool->magic ) { | |
317 | len = sizeof *pool; | |
318 | #if ARENA_POOL_LOCK | |
319 | lock = pool->lock; | |
320 | PZ_Lock(lock); | |
321 | #endif | |
322 | } | |
323 | #ifndef __APPLE__ | |
324 | /* dmitch - not needed */ | |
325 | if (!pvd) { | |
326 | /* Each of NSPR's DLLs has a function libVersionPoint(). | |
327 | ** We could do a lot of extra work to be sure we're calling the | |
328 | ** one in the DLL that holds PR_FreeArenaPool, but instead we | |
329 | ** rely on the fact that ALL NSPR DLLs in the same directory | |
330 | ** must be from the same release, and we call which ever one we get. | |
331 | */ | |
332 | /* no need for thread protection here */ | |
333 | pvd = libVersionPoint(); | |
334 | if ((pvd->vMajor > 4) || | |
335 | (pvd->vMajor == 4 && pvd->vMinor > 1) || | |
336 | (pvd->vMajor == 4 && pvd->vMinor == 1 && pvd->vPatch >= 1)) { | |
337 | const char *ev = PR_GetEnv("NSS_DISABLE_ARENA_FREE_LIST"); | |
338 | if (!ev) doFreeArenaPool = PR_TRUE; | |
339 | } | |
340 | } | |
341 | #endif | |
60c433a9 A |
342 | if (zero) { |
343 | PL_ClearArenaPool(arena, 0); | |
344 | } | |
345 | ||
b1ab9ed8 A |
346 | if (doFreeArenaPool) { |
347 | PL_FreeArenaPool(arena); | |
348 | } else { | |
349 | PL_FinishArenaPool(arena); | |
350 | } | |
351 | #if ARENA_POOL_LOCK | |
352 | if (lock) { | |
353 | PZ_Unlock(lock); | |
354 | PZ_DestroyLock(lock); | |
355 | } | |
356 | #endif | |
357 | PORT_ZFree(arena, len); | |
358 | } | |
359 | ||
360 | void * | |
361 | PORT_ArenaGrow(PLArenaPool *arena, void *ptr, size_t oldsize, size_t newsize) | |
362 | { | |
363 | PORTArenaPool *pool = (PORTArenaPool *)arena; | |
b1ab9ed8 | 364 | |
60c433a9 A |
365 | if (newsize > MAX_SIZE) { |
366 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
367 | return NULL; | |
368 | } | |
369 | #ifdef __APPLE__ | |
370 | if (newsize < oldsize) { | |
371 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); // Not expected | |
372 | return NULL; | |
373 | } | |
374 | #endif | |
b1ab9ed8 | 375 | if (ARENAPOOL_MAGIC == pool->magic ) { |
60c433a9 A |
376 | #if ARENA_POOL_LOCK |
377 | PZ_Lock(pool->lock); | |
378 | #endif | |
379 | /* Do we do a THREADMARK check here? */ | |
380 | PL_ARENA_GROW(ptr, arena, (PRUint32)oldsize, (PRUint32)( newsize - oldsize ) ); | |
381 | #if ARENA_POOL_LOCK | |
382 | PZ_Unlock(pool->lock); | |
383 | #endif | |
b1ab9ed8 | 384 | } else { |
60c433a9 | 385 | PL_ARENA_GROW(ptr, arena, (PRUint32)oldsize, (PRUint32)( newsize - oldsize ) ); |
b1ab9ed8 A |
386 | } |
387 | ||
388 | return(ptr); | |
389 | } | |
390 | ||
391 | void * | |
392 | PORT_ArenaMark(PLArenaPool *arena) | |
393 | { | |
394 | #if ARENA_MARK_ENABLE | |
395 | void * result; | |
396 | ||
397 | PORTArenaPool *pool = (PORTArenaPool *)arena; | |
398 | if (ARENAPOOL_MAGIC == pool->magic ) { | |
399 | PZ_Lock(pool->lock); | |
400 | #ifdef THREADMARK | |
401 | { | |
402 | threadmark_mark *tm, **pw; | |
403 | PRThread * currentThread = PR_GetCurrentThread(); | |
404 | ||
405 | if (! pool->marking_thread ) { | |
406 | /* First mark */ | |
407 | pool->marking_thread = currentThread; | |
408 | } else if (currentThread != pool->marking_thread ) { | |
409 | PZ_Unlock(pool->lock); | |
410 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
411 | PORT_Assert(0); | |
412 | return NULL; | |
413 | } | |
414 | ||
415 | result = PL_ARENA_MARK(arena); | |
416 | PL_ARENA_ALLOCATE(tm, arena, sizeof(threadmark_mark)); | |
417 | if (!tm) { | |
418 | PZ_Unlock(pool->lock); | |
419 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
420 | return NULL; | |
421 | } | |
422 | ||
423 | tm->mark = result; | |
424 | tm->next = (threadmark_mark *)NULL; | |
425 | ||
426 | pw = &pool->first_mark; | |
427 | while( *pw ) { | |
428 | pw = &(*pw)->next; | |
429 | } | |
430 | ||
431 | *pw = tm; | |
432 | } | |
433 | #else /* THREADMARK */ | |
434 | result = PL_ARENA_MARK(arena); | |
435 | #endif /* THREADMARK */ | |
436 | PZ_Unlock(pool->lock); | |
437 | } else { | |
438 | /* a "pure" NSPR arena */ | |
439 | result = PL_ARENA_MARK(arena); | |
440 | } | |
441 | return result; | |
442 | #else | |
443 | /* Some code in libsecurity_smime really checks for a nonzero | |
444 | * return here, so... */ | |
445 | return (void *)-1; | |
446 | #endif | |
447 | } | |
448 | ||
449 | void | |
450 | PORT_ArenaRelease(PLArenaPool *arena, void *mark) | |
451 | { | |
452 | #if ARENA_MARK_ENABLE | |
453 | PORTArenaPool *pool = (PORTArenaPool *)arena; | |
454 | if (ARENAPOOL_MAGIC == pool->magic ) { | |
455 | PZ_Lock(pool->lock); | |
456 | #ifdef THREADMARK | |
457 | { | |
458 | threadmark_mark **pw, *tm; | |
459 | ||
460 | if (PR_GetCurrentThread() != pool->marking_thread ) { | |
461 | PZ_Unlock(pool->lock); | |
462 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
463 | PORT_Assert(0); | |
464 | return /* no error indication available */ ; | |
465 | } | |
466 | ||
467 | pw = &pool->first_mark; | |
468 | while( *pw && (mark != (*pw)->mark) ) { | |
469 | pw = &(*pw)->next; | |
470 | } | |
471 | ||
472 | if (! *pw ) { | |
473 | /* bad mark */ | |
474 | PZ_Unlock(pool->lock); | |
475 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
476 | PORT_Assert(0); | |
477 | return /* no error indication available */ ; | |
478 | } | |
479 | ||
480 | tm = *pw; | |
481 | *pw = (threadmark_mark *)NULL; | |
482 | ||
483 | PL_ARENA_RELEASE(arena, mark); | |
484 | ||
485 | if (! pool->first_mark ) { | |
486 | pool->marking_thread = (PRThread *)NULL; | |
487 | } | |
488 | } | |
489 | #else /* THREADMARK */ | |
490 | PL_ARENA_RELEASE(arena, mark); | |
491 | #endif /* THREADMARK */ | |
492 | PZ_Unlock(pool->lock); | |
493 | } else { | |
494 | PL_ARENA_RELEASE(arena, mark); | |
495 | } | |
496 | #endif /* ARENA_MARK_ENABLE */ | |
497 | } | |
498 | ||
499 | void | |
500 | PORT_ArenaUnmark(PLArenaPool *arena, void *mark) | |
501 | { | |
502 | #if ARENA_MARK_ENABLE | |
503 | #ifdef THREADMARK | |
504 | PORTArenaPool *pool = (PORTArenaPool *)arena; | |
505 | if (ARENAPOOL_MAGIC == pool->magic ) { | |
506 | threadmark_mark **pw, *tm; | |
507 | ||
508 | PZ_Lock(pool->lock); | |
509 | ||
510 | if (PR_GetCurrentThread() != pool->marking_thread ) { | |
511 | PZ_Unlock(pool->lock); | |
512 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
513 | PORT_Assert(0); | |
514 | return /* no error indication available */ ; | |
515 | } | |
516 | ||
517 | pw = &pool->first_mark; | |
518 | while( ((threadmark_mark *)NULL != *pw) && (mark != (*pw)->mark) ) { | |
519 | pw = &(*pw)->next; | |
520 | } | |
521 | ||
522 | if ((threadmark_mark *)NULL == *pw ) { | |
523 | /* bad mark */ | |
524 | PZ_Unlock(pool->lock); | |
525 | PORT_SetError(SEC_ERROR_NO_MEMORY); | |
526 | PORT_Assert(0); | |
527 | return /* no error indication available */ ; | |
528 | } | |
529 | ||
530 | tm = *pw; | |
531 | *pw = (threadmark_mark *)NULL; | |
532 | ||
533 | if (! pool->first_mark ) { | |
534 | pool->marking_thread = (PRThread *)NULL; | |
535 | } | |
536 | ||
537 | PZ_Unlock(pool->lock); | |
538 | } | |
539 | #endif /* THREADMARK */ | |
540 | #endif /* ARENA_MARK_ENABLE */ | |
541 | } | |
542 | ||
543 | char * | |
544 | PORT_ArenaStrdup(PLArenaPool *arena, const char *str) { | |
545 | size_t len = PORT_Strlen(str)+1; | |
546 | char *newstr; | |
547 | ||
548 | newstr = (char*)PORT_ArenaAlloc(arena,len); | |
549 | if (newstr) { | |
550 | PORT_Memcpy(newstr,str,len); | |
551 | } | |
552 | return newstr; | |
553 | } | |
554 | ||
555 | /********************** end of arena functions ***********************/ | |
556 | ||
557 | #ifndef __APPLE__ | |
558 | ||
559 | /****************** unicode conversion functions ***********************/ | |
560 | /* | |
561 | * NOTE: These conversion functions all assume that the multibyte | |
562 | * characters are going to be in NETWORK BYTE ORDER, not host byte | |
563 | * order. This is because the only time we deal with UCS-2 and UCS-4 | |
564 | * are when the data was received from or is going to be sent out | |
565 | * over the wire (in, e.g. certificates). | |
566 | */ | |
567 | ||
568 | void | |
569 | PORT_SetUCS4_UTF8ConversionFunction(PORTCharConversionFunc convFunc) | |
570 | { | |
571 | ucs4Utf8ConvertFunc = convFunc; | |
572 | } | |
573 | ||
574 | void | |
575 | PORT_SetUCS2_ASCIIConversionFunction(PORTCharConversionWSwapFunc convFunc) | |
576 | { | |
577 | ucs2AsciiConvertFunc = convFunc; | |
578 | } | |
579 | ||
580 | void | |
581 | PORT_SetUCS2_UTF8ConversionFunction(PORTCharConversionFunc convFunc) | |
582 | { | |
583 | ucs2Utf8ConvertFunc = convFunc; | |
584 | } | |
585 | ||
586 | //#ifndef __APPLE__ | |
587 | /* dmitch - not needed */ | |
588 | PRBool | |
589 | PORT_UCS4_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf, | |
590 | unsigned int inBufLen, unsigned char *outBuf, | |
591 | unsigned int maxOutBufLen, unsigned int *outBufLen) | |
592 | { | |
593 | if(!ucs4Utf8ConvertFunc) { | |
594 | return sec_port_ucs4_utf8_conversion_function(toUnicode, | |
595 | inBuf, inBufLen, outBuf, maxOutBufLen, outBufLen); | |
596 | } | |
597 | ||
598 | return (*ucs4Utf8ConvertFunc)(toUnicode, inBuf, inBufLen, outBuf, | |
599 | maxOutBufLen, outBufLen); | |
600 | } | |
601 | ||
602 | PRBool | |
603 | PORT_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf, | |
604 | unsigned int inBufLen, unsigned char *outBuf, | |
605 | unsigned int maxOutBufLen, unsigned int *outBufLen) | |
606 | { | |
607 | if(!ucs2Utf8ConvertFunc) { | |
608 | return sec_port_ucs2_utf8_conversion_function(toUnicode, | |
609 | inBuf, inBufLen, outBuf, maxOutBufLen, outBufLen); | |
610 | } | |
611 | ||
612 | return (*ucs2Utf8ConvertFunc)(toUnicode, inBuf, inBufLen, outBuf, | |
613 | maxOutBufLen, outBufLen); | |
614 | } | |
615 | //#endif /* __APPLE__ */ | |
616 | ||
617 | PRBool | |
618 | PORT_UCS2_ASCIIConversion(PRBool toUnicode, unsigned char *inBuf, | |
619 | unsigned int inBufLen, unsigned char *outBuf, | |
620 | unsigned int maxOutBufLen, unsigned int *outBufLen, | |
621 | PRBool swapBytes) | |
622 | { | |
623 | if(!ucs2AsciiConvertFunc) { | |
624 | return PR_FALSE; | |
625 | } | |
626 | ||
627 | return (*ucs2AsciiConvertFunc)(toUnicode, inBuf, inBufLen, outBuf, | |
628 | maxOutBufLen, outBufLen, swapBytes); | |
629 | } | |
630 | ||
631 | ||
632 | /* Portable putenv. Creates/replaces an environment variable of the form | |
633 | * envVarName=envValue | |
634 | */ | |
635 | int | |
636 | NSS_PutEnv(const char * envVarName, const char * envValue) | |
637 | { | |
638 | #if defined(XP_MAC) || defined(_WIN32_WCE) | |
639 | return SECFailure; | |
640 | #else | |
641 | SECStatus result = SECSuccess; | |
642 | char * encoded; | |
643 | int putEnvFailed; | |
644 | #ifdef _WIN32 | |
645 | PRBool setOK; | |
646 | ||
647 | setOK = SetEnvironmentVariable(envVarName, envValue); | |
648 | if (!setOK) { | |
649 | SET_ERROR_CODE | |
650 | return SECFailure; | |
651 | } | |
652 | #endif | |
653 | ||
654 | encoded = (char *)PORT_ZAlloc(strlen(envVarName) + 2 + strlen(envValue)); | |
655 | strcpy(encoded, envVarName); | |
656 | strcat(encoded, "="); | |
657 | strcat(encoded, envValue); | |
658 | ||
659 | putEnvFailed = putenv(encoded); /* adopt. */ | |
660 | if (putEnvFailed) { | |
661 | SET_ERROR_CODE | |
662 | result = SECFailure; | |
663 | PORT_Free(encoded); | |
664 | } | |
665 | return result; | |
666 | #endif | |
667 | } | |
668 | #endif /* __APPLE__ */ | |
669 |