~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to lib/util/util.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
   Samba utility functions
 
4
   Copyright (C) Andrew Tridgell 1992-1998
 
5
   Copyright (C) Jeremy Allison 2001-2002
 
6
   Copyright (C) Simo Sorce 2001
 
7
   Copyright (C) Jim McDonough (jmcd@us.ibm.com)  2003.
 
8
   Copyright (C) James J Myers 2003
 
9
   
 
10
   This program 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 3 of the License, or
 
13
   (at your option) any later version.
 
14
   
 
15
   This program is distributed in the hope that it will be useful,
 
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
   GNU General Public License for more details.
 
19
   
 
20
   You should have received a copy of the GNU General Public License
 
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
22
*/
 
23
 
 
24
#include "includes.h"
 
25
#include "system/network.h"
 
26
#include "system/filesys.h"
 
27
#include "system/locale.h"
 
28
#undef malloc
 
29
#undef strcasecmp
 
30
#undef strncasecmp
 
31
#undef strdup
 
32
#undef realloc
 
33
 
 
34
/**
 
35
 * @file
 
36
 * @brief Misc utility functions
 
37
 */
 
38
 
 
39
/**
 
40
 Find a suitable temporary directory. The result should be copied immediately
 
41
 as it may be overwritten by a subsequent call.
 
42
**/
 
43
_PUBLIC_ const char *tmpdir(void)
 
44
{
 
45
        char *p;
 
46
        if ((p = getenv("TMPDIR")))
 
47
                return p;
 
48
        return "/tmp";
 
49
}
 
50
 
 
51
 
 
52
/**
 
53
 Check if a file exists - call vfs_file_exist for samba files.
 
54
**/
 
55
_PUBLIC_ bool file_exist(const char *fname)
 
56
{
 
57
        struct stat st;
 
58
 
 
59
        if (stat(fname, &st) != 0) {
 
60
                return false;
 
61
        }
 
62
 
 
63
        return ((S_ISREG(st.st_mode)) || (S_ISFIFO(st.st_mode)));
 
64
}
 
65
 
 
66
/**
 
67
 Check a files mod time.
 
68
**/
 
69
 
 
70
_PUBLIC_ time_t file_modtime(const char *fname)
 
71
{
 
72
        struct stat st;
 
73
  
 
74
        if (stat(fname,&st) != 0) 
 
75
                return(0);
 
76
 
 
77
        return(st.st_mtime);
 
78
}
 
79
 
 
80
/**
 
81
 Check if a directory exists.
 
82
**/
 
83
 
 
84
_PUBLIC_ bool directory_exist(const char *dname)
 
85
{
 
86
        struct stat st;
 
87
        bool ret;
 
88
 
 
89
        if (stat(dname,&st) != 0) {
 
90
                return false;
 
91
        }
 
92
 
 
93
        ret = S_ISDIR(st.st_mode);
 
94
        if(!ret)
 
95
                errno = ENOTDIR;
 
96
        return ret;
 
97
}
 
98
 
 
99
/**
 
100
 * Try to create the specified directory if it didn't exist.
 
101
 *
 
102
 * @retval true if the directory already existed and has the right permissions 
 
103
 * or was successfully created.
 
104
 */
 
105
_PUBLIC_ bool directory_create_or_exist(const char *dname, uid_t uid, 
 
106
                               mode_t dir_perms)
 
