core: ut.h: added sint2strbuf()
[sip-router] / ut.h
1 /*
2  *$Id$
3  *
4  * - various general purpose functions
5  *
6  * Copyright (C) 2001-2003 FhG Fokus
7  *
8  * This file is part of ser, a free SIP server.
9  *
10  * ser is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * For a license to use the ser software under conditions
16  * other than those described here, or to purchase support for this
17  * software, please contact iptel.org by e-mail at the following addresses:
18  *    info@iptel.org
19  *
20  * ser is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License 
26  * along with this program; if not, write to the Free Software 
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  *
29  * History
30  * ------
31  * 2003-01-18 un_escape function introduced for convenience of code needing
32  *            the complex&slow feature of unescaping
33  * 2003-01-28 scratchpad removed (jiri)
34  * 2003-01-29 pathmax added (jiri)
35  * 2003-02-13 strlower added (janakj)
36  * 2003-02-28 scratchpad compatibility abandoned (jiri)
37  * 2003-03-30 str2int and str2float added (janakj)
38  * 2003-04-26 ZSW (jiri)
39  * 2004-03-08 updated int2str (64 bits, INT2STR_MAX_LEN used) (andrei)
40  * 2005-11-29 reverse_hex2int/int2reverse_hex switched to unsigned int (andrei)
41  * 2005-12-09 added msgid_var (andrei)
42  * 2007-05-14 added get_sys_ver() (andrei)
43  * 2007-06-05 added MAX_UVAR_VALUE(), MAX_int(a,b) MIN_int(a,b) (andrei)
44  * 2008-05-21 added ushort2sbuf(), ushort2str() (andrei)
45  * 2009-03-16 added sint2strbuf() and incremented INST2STR_MAX_LEN to account
46  *             for sign (andrei)
47  */
48 /** various helper functions.
49  * @file
50  */
51
52
53 #ifndef ut_h
54 #define ut_h
55
56 #include "comp_defs.h"
57
58 #include <sys/types.h>
59 #include <sys/select.h>
60 #include <sys/time.h>
61 #include <limits.h>
62 #include <time.h>
63 #include <unistd.h>
64 #include <ctype.h>
65 #include <string.h>
66 #include <strings.h>
67
68 #include "compiler_opt.h"
69 #include "config.h"
70 #include "dprint.h"
71 #include "str.h"
72 #include "mem/mem.h"
73 #include "mem/shm_mem.h"
74
75
76
77 /* zero-string wrapper */
78 #define ZSW(_c) ((_c)?(_c):"")
79
80 /* returns string beginning and length without insignificant chars */
81 #define trim_len( _len, _begin, _mystr ) \
82         do{     static char _c; \
83                 (_len)=(_mystr).len; \
84                 while ((_len) && ((_c=(_mystr).s[(_len)-1])==0 || _c=='\r' || \
85                                         _c=='\n' || _c==' ' || _c=='\t' )) \
86                         (_len)--; \
87                 (_begin)=(_mystr).s; \
88                 while ((_len) && ((_c=*(_begin))==' ' || _c=='\t')) { \
89                         (_len)--;\
90                         (_begin)++; \
91                 } \
92         }while(0)
93
94 #define trim_r( _mystr ) \
95         do{     static char _c; \
96                 while( ((_mystr).len) && ( ((_c=(_mystr).s[(_mystr).len-1]))==0 ||\
97                                                                         _c=='\r' || _c=='\n' ) \
98                                 ) \
99                         (_mystr).len--; \
100         }while(0)
101
102
103 #define  translate_pointer( _new_buf , _org_buf , _p) \
104         ( (_p)?(_new_buf + (_p-_org_buf)):(0) )
105
106 #define via_len(_via) \
107         ((_via)->bsize-((_via)->name.s-\
108                 ((_via)->hdr.s+(_via)->hdr.len)))
109
110
111
112 /* rounds to sizeof(type), but type must have a 2^k size (e.g. short, int,
113  * long, void*) */
114 #define ROUND2TYPE(s, type) \
115         (((s)+(sizeof(type)-1))&(~(sizeof(type)-1)))
116
117
118 /* rounds to sizeof(char*) - the first 4 byte multiple on 32 bit archs
119  * and the first 8 byte multiple on 64 bit archs */
120 #define ROUND_POINTER(s) ROUND2TYPE(s, char*)
121
122 /* rounds to sizeof(long) - the first 4 byte multiple on 32 bit archs
123  * and the first 8 byte multiple on 64 bit archs  (equiv. to ROUND_POINTER)*/
124 #define ROUND_LONG(s)  ROUND2TYPE(s, long)
125
126 /* rounds to sizeof(int) - the first t byte multiple on 32 and 64  bit archs */
127 #define ROUND_INT(s) ROUND2TYPE(s, int)
128
129 /* rounds to sizeof(short) - the first 2 byte multiple */
130 #define ROUND_SHORT(s) ROUND2TYPE(s, short)
131
132
133 /* params: v - either a variable name, structure member or a type
134  * returns an unsigned long containing the maximum possible value that will
135  * fit in v, if v is unsigned or converted to an unsigned version
136  * example: MAX_UVAR_VALUE(unsigned short); MAX_UVAR_VALUE(i);
137  *  MAX_UVAR_VALUE(((struct foo*)0)->bar) */
138 #define MAX_UVAR_VALUE(v) \
139         (((unsigned long)(-1))>>((sizeof(unsigned long)-sizeof(v))*8UL))
140
141
142 #define MIN_int(a, b) (((a)<(b))?(a):(b))
143 #define MAX_int(a, b) (((a)>(b))?(a):(b))
144
145 #define MIN_unsigned(a, b) (unsigned)(((unsigned)(a)<(unsigned)(b))?(a):(b))
146 #define MAX_unsigned(a, b) (unsigned)(((unsigned)(a)>(unsigned)(b))?(a):(b))
147
148 #if 0
149 #define MIN_int(a, b) ((b)+(((a)-(b))& -((a)<(b))))
150 #define MAX_int(a, b) ((a)-(((a)-(b))& -((b)>(a))))
151
152 /* depend on signed right shift result which depends on the compiler */
153 #define MIN_int(a, b) ((b)+(((a)-(b))&(((a)-(b))>>(sizeof(int)*8-1))))
154 #define MAX_int(a, b) ((a)-(((a)-(b))&(((a)-(b))>>(sizeof(int)*8-1))))
155 #endif
156
157
158 #define append_str(_dest,_src,_len)                             \
159         do{                                                                                     \
160                 memcpy( (_dest) , (_src) , (_len) );    \
161                 (_dest) += (_len) ;                                             \
162         }while(0);                                                                      \
163
164         
165 /*! append _c char to _dest string */
166 #define append_chr(_dest,_c) \
167         *((_dest)++) = _c;
168
169
170 /* links a value to a msgid */
171 struct msgid_var{
172         union{
173                 char char_val;
174                 int int_val;
175                 long long_val;
176         }u;
177         unsigned int msgid;
178 };
179
180 /* return the value or 0 if the msg_id doesn't match */
181 #define get_msgid_val(var, id, type)\
182         ((type)((type)((var).msgid!=(id))-1)&((var).u.type##_val))
183
184 #define set_msgid_val(var, id, type, value)\
185         do{\
186                 (var).msgid=(id); \
187                 (var).u.type##_val=(value); \
188         }while(0)
189
190 /* char to hex conversion table */
191 static char fourbits2char[16] = { '0', '1', '2', '3', '4', '5',
192         '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
193
194
195 /* converts a str to an u. short, returns the u. short and sets *err on
196  * error and if err!=null
197   */
198 static inline unsigned short str2s(const char* s, unsigned int len,
199                                                                         int *err)
200 {
201         unsigned short ret;
202         int i;
203         unsigned char *limit;
204         unsigned char *init;
205         unsigned char* str;
206
207         /*init*/
208         str=(unsigned char*)s;
209         ret=i=0;
210         limit=str+len;
211         init=str;
212
213         for(;str<limit ;str++){
214                 if ( (*str <= '9' ) && (*str >= '0') ){
215                                 ret=ret*10+*str-'0';
216                                 i++;
217                                 if (i>5) goto error_digits;
218                 }else{
219                                 /* error unknown char */
220                                 goto error_char;
221                 }
222         }
223         if (err) *err=0;
224         return ret;
225
226 error_digits:
227         /*DBG("str2s: ERROR: too many letters in [%.*s]\n", (int)len, init); */
228         if (err) *err=1;
229         return 0;
230 error_char:
231         /*DBG("str2s: ERROR: unexpected char %c in %.*s\n", *str, (int)len, init);
232          * */
233         if (err) *err=1;
234         return 0;
235 }
236
237
238
239 static inline int btostr( char *p,  unsigned char val)
240 {
241         unsigned int a,b,i =0;
242
243         if ( (a=val/100)!=0 )
244                 *(p+(i++)) = a+'0';         /*first digit*/
245         if ( (b=val%100/10)!=0 || a)
246                 *(p+(i++)) = b+'0';        /*second digit*/
247         *(p+(i++)) = '0'+val%10;              /*third digit*/
248
249         return i;
250 }
251
252
253 #define INT2STR_MAX_LEN  (19+1+1+1) /* 2^64~= 16*10^18 =>
254                                                                            19+1 digits + sign + \0 */
255
256 /* 
257  * returns a pointer to a static buffer containing l in asciiz (with base "base") & sets len 
258  * left padded with 0 to "size"
259  */
260 static inline char* int2str_base_0pad(unsigned int l, int* len, int base, 
261                                                                                         int size)
262 {
263         static char r[INT2STR_MAX_LEN];
264         int i, j;
265
266         if (base < 2) {
267                 BUG("base underflow\n");
268                 return NULL;
269         }
270         if (base > 36) {
271                 BUG("base overflow\n");
272                 return NULL;
273         }
274         i=INT2STR_MAX_LEN-2;
275         j=i-size;
276         r[INT2STR_MAX_LEN-1]=0; /* null terminate */
277         do{
278                 r[i]=l%base;
279                 if (r[i]<10)
280                         r[i]+='0';
281                 else
282                         r[i]+='a'-10;
283                 i--;
284                 l/=base;
285         }while((l || i>j) && (i>=0));
286         if (l && (i<0)){
287                 BUG("result buffer overflow\n");
288         }
289         if (len) *len=(INT2STR_MAX_LEN-2)-i;
290         return &r[i+1];
291 }
292
293 /* returns a pointer to a static buffer containing l in asciiz (with base "base") & sets len */
294 static inline char* int2str_base(unsigned int l, int* len, int base)
295 {
296         return int2str_base_0pad(l, len, base, 0);
297 }
298
299
300
301 /** unsigned long to str conversion using a provided buffer.
302  * Converts/prints an unsigned long to a string. The result buffer must be
303  * provided  and its length must be at least INT2STR_MAX_LEN.
304  * @param l - unsigned long to be converted
305  * @param r - pointer to result buffer
306  * @param r_size - result buffer size, must be at least INT2STR_MAX_LEN.
307  * @param *len - length of the written string, _without_ the terminating 0.
308  * @return  pointer _inside_ r, to the converted string (note: the string
309  *  is written from the end of the buffer and not from the start and hence
310  *  the returned pointer will most likely not be equal to r). In case of error
311  *  it returns 0 (the only error being insufficient provided buffer size).
312  */
313 static inline char* int2strbuf(unsigned long l, char *r, int r_size, int* len)
314 {
315         int i;
316
317         if(unlikely(r_size<INT2STR_MAX_LEN)) {
318                 if (len)
319                         *len = 0;
320                 return 0; /* => if someone misuses it => crash (feature no. 1) */
321         }
322         i=INT2STR_MAX_LEN-2;
323         r[INT2STR_MAX_LEN-1]=0; /* null terminate */
324         do{
325                 r[i]=l%10+'0';
326                 i--;
327                 l/=10;
328         }while(l && (i>=0));
329         if (l && (i<0)){
330                 LOG(L_CRIT, "BUG: int2str: overflow\n");
331         }
332         if (len) *len=(INT2STR_MAX_LEN-2)-i;
333         return &r[i+1];
334 }
335
336 extern char ut_buf_int2str[INT2STR_MAX_LEN];
337 /** interger(long) to string conversion.
338  * This version uses a static buffer (shared with sint2str()).
339  * WARNING: other function calls might overwrite the static buffer, so
340  * either always save the result immediately or use int2strbuf(...).
341  * @param l - unsigned long to be converted/printed.
342  * @param *len - will be filled with the final length (without the terminating
343  *   0).
344  * @return a pointer to a static buffer containing l in asciiz & sets len.
345  */
346 static inline char* int2str(unsigned long l, int* len)
347 {
348         return int2strbuf(l, ut_buf_int2str, INT2STR_MAX_LEN, len);
349 }
350
351
352
353 /** signed long to str conversion using a provided buffer.
354  * Converts a long to a signed string. The result buffer must be provided
355  * and its length must be at least INT2STR_MAX_LEN.
356  * @param l - long to be converted
357  * @param r - pointer to result buffer
358  * @param r_size - result buffer size, must be at least INT2STR_MAX_LEN.
359  * @param *len - length of the written string, _without_ the terminating 0.
360  * @return  pointer _inside_ r, to the converted string (note: the string
361  *  is written from the end of the buffer and not from the start and hence
362  *  the returned pointer will most likely not be equal to r). In case of error
363  *  it returns 0 (the only error being insufficient provided buffer size).
364  */
365 static inline char* sint2strbuf(long l, char* r, int r_size, int* len)
366 {
367         int sign;
368         char *p;
369         int p_len;
370
371         sign = 0;
372         if(l<0) {
373                 sign = 1;
374                 l = -l;
375         }
376         p = int2strbuf((unsigned long)l, r, r_size, &p_len);
377         if(sign && *len<(r_size-1)) {
378                 *(--p) = '-';
379                 p_len++;;
380         }
381         if (likely(len))
382                 *len = p_len;
383         return p;
384 }
385
386
387 /** Signed INTeger-TO-STRing: converts a long to a string.
388  * This version uses a static buffer, shared with int2str().
389  * WARNING: other function calls might overwrite the static buffer, so
390  * either always save the result immediately or use sint2strbuf(...).
391  * @param l - long to be converted/printed.
392  * @param *len - will be filled with the final length (without the terminating
393  *   0).
394  * @return a pointer to a static buffer containing l in asciiz & sets len.
395  */
396 static inline char* sint2str(long l, int* len)
397 {
398         return sint2strbuf(l, ut_buf_int2str, INT2STR_MAX_LEN, len);
399 }
400
401
402
403 #define USHORT2SBUF_MAX_LEN  5 /* 65535*/
404 /* converts an unsigned short (16 bits) to asciiz
405  * returns bytes written or 0 on error
406  * the passed len must be at least USHORT2SBUF_MAX chars or error
407  * would be returned.
408  * (optimized for port conversion (4 or 5 digits most of the time)*/
409 static inline int ushort2sbuf(unsigned short u, char* buf, int len)
410 {
411         int offs;
412         unsigned char a, b, c, d;
413         
414         if (unlikely(len<USHORT2SBUF_MAX_LEN))
415                 return 0;
416         offs=0;
417         a=u/10000; u%=10000;
418         buf[offs]=a+'0'; offs+=(a!=0);
419         b=u/1000;  u%=1000;
420         buf[offs]=b+'0'; offs+=((offs|b)!=0);
421         c=u/100;   u%=100;
422         buf[offs]=c+'0'; offs+=((offs|c)!=0);
423         d=u/10;    u%=10;
424         buf[offs]=d+'0'; offs+=((offs|d)!=0);
425         buf[offs]=(unsigned char)u+'0';
426         return offs+1;
427 }
428
429
430
431 #define USHORT2STR_MAX_LEN  (USHORT2SBUF_MAX_LEN+1) /* 65535\0*/
432 /* converts an unsigned short (16 bits) to asciiz
433  * (optimized for port conversiob (4 or 5 digits most of the time)*/
434 static inline char* ushort2str(unsigned short u)
435 {
436         static char buf[USHORT2STR_MAX_LEN];
437         int len;
438
439         len=ushort2sbuf(u, buf, sizeof(buf)-1);
440         buf[len]=0;
441         return buf;
442 }
443
444
445
446 /* faster memchr version */
447 static inline char* q_memchr(char* p, int c, unsigned int size)
448 {
449         char* end;
450
451         end=p+size;
452         for(;p<end;p++){
453                 if (*p==(unsigned char)c) return p;
454         }
455         return 0;
456 }
457         
458
459 /* returns -1 on error, 1! on success (consistent with int2reverse_hex) */
460 inline static int reverse_hex2int( char *c, int len, unsigned int* res)
461 {
462         char *pc;
463         char mychar;
464
465         *res=0;
466         for (pc=c+len-1; len>0; pc--, len--) {
467                 *res <<= 4 ;
468                 mychar=*pc;
469                 if ( mychar >='0' && mychar <='9') *res+=mychar -'0';
470                 else if (mychar >='a' && mychar <='f') *res+=mychar -'a'+10;
471                 else if (mychar  >='A' && mychar <='F') *res+=mychar -'A'+10;
472                 else return -1;
473         }
474         return 1;
475 }
476
477 inline static int int2reverse_hex( char **c, int *size, unsigned int nr )
478 {
479         unsigned short digit;
480
481         if (*size && nr==0) {
482                 **c = '0';
483                 (*c)++;
484                 (*size)--;
485                 return 1;
486         }
487
488         while (*size && nr ) {
489                 digit = nr & 0xf ;
490                 **c= digit >= 10 ? digit + 'a' - 10 : digit + '0';
491                 nr >>= 4;
492                 (*c)++;
493                 (*size)--;
494         }
495         return nr ? -1 /* number not processed; too little space */ : 1;
496 }
497
498 /* double output length assumed ; does NOT zero-terminate */
499 inline static int string2hex( 
500         /* input */ unsigned char *str, int len,
501         /* output */ char *hex )
502 {
503         int orig_len;
504
505         if (len==0) {
506                 *hex='0';
507                 return 1;
508         }
509
510         orig_len=len;
511         while ( len ) {
512
513                 *hex=fourbits2char[(*str) >> 4];
514                 hex++;
515                 *hex=fourbits2char[(*str) & 0xf];
516                 hex++;
517                 len--;
518                 str++;
519
520         }
521         return orig_len-len;
522 }
523
524 /* portable sleep in microseconds (no interrupt handling now) */
525
526 inline static void sleep_us( unsigned int nusecs )
527 {
528         struct timeval tval;
529         tval.tv_sec =nusecs/1000000;
530         tval.tv_usec=nusecs%1000000;
531         select(0, NULL, NULL, NULL, &tval );
532 }
533
534
535 /* portable determination of max_path */
536 inline static int pathmax()
537 {
538 #ifdef PATH_MAX
539         static int pathmax=PATH_MAX;
540 #else
541         static int pathmax=0;
542 #endif
543         if (pathmax==0) { /* init */
544                 pathmax=pathconf("/", _PC_PATH_MAX);
545                 pathmax=(pathmax<=0)?PATH_MAX_GUESS:pathmax+1;
546         }
547         return pathmax;
548 }
549
550 inline static int hex2int(char hex_digit)
551 {
552         if (hex_digit>='0' && hex_digit<='9')
553                 return hex_digit-'0';
554         if (hex_digit>='a' && hex_digit<='f')
555                 return hex_digit-'a'+10;
556         if (hex_digit>='A' && hex_digit<='F')
557                 return hex_digit-'A'+10;
558         /* no valid hex digit ... */
559         LOG(L_ERR, "ERROR: hex2int: '%c' is no hex char\n", hex_digit );
560         return -1;
561 }
562
563 /* Un-escape URI user  -- it takes a pointer to original user
564    str, as well as the new, unescaped one, which MUST have
565    an allocated buffer linked to the 'str' structure ;
566    (the buffer can be allocated with the same length as
567    the original string -- the output string is always
568    shorter (if escaped characters occur) or same-long
569    as the original one).
570
571    only printable characters are permitted
572
573         <0 is returned on an unescaping error, length of the
574         unescaped string otherwise
575 */
576 inline static int un_escape(str *user, str *new_user ) 
577 {
578         int i, j, value;
579         int hi, lo;
580
581         if( new_user==0 || new_user->s==0) {
582                 LOG(L_CRIT, "BUG: un_escape: called with invalid param\n");
583                 return -1;
584         }
585
586         new_user->len = 0;
587         j = 0;
588
589         for (i = 0; i < user->len; i++) {
590                 if (user->s[i] == '%') {
591                         if (i + 2 >= user->len) {
592                                 LOG(L_ERR, "ERROR: un_escape: escape sequence too short in"
593                                         " '%.*s' @ %d\n",
594                                         user->len, user->s, i );
595                                 goto error;
596                         }
597                         hi=hex2int(user->s[i + 1]);
598                         if (hi<0) {
599                                 LOG(L_ERR, "ERROR: un_escape: non-hex high digit in an escape sequence in"
600                                         " '%.*s' @ %d\n",
601                                         user->len, user->s, i+1 );
602                                 goto error;
603                         }
604                         lo=hex2int(user->s[i + 2]);
605                         if (lo<0) {
606                                 LOG(L_ERR, "ERROR: non-hex low digit in an escape sequence in "
607                                         "'%.*s' @ %d\n",
608                                         user->len, user->s, i+2 );
609                                 goto error;
610                         }
611                         value=(hi<<4)+lo;
612                         if (value < 32 || value > 126) {
613                                 LOG(L_ERR, "ERROR: non-ASCII escaped character in '%.*s' @ %d\n",
614                                         user->len, user->s, i );
615                                 goto error;
616                         }
617                         new_user->s[j] = value;
618                         i+=2; /* consume the two hex digits, for cycle will move to the next char */
619                 } else {
620                         new_user->s[j] = user->s[i];
621                 }
622         j++; /* good -- we translated another character */
623         }
624         new_user->len = j;
625         return j;
626
627 error:
628         new_user->len = j;
629         return -1;
630
631
632
633 /*
634  * Convert a string to lower case
635  */
636 static inline void strlower(str* _s)
637 {
638         int i;
639
640         for(i = 0; i < _s->len; i++) {
641                 _s->s[i] = tolower(_s->s[i]);
642         }
643 }
644
645
646 /*
647  * Convert a str into integer
648  */
649 static inline int str2int(str* _s, unsigned int* _r)
650 {
651         int i;
652         
653         *_r = 0;
654         for(i = 0; i < _s->len; i++) {
655                 if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) {
656                         *_r *= 10;
657                         *_r += _s->s[i] - '0';
658                 } else {
659                         return -1;
660                 }
661         }
662         
663         return 0;
664 }
665
666 /*
667  * Convert an str to signed integer
668  */
669 static inline int str2sint(str* _s, int* _r)
670 {
671         int i;
672         int sign;
673
674         if (_s->len == 0) return -1;
675
676         *_r = 0;
677         sign = 1;
678         i = 0;
679         if (_s->s[0] == '+') {
680                 i++;
681         } else if (_s->s[0] == '-') {
682                 sign = -1;
683                 i++;
684         }
685         for(; i < _s->len; i++) {
686                 if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) {
687                         *_r *= 10;
688                         *_r += _s->s[i] - '0';
689                 } else {
690                         return -1;
691                 }
692         }
693         *_r *= sign;
694
695         return 0;
696 }
697
698
699
700 #ifdef SHM_MEM
701 /**
702  * \brief Make a copy of a str structure using shm_malloc
703  * \param dst destination
704  * \param src source
705  * \return 0 on success, -1 on failure
706  */
707 static inline int shm_str_dup(str* dst, const str* src)
708 {
709         dst->s = shm_malloc(src->len);
710         if (!dst->s) {
711                 SHM_MEM_ERROR;
712                 return -1;
713         }
714
715         memcpy(dst->s, src->s, src->len);
716         dst->len = src->len;
717         return 0;
718 }
719 #endif /* SHM_MEM */
720
721
722
723 /**
724  * \brief Make a copy of a str structure using pkg_malloc
725  * \param dst destination
726  * \param src source
727  * \return 0 on success, -1 on failure
728  */
729 static inline int pkg_str_dup(str* dst, const str* src)
730 {
731         dst->s = pkg_malloc(src->len);
732         if (dst->s==NULL)
733         {
734                 PKG_MEM_ERROR;
735                 return -1;
736         }
737
738         memcpy(dst->s, src->s, src->len);
739         dst->len = src->len;
740         return 0;
741 }
742
743 /**
744  * \brief Compare two str's case sensitive
745  * \param str1 first str
746  * \param str2 second str
747  * \return 0 if both are equal, positive if str1 is greater, negative if str2 is greater, -2 on errors
748  */
749 static inline int str_strcmp(const str *str1, const str *str2)
750 {
751         if(str1==NULL || str2==NULL || str1->s ==NULL || str2->s==NULL || str1->len<0 || str2->len<0)
752         {
753                 LM_ERR("bad parameters\n");
754                 return -2;
755         }
756
757         if (str1->len < str2->len)
758                 return -1;
759         else if (str1->len > str2->len)
760                 return 1;
761         else
762                 return strncmp(str1->s, str2->s, str1->len);
763 }
764
765 /**
766  * \brief Compare two str's case insensitive
767  * \param str1 first str
768  * \param str2 second str
769  * \return 0 if both are equal, positive if str1 is greater, negative if str2 is greater, -2 on errors
770  */
771 static inline int str_strcasecmp(const str *str1, const str *str2)
772 {
773         if(str1==NULL || str2==NULL || str1->s ==NULL || str2->s==NULL || str1->len<0 || str2->len<0)
774         {
775                 LM_ERR("bad parameters\n");
776                 return -2;
777         }
778         if (str1->len < str2->len)
779                 return -1;
780         else if (str1->len > str2->len)
781                 return 1;
782         else
783                 return strncasecmp(str1->s, str2->s, str1->len);
784 }
785
786 /* converts a username into uid:gid,
787  * returns -1 on error & 0 on success */
788 int user2uid(int* uid, int* gid, char* user);
789
790 /* converts a group name into a gid
791  * returns -1 on error, 0 on success */
792 int group2gid(int* gid, char* group);
793
794 /*
795  * Replacement of timegm (does not exists on all platforms
796  * Taken from 
797  * http://lists.samba.org/archive/samba-technical/2002-November/025737.html
798  */
799 time_t _timegm(struct tm* t);
800
801 /* Convert time_t value that is relative to local timezone to UTC */
802 time_t local2utc(time_t in);
803
804 /* Convert time_t value in UTC to to value relative to local time zone */
805 time_t utc2local(time_t in);
806
807 /*
808  * Return str as zero terminated string allocated
809  * using pkg_malloc
810  */
811 char* as_asciiz(str* s);
812
813
814 /* return system version (major.minor.minor2) as
815  *  (major<<16)|(minor)<<8|(minor2)
816  * (if some of them are missing, they are set to 0)
817  * if the parameters are not null they are set to the coresp. part */
818 unsigned int get_sys_version(int* major, int* minor, int* minor2);
819
820 /** Converts relative pathnames to absolute pathnames. This function returns
821  * the full pathname of a file in parameter. If the file pathname does not
822  * start with / then it will be converted into an absolute pathname. The
823  * function gets the absolute directory pathname from \c base and appends \c
824  * file to it. The first parameter can be NULL, in this case the function will
825  * use the location of the main SER configuration file as reference.
826  * @param base filename to be used as reference when \c file is relative. It
827  *             must be absolute. The location of the SER configuration file
828  *             will be used as reference if you set the value of this
829  *             parameter to NULL.
830  * @param file A pathname to be converted to absolute.
831  * @return A string containing absolute pathname, the string must be freed
832  * with free. NULL on error.
833  */
834 char* get_abs_pathname(str* base, str* file);
835
836 #endif