Whamcloud - gitweb
LU-5427 lbuild: Fix compilation with MPSS 3.3
[fs/lustre-release.git] / libcfs / libcfs / winnt / winnt-utils.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  */
34
35
36 /*
37  * miscellaneous libcfs stuff
38  */
39 #define DEBUG_SUBSYSTEM S_LNET
40 #include <libcfs/libcfs.h>
41 #include <errno.h>
42
43 /*
44  *  IDR support routines
45  *
46  *  local global id <-> handle context
47  */
48
49 /* idr definitions */
50
51 #define IDR_BITS 7
52 #define IDR_FULL 0xffffffff
53 #define IDR_SIZE (1 << IDR_BITS)
54 #define IDR_MASK ((1 << IDR_BITS)-1)
55 #define MAX_ID_SHIFT (sizeof(int)*8 - 1)
56 #define MAX_ID_BIT (1U << MAX_ID_SHIFT)
57 #define MAX_ID_MASK (MAX_ID_BIT - 1)
58 #define MAX_LEVEL (MAX_ID_SHIFT + IDR_BITS - 1) / IDR_BITS
59 #define IDR_FREE_MAX MAX_LEVEL + MAX_LEVEL
60
61 #define idr_set_bit(bit, v) (v) |= (1<<(bit))
62 #define idr_clear_bit(bit, v) (v) &= ~(1<<(bit))
63 #define idr_test_bit(bit, v) ((v) & (1<<(bit)))
64
65 struct idr_layer {
66         uint32_t            bitmap;
67         struct idr_layer   *ary[IDR_SIZE];
68         int                             count;
69 };
70
71 struct idr_context {
72         struct idr_layer *top;
73         struct idr_layer *id_free;
74         int               layers;
75         int               id_free_cnt;
76 };
77
78
79 /*
80  * id (fd) <-> pointer (HANDLE)
81  */
82
83 /**********************************************************
84   private structures and routines for id implementation
85 ***********************************************************/
86                                    
87 static struct idr_layer *alloc_layer(struct idr_context *idp)
88 {
89         struct idr_layer *p;
90
91         if (!(p = idp->id_free))
92                 return NULL;
93         idp->id_free = p->ary[0];
94         idp->id_free_cnt--;
95         p->ary[0] = NULL;
96         return p;
97 }
98
99 static int find_next_idrbit(uint32_t bm, int maxid, int n)
100 {
101         while (n<maxid && !idr_test_bit(n, bm)) n++;
102         return n;
103 }
104
105 static void free_layer(struct idr_context *idp, struct idr_layer *p)
106 {
107         p->ary[0] = idp->id_free;
108         idp->id_free = p;
109         idp->id_free_cnt++;
110 }
111
112 static int idr_pre_get(struct idr_context *idp)
113 {
114         while (idp->id_free_cnt < IDR_FREE_MAX) {
115                 struct idr_layer *new;
116
117         new = kmalloc(sizeof(struct idr_layer), __GFP_ZERO);
118                 if(new == NULL)
119                         return (0);
120                 free_layer(idp, new);
121         }
122         return 1;
123 }
124
125 static int sub_alloc(struct idr_context *idp, void *ptr, int *starting_id)
126 {
127         int n, m, sh;
128         struct idr_layer *p, *new;
129         struct idr_layer *pa[MAX_LEVEL];
130         int l, id;
131         uint32_t bm;
132
133         memset(pa, 0, sizeof(pa));
134
135         id = *starting_id;
136         p = idp->top;
137         l = idp->layers;
138         pa[l--] = NULL;
139         while (1) {
140                 /*
141                  * We run around this while until we reach the leaf node...
142                  */
143                 n = (id >> (IDR_BITS*l)) & IDR_MASK;
144                 bm = ~p->bitmap;
145                 m = find_next_idrbit(bm, IDR_SIZE, n);
146                 if (m == IDR_SIZE) {
147                         /* no space available go back to previous layer. */
148                         l++;
149                         id = (id | ((1 << (IDR_BITS*l))-1)) + 1;
150                         if (!(p = pa[l])) {
151                                 *starting_id = id;
152                                 return -2;
153                         }
154                         continue;
155                 }
156                 if (m != n) {
157                         sh = IDR_BITS*l;
158                         id = ((id >> sh) ^ n ^ m) << sh;
159                 }
160                 if ((id >= MAX_ID_BIT) || (id < 0))
161                         return -1;
162                 if (l == 0)
163                         break;
164                 /*
165                  * Create the layer below if it is missing.
166                  */
167                 if (!p->ary[m]) {
168                         if (!(new = alloc_layer(idp)))
169                                 return -1;
170                         p->ary[m] = new;
171                         p->count++;
172                 }
173                 pa[l--] = p;
174                 p = p->ary[m];
175         }
176         /*
177          * We have reached the leaf node, plant the
178          * users pointer and return the raw id.
179          */
180         p->ary[m] = (struct idr_layer *)ptr;
181         idr_set_bit(m, p->bitmap);
182         p->count++;
183         /*
184          * If this layer is full mark the bit in the layer above
185          * to show that this part of the radix tree is full.
186          * This may complete the layer above and require walking
187          * up the radix tree.
188          */
189         n = id;
190         while (p->bitmap == IDR_FULL) {
191                 if (!(p = pa[++l]))
192                         break;
193                 n = n >> IDR_BITS;
194                 idr_set_bit((n & IDR_MASK), p->bitmap);
195         }
196         return(id);
197 }
198
199 static int idr_get_new_above_int(struct idr_context *idp, void *ptr, int starting_id)
200 {
201         struct idr_layer *p, *new;
202         int layers, v, id;
203
204         idr_pre_get(idp);
205         
206         id = starting_id;
207 build_up:
208         p = idp->top;
209         layers = idp->layers;
210         if (!p) {
211                 if (!(p = alloc_layer(idp)))
212                         return -1;
213                 layers = 1;
214         }
215         /*
216          * Add a new layer to the top of the tree if the requested
217          * id is larger than the currently allocated space.
218          */
219         while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDR_BITS)))) {
220                 layers++;
221                 if (!p->count)
222                         continue;
223                 if (!(new = alloc_layer(idp))) {
224                         /*
225                          * The allocation failed.  If we built part of
226                          * the structure tear it down.
227                          */
228                         for (new = p; p && p != idp->top; new = p) {
229                                 p = p->ary[0];
230                                 new->ary[0] = NULL;
231                                 new->bitmap = new->count = 0;
232                                 free_layer(idp, new);
233                         }
234                         return -1;
235                 }
236                 new->ary[0] = p;
237                 new->count = 1;
238                 if (p->bitmap == IDR_FULL)
239                         idr_set_bit(0, new->bitmap);
240                 p = new;
241         }
242         idp->top = p;
243         idp->layers = layers;
244         v = sub_alloc(idp, ptr, &id);
245         if (v == -2)
246                 goto build_up;
247         return(v);
248 }
249
250 static int sub_remove(struct idr_context *idp, int shift, int id)
251 {
252         struct idr_layer *p = idp->top;
253         struct idr_layer **pa[MAX_LEVEL];
254         struct idr_layer ***paa = &pa[0];
255         int n;
256
257         *paa = NULL;
258         *++paa = &idp->top;
259
260         while ((shift > 0) && p) {
261                 n = (id >> shift) & IDR_MASK;
262                 idr_clear_bit(n, p->bitmap);
263                 *++paa = &p->ary[n];
264                 p = p->ary[n];
265                 shift -= IDR_BITS;
266         }
267         n = id & IDR_MASK;
268         if (p != NULL && idr_test_bit(n, p->bitmap)) {
269                 idr_clear_bit(n, p->bitmap);
270                 p->ary[n] = NULL;
271                 while(*paa && ! --((**paa)->count)){
272                         free_layer(idp, **paa);
273                         **paa-- = NULL;
274                 }
275                 if ( ! *paa )
276                         idp->layers = 0;
277                 return 0;
278         }
279         return -1;
280 }
281
282 static void *_idr_find(struct idr_context *idp, int id)
283 {
284         int n;
285         struct idr_layer *p;
286
287         n = idp->layers * IDR_BITS;
288         p = idp->top;
289         /*
290          * This tests to see if bits outside the current tree are
291          * present.  If so, tain't one of ours!
292          */
293         if ((id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS))
294              return NULL;
295
296         /* Mask off upper bits we don't use for the search. */
297         id &= MAX_ID_MASK;
298
299         while (n >= IDR_BITS && p) {
300                 n -= IDR_BITS;
301                 p = p->ary[(id >> n) & IDR_MASK];
302         }
303         return((void *)p);
304 }
305
306 static int _idr_remove(struct idr_context *idp, int id)
307 {
308         struct idr_layer *p;
309
310         /* Mask off upper bits we don't use for the search. */
311         id &= MAX_ID_MASK;
312
313         if (sub_remove(idp, (idp->layers - 1) * IDR_BITS, id) == -1) {
314                 return -1;
315         }
316
317         if ( idp->top && idp->top->count == 1 && 
318              (idp->layers > 1) &&
319              idp->top->ary[0]) {
320                 /* We can drop a layer */
321                 p = idp->top->ary[0];
322                 idp->top->bitmap = idp->top->count = 0;
323                 free_layer(idp, idp->top);
324                 idp->top = p;
325                 --idp->layers;
326         }
327         while (idp->id_free_cnt >= IDR_FREE_MAX) {
328                 p = alloc_layer(idp);
329                 kfree(p);
330         }
331         return 0;
332 }
333
334 /**********************************************************
335   publick interfaces of id vs handle conversion
336 ***********************************************************/
337
338 /**
339   initialise a idr tree.
340  */
341 struct idr_context *cfs_idr_init()
342 {
343     struct idr_context * idp = NULL;
344     idp = kmalloc(sizeof(struct idr_context), 0);
345     if (idp) {
346         memset(idp, 0, sizeof(struct idr_context));
347     }
348
349     return idp;
350 }
351
352 /**
353   remove an id from the idr tree
354 */
355 int cfs_idr_remove(struct idr_context *idp, int id)
356 {
357         int ret;
358         ret = _idr_remove((struct idr_context *)idp, id);
359         if (ret != 0) {
360                 CWARN("WARNING: attempt to remove unset id %d in idtree\n", id);
361         }
362         return ret;
363 }
364
365 /**
366   allocate the next available id, and assign 'ptr' into its slot.
367   you can retrieve later this pointer using idr_find()
368 */
369 int cfs_idr_get_new(struct idr_context *idp, void *ptr)
370 {
371         int ret = idr_get_new_above_int(idp, ptr, 0);
372         if (ret > MAX_ID_MASK) {
373                 cfs_idr_remove(idp, ret);
374                 return -1;
375         }
376         return ret;
377 }
378
379 /**
380    allocate a new id, giving the first available value greater than or
381    equal to the given starting id
382 */
383 int cfs_idr_get_new_above(struct idr_context *idp, void *ptr, int starting_id)
384 {
385         int ret = idr_get_new_above_int(idp, ptr, starting_id);
386         if (ret > MAX_ID_MASK) {
387                 cfs_idr_remove(idp, ret);
388                 return -1;
389         }
390         return ret;
391 }
392
393 /**
394   find a pointer value previously set with idr_get_new given an id
395 */
396 void *cfs_idr_find(struct idr_context *idp, int id)
397 {
398         return _idr_find(idp, id);
399 }
400
401 /**
402   destroy a idr tree. 
403  */
404 void cfs_idr_exit(struct idr_context *idp)
405 {
406     if (idp) {
407             kfree(idp);
408     }
409 }
410
411 /*
412  * convert <fcntl.h> flag from client to server.
413  * 
414  * nt kernel uses several members to describe the open flags
415  * such as DesiredAccess/ShareAccess/CreateDisposition/CreateOptions
416  * so it's better to convert when using, not here.
417  */
418
419 int convert_client_oflag(int cflag, int *result)
420 {
421     *result = 0;
422         return 0;
423 }
424
425 int cfs_error_code(NTSTATUS Status)
426 {
427     switch (Status) {
428
429         case STATUS_ACCESS_DENIED:
430             return (-EACCES);
431
432         case STATUS_ACCESS_VIOLATION:
433             return (-EFAULT);
434     
435         case STATUS_BUFFER_TOO_SMALL:
436             return (-ETOOSMALL);
437
438         case STATUS_INVALID_PARAMETER:
439             return (-EINVAL);
440
441         case STATUS_NOT_IMPLEMENTED:
442         case STATUS_NOT_SUPPORTED:
443             return (-EOPNOTSUPP);
444
445         case STATUS_INVALID_ADDRESS:
446         case STATUS_INVALID_ADDRESS_COMPONENT:
447             return (-EADDRNOTAVAIL);
448
449         case STATUS_NO_SUCH_DEVICE:
450         case STATUS_NO_SUCH_FILE:
451         case STATUS_OBJECT_NAME_NOT_FOUND:
452         case STATUS_OBJECT_PATH_NOT_FOUND:  
453         case STATUS_NETWORK_BUSY:
454         case STATUS_INVALID_NETWORK_RESPONSE:
455         case STATUS_UNEXPECTED_NETWORK_ERROR:
456             return (-ENETDOWN);
457
458         case STATUS_BAD_NETWORK_PATH:
459         case STATUS_NETWORK_UNREACHABLE:
460         case STATUS_PROTOCOL_UNREACHABLE:     
461             return (-ENETUNREACH);
462
463         case STATUS_LOCAL_DISCONNECT:
464         case STATUS_TRANSACTION_ABORTED:
465         case STATUS_CONNECTION_ABORTED:
466             return (-ECONNABORTED);
467
468         case STATUS_REMOTE_DISCONNECT:
469         case STATUS_LINK_FAILED:
470         case STATUS_CONNECTION_DISCONNECTED:
471         case STATUS_CONNECTION_RESET:
472         case STATUS_PORT_UNREACHABLE:
473             return (-ECONNRESET);
474
475         case STATUS_INSUFFICIENT_RESOURCES:
476             return (-ENOMEM);
477
478         case STATUS_PAGEFILE_QUOTA:
479         case STATUS_NO_MEMORY:
480         case STATUS_CONFLICTING_ADDRESSES:
481         case STATUS_QUOTA_EXCEEDED:
482         case STATUS_TOO_MANY_PAGING_FILES:
483         case STATUS_WORKING_SET_QUOTA:
484         case STATUS_COMMITMENT_LIMIT:
485         case STATUS_TOO_MANY_ADDRESSES:
486         case STATUS_REMOTE_RESOURCES:
487             return (-ENOBUFS);
488
489         case STATUS_INVALID_CONNECTION:
490             return (-ENOTCONN);
491
492         case STATUS_PIPE_DISCONNECTED:
493             return (-ESHUTDOWN);
494
495         case STATUS_TIMEOUT:
496         case STATUS_IO_TIMEOUT:
497         case STATUS_LINK_TIMEOUT:
498             return (-ETIMEDOUT);
499
500         case STATUS_REMOTE_NOT_LISTENING:
501         case STATUS_CONNECTION_REFUSED:
502             return (-ECONNREFUSED);
503
504         case STATUS_HOST_UNREACHABLE:
505             return (-EHOSTUNREACH);
506
507         case STATUS_PENDING:
508         case STATUS_DEVICE_NOT_READY:
509             return (-EAGAIN);
510
511         case STATUS_CANCELLED:
512         case STATUS_REQUEST_ABORTED:
513             return (-EINTR);
514
515         case STATUS_BUFFER_OVERFLOW:
516         case STATUS_INVALID_BUFFER_SIZE:
517             return (-EMSGSIZE);
518
519         case STATUS_ADDRESS_ALREADY_EXISTS:
520             return (-EADDRINUSE);
521     }
522
523     if (NT_SUCCESS(Status)) 
524         return 0;
525
526     return (-EINVAL);
527 }
528
529 /*
530  * Convert server error code to client format. Error codes are from
531  * Linux errno.h, so for Linux client---identity.
532  */
533 int convert_server_error(__u64 ecode)
534 {
535         return cfs_error_code((NTSTATUS)ecode);
536 }
537
538 char * strsep(char **strp, const char *delim)
539 {
540     char *begin, *end;
541
542     begin = *strp;
543     if (begin == NULL) {
544         return NULL;
545     }
546
547     if (delim[0] == '\0' || delim[1] == '\0') {
548         char ch = delim[0];
549         if (ch == '\0') {
550                 end = NULL;
551         } else {
552                 if (*begin == ch) {
553                     end = begin;
554                 } else if (*begin == '\0') {
555                     end = NULL;
556                 } else {
557                     end = strchr (begin + 1, ch);
558                 }
559         }
560     } else {
561         end = strpbrk (begin, delim);
562     }
563
564     if (end) {
565         *end++ = '\0';
566         *strp = end;
567     } else {
568         *strp = NULL;
569     }
570
571     return begin;
572 }
573
574 /*
575  * strnchr - Find a character in a length limited string
576  * @s: The string to be searched
577  * @count: The number of characters to be searched
578  * @c: The character to search for
579  */
580
581 char *strnchr(const char *s, size_t count, int c)
582 {
583     for (; count-- && *s != '\0'; ++s)
584         if (*s == (char) c)
585             return (char *) s;
586     return NULL;
587 }
588
589 __u64 strtoull(char *nptr, char **endptr,int base)
590 {
591         char *s = nptr;
592         __u64 acc, cutoff;
593         int c, neg = 0, any, cutlim;
594
595         /*
596          * See strtol for comments as to the logic used.
597          */
598         do {
599                 c = *s++;
600         } while (cfs_isspace(c));
601         if (c == '-') {
602                 neg = 1;
603                 c = *s++;
604         } else if (c == '+')
605                 c = *s++;
606         if ((base == 0 || base == 16) &&
607             c == '0' && (*s == 'x' || *s == 'X')) {
608                 c = s[1];
609                 s += 2;
610                 base = 16;
611         }
612         if (base == 0)
613                 base = c == '0' ? 8 : 10;
614         cutoff = (__u64)ULONG_LONG_MAX / (__u64)base;
615         cutlim = (int)((__u64)ULONG_LONG_MAX % (__u64)base);
616         for (acc = 0, any = 0;; c = *s++) {
617                 if (cfs_isdigit(c))
618                         c -= '0';
619                 else if (cfs_isalpha(c))
620                         c -= cfs_isupper(c) ? 'A' - 10 : 'a' - 10;
621                 else
622                         break;
623                 if (c >= base)
624                         break;
625                if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
626                         any = -1;
627                 else {
628                         any = 1;
629                         acc *= base;
630                         acc += c;
631                 }
632         }
633         if (any < 0) {
634                 acc = ULONG_LONG_MAX;
635         } else if (neg)
636                 acc = 0 - acc;
637         if (endptr != 0)
638                 *endptr = (char *) (any ? s - 1 : nptr);
639         return (acc);
640 }
641
642 #if __KERNEL__
643
644 #define BASE 65521L /* largest prime smaller than 65536 */
645 #define NMAX 5552
646 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
647
648 #define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
649 #define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
650 #define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
651 #define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
652 #define DO16(buf)   DO8(buf,0); DO8(buf,8);
653
654 /* ========================================================================= */
655 /* 
656     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
657   return the updated checksum. If buf is NULL, this function returns
658   the required initial value for the checksum.
659   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
660   much faster. Usage example:
661
662     uLong adler = adler32(0L, NULL, 0);
663
664     while (read_buffer(buffer, length) != EOF) {
665       adler = adler32(adler, buffer, length);
666     }
667     if (adler != original_adler) error();
668 */
669
670 ULONG zlib_adler32(ULONG adler,
671                    const BYTE *buf,
672                    UINT len)
673 {
674     unsigned long s1 = adler & 0xffff;
675     unsigned long s2 = (adler >> 16) & 0xffff;
676     int k;
677
678     if (buf == NULL) return 1L;
679
680     while (len > 0) {
681         k = len < NMAX ? len : NMAX;
682         len -= k;
683         while (k >= 16) {
684             DO16(buf);
685             buf += 16;
686             k -= 16;
687         }
688         if (k != 0) do {
689             s1 += *buf++;
690             s2 += s1;
691         } while (--k);
692         s1 %= BASE;
693         s2 %= BASE;
694     }
695     return (s2 << 16) | s1;
696 }
697
698 #if  !defined(NTDDI_VERSION) || NTDDI_VERSION < 0x06000000
699 _CRTIMP size_t  __cdecl strnlen(const char * _Str, size_t _MaxCount)
700 {
701         size_t len = 0;
702         while(len < _MaxCount && _Str[len++]);
703         return len;
704 }
705 #endif
706
707 int (__cdecl *_cfs_isalpha)(int);
708 int (__cdecl *_cfs_isspace)(int);
709 int (__cdecl *_cfs_isupper)(int);
710 int (__cdecl *_cfs_isdigit)(int);
711 int (__cdecl *_cfs_isxdigit)(int);
712
713 int cfs_isalpha(int c)
714 {
715     if (_cfs_isalpha) {
716         return _cfs_isalpha(c);
717     } else {
718         return ((c >= 'a' && c <= 'z') ||
719                 (c >= 'A' && c <= 'Z'));
720     }
721 }
722
723 int cfs_isspace(int c)
724 {
725     if (_cfs_isspace) {
726         return _cfs_isspace(c);
727     } else {
728         return ((c >= 0x09 && c <= 0x0d) ||
729                 (c == 0x20));
730     }
731 }
732
733 int cfs_isupper(int c)
734 {
735     if (_cfs_isupper) {
736         return _cfs_isupper(c);
737     } else {
738         return (c >= 'A' && c <= 'Z');
739     }
740 }
741
742 int cfs_isdigit(int c)
743 {
744     if (_cfs_isdigit) {
745         return _cfs_isdigit(c);
746     } else {
747         return (c >= '0' && c <= '9');
748     }
749 }
750
751 int cfs_isxdigit(int c)
752 {
753     if (_cfs_isxdigit) {
754         return _cfs_isxdigit(c);
755     } else {
756         return ((c >= '0' && c <= '9') ||
757                 (c >= 'A' && c <= 'F') ||
758                 (c >= 'a' && c <= 'F'));
759     }
760 }
761
762 void cfs_libc_init()
763 {
764     UNICODE_STRING  fn;
765     int             i;
766
767     struct {WCHAR * name; PVOID * addr;} funcs[] = {
768             { L"isspace", (PVOID *)&_cfs_isspace},
769             { L"isalpha", (PVOID *)&_cfs_isalpha},
770             { L"isupper", (PVOID *)&_cfs_isupper},
771             { L"isdigit", (PVOID *)&_cfs_isdigit},
772             { L"isxdigit",(PVOID *)&_cfs_isxdigit},
773             { NULL, NULL },
774             };
775
776     for (i=0; funcs[i].name != NULL; i++) {
777         RtlInitUnicodeString(&fn, funcs[i].name);
778         *(funcs[i].addr) = MmGetSystemRoutineAddress(&fn);
779     }
780
781 #if DBG
782     ASSERT(cfs_isspace(0x20) && cfs_isspace(0x09) &&
783            cfs_isspace(0x0a) && cfs_isspace(0x0d) &&
784            !cfs_isspace('a') && !cfs_isspace('0'));
785     ASSERT(cfs_isalpha('a')  && cfs_isalpha('Z') && 
786            !cfs_isalpha('0') && !cfs_isalpha('='));
787     ASSERT(cfs_isupper('A')  && cfs_isupper('Z') && 
788            !cfs_isupper('a') && !cfs_isupper('='));
789     ASSERT(cfs_isdigit('0')   && cfs_isdigit('9') && 
790            !cfs_isdigit('a')  && !cfs_isdigit('#'));
791     ASSERT(cfs_isxdigit('0')  && cfs_isxdigit('9') && 
792            cfs_isxdigit('a')  && cfs_isxdigit('A') &&
793            cfs_isxdigit('F')  && cfs_isxdigit('f') &&
794            !cfs_isxdigit('G') && !cfs_isxdigit('z'));
795 #endif    
796 }
797
798 #else
799
800 unsigned int libcfs_subsystem_debug = ~0;
801
802 int cfs_isalpha(int c)
803 {
804     return isalpha(c);
805 }
806
807 int cfs_isspace(int c)
808 {
809     return isspace(c);
810 }
811
812 int cfs_isupper(int c)
813 {
814     return isupper(c);
815 }
816
817 int cfs_isdigit(int c)
818 {
819     return isdigit(c);
820 }
821
822 int cfs_isxdigit(int c)
823 {
824     return isxdigit(c);
825 }
826
827 void cfs_libc_init()
828 {
829 }
830
831
832 #endif