107
{
 
108
        mode_t old_umask;
 
109
        struct stat st;
 
110
      
 
111
        old_umask = umask(0);
 
112
        if (lstat(dname, &st) == -1) {
 
113
                if (errno == ENOENT) {
 
114
                        /* Create directory */
 
115
                        if (mkdir(dname, dir_perms) == -1) {
 
116
                                DEBUG(0, ("error creating directory "
 
117
                                          "%s: %s\n", dname, 
 
118
                                          strerror(errno)));
 
119
                                umask(old_umask);
 
120
                                return false;
 
121
                        }
 
122
                } else {
 
123
                        DEBUG(0, ("lstat failed on directory %s: %s\n",
 
124
                                  dname, strerror(errno)));
 
125
                        umask(old_umask);
 
126
                        return false;
 
127
                }
 
128
        } else {
 
129
                /* Check ownership and permission on existing directory */
 
130
                if (!S_ISDIR(st.st_mode)) {
 
131
                        DEBUG(0, ("directory %s isn't a directory\n",
 
132
                                dname));
 
133
                        umask(old_umask);
 
134
                        return false;
 
135
                }
 
136
                if ((st.st_uid != uid) || 
 
137
                    ((st.st_mode & 0777) != dir_perms)) {
 
138
                        DEBUG(0, ("invalid permissions on directory "
 
139
                                  "%s\n", dname));
 
140
                        umask(old_umask);
 
141
                        return false;
 
142
                }
 
143
        }
 
144
        return true;
 
145
}       
 
146
 
 
147
 
 
148
/**
 
149
 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
 
150
 else
 
151
  if SYSV use O_NDELAY
 
152
  if BSD use FNDELAY
 
153
**/
 
154
 
 
155
_PUBLIC_ int set_blocking(int fd, bool set)
 
156
{
 
157
        int val;
 
158
#ifdef O_NONBLOCK
 
159
#define FLAG_TO_SET O_NONBLOCK
 
160
#else
 
161
#ifdef SYSV
 
162
#define FLAG_TO_SET O_NDELAY
 
163
#else /* BSD */
 
164
#define FLAG_TO_SET FNDELAY
 
165
#endif
 
166
#endif
 
167
 
 
168
        if((val = fcntl(fd, F_GETFL, 0)) == -1)
 
169
                return -1;
 
170
        if(set) /* Turn blocking on - ie. clear nonblock flag */
 
171
                val &= ~FLAG_TO_SET;
 
172
        else
 
173
                val |= FLAG_TO_SET;
 
174
        return fcntl( fd, F_SETFL, val);
 
175
#undef FLAG_TO_SET
 
176
}
 
177
 
 
178
 
 
179
/**
 
180
 Sleep for a specified number of milliseconds.
 
181
**/
 
182
 
 
183
_PUBLIC_ void msleep(unsigned int t)
 
184
{
 
185
        struct timeval tval;  
 
186
 
 
187
        tval.tv_sec = t/1000;
 
188
        tval.tv_usec = 1000*(t%1000);
 
189
        /* this should be the real select - do NOT replace
 
190
           with sys_select() */
 
191
        select(0,NULL,NULL,NULL,&tval);
 
192
}
 
193
 
 
194
/**
 
195
 Get my own name, return in talloc'ed storage.
 
196
**/
 
197
 
 
198
_PUBLIC_ char *get_myname(TALLOC_CTX *ctx)
 
199
{
 
200
        char *p;
 
201
        char hostname[HOST_NAME_MAX];
 
202
 
 
203
        /* get my host name */
 
204
        if (gethostname(hostname, sizeof(hostname)) == -1) {
 
205
                DEBUG(0,("gethostname failed\n"));
 
206
                return NULL;
 
207
        }
 
208
 
 
209
        /* Ensure null termination. */
 
210
        hostname[sizeof(hostname)-1] = '\0';
 
211
 
 
212
        /* split off any parts after an initial . */
 
213
        p = strchr_m(hostname, '.');
 
214
        if (p) {
 
215
                *p = 0;
 
216
        }
 
217
 
 
218
        return talloc_strdup(ctx, hostname);
 
219
}
 
220
 
 
221
/**
 
222
 Check if a process exists. Does this work on all unixes?
 
223
**/
 
224
 
 
225
_PUBLIC_ bool process_exists_by_pid(pid_t pid)
 
226
{
 
227
        /* Doing kill with a non-positive pid causes messages to be
 
228
         * sent to places we don't want. */
 
229
        SMB_ASSERT(pid > 0);
 
230
        return(kill(pid,0) == 0 || errno != ESRCH);
 
231
}
 
