File Coverage

deps/libgit2/src/util/util.c
Criterion Covered Total %
statement 154 317 48.5
branch 102 242 42.1
condition n/a
subroutine n/a
pod n/a
total 256 559 45.8


line stmt bran cond sub pod time code
1             /*
2             * Copyright (C) the libgit2 contributors. All rights reserved.
3             *
4             * This file is part of libgit2, distributed under the GNU GPL v2 with
5             * a Linking Exception. For full terms see the included COPYING file.
6             */
7              
8             #include "util.h"
9              
10             #include "git2_util.h"
11              
12             #ifdef GIT_WIN32
13             # include "win32/utf-conv.h"
14             # include "win32/w32_buffer.h"
15              
16             # ifndef WIN32_LEAN_AND_MEAN
17             # define WIN32_LEAN_AND_MEAN
18             # endif
19             # include
20              
21             # ifdef GIT_QSORT_S
22             # include
23             # endif
24             #endif
25              
26             #ifdef _MSC_VER
27             # include
28             #endif
29              
30             #if defined(hpux) || defined(__hpux) || defined(_hpux)
31             # include
32             #endif
33              
34 2614           int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
35             {
36             const char *p;
37             int64_t n, nn, v;
38             int c, ovfl, neg, ndig;
39              
40 2614           p = nptr;
41 2614           neg = 0;
42 2614           n = 0;
43 2614           ndig = 0;
44 2614           ovfl = 0;
45              
46             /*
47             * White space
48             */
49 2614 50         while (nptr_len && git__isspace(*p))
    50          
50 0           p++, nptr_len--;
51              
52 2614 50         if (!nptr_len)
53 0           goto Return;
54              
55             /*
56             * Sign
57             */
58 2614 100         if (*p == '-' || *p == '+') {
    50          
59 9 50         if (*p == '-')
60 9           neg = 1;
61 9           p++;
62 9           nptr_len--;
63             }
64              
65 2614 50         if (!nptr_len)
66 0           goto Return;
67              
68             /*
69             * Automatically detect the base if none was given to us.
70             * Right now, we assume that a number starting with '0x'
71             * is hexadecimal and a number starting with '0' is
72             * octal.
73             */
74 2614 100         if (base == 0) {
75 78 100         if (*p != '0')
76 15           base = 10;
77 63 50         else if (nptr_len > 2 && (p[1] == 'x' || p[1] == 'X'))
    0          
    0          
78 0           base = 16;
79             else
80 63           base = 8;
81             }
82              
83 2614 50         if (base < 0 || 36 < base)
    50          
84             goto Return;
85              
86             /*
87             * Skip prefix of '0x'-prefixed hexadecimal numbers. There is no
88             * need to do the same for '0'-prefixed octal numbers as a
89             * leading '0' does not have any impact. Also, if we skip a
90             * leading '0' in such a string, then we may end up with no
91             * digits left and produce an error later on which isn't one.
92             */
93 2614 50         if (base == 16 && nptr_len > 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
    0          
    0          
    0          
    0          
94 0           p += 2;
95 0           nptr_len -= 2;
96             }
97              
98             /*
99             * Non-empty sequence of digits
100             */
101 14569 100         for (; nptr_len > 0; p++,ndig++,nptr_len--) {
102 12803           c = *p;
103 12803           v = base;
104 12803 100         if ('0'<=c && c<='9')
    100          
105 11955           v = c - '0';
106 848 100         else if ('a'<=c && c<='z')
    50          
107 14           v = c - 'a' + 10;
108 834 50         else if ('A'<=c && c<='Z')
    0          
109 0           v = c - 'A' + 10;
110 12803 100         if (v >= base)
111 848           break;
112 11955 100         v = neg ? -v : v;
113 11955 50         if (git__multiply_int64_overflow(&nn, n, base) || git__add_int64_overflow(&n, nn, v)) {
    50          
114 0           ovfl = 1;
115             /* Keep on iterating until the end of this number */
116 0           continue;
117             }
118             }
119              
120             Return:
121 2614 100         if (ndig == 0) {
122 14           git_error_set(GIT_ERROR_INVALID, "failed to convert string to long: not a number");
123 14           return -1;
124             }
125              
126 2600 100         if (endptr)
127 1472           *endptr = p;
128              
129 2600 50         if (ovfl) {
130 0           git_error_set(GIT_ERROR_INVALID, "failed to convert string to long: overflow error");
131 0           return -1;
132             }
133              
134 2600           *result = n;
135 2614           return 0;
136             }
137              
138 830           int git__strntol32(int32_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
139             {
140             const char *tmp_endptr;
141             int32_t tmp_int;
142             int64_t tmp_long;
143             int error;
144              
145 830 50         if ((error = git__strntol64(&tmp_long, nptr, nptr_len, &tmp_endptr, base)) < 0)
146 0           return error;
147              
148 830           tmp_int = tmp_long & 0xFFFFFFFF;
149 830 50         if (tmp_int != tmp_long) {
150 0           int len = (int)(tmp_endptr - nptr);
151 0           git_error_set(GIT_ERROR_INVALID, "failed to convert: '%.*s' is too large", len, nptr);
152 0           return -1;
153             }
154              
155 830           *result = tmp_int;
156 830 50         if (endptr)
157 830           *endptr = tmp_endptr;
158              
159 830           return error;
160             }
161              
162 17           int git__strcasecmp(const char *a, const char *b)
163             {
164 37 100         while (*a && *b && git__tolower(*a) == git__tolower(*b))
    100          
    100          
165 20           ++a, ++b;
166 17           return ((unsigned char)git__tolower(*a) - (unsigned char)git__tolower(*b));
167             }
168              
169 0           int git__strcasesort_cmp(const char *a, const char *b)
170             {
171 0           int cmp = 0;
172              
173 0 0         while (*a && *b) {
    0          
174 0 0         if (*a != *b) {
175 0 0         if (git__tolower(*a) != git__tolower(*b))
176 0           break;
177             /* use case in sort order even if not in equivalence */
178 0 0         if (!cmp)
179 0           cmp = (int)(*(const uint8_t *)a) - (int)(*(const uint8_t *)b);
180             }
181              
182 0           ++a, ++b;
183             }
184              
185 0 0         if (*a || *b)
    0          
186 0           return (unsigned char)git__tolower(*a) - (unsigned char)git__tolower(*b);
187              
188 0           return cmp;
189             }
190              
191 14           int git__strncasecmp(const char *a, const char *b, size_t sz)
192             {
193             int al, bl;
194              
195             do {
196 36           al = (unsigned char)git__tolower(*a);
197 36           bl = (unsigned char)git__tolower(*b);
198 36           ++a, ++b;
199 36 100         } while (--sz && al && al == bl);
    50          
    100          
200              
201 14           return al - bl;
202             }
203              
204 0           void git__strntolower(char *str, size_t len)
205             {
206             size_t i;
207              
208 0 0         for (i = 0; i < len; ++i) {
209 0           str[i] = (char)git__tolower(str[i]);
210             }
211 0           }
212              
213 0           void git__strtolower(char *str)
214             {
215 0           git__strntolower(str, strlen(str));
216 0           }
217              
218 2825           GIT_INLINE(int) prefixcmp(const char *str, size_t str_n, const char *prefix, bool icase)
219             {
220             int s, p;
221              
222 9363 100         while (str_n--) {
223 8235           s = (unsigned char)*str++;
224 8235           p = (unsigned char)*prefix++;
225              
226 8235 50         if (icase) {
227 0           s = git__tolower(s);
228 0           p = git__tolower(p);
229             }
230              
231 8235 100         if (!p)
232 178           return 0;
233              
234 8057 100         if (s != p)
235 1519           return s - p;
236             }
237              
238 1128           return (0 - *prefix);
239             }
240              
241 11753           int git__prefixcmp(const char *str, const char *prefix)
242             {
243             unsigned char s, p;
244              
245             while (1) {
246 244784           p = *prefix++;
247 244784           s = *str++;
248              
249 244784 100         if (!p)
250 6660           return 0;
251              
252 238124 100         if (s != p)
253 5093           return s - p;
254 233031           }
255             }
256              
257 2825           int git__prefixncmp(const char *str, size_t str_n, const char *prefix)
258             {
259 2825           return prefixcmp(str, str_n, prefix, false);
260             }
261              
262 0           int git__prefixcmp_icase(const char *str, const char *prefix)
263             {
264 0           return prefixcmp(str, SIZE_MAX, prefix, true);
265             }
266              
267 0           int git__prefixncmp_icase(const char *str, size_t str_n, const char *prefix)
268             {
269 0           return prefixcmp(str, str_n, prefix, true);
270             }
271              
272 2570           int git__suffixcmp(const char *str, const char *suffix)
273             {
274 2570           size_t a = strlen(str);
275 2570           size_t b = strlen(suffix);
276 2570 100         if (a < b)
277 1145           return -1;
278 1425           return strcmp(str + (a - b), suffix);
279             }
280              
281 0           char *git__strtok(char **end, const char *sep)
282             {
283 0           char *ptr = *end;
284              
285 0 0         while (*ptr && strchr(sep, *ptr))
    0          
286 0           ++ptr;
287              
288 0 0         if (*ptr) {
289 0           char *start = ptr;
290 0           *end = start + 1;
291              
292 0 0         while (**end && !strchr(sep, **end))
    0          
293 0           ++*end;
294              
295 0 0         if (**end) {
296 0           **end = '\0';
297 0           ++*end;
298             }
299              
300 0           return start;
301             }
302              
303 0           return NULL;
304             }
305              
306             /* Similar to strtok, but does not collapse repeated tokens. */
307 0           char *git__strsep(char **end, const char *sep)
308             {
309 0           char *start = *end, *ptr = *end;
310              
311 0 0         while (*ptr && !strchr(sep, *ptr))
    0          
312 0           ++ptr;
313              
314 0 0         if (*ptr) {
315 0           *end = ptr + 1;
316 0           *ptr = '\0';
317              
318 0           return start;
319             }
320              
321 0           return NULL;
322             }
323              
324 3246           size_t git__linenlen(const char *buffer, size_t buffer_len)
325             {
326 3246           char *nl = memchr(buffer, '\n', buffer_len);
327 3246 100         return nl ? (size_t)(nl - buffer) + 1 : buffer_len;
328             }
329              
330             /*
331             * Adapted Not So Naive algorithm from http://www-igm.univ-mlv.fr/~lecroq/string/
332             */
333 0           const void * git__memmem(const void *haystack, size_t haystacklen,
334             const void *needle, size_t needlelen)
335             {
336             const char *h, *n;
337             size_t j, k, l;
338              
339 0 0         if (needlelen > haystacklen || !haystacklen || !needlelen)
    0          
    0          
340 0           return NULL;
341              
342 0           h = (const char *) haystack,
343 0           n = (const char *) needle;
344              
345 0 0         if (needlelen == 1)
346 0           return memchr(haystack, *n, haystacklen);
347              
348 0 0         if (n[0] == n[1]) {
349 0           k = 2;
350 0           l = 1;
351             } else {
352 0           k = 1;
353 0           l = 2;
354             }
355              
356 0           j = 0;
357 0 0         while (j <= haystacklen - needlelen) {
358 0 0         if (n[1] != h[j + 1]) {
359 0           j += k;
360             } else {
361 0 0         if (memcmp(n + 2, h + j + 2, needlelen - 2) == 0 &&
    0          
362 0           n[0] == h[j])
363 0           return h + j;
364 0           j += l;
365             }
366             }
367              
368 0           return NULL;
369             }
370              
371 0           void git__hexdump(const char *buffer, size_t len)
372             {
373             static const size_t LINE_WIDTH = 16;
374              
375             size_t line_count, last_line, i, j;
376             const char *line;
377              
378 0           line_count = (len / LINE_WIDTH);
379 0           last_line = (len % LINE_WIDTH);
380              
381 0 0         for (i = 0; i < line_count; ++i) {
382 0           printf("%08" PRIxZ " ", (i * LINE_WIDTH));
383              
384 0           line = buffer + (i * LINE_WIDTH);
385 0 0         for (j = 0; j < LINE_WIDTH; ++j, ++line) {
386 0           printf("%02x ", (unsigned char)*line & 0xFF);
387              
388 0 0         if (j == (LINE_WIDTH / 2))
389 0           printf(" ");
390             }
391              
392 0           printf(" |");
393              
394 0           line = buffer + (i * LINE_WIDTH);
395 0 0         for (j = 0; j < LINE_WIDTH; ++j, ++line)
396 0 0         printf("%c", (*line >= 32 && *line <= 126) ? *line : '.');
    0          
397              
398 0           printf("|\n");
399             }
400              
401 0 0         if (last_line > 0) {
402 0           printf("%08" PRIxZ " ", (line_count * LINE_WIDTH));
403              
404 0           line = buffer + (line_count * LINE_WIDTH);
405 0 0         for (j = 0; j < last_line; ++j, ++line) {
406 0           printf("%02x ", (unsigned char)*line & 0xFF);
407              
408 0 0         if (j == (LINE_WIDTH / 2))
409 0           printf(" ");
410             }
411              
412 0 0         if (j < (LINE_WIDTH / 2))
413 0           printf(" ");
414 0 0         for (j = 0; j < (LINE_WIDTH - last_line); ++j)
415 0           printf(" ");
416              
417 0           printf(" |");
418              
419 0           line = buffer + (line_count * LINE_WIDTH);
420 0 0         for (j = 0; j < last_line; ++j, ++line)
421 0 0         printf("%c", (*line >= 32 && *line <= 126) ? *line : '.');
    0          
422              
423 0           printf("|\n");
424             }
425              
426 0           printf("\n");
427 0           }
428              
429             #ifdef GIT_LEGACY_HASH
430             uint32_t git__hash(const void *key, int len, unsigned int seed)
431             {
432             const uint32_t m = 0x5bd1e995;
433             const int r = 24;
434             uint32_t h = seed ^ len;
435              
436             const unsigned char *data = (const unsigned char *)key;
437              
438             while(len >= 4) {
439             uint32_t k = *(uint32_t *)data;
440              
441             k *= m;
442             k ^= k >> r;
443             k *= m;
444              
445             h *= m;
446             h ^= k;
447              
448             data += 4;
449             len -= 4;
450             }
451              
452             switch(len) {
453             case 3: h ^= data[2] << 16;
454             case 2: h ^= data[1] << 8;
455             case 1: h ^= data[0];
456             h *= m;
457             };
458              
459             h ^= h >> 13;
460             h *= m;
461             h ^= h >> 15;
462              
463             return h;
464             }
465             #else
466             /*
467             Cross-platform version of Murmurhash3
468             http://code.google.com/p/smhasher/wiki/MurmurHash3
469             by Austin Appleby (aappleby@gmail.com)
470              
471             This code is on the public domain.
472             */
473 0           uint32_t git__hash(const void *key, int len, uint32_t seed)
474             {
475              
476             #define MURMUR_BLOCK() {\
477             k1 *= c1; \
478             k1 = git__rotl(k1,11);\
479             k1 *= c2;\
480             h1 ^= k1;\
481             h1 = h1*3 + 0x52dce729;\
482             c1 = c1*5 + 0x7b7d159c;\
483             c2 = c2*5 + 0x6bce6396;\
484             }
485              
486 0           const uint8_t *data = (const uint8_t*)key;
487 0           const int nblocks = len / 4;
488              
489 0           const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4);
490 0           const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
491              
492 0           uint32_t h1 = 0x971e137b ^ seed;
493             uint32_t k1;
494              
495 0           uint32_t c1 = 0x95543787;
496 0           uint32_t c2 = 0x2ad7eb25;
497              
498             int i;
499              
500 0 0         for (i = -nblocks; i; i++) {
501 0           k1 = blocks[i];
502 0           MURMUR_BLOCK();
503             }
504              
505 0           k1 = 0;
506              
507 0           switch(len & 3) {
508 0           case 3: k1 ^= tail[2] << 16;
509             /* fall through */
510 0           case 2: k1 ^= tail[1] << 8;
511             /* fall through */
512 0           case 1: k1 ^= tail[0];
513 0           MURMUR_BLOCK();
514             }
515              
516 0           h1 ^= len;
517 0           h1 ^= h1 >> 16;
518 0           h1 *= 0x85ebca6b;
519 0           h1 ^= h1 >> 13;
520 0           h1 *= 0xc2b2ae35;
521 0           h1 ^= h1 >> 16;
522              
523 0           return h1;
524             }
525             #endif
526              
527             /**
528             * A modified `bsearch` from the BSD glibc.
529             *
530             * Copyright (c) 1990 Regents of the University of California.
531             * All rights reserved.
532             * Redistribution and use in source and binary forms, with or without
533             * modification, are permitted provided that the following conditions
534             * are met:
535             * 1. Redistributions of source code must retain the above copyright
536             * notice, this list of conditions and the following disclaimer.
537             * 2. Redistributions in binary form must reproduce the above copyright
538             * notice, this list of conditions and the following disclaimer in the
539             * documentation and/or other materials provided with the distribution.
540             * 3. [rescinded 22 July 1999]
541             * 4. Neither the name of the University nor the names of its contributors
542             * may be used to endorse or promote products derived from this software
543             * without specific prior written permission.
544             *
545             * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
546             * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
547             * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
548             * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
549             * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
550             * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
551             * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
552             * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
553             * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
554             * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
555             * SUCH DAMAGE.
556             */
557 3507           int git__bsearch(
558             void **array,
559             size_t array_len,
560             const void *key,
561             int (*compare)(const void *, const void *),
562             size_t *position)
563             {
564             size_t lim;
565 3507           int cmp = -1;
566 3507           void **part, **base = array;
567              
568 7712 100         for (lim = array_len; lim != 0; lim >>= 1) {
569 4406           part = base + (lim >> 1);
570 4406           cmp = (*compare)(key, *part);
571 4406 100         if (cmp == 0) {
572 201           base = part;
573 201           break;
574             }
575 4205 100         if (cmp > 0) { /* key > p; take right partition */
576 1176           base = part + 1;
577 1176           lim--;
578             } /* else take left partition */
579             }
580              
581 3507 100         if (position)
582 3504           *position = (base - array);
583              
584 3507 100         return (cmp == 0) ? 0 : GIT_ENOTFOUND;
585             }
586              
587 0           int git__bsearch_r(
588             void **array,
589             size_t array_len,
590             const void *key,
591             int (*compare_r)(const void *, const void *, void *),
592             void *payload,
593             size_t *position)
594             {
595             size_t lim;
596 0           int cmp = -1;
597 0           void **part, **base = array;
598              
599 0 0         for (lim = array_len; lim != 0; lim >>= 1) {
600 0           part = base + (lim >> 1);
601 0           cmp = (*compare_r)(key, *part, payload);
602 0 0         if (cmp == 0) {
603 0           base = part;
604 0           break;
605             }
606 0 0         if (cmp > 0) { /* key > p; take right partition */
607 0           base = part + 1;
608 0           lim--;
609             } /* else take left partition */
610             }
611              
612 0 0         if (position)
613 0           *position = (base - array);
614              
615 0 0         return (cmp == 0) ? 0 : GIT_ENOTFOUND;
616             }
617              
618             /**
619             * A strcmp wrapper
620             *
621             * We don't want direct pointers to the CRT on Windows, we may
622             * get stdcall conflicts.
623             */
624 104           int git__strcmp_cb(const void *a, const void *b)
625             {
626 104           return strcmp((const char *)a, (const char *)b);
627             }
628              
629 0           int git__strcasecmp_cb(const void *a, const void *b)
630             {
631 0           return strcasecmp((const char *)a, (const char *)b);
632             }
633              
634 649           int git__parse_bool(int *out, const char *value)
635             {
636             /* A missing value means true */
637 649 50         if (value == NULL ||
    100          
638 290 50         !strcasecmp(value, "true") ||
639 290 50         !strcasecmp(value, "yes") ||
640 290           !strcasecmp(value, "on")) {
641 359           *out = 1;
642 359           return 0;
643             }
644 290 100         if (!strcasecmp(value, "false") ||
    50          
645 14 50         !strcasecmp(value, "no") ||
646 14 50         !strcasecmp(value, "off") ||
647 14           value[0] == '\0') {
648 276           *out = 0;
649 276           return 0;
650             }
651              
652 14           return -1;
653             }
654              
655 32           size_t git__unescape(char *str)
656             {
657 32           char *scan, *pos = str;
658              
659 32 50         if (!str)
660 0           return 0;
661              
662 173 100         for (scan = str; *scan; pos++, scan++) {
663 141 50         if (*scan == '\\' && *(scan + 1) != '\0')
    0          
664 0           scan++; /* skip '\' but include next char */
665 141 50         if (pos != scan)
666 0           *pos = *scan;
667             }
668              
669 32 50         if (pos != scan) {
670 0           *pos = '\0';
671             }
672              
673 32           return (pos - str);
674             }
675              
676             #if defined(GIT_QSORT_S) || defined(GIT_QSORT_R_BSD)
677             typedef struct {
678             git__sort_r_cmp cmp;
679             void *payload;
680             } git__qsort_r_glue;
681              
682             static int GIT_LIBGIT2_CALL git__qsort_r_glue_cmp(
683             void *payload, const void *a, const void *b)
684             {
685             git__qsort_r_glue *glue = payload;
686             return glue->cmp(a, b, glue->payload);
687             }
688             #endif
689              
690              
691             #if !defined(GIT_QSORT_R_BSD) && \
692             !defined(GIT_QSORT_R_GNU) && \
693             !defined(GIT_QSORT_S)
694 4           static void swap(uint8_t *a, uint8_t *b, size_t elsize)
695             {
696             char tmp[256];
697              
698 8 100         while (elsize) {
699 4           size_t n = elsize < sizeof(tmp) ? elsize : sizeof(tmp);
700 4           memcpy(tmp, a + elsize - n, n);
701 4           memcpy(a + elsize - n, b + elsize - n, n);
702 4           memcpy(b + elsize - n, tmp, n);
703 4           elsize -= n;
704             }
705 4           }
706              
707 22           static void insertsort(
708             void *els, size_t nel, size_t elsize,
709             git__sort_r_cmp cmp, void *payload)
710             {
711 22           uint8_t *base = els;
712 22           uint8_t *end = base + nel * elsize;
713             uint8_t *i, *j;
714              
715 72 100         for (i = base + elsize; i < end; i += elsize)
716 54 50         for (j = i; j > base && cmp(j, j - elsize, payload) < 0; j -= elsize)
    100          
717 4           swap(j, j - elsize, elsize);
718 22           }
719             #endif
720              
721 22           void git__qsort_r(
722             void *els, size_t nel, size_t elsize, git__sort_r_cmp cmp, void *payload)
723             {
724             #if defined(GIT_QSORT_R_BSD)
725             git__qsort_r_glue glue = { cmp, payload };
726             qsort_r(els, nel, elsize, &glue, git__qsort_r_glue_cmp);
727             #elif defined(GIT_QSORT_R_GNU)
728             qsort_r(els, nel, elsize, cmp, payload);
729             #elif defined(GIT_QSORT_S)
730             git__qsort_r_glue glue = { cmp, payload };
731             qsort_s(els, nel, elsize, git__qsort_r_glue_cmp, &glue);
732             #else
733 22           insertsort(els, nel, elsize, cmp, payload);
734             #endif
735 22           }
736              
737             #ifdef GIT_WIN32
738             int git__getenv(git_str *out, const char *name)
739             {
740             wchar_t *wide_name = NULL, *wide_value = NULL;
741             DWORD value_len;
742             int error = -1;
743              
744             git_str_clear(out);
745              
746             if (git__utf8_to_16_alloc(&wide_name, name) < 0)
747             return -1;
748              
749             if ((value_len = GetEnvironmentVariableW(wide_name, NULL, 0)) > 0) {
750             wide_value = git__malloc(value_len * sizeof(wchar_t));
751             GIT_ERROR_CHECK_ALLOC(wide_value);
752              
753             value_len = GetEnvironmentVariableW(wide_name, wide_value, value_len);
754             }
755              
756             if (value_len)
757             error = git_str_put_w(out, wide_value, value_len);
758             else if (GetLastError() == ERROR_SUCCESS || GetLastError() == ERROR_ENVVAR_NOT_FOUND)
759             error = GIT_ENOTFOUND;
760             else
761             git_error_set(GIT_ERROR_OS, "could not read environment variable '%s'", name);
762              
763             git__free(wide_name);
764             git__free(wide_value);
765             return error;
766             }
767             #else
768 261           int git__getenv(git_str *out, const char *name)
769             {
770 261           const char *val = getenv(name);
771              
772 261           git_str_clear(out);
773              
774 261 100         if (!val)
775 87           return GIT_ENOTFOUND;
776              
777 174           return git_str_puts(out, val);
778             }
779             #endif
780              
781             /*
782             * By doing this in two steps we can at least get
783             * the function to be somewhat coherent, even
784             * with this disgusting nest of #ifdefs.
785             */
786             #ifndef _SC_NPROCESSORS_ONLN
787             # ifdef _SC_NPROC_ONLN
788             # define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
789             # elif defined _SC_CRAY_NCPU
790             # define _SC_NPROCESSORS_ONLN _SC_CRAY_NCPU
791             # endif
792             #endif
793              
794 3           int git__online_cpus(void)
795             {
796             #ifdef _SC_NPROCESSORS_ONLN
797             long ncpus;
798             #endif
799              
800             #ifdef _WIN32
801             SYSTEM_INFO info;
802             GetSystemInfo(&info);
803              
804             if ((int)info.dwNumberOfProcessors > 0)
805             return (int)info.dwNumberOfProcessors;
806             #elif defined(hpux) || defined(__hpux) || defined(_hpux)
807             struct pst_dynamic psd;
808              
809             if (!pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0))
810             return (int)psd.psd_proc_cnt;
811             #endif
812              
813             #ifdef _SC_NPROCESSORS_ONLN
814 3 50         if ((ncpus = (long)sysconf(_SC_NPROCESSORS_ONLN)) > 0)
815 3           return (int)ncpus;
816             #endif
817              
818 0           return 1;
819             }