232
 
 
233
/**
 
234
 Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
 
235
 is dealt with in posix.c
 
236
**/
 
237
 
 
238
_PUBLIC_ bool fcntl_lock(int fd, int op, off_t offset, off_t count, int type)
 
239
{
 
240
        struct flock lock;
 
241
        int ret;
 
242
 
 
243
        DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
 
244
 
 
245
        lock.l_type = type;
 
246
        lock.l_whence = SEEK_SET;
 
247
        lock.l_start = offset;
 
248
        lock.l_len = count;
 
249
        lock.l_pid = 0;
 
250
 
 
251
        ret = fcntl(fd,op,&lock);
 
252
 
 
253
        if (ret == -1 && errno != 0)
 
254
                DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
 
255
 
 
256
        /* a lock query */
 
257
        if (op == F_GETLK) {
 
258
                if ((ret != -1) &&
 
259
                                (lock.l_type != F_UNLCK) && 
 
260
                                (lock.l_pid != 0) && 
 
261
                                (lock.l_pid != getpid())) {
 
262
                        DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
 
263
                        return true;
 
264
                }
 
265
 
 
266
                /* it must be not locked or locked by me */
 
267
                return false;
 
268
        }
 
269
 
 
270
        /* a lock set or unset */
 
271
        if (ret == -1) {
 
272
                DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
 
273
                        (double)offset,(double)count,op,type,strerror(errno)));
 
274
                return false;
 
275
        }
 
276
 
 
277
        /* everything went OK */
 
278
        DEBUG(8,("fcntl_lock: Lock call successful\n"));
 
279
 
 
280
        return true;
 
281
}
 
282
 
 
283
void print_asc(int level, const uint8_t *buf,int len)
 
284
{
 
285
        int i;
 
286
        for (i=0;i<len;i++)
 
287
                DEBUGADD(level,("%c", isprint(buf[i])?buf[i]:'.'));
 
288
}
 
289
 
 
290
/**
 
291
 * Write dump of binary data to the log file.
 
292
 *
 
293
 * The data is only written if the log level is at least level.
 
294
 */
 
295
static void _dump_data(int level, const uint8_t *buf, int len,
 
296
                       bool omit_zero_bytes)
 
297
{
 
298
        int i=0;
 
299
        const uint8_t empty[16];
 
300
        bool skipped = false;
 
301
 
 
302
        if (len<=0) return;
 
303
 
 
304
        if (!DEBUGLVL(level)) return;
 
305
 
 
306
        memset(&empty, '\0', 16);
 
307
 
 
308
        for (i=0;i<len;) {
 
309
 
 
310
                if (i%16 == 0) {
 
311
                        if ((omit_zero_bytes == true) &&
 
312
                            (i > 0) &&
 
313
                            (len > i+16) &&
 
314
                            (memcmp(&buf[i], &empty, 16) == 0))
 
315
                        {
 
316
                                i +=16;
 
317
                                continue;
 
318
                        }
 
319
 
 
320
                        if (i<len)  {
 
321
                                DEBUGADD(level,("[%04X] ",i));
 
322
                        }
 
323
                }
 
324
 
 
325
                DEBUGADD(level,("%02X ",(int)buf[i]));
 
326
                i++;
 
327
                if (i%8 == 0) DEBUGADD(level,("  "));
 
328
                if (i%16 == 0) {
 
329
 
 
330
                        print_asc(level,&buf[i-16],8); DEBUGADD(level,(" "));
 
331
                        print_asc(level,&buf[i-8],8); DEBUGADD(level,("\n"));
 
332
 
 
333
                        if ((omit_zero_bytes == true) &&
 
334
                            (len > i+16) &&
 
335
                            (memcmp(&buf[i], &empty, 16) == 0)) {
 
336
                                if (!skipped) {
 
337
                                        DEBUGADD(level,("skipping zero buffer bytes\n"));
 
338
                                        skipped = true;
 
339
                                }
 
340
                        }
 
341
                }
 
342
        }
 
343
 
 
344
        if (i%16) {
 
345
                int n;
 
346
                n = 16 - (i%16);
 
347
                DEBUGADD(level,(" "));
 
348
                if (n>8) DEBUGADD(level,(" "));
 
349
                while (n--) DEBUGADD(level,("   "));
 
350
                n = MIN(8,i%16);
 
351
                print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,( " " ));
 
352
                n = (i%16) - n;
 
353
                if (n>0) print_asc(level,&buf[i-n],n);
 
354
                DEBUGADD(level,("\n"));
 
355
        }
 
356
 
 
357
}
 
358
 
 
359
/**
 
360
 * Write dump of binary data to the log file.
 
361
 *
 
362
 * The data is only written if the log level is at least level.
 
363
 */
 
364
_PUBLIC_ void dump_data(int level, const uint8_t *buf, int len)
 
365
{
 
366
        _dump_data(level, buf, len, false);
 
367
}
 
368
 
 
369
/**
 
370
 * Write dump of binary data to the log file.
 
371
 *
 
372
 * The data is only written if the log level is at least level.
 
373
 * 16 zero bytes in a row are ommited
 
374
 */
 
375
_PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len)
 
376
{
 
377
        _dump_data(level, buf, len, true);
 
378
}
 
379
 
 
380
 
 
381
/**
 
382
 malloc that aborts with smb_panic on fail or zero size.
 
383
**/
 
384
 
 
385
_PUBLIC_ void *smb_xmalloc(size_t size)
 
386
{
 
387
        void *p;
 
388
        if (size == 0)
 
389
                smb_panic("smb_xmalloc: called with zero size.\n");
 
390
        if ((p = malloc(size)) == NULL)
 
391
                smb_panic("smb_xmalloc: malloc fail.\n");
 
392
        return p;
 
393
}
 
394
 
 
395
/**
 
396
 Memdup with smb_panic on fail.
 
397
**/
 
398
 
 
399
_PUBLIC_ void *smb_xmemdup(const void *p, size_t size)
 
400
{
 
401
        void *p2;
 
402
        p2 = smb_xmalloc(size);
 
403
        memcpy(p2, p, size);
 
404
        return p2;
 
405
}
 
406
 
 
407
/**
 
408
 strdup that aborts on malloc fail.
 
409
**/
 
410
 
 
411
char *smb_xstrdup(const char *s)
 
412
{
 
413
#if defined(PARANOID_MALLOC_CHECKER)
 
414
#ifdef strdup
 
415
#undef strdup
 
416
#endif
 
417
#endif
 
418
 
 
419
#ifndef HAVE_STRDUP
 
420
#define strdup rep_strdup
 
421
#endif
 
422
 
 
423
        char *s1 = strdup(s);
 
424
#if defined(PARANOID_MALLOC_CHECKER)
 
425
#ifdef strdup
 
426
#undef strdup
 
427
#endif
 
428
#define strdup(s) __ERROR_DONT_USE_STRDUP_DIRECTLY
 
429
#endif
 
430
        if (!s1) {
 
431
                smb_panic("smb_xstrdup: malloc failed");
 
432
        }
 
433
        return s1;
 
434
 
 
435
}
 
436
 
 
437
/**
 
438
 strndup that aborts on malloc fail.
 
439
**/
 
440
 
 
441
char *smb_xstrndup(const char *s, size_t n)
 
442
{
 
443
#if defined(PARANOID_MALLOC_CHECKER)
 
444
#ifdef strndup
 
445
#undef strndup
 
446
#endif
 
447
#endif
 
448
 
 
449
#if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP))
 
450
#undef HAVE_STRNDUP
 
451
#define strndup rep_strndup
 
452
#endif
 
453
 
 
454
        char *s1 = strndup(s, n);
 
455
#if defined(PARANOID_MALLOC_CHECKER)
 
456
#ifdef strndup
 
457
#undef strndup
 
458
#endif
 
459
#define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY
 
460
#endif
 
461
        if (!s1) {
 
462
                smb_panic("smb_xstrndup: malloc failed");
 
463
        }
 
464
        return s1;
 
465
}
 
466
 
 
467
 
 
468
 
 
469
/**
 
470
 Like strdup but for memory.
 
471
**/
 
472
 
 
473
_PUBLIC_ void *memdup(const void *p, size_t size)
 
474
{
 
475
        void *p2;
 
476
        if (size == 0)
 
477
                return NULL;
 
478
        p2 = malloc(size);
 
479
        if (!p2)
 
480
                return NULL;
 
481
        memcpy(p2, p, size);
 
482
        return p2;
 
483
}
 
484
 
 
485
/**
 
486
 * Write a password to the log file.
 
487
 *
 
488
 * @note Only actually does something if DEBUG_PASSWORD was defined during 
 
489
 * compile-time.
 
490
 */
 
491
_PUBLIC_ void dump_data_pw(const char *msg, const uint8_t * data, size_t len)
 
492
{
 
493
#ifdef DEBUG_PASSWORD
 
494
        DEBUG(11, ("%s", msg));
 
495
        if (data != NULL && len > 0)
 
496
        {
 
497
                dump_data(11, data, len);
 
498
        }
 
499
#endif
 
500
}
 
501
 
 
502
 
 
503
/**
 
504
 * see if a range of memory is all zero. A NULL pointer is considered
 
505
 * to be all zero 
 
506
 */
 
507
_PUBLIC_ bool all_zero(const uint8_t *ptr, size_t size)
 
508
{
 
509
        int i;
 
510
        if (!ptr) return true;
 
511
        for (i=0;i<size;i++) {
 
512
                if (ptr[i]) return false;
 
513
        }
 
514
        return true;
 
515
}
 
516
 
 
517
/**
 
518
  realloc an array, checking for integer overflow in the array size
 
519
*/
 
520
_PUBLIC_ void *realloc_array(void *ptr, size_t el_size, unsigned count, bool free_on_fail)
 
521
{
 
522
#define MAX_MALLOC_SIZE 0x7fffffff
 
523
        if (count == 0 ||
 
524
            count >= MAX_MALLOC_SIZE/el_size) {
 
525
                if (free_on_fail)
 
526
                        SAFE_FREE(ptr);
 
527
                return NULL;
 
528
        }
 
529
        if (!ptr) {
 
530
                return malloc(el_size * count);
 
531
        }
 
532
        return realloc(ptr, el_size * count);
 
533
}
 
534
 
 
535
/****************************************************************************
 
536
 Type-safe malloc.
 
537
****************************************************************************/
 
538
 
 
539
void *malloc_array(size_t el_size, unsigned int count)
 
540
{
 
541
        return realloc_array(NULL, el_size, count, false);
 
542
}
 
543
 
 
544
/**
 
545
 Trim the specified elements off the front and back of a string.
 
546
**/
 
547
_PUBLIC_ bool trim_string(char *s, const char *front, const char *back)
 
548
{
 
549
        bool ret = false;
 
550
        size_t front_len;
 
551
        size_t back_len;
 
552
        size_t len;
 
553
 
 
554
        /* Ignore null or empty strings. */
 
555
        if (!s || (s[0] == '\0'))
 
556
                return false;
 
557
 
 
558
        front_len       = front? strlen(front) : 0;
 
559
        back_len        = back? strlen(back) : 0;
 
560
 
 
561
        len = strlen(s);
 
562
 
 
563
        if (front_len) {
 
564
                while (len && strncmp(s, front, front_len)==0) {
 
565
                        /* Must use memmove here as src & dest can
 
566
                         * easily overlap. Found by valgrind. JRA. */
 
567
                        memmove(s, s+front_len, (len-front_len)+1);
 
568
                        len -= front_len;
 
569
                        ret=true;
 
570
                }
 
571
        }
 
572
        
 
573
        if (back_len) {
 
574
                while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
 
575
                        s[len-back_len]='\0';
 
576
                        len -= back_len;
 
577
                        ret=true;
 
578
                }
 
579
        }
 
580
        return ret;
 
581
}
 
582
 
 
583
/**
 
584
 Find the number of 'c' chars in a string
 
585
**/
 
586
_PUBLIC_ _PURE_ size_t count_chars(const char *s, char c)
 
587
{
 
588
        size_t count = 0;
 
589
 
 
590
        while (*s) {
 
591
                if (*s == c) count++;
 
592
                s ++;
 
593
        }
 
594
 
 
595
        return count;
 
596
}
 
597
 
 
598
/**
 
599
 Routine to get hex characters and turn them into a 16 byte array.
 
600
 the array can be variable length, and any non-hex-numeric
 
601
 characters are skipped.  "0xnn" or "0Xnn" is specially catered
 
602
 for.
 
603
 
 
604
 valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
 
605
 
 
606
 
 
607
**/
 
608
_PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t strhex_len)
 
609
{
 
610
        size_t i;
 
611
        size_t num_chars = 0;
 
612
        uint8_t   lonybble, hinybble;
 
613
        const char     *hexchars = "0123456789ABCDEF";
 
614
        char           *p1 = NULL, *p2 = NULL;
 
615
 
 
616
        for (i = 0; i < strhex_len && strhex[i] != 0; i++) {
 
617
                if (strncasecmp(hexchars, "0x", 2) == 0) {
 
618
                        i++; /* skip two chars */
 
619
                        continue;
 
620
                }
 
621
 
 
622
                if (!(p1 = strchr(hexchars, toupper((unsigned char)strhex[i]))))
 
623
                        break;
 
624
 
 
625
                i++; /* next hex digit */
 
626
 
 
627
                if (!(p2 = strchr(hexchars, toupper((unsigned char)strhex[i]))))
 
628
                        break;
 
629
 
 
630
                /* get the two nybbles */
 
631
                hinybble = PTR_DIFF(p1, hexchars);
 
632
                lonybble = PTR_DIFF(p2, hexchars);
 
633
 
 
634
                if (num_chars >= p_len) {
 
635
                        break;
 
636
                }
 
637
 
 
638
                p[num_chars] = (hinybble << 4) | lonybble;
 
639
                num_chars++;
 
640
 
 
641
                p1 = NULL;
 
642
                p2 = NULL;
 
643
        }
 
644
        return num_chars;
 
645
}
 
646
 
 
647
/** 
 
648
 * Parse a hex string and return a data blob. 
 
649
 */
 
650
_PUBLIC_ _PURE_ DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex) 
 
651
{
 
652
        DATA_BLOB ret_blob = data_blob_talloc(mem_ctx, NULL, strlen(strhex)/2+1);
 
653
 
 
654
        ret_blob.length = strhex_to_str((char *)ret_blob.data, ret_blob.length,
 
655
                                        strhex,
 
656
                                        strlen(strhex));
 
657
 
 
658
        return ret_blob;
 
659
}
 
660
 
 
661
 
 
662
/**
 
663
 * Routine to print a buffer as HEX digits, into an allocated string.
 
664
 */
 
665
_PUBLIC_ void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer)
 
666
{
 
667
        int i;
 
668
        char *hex_buffer;
 
669
 
 
670
        *out_hex_buffer = malloc_array_p(char, (len*2)+1);
 
671
        hex_buffer = *out_hex_buffer;
 
672
 
 
673
        for (i = 0; i < len; i++)
 
674
                slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
 
675
}
 
676
 
 
677
/**
 
678
 * talloc version of hex_encode()
 
679
 */
 
680
_PUBLIC_ char *hex_encode_talloc(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len)
 
681
{
 
682
        int i;
 
683
        char *hex_buffer;
 
684
 
 
685
        hex_buffer = talloc_array(mem_ctx, char, (len*2)+1);
 
686
        if (!hex_buffer) {
 
687
                return NULL;
 
688
        }
 
689
 
 
690
        for (i = 0; i < len; i++)
 
691
                slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
 
692
 
 
693
        talloc_set_name_const(hex_buffer, hex_buffer);
 
694
        return hex_buffer;
 
695
}
 
696
 
 
697
/**
 
698
 Unescape a URL encoded string, in place.
 
699
**/
 
700
 
 
701
_PUBLIC_ void rfc1738_unescape(char *buf)
 
702
{
 
703
        char *p=buf;
 
704
 
 
705
        while (p && *p && (p=strchr(p,'%'))) {
 
706
                int c1 = p[1];
 
707
                int c2 = p[2];
 
708
 
 
709
                if (c1 >= '0' && c1 <= '9')
 
710
                        c1 = c1 - '0';
 
711
                else if (c1 >= 'A' && c1 <= 'F')
 
712
                        c1 = 10 + c1 - 'A';
 
713
                else if (c1 >= 'a' && c1 <= 'f')
 
714
                        c1 = 10 + c1 - 'a';
 
715
                else {p++; continue;}
 
716
 
 
717
                if (c2 >= '0' && c2 <= '9')
 
718
                        c2 = c2 - '0';
 
719
                else if (c2 >= 'A' && c2 <= 'F')
 
720
                        c2 = 10 + c2 - 'A';
 
721
                else if (c2 >= 'a' && c2 <= 'f')
 
722
                        c2 = 10 + c2 - 'a';
 
723
                else {p++; continue;}
 
724
                        
 
725
                *p = (c1<<4) | c2;
 
726
 
 
727
                memmove(p+1, p+3, strlen(p+3)+1);
 
728
                p++;
 
729
        }
 
730
}
 
731
 
 
732
/**
 
733
  varient of strcmp() that handles NULL ptrs
 
734
**/
 
735
_PUBLIC_ int strcmp_safe(const char *s1, const char *s2)
 
736
{
 
737
        if (s1 == s2) {
 
738
                return 0;
 
739
        }
 
740
        if (s1 == NULL || s2 == NULL) {
 
741
                return s1?-1:1;
 
742
        }
 
743
        return strcmp(s1, s2);
 
744
}
 
745
 
 
746
 
 
747
/**
 
748
return the number of bytes occupied by a buffer in ASCII format
 
749
the result includes the null termination
 
750
limited by 'n' bytes
 
751
**/
 
752
_PUBLIC_ size_t ascii_len_n(const char *src, size_t n)
 
753
{
 
754
        size_t len;
 
755
 
 
756
        len = strnlen(src, n);
 
757
        if (len+1 <= n) {
 
758
                len += 1;
 
759
        }
 
760
 
 
761
        return len;
 
762
}
 
763
 
 
764
/**
 
765
 Set a boolean variable from the text value stored in the passed string.
 
766
 Returns true in success, false if the passed string does not correctly 
 
767
 represent a boolean.
 
768
**/
 
769
 
 
770
_PUBLIC_ bool set_boolean(const char *boolean_string, bool *boolean)
 
771
{
 
772
        if (strwicmp(boolean_string, "yes") == 0 ||
 
773
            strwicmp(boolean_string, "true") == 0 ||
 
774
            strwicmp(boolean_string, "on") == 0 ||
 
775
            strwicmp(boolean_string, "1") == 0) {
 
776
                *boolean = true;
 
777
                return true;
 
778
        } else if (strwicmp(boolean_string, "no") == 0 ||
 
779
                   strwicmp(boolean_string, "false") == 0 ||
 
780
                   strwicmp(boolean_string, "off") == 0 ||
 
781
                   strwicmp(boolean_string, "0") == 0) {
 
782
                *boolean = false;
 
783
                return true;
 
784
        }
 
785
        return false;
 
786
}
 
787
 
 
788
/**
 
789
return the number of bytes occupied by a buffer in CH_UTF16 format
 
790
the result includes the null termination
 
791
**/
 
792
_PUBLIC_ size_t utf16_len(const void *buf)
 
793
{
 
794
        size_t len;
 
795
 
 
796
        for (len = 0; SVAL(buf,len); len += 2) ;
 
797
 
 
798
        return len + 2;
 
799
}
 
800
 
 
801
/**
 
802
return the number of bytes occupied by a buffer in CH_UTF16 format
 
803
the result includes the null termination
 
804
limited by 'n' bytes
 
805
**/
 
806
_PUBLIC_ size_t utf16_len_n(const void *src, size_t n)
 
807
{
 
808
        size_t len;
 
809
 
 
810
        for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;
 
811
 
 
812
        if (len+2 <= n) {
 
813
                len += 2;
 
814
        }
 
815
 
 
816
        return len;
 
817
}
 
818
 
 
819
/**
 
820
 * @file
 
821
 * @brief String utilities.
 
822
 **/
 
823
 
 
824
static bool next_token_internal_talloc(TALLOC_CTX *ctx,
 
825
                                const char **ptr,
 
826
                                char **pp_buff,
 
827
                                const char *sep,
 
828
                                bool ltrim)
 
829
{
 
830
        char *s;
 
831
        char *saved_s;
 
832
        char *pbuf;
 
833
        bool quoted;
 
834
        size_t len=1;
 
835
 
 
836
        *pp_buff = NULL;
 
837
        if (!ptr) {
 
838
                return(false);
 
839
        }
 
840
 
 
841
        s = (char *)*ptr;
 
842
 
 
843
        /* default to simple separators */
 
844
        if (!sep) {
 
845
                sep = " \t\n\r";
 
846
        }
 
847
 
 
848
        /* find the first non sep char, if left-trimming is requested */
 
849
        if (ltrim) {
 
850
                while (*s && strchr_m(sep,*s)) {
 
851
                        s++;
 
852
                }
 
853
        }
 
854
 
 
855
        /* nothing left? */
 
856
        if (!*s) {
 
857
                return false;
 
858
        }
 
859
 
 
860
        /* When restarting we need to go from here. */
 
861
        saved_s = s;
 
862
 
 
863
        /* Work out the length needed. */
 
864
        for (quoted = false; *s &&
 
865
                        (quoted || !strchr_m(sep,*s)); s++) {
 
866
                if (*s == '\"') {
 
867
                        quoted = !quoted;
 
868
                } else {
 
869
                        len++;
 
870
                }
 
871
        }
 
872
 
 
873
        /* We started with len = 1 so we have space for the nul. */
 
874
        *pp_buff = talloc_array(ctx, char, len);
 
875
        if (!*pp_buff) {
 
876
                return false;
 
877
        }
 
878
 
 
879
        /* copy over the token */
 
880
        pbuf = *pp_buff;
 
881
        s = saved_s;
 
882
        for (quoted = false; *s &&
 
883
                        (quoted || !strchr_m(sep,*s)); s++) {
 
884
                if ( *s == '\"' ) {
 
885
                        quoted = !quoted;
 
886
                } else {
 
887
                        *pbuf++ = *s;
 
888
                }
 
889
        }
 
890
 
 
891
        *ptr = (*s) ? s+1 : s;
 
892
        *pbuf = 0;
 
893
 
 
894
        return true;
 
895
}
 
896
 
 
897
bool next_token_talloc(TALLOC_CTX *ctx,
 
898
                        const char **ptr,
 
899
                        char **pp_buff,
 
900
                        const char *sep)
 
901
{
 
902
        return next_token_internal_talloc(ctx, ptr, pp_buff, sep, true);
 
903
}
 
904
 
 
905
/*
 
906
 * Get the next token from a string, return false if none found.  Handles
 
907
 * double-quotes.  This version does not trim leading separator characters
 
908
 * before looking for a token.
 
909
 */
 
910
 
 
911
bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx,
 
912
                        const char **ptr,
 
913
                        char **pp_buff,
 
914
                        const char *sep)
 
915
{
 
916
        return next_token_internal_talloc(ctx, ptr, pp_buff, sep, false);
 
917
}
 
918
 
 
919