source: trunk/samba/source/lib/util.c @ 26

Last change on this file since 26 was 26, checked in by Paul Smedley, 14 years ago

Updated source to 3.0.25rc1

File size: 80.1 KB
Line 
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 Peach 2006
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 2 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, write to the Free Software
22   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23*/
24
25#include "includes.h"
26
27extern fstring local_machine;
28extern char *global_clobber_region_function;
29extern unsigned int global_clobber_region_line;
30extern fstring remote_arch;
31
32/* Max allowable allococation - 256mb - 0x10000000 */
33#define MAX_ALLOC_SIZE (1024*1024*256)
34
35#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
36#ifdef WITH_NISPLUS_HOME
37#ifdef BROKEN_NISPLUS_INCLUDE_FILES
38/*
39 * The following lines are needed due to buggy include files
40 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
41 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
42 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
43 * an enum in /usr/include/rpcsvc/nis.h.
44 */
45
46#if defined(GROUP)
47#undef GROUP
48#endif
49
50#if defined(GROUP_OBJ)
51#undef GROUP_OBJ
52#endif
53
54#endif /* BROKEN_NISPLUS_INCLUDE_FILES */
55
56#include <rpcsvc/nis.h>
57
58#endif /* WITH_NISPLUS_HOME */
59#endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
60
61enum protocol_types Protocol = PROTOCOL_COREPLUS;
62
63/* a default finfo structure to ensure all fields are sensible */
64file_info def_finfo;
65
66/* this is used by the chaining code */
67int chain_size = 0;
68
69int trans_num = 0;
70
71static enum remote_arch_types ra_type = RA_UNKNOWN;
72pstring user_socket_options=DEFAULT_SOCKET_OPTIONS;   
73
74/***********************************************************************
75 Definitions for all names.
76***********************************************************************/
77
78static char *smb_myname;
79static char *smb_myworkgroup;
80static char *smb_scope;
81static int smb_num_netbios_names;
82static char **smb_my_netbios_names;
83
84/***********************************************************************
85 Allocate and set myname. Ensure upper case.
86***********************************************************************/
87
88BOOL set_global_myname(const char *myname)
89{
90        SAFE_FREE(smb_myname);
91        smb_myname = SMB_STRDUP(myname);
92        if (!smb_myname)
93                return False;
94        strupper_m(smb_myname);
95        return True;
96}
97
98const char *global_myname(void)
99{
100        return smb_myname;
101}
102
103/***********************************************************************
104 Allocate and set myworkgroup. Ensure upper case.
105***********************************************************************/
106
107BOOL set_global_myworkgroup(const char *myworkgroup)
108{
109        SAFE_FREE(smb_myworkgroup);
110        smb_myworkgroup = SMB_STRDUP(myworkgroup);
111        if (!smb_myworkgroup)
112                return False;
113        strupper_m(smb_myworkgroup);
114        return True;
115}
116
117const char *lp_workgroup(void)
118{
119        return smb_myworkgroup;
120}
121
122/***********************************************************************
123 Allocate and set scope. Ensure upper case.
124***********************************************************************/
125
126BOOL set_global_scope(const char *scope)
127{
128        SAFE_FREE(smb_scope);
129        smb_scope = SMB_STRDUP(scope);
130        if (!smb_scope)
131                return False;
132        strupper_m(smb_scope);
133        return True;
134}
135
136/*********************************************************************
137 Ensure scope is never null string.
138*********************************************************************/
139
140const char *global_scope(void)
141{
142        if (!smb_scope)
143                set_global_scope("");
144        return smb_scope;
145}
146
147static void free_netbios_names_array(void)
148{
149        int i;
150
151        for (i = 0; i < smb_num_netbios_names; i++)
152                SAFE_FREE(smb_my_netbios_names[i]);
153
154        SAFE_FREE(smb_my_netbios_names);
155        smb_num_netbios_names = 0;
156}
157
158static BOOL allocate_my_netbios_names_array(size_t number)
159{
160        free_netbios_names_array();
161
162        smb_num_netbios_names = number + 1;
163        smb_my_netbios_names = SMB_MALLOC_ARRAY( char *, smb_num_netbios_names );
164
165        if (!smb_my_netbios_names)
166                return False;
167
168        memset(smb_my_netbios_names, '\0', sizeof(char *) * smb_num_netbios_names);
169        return True;
170}
171
172static BOOL set_my_netbios_names(const char *name, int i)
173{
174        SAFE_FREE(smb_my_netbios_names[i]);
175
176        smb_my_netbios_names[i] = SMB_STRDUP(name);
177        if (!smb_my_netbios_names[i])
178                return False;
179        strupper_m(smb_my_netbios_names[i]);
180        return True;
181}
182
183/***********************************************************************
184 Free memory allocated to global objects
185***********************************************************************/
186
187void gfree_names(void)
188{
189        SAFE_FREE( smb_myname );
190        SAFE_FREE( smb_myworkgroup );
191        SAFE_FREE( smb_scope );
192        free_netbios_names_array();
193}
194
195void gfree_all( void )
196{
197        gfree_names(); 
198        gfree_loadparm();
199        gfree_case_tables();
200        gfree_debugsyms();
201        gfree_charcnv();
202        gfree_messages();
203        gfree_interfaces();
204
205        /* release the talloc null_context memory last */
206        talloc_disable_null_tracking();
207}
208
209const char *my_netbios_names(int i)
210{
211        return smb_my_netbios_names[i];
212}
213
214BOOL set_netbios_aliases(const char **str_array)
215{
216        size_t namecount;
217
218        /* Work out the max number of netbios aliases that we have */
219        for( namecount=0; str_array && (str_array[namecount] != NULL); namecount++ )
220                ;
221
222        if ( global_myname() && *global_myname())
223                namecount++;
224
225        /* Allocate space for the netbios aliases */
226        if (!allocate_my_netbios_names_array(namecount))
227                return False;
228
229        /* Use the global_myname string first */
230        namecount=0;
231        if ( global_myname() && *global_myname()) {
232                set_my_netbios_names( global_myname(), namecount );
233                namecount++;
234        }
235
236        if (str_array) {
237                size_t i;
238                for ( i = 0; str_array[i] != NULL; i++) {
239                        size_t n;
240                        BOOL duplicate = False;
241
242                        /* Look for duplicates */
243                        for( n=0; n<namecount; n++ ) {
244                                if( strequal( str_array[i], my_netbios_names(n) ) ) {
245                                        duplicate = True;
246                                        break;
247                                }
248                        }
249                        if (!duplicate) {
250                                if (!set_my_netbios_names(str_array[i], namecount))
251                                        return False;
252                                namecount++;
253                        }
254                }
255        }
256        return True;
257}
258
259/****************************************************************************
260  Common name initialization code.
261****************************************************************************/
262
263BOOL init_names(void)
264{
265        char *p;
266        int n;
267
268        if (global_myname() == NULL || *global_myname() == '\0') {
269                if (!set_global_myname(myhostname())) {
270                        DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
271                        return False;
272                }
273        }
274
275        if (!set_netbios_aliases(lp_netbios_aliases())) {
276                DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
277                return False;
278        }                       
279
280        fstrcpy( local_machine, global_myname() );
281        trim_char( local_machine, ' ', ' ' );
282        p = strchr( local_machine, ' ' );
283        if (p)
284                *p = 0;
285        strlower_m( local_machine );
286
287        DEBUG( 5, ("Netbios name list:-\n") );
288        for( n=0; my_netbios_names(n); n++ )
289                DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names(n) ) );
290
291        return( True );
292}
293
294/**************************************************************************n
295 Find a suitable temporary directory. The result should be copied immediately
296 as it may be overwritten by a subsequent call.
297****************************************************************************/
298
299const char *tmpdir(void)
300{
301        char *p;
302        if ((p = getenv("TMPDIR")))
303                return p;
304        return "/tmp";
305}
306
307/****************************************************************************
308 Add a gid to an array of gids if it's not already there.
309****************************************************************************/
310
311BOOL add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
312                             gid_t **gids, size_t *num_gids)
313{
314        int i;
315
316        if ((*num_gids != 0) && (*gids == NULL)) {
317                /*
318                 * A former call to this routine has failed to allocate memory
319                 */
320                return False;
321        }
322
323        for (i=0; i<*num_gids; i++) {
324                if ((*gids)[i] == gid) {
325                        return True;
326                }
327        }
328
329        *gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1);
330        if (*gids == NULL) {
331                *num_gids = 0;
332                return False;
333        }
334
335        (*gids)[*num_gids] = gid;
336        *num_gids += 1;
337        return True;
338}
339
340/****************************************************************************
341 Like atoi but gets the value up to the separator character.
342****************************************************************************/
343
344static const char *Atoic(const char *p, int *n, const char *c)
345{
346        if (!isdigit((int)*p)) {
347                DEBUG(5, ("Atoic: malformed number\n"));
348                return NULL;
349        }
350
351        (*n) = atoi(p);
352
353        while ((*p) && isdigit((int)*p))
354                p++;
355
356        if (strchr_m(c, *p) == NULL) {
357                DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c));
358                return NULL;
359        }
360
361        return p;
362}
363
364/*************************************************************************
365 Reads a list of numbers.
366 *************************************************************************/
367
368const char *get_numlist(const char *p, uint32 **num, int *count)
369{
370        int val;
371
372        if (num == NULL || count == NULL)
373                return NULL;
374
375        (*count) = 0;
376        (*num  ) = NULL;
377
378        while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':') {
379                *num = SMB_REALLOC_ARRAY((*num), uint32, (*count)+1);
380                if (!(*num)) {
381                        return NULL;
382                }
383                (*num)[(*count)] = val;
384                (*count)++;
385                p++;
386        }
387
388        return p;
389}
390
391/*******************************************************************
392 Check if a file exists - call vfs_file_exist for samba files.
393********************************************************************/
394
395BOOL file_exist(const char *fname,SMB_STRUCT_STAT *sbuf)
396{
397        SMB_STRUCT_STAT st;
398        if (!sbuf)
399                sbuf = &st;
400 
401        if (sys_stat(fname,sbuf) != 0) 
402                return(False);
403
404        return((S_ISREG(sbuf->st_mode)) || (S_ISFIFO(sbuf->st_mode)));
405}
406
407/*******************************************************************
408 Check a files mod time.
409********************************************************************/
410
411time_t file_modtime(const char *fname)
412{
413        SMB_STRUCT_STAT st;
414 
415        if (sys_stat(fname,&st) != 0) 
416                return(0);
417
418        return(st.st_mtime);
419}
420
421/*******************************************************************
422 Check if a directory exists.
423********************************************************************/
424
425BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
426{
427        SMB_STRUCT_STAT st2;
428        BOOL ret;
429
430        if (!st)
431                st = &st2;
432
433        if (sys_stat(dname,st) != 0) 
434                return(False);
435
436        ret = S_ISDIR(st->st_mode);
437        if(!ret)
438                errno = ENOTDIR;
439        return ret;
440}
441
442/*******************************************************************
443 Returns the size in bytes of the named file.
444********************************************************************/
445
446SMB_OFF_T get_file_size(char *file_name)
447{
448        SMB_STRUCT_STAT buf;
449        buf.st_size = 0;
450        if(sys_stat(file_name,&buf) != 0)
451                return (SMB_OFF_T)-1;
452        return(buf.st_size);
453}
454
455/*******************************************************************
456 Return a string representing an attribute for a file.
457********************************************************************/
458
459char *attrib_string(uint16 mode)
460{
461        static fstring attrstr;
462
463        attrstr[0] = 0;
464
465        if (mode & aVOLID) fstrcat(attrstr,"V");
466        if (mode & aDIR) fstrcat(attrstr,"D");
467        if (mode & aARCH) fstrcat(attrstr,"A");
468        if (mode & aHIDDEN) fstrcat(attrstr,"H");
469        if (mode & aSYSTEM) fstrcat(attrstr,"S");
470        if (mode & aRONLY) fstrcat(attrstr,"R");         
471
472        return(attrstr);
473}
474
475/*******************************************************************
476 Show a smb message structure.
477********************************************************************/
478
479void show_msg(char *buf)
480{
481        int i;
482        int bcc=0;
483
484        if (!DEBUGLVL(5))
485                return;
486       
487        DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
488                        smb_len(buf),
489                        (int)CVAL(buf,smb_com),
490                        (int)CVAL(buf,smb_rcls),
491                        (int)CVAL(buf,smb_reh),
492                        (int)SVAL(buf,smb_err),
493                        (int)CVAL(buf,smb_flg),
494                        (int)SVAL(buf,smb_flg2)));
495        DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
496                        (int)SVAL(buf,smb_tid),
497                        (int)SVAL(buf,smb_pid),
498                        (int)SVAL(buf,smb_uid),
499                        (int)SVAL(buf,smb_mid)));
500        DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
501
502        for (i=0;i<(int)CVAL(buf,smb_wct);i++)
503                DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
504                        SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
505       
506        bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
507
508        DEBUGADD(5,("smb_bcc=%d\n",bcc));
509
510        if (DEBUGLEVEL < 10)
511                return;
512
513        if (DEBUGLEVEL < 50)
514                bcc = MIN(bcc, 512);
515
516        dump_data(10, smb_buf(buf), bcc);       
517}
518
519/*******************************************************************
520 Set the length and marker of an smb packet.
521********************************************************************/
522
523void smb_setlen(char *buf,int len)
524{
525        _smb_setlen(buf,len);
526
527        SCVAL(buf,4,0xFF);
528        SCVAL(buf,5,'S');
529        SCVAL(buf,6,'M');
530        SCVAL(buf,7,'B');
531}
532
533/*******************************************************************
534 Setup the word count and byte count for a smb message.
535********************************************************************/
536
537int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
538{
539        if (zero && (num_words || num_bytes)) {
540                memset(buf + smb_size,'\0',num_words*2 + num_bytes);
541        }
542        SCVAL(buf,smb_wct,num_words);
543        SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes); 
544        smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
545        return (smb_size + num_words*2 + num_bytes);
546}
547
548/*******************************************************************
549 Setup only the byte count for a smb message.
550********************************************************************/
551
552int set_message_bcc(char *buf,int num_bytes)
553{
554        int num_words = CVAL(buf,smb_wct);
555        SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes); 
556        smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
557        return (smb_size + num_words*2 + num_bytes);
558}
559
560/*******************************************************************
561 Setup only the byte count for a smb message, using the end of the
562 message as a marker.
563********************************************************************/
564
565int set_message_end(void *outbuf,void *end_ptr)
566{
567        return set_message_bcc((char *)outbuf,PTR_DIFF(end_ptr,smb_buf((char *)outbuf)));
568}
569
570/*******************************************************************
571 Reduce a file name, removing .. elements.
572********************************************************************/
573
574void dos_clean_name(char *s)
575{
576        char *p=NULL;
577
578        DEBUG(3,("dos_clean_name [%s]\n",s));
579
580        /* remove any double slashes */
581        all_string_sub(s, "\\\\", "\\", 0);
582
583        /* Remove leading .\\ characters */
584        if(strncmp(s, ".\\", 2) == 0) {
585                trim_string(s, ".\\", NULL);
586                if(*s == 0)
587                        pstrcpy(s,".\\");
588        }
589
590        while ((p = strstr_m(s,"\\..\\")) != NULL) {
591                pstring s1;
592
593                *p = 0;
594                pstrcpy(s1,p+3);
595
596                if ((p=strrchr_m(s,'\\')) != NULL)
597                        *p = 0;
598                else
599                        *s = 0;
600                pstrcat(s,s1);
601        } 
602
603        trim_string(s,NULL,"\\..");
604        all_string_sub(s, "\\.\\", "\\", 0);
605}
606
607/*******************************************************************
608 Reduce a file name, removing .. elements.
609********************************************************************/
610
611void unix_clean_name(char *s)
612{
613        char *p=NULL;
614
615        DEBUG(3,("unix_clean_name [%s]\n",s));
616
617        /* remove any double slashes */
618        all_string_sub(s, "//","/", 0);
619
620        /* Remove leading ./ characters */
621        if(strncmp(s, "./", 2) == 0) {
622                trim_string(s, "./", NULL);
623                if(*s == 0)
624                        pstrcpy(s,"./");
625        }
626
627        while ((p = strstr_m(s,"/../")) != NULL) {
628                pstring s1;
629
630                *p = 0;
631                pstrcpy(s1,p+3);
632
633                if ((p=strrchr_m(s,'/')) != NULL)
634                        *p = 0;
635                else
636                        *s = 0;
637                pstrcat(s,s1);
638        } 
639
640        trim_string(s,NULL,"/..");
641        all_string_sub(s, "/./", "/", 0);
642}
643
644void clean_name(char *s)
645{
646        dos_clean_name(s);
647        unix_clean_name(s);
648}
649
650/*******************************************************************
651 Close the low 3 fd's and open dev/null in their place.
652********************************************************************/
653
654void close_low_fds(BOOL stderr_too)
655{
656#ifndef VALGRIND
657        int fd;
658        int i;
659
660        close(0);
661        close(1); 
662
663        if (stderr_too)
664                close(2);
665
666        /* try and use up these file descriptors, so silly
667                library routines writing to stdout etc won't cause havoc */
668        for (i=0;i<3;i++) {
669                if (i == 2 && !stderr_too)
670                        continue;
671
672                fd = sys_open("/dev/null",O_RDWR,0);
673                if (fd < 0)
674                        fd = sys_open("/dev/null",O_WRONLY,0);
675                if (fd < 0) {
676                        DEBUG(0,("Can't open /dev/null\n"));
677                        return;
678                }
679                if (fd != i) {
680                        DEBUG(0,("Didn't get file descriptor %d\n",i));
681                        return;
682                }
683        }
684#endif
685}
686
687/*******************************************************************
688 Write data into an fd at a given offset. Ignore seek errors.
689********************************************************************/
690
691ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos)
692{
693        size_t total=0;
694        ssize_t ret;
695
696        if (pos == (SMB_OFF_T)-1) {
697                return write_data(fd, buffer, N);
698        }
699#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
700        while (total < N) {
701                ret = sys_pwrite(fd,buffer + total,N - total, pos);
702                if (ret == -1 && errno == ESPIPE) {
703                        return write_data(fd, buffer + total,N - total);
704                }
705                if (ret == -1) {
706                        DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
707                        return -1;
708                }
709                if (ret == 0) {
710                        return total;
711                }
712                total += ret;
713                pos += ret;
714        }
715        return (ssize_t)total;
716#else
717        /* Use lseek and write_data. */
718        if (sys_lseek(fd, pos, SEEK_SET) == -1) {
719                if (errno != ESPIPE) {
720                        return -1;
721                }
722        }
723        return write_data(fd, buffer, N);
724#endif
725}
726
727/****************************************************************************
728 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
729 else
730  if SYSV use O_NDELAY
731  if BSD use FNDELAY
732****************************************************************************/
733
734int set_blocking(int fd, BOOL set)
735{
736        int val;
737#ifdef O_NONBLOCK
738#define FLAG_TO_SET O_NONBLOCK
739#else
740#ifdef SYSV
741#define FLAG_TO_SET O_NDELAY
742#else /* BSD */
743#define FLAG_TO_SET FNDELAY
744#endif
745#endif
746
747        if((val = sys_fcntl_long(fd, F_GETFL, 0)) == -1)
748                return -1;
749        if(set) /* Turn blocking on - ie. clear nonblock flag */
750                val &= ~FLAG_TO_SET;
751        else
752                val |= FLAG_TO_SET;
753        return sys_fcntl_long( fd, F_SETFL, val);
754#undef FLAG_TO_SET
755}
756
757/****************************************************************************
758 Transfer some data between two fd's.
759****************************************************************************/
760
761#ifndef TRANSFER_BUF_SIZE
762#define TRANSFER_BUF_SIZE 65536
763#endif
764
765ssize_t transfer_file_internal(int infd, int outfd, size_t n, ssize_t (*read_fn)(int, void *, size_t),
766                                                ssize_t (*write_fn)(int, const void *, size_t))
767{
768        char *buf;
769        size_t total = 0;
770        ssize_t read_ret;
771        ssize_t write_ret;
772        size_t num_to_read_thistime;
773        size_t num_written = 0;
774
775        if ((buf = SMB_MALLOC_ARRAY(char, TRANSFER_BUF_SIZE)) == NULL)
776                return -1;
777
778        while (total < n) {
779                num_to_read_thistime = MIN((n - total), TRANSFER_BUF_SIZE);
780
781                read_ret = (*read_fn)(infd, buf, num_to_read_thistime);
782                if (read_ret == -1) {
783                        DEBUG(0,("transfer_file_internal: read failure. Error = %s\n", strerror(errno) ));
784                        SAFE_FREE(buf);
785                        return -1;
786                }
787                if (read_ret == 0)
788                        break;
789
790                num_written = 0;
791 
792                while (num_written < read_ret) {
793                        write_ret = (*write_fn)(outfd,buf + num_written, read_ret - num_written);
794 
795                        if (write_ret == -1) {
796                                DEBUG(0,("transfer_file_internal: write failure. Error = %s\n", strerror(errno) ));
797                                SAFE_FREE(buf);
798                                return -1;
799                        }
800                        if (write_ret == 0)
801                                return (ssize_t)total;
802 
803                        num_written += (size_t)write_ret;
804                }
805
806                total += (size_t)read_ret;
807        }
808
809        SAFE_FREE(buf);
810        return (ssize_t)total;         
811}
812
813SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n)
814{
815        return (SMB_OFF_T)transfer_file_internal(infd, outfd, (size_t)n, sys_read, sys_write);
816}
817
818/*******************************************************************
819 Sleep for a specified number of milliseconds.
820********************************************************************/
821
822void smb_msleep(unsigned int t)
823{
824#if defined(HAVE_NANOSLEEP)
825        struct timespec tval;
826        int ret;
827
828        tval.tv_sec = t/1000;
829        tval.tv_nsec = 1000000*(t%1000);
830
831        do {
832                errno = 0;
833                ret = nanosleep(&tval, &tval);
834        } while (ret < 0 && errno == EINTR && (tval.tv_sec > 0 || tval.tv_nsec > 0));
835#else
836        unsigned int tdiff=0;
837        struct timeval tval,t1,t2; 
838        fd_set fds;
839
840        GetTimeOfDay(&t1);
841        t2 = t1;
842 
843        while (tdiff < t) {
844                tval.tv_sec = (t-tdiff)/1000;
845                tval.tv_usec = 1000*((t-tdiff)%1000);
846
847                /* Never wait for more than 1 sec. */
848                if (tval.tv_sec > 1) {
849                        tval.tv_sec = 1; 
850                        tval.tv_usec = 0;
851                }
852
853                FD_ZERO(&fds);
854                errno = 0;
855                sys_select_intr(0,&fds,NULL,NULL,&tval);
856
857                GetTimeOfDay(&t2);
858                if (t2.tv_sec < t1.tv_sec) {
859                        /* Someone adjusted time... */
860                        t1 = t2;
861                }
862
863                tdiff = TvalDiff(&t1,&t2);
864        }
865#endif
866}
867
868/****************************************************************************
869 Become a daemon, discarding the controlling terminal.
870****************************************************************************/
871
872void become_daemon(BOOL Fork, BOOL no_process_group)
873{
874#ifdef __OS2__
875// fork daemonize scheme not working in os/2, thus the parent process will currently kill and reap all children when it exits
876        Fork = False;
877#endif
878        if (Fork) {
879                if (sys_fork()) {
880                        _exit(0);
881                }
882        }
883
884  /* detach from the terminal */
885#ifdef HAVE_SETSID
886        if (!no_process_group) setsid();
887#elif defined(TIOCNOTTY)
888        if (!no_process_group) {
889                int i = sys_open("/dev/tty", O_RDWR, 0);
890                if (i != -1) {
891                        ioctl(i, (int) TIOCNOTTY, (char *)0);     
892                        close(i);
893                }
894        }
895#endif /* HAVE_SETSID */
896
897        /* Close fd's 0,1,2. Needed if started by rsh */
898        close_low_fds(False);  /* Don't close stderr, let the debug system
899                                  attach it to the logfile */
900}
901
902/****************************************************************************
903 Put up a yes/no prompt.
904****************************************************************************/
905
906BOOL yesno(char *p)
907{
908        pstring ans;
909        printf("%s",p);
910
911        if (!fgets(ans,sizeof(ans)-1,stdin))
912                return(False);
913
914        if (*ans == 'y' || *ans == 'Y')
915                return(True);
916
917        return(False);
918}
919
920#if defined(PARANOID_MALLOC_CHECKER)
921
922/****************************************************************************
923 Internal malloc wrapper. Externally visible.
924****************************************************************************/
925
926void *malloc_(size_t size)
927{
928#undef malloc
929        return malloc(size);
930#define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
931}
932
933/****************************************************************************
934 Internal calloc wrapper. Not externally visible.
935****************************************************************************/
936
937static void *calloc_(size_t count, size_t size)
938{
939#undef calloc
940        return calloc(count, size);
941#define calloc(n,s) __ERROR_DONT_USE_CALLOC_DIRECTLY
942}
943
944/****************************************************************************
945 Internal realloc wrapper. Not externally visible.
946****************************************************************************/
947
948static void *realloc_(void *ptr, size_t size)
949{
950#undef realloc
951        return realloc(ptr, size);
952#define realloc(p,s) __ERROR_DONT_USE_RELLOC_DIRECTLY
953}
954
955#endif /* PARANOID_MALLOC_CHECKER */
956
957/****************************************************************************
958 Type-safe malloc.
959****************************************************************************/
960
961void *malloc_array(size_t el_size, unsigned int count)
962{
963        if (count >= MAX_ALLOC_SIZE/el_size) {
964                return NULL;
965        }
966
967#if defined(PARANOID_MALLOC_CHECKER)
968        return malloc_(el_size*count);
969#else
970        return malloc(el_size*count);
971#endif
972}
973
974/****************************************************************************
975 Type-safe memalign
976****************************************************************************/
977
978void *memalign_array(size_t el_size, size_t align, unsigned int count)
979{
980        if (count >= MAX_ALLOC_SIZE/el_size) {
981                return NULL;
982        }
983
984        return sys_memalign(align, el_size*count);
985}
986
987/****************************************************************************
988 Type-safe calloc.
989****************************************************************************/
990
991void *calloc_array(size_t size, size_t nmemb)
992{
993        if (nmemb >= MAX_ALLOC_SIZE/size) {
994                return NULL;
995        }
996#if defined(PARANOID_MALLOC_CHECKER)
997        return calloc_(nmemb, size);
998#else
999        return calloc(nmemb, size);
1000#endif
1001}
1002
1003/****************************************************************************
1004 Expand a pointer to be a particular size.
1005 Note that this version of Realloc has an extra parameter that decides
1006 whether to free the passed in storage on allocation failure or if the
1007 new size is zero.
1008
1009 This is designed for use in the typical idiom of :
1010
1011 p = SMB_REALLOC(p, size)
1012 if (!p) {
1013    return error;
1014 }
1015
1016 and not to have to keep track of the old 'p' contents to free later, nor
1017 to worry if the size parameter was zero. In the case where NULL is returned
1018 we guarentee that p has been freed.
1019
1020 If free later semantics are desired, then pass 'free_old_on_error' as False which
1021 guarentees that the old contents are not freed on error, even if size == 0. To use
1022 this idiom use :
1023
1024 tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
1025 if (!tmp) {
1026    SAFE_FREE(p);
1027    return error;
1028 } else {
1029    p = tmp;
1030 }
1031
1032 Changes were instigated by Coverity error checking. JRA.
1033****************************************************************************/
1034
1035void *Realloc(void *p, size_t size, BOOL free_old_on_error)
1036{
1037        void *ret=NULL;
1038
1039        if (size == 0) {
1040                if (free_old_on_error) {
1041                        SAFE_FREE(p);
1042                }
1043                DEBUG(2,("Realloc asked for 0 bytes\n"));
1044                return NULL;
1045        }
1046
1047#if defined(PARANOID_MALLOC_CHECKER)
1048        if (!p) {
1049                ret = (void *)malloc_(size);
1050        } else {
1051                ret = (void *)realloc_(p,size);
1052        }
1053#else
1054        if (!p) {
1055                ret = (void *)malloc(size);
1056        } else {
1057                ret = (void *)realloc(p,size);
1058        }
1059#endif
1060
1061        if (!ret) {
1062                if (free_old_on_error && p) {
1063                        SAFE_FREE(p);
1064                }
1065                DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
1066        }
1067
1068        return(ret);
1069}
1070
1071/****************************************************************************
1072 Type-safe realloc.
1073****************************************************************************/
1074
1075void *realloc_array(void *p, size_t el_size, unsigned int count, BOOL free_old_on_error)
1076{
1077        if (count >= MAX_ALLOC_SIZE/el_size) {
1078                if (free_old_on_error) {
1079                        SAFE_FREE(p);
1080                }
1081                return NULL;
1082        }
1083        return Realloc(p, el_size*count, free_old_on_error);
1084}
1085
1086/****************************************************************************
1087 (Hopefully) efficient array append.
1088****************************************************************************/
1089
1090void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
1091                        void *element, void *_array, uint32 *num_elements,
1092                        ssize_t *array_size)
1093{
1094        void **array = (void **)_array;
1095
1096        if (*array_size < 0) {
1097                return;
1098        }
1099
1100        if (*array == NULL) {
1101                if (*array_size == 0) {
1102                        *array_size = 128;
1103                }
1104
1105                if (*array_size >= MAX_ALLOC_SIZE/element_size) {
1106                        goto error;
1107                }
1108
1109                *array = TALLOC(mem_ctx, element_size * (*array_size));
1110                if (*array == NULL) {
1111                        goto error;
1112                }
1113        }
1114
1115        if (*num_elements == *array_size) {
1116                *array_size *= 2;
1117
1118                if (*array_size >= MAX_ALLOC_SIZE/element_size) {
1119                        goto error;
1120                }
1121
1122                *array = TALLOC_REALLOC(mem_ctx, *array,
1123                                        element_size * (*array_size));
1124
1125                if (*array == NULL) {
1126                        goto error;
1127                }
1128        }
1129
1130        memcpy((char *)(*array) + element_size*(*num_elements),
1131               element, element_size);
1132        *num_elements += 1;
1133
1134        return;
1135
1136 error:
1137        *num_elements = 0;
1138        *array_size = -1;
1139}
1140
1141/****************************************************************************
1142 Free memory, checks for NULL.
1143 Use directly SAFE_FREE()
1144 Exists only because we need to pass a function pointer somewhere --SSS
1145****************************************************************************/
1146
1147void safe_free(void *p)
1148{
1149        SAFE_FREE(p);
1150}
1151
1152/****************************************************************************
1153 Get my own name and IP.
1154****************************************************************************/
1155
1156BOOL get_myname(char *my_name)
1157{
1158        pstring hostname;
1159
1160        *hostname = 0;
1161
1162        /* get my host name */
1163        if (gethostname(hostname, sizeof(hostname)) == -1) {
1164                DEBUG(0,("gethostname failed\n"));
1165                return False;
1166        } 
1167
1168        /* Ensure null termination. */
1169        hostname[sizeof(hostname)-1] = '\0';
1170
1171        if (my_name) {
1172                /* split off any parts after an initial . */
1173                char *p = strchr_m(hostname,'.');
1174
1175                if (p)
1176                        *p = 0;
1177               
1178                fstrcpy(my_name,hostname);
1179        }
1180       
1181        return(True);
1182}
1183
1184/****************************************************************************
1185 Get my own canonical name, including domain.
1186****************************************************************************/
1187
1188BOOL get_mydnsfullname(fstring my_dnsname)
1189{
1190        static fstring dnshostname;
1191        struct hostent *hp;
1192
1193        if (!*dnshostname) {
1194                /* get my host name */
1195                if (gethostname(dnshostname, sizeof(dnshostname)) == -1) {
1196                        *dnshostname = '\0';
1197                        DEBUG(0,("gethostname failed\n"));
1198                        return False;
1199                } 
1200
1201                /* Ensure null termination. */
1202                dnshostname[sizeof(dnshostname)-1] = '\0';
1203
1204                /* Ensure we get the cannonical name. */
1205                if (!(hp = sys_gethostbyname(dnshostname))) {
1206                        *dnshostname = '\0';
1207                        return False;
1208                }
1209                fstrcpy(dnshostname, hp->h_name);
1210        }
1211        fstrcpy(my_dnsname, dnshostname);
1212        return True;
1213}
1214
1215/****************************************************************************
1216 Get my own domain name.
1217****************************************************************************/
1218
1219BOOL get_mydnsdomname(fstring my_domname)
1220{
1221        fstring domname;
1222        char *p;
1223
1224        *my_domname = '\0';
1225        if (!get_mydnsfullname(domname)) {
1226                return False;
1227        }       
1228        p = strchr_m(domname, '.');
1229        if (p) {
1230                p++;
1231                fstrcpy(my_domname, p);
1232        }
1233
1234        return False;
1235}
1236
1237/****************************************************************************
1238 Interpret a protocol description string, with a default.
1239****************************************************************************/
1240
1241int interpret_protocol(const char *str,int def)
1242{
1243        if (strequal(str,"NT1"))
1244                return(PROTOCOL_NT1);
1245        if (strequal(str,"LANMAN2"))
1246                return(PROTOCOL_LANMAN2);
1247        if (strequal(str,"LANMAN1"))
1248                return(PROTOCOL_LANMAN1);
1249        if (strequal(str,"CORE"))
1250                return(PROTOCOL_CORE);
1251        if (strequal(str,"COREPLUS"))
1252                return(PROTOCOL_COREPLUS);
1253        if (strequal(str,"CORE+"))
1254                return(PROTOCOL_COREPLUS);
1255 
1256        DEBUG(0,("Unrecognised protocol level %s\n",str));
1257 
1258        return(def);
1259}
1260
1261/****************************************************************************
1262 Return true if a string could be a pure IP address.
1263****************************************************************************/
1264
1265BOOL is_ipaddress(const char *str)
1266{
1267        BOOL pure_address = True;
1268        int i;
1269 
1270        for (i=0; pure_address && str[i]; i++)
1271                if (!(isdigit((int)str[i]) || str[i] == '.'))
1272                        pure_address = False;
1273
1274        /* Check that a pure number is not misinterpreted as an IP */
1275        pure_address = pure_address && (strchr_m(str, '.') != NULL);
1276
1277        return pure_address;
1278}
1279
1280/****************************************************************************
1281 Interpret an internet address or name into an IP address in 4 byte form.
1282****************************************************************************/
1283
1284uint32 interpret_addr(const char *str)
1285{
1286        struct hostent *hp;
1287        uint32 res;
1288
1289        if (strcmp(str,"0.0.0.0") == 0)
1290                return(0);
1291        if (strcmp(str,"255.255.255.255") == 0)
1292                return(0xFFFFFFFF);
1293
1294  /* if it's in the form of an IP address then get the lib to interpret it */
1295        if (is_ipaddress(str)) {
1296                res = inet_addr(str);
1297        } else {
1298                /* otherwise assume it's a network name of some sort and use
1299                        sys_gethostbyname */
1300                if ((hp = sys_gethostbyname(str)) == 0) {
1301                        DEBUG(3,("sys_gethostbyname: Unknown host. %s\n",str));
1302                        return 0;
1303                }
1304
1305                if(hp->h_addr == NULL) {
1306                        DEBUG(3,("sys_gethostbyname: host address is invalid for host %s\n",str));
1307                        return 0;
1308                }
1309                putip((char *)&res,(char *)hp->h_addr);
1310        }
1311
1312        if (res == (uint32)-1)
1313                return(0);
1314
1315        return(res);
1316}
1317
1318/*******************************************************************
1319 A convenient addition to interpret_addr().
1320******************************************************************/
1321
1322struct in_addr *interpret_addr2(const char *str)
1323{
1324        static struct in_addr ret;
1325        uint32 a = interpret_addr(str);
1326        ret.s_addr = a;
1327        return(&ret);
1328}
1329
1330/*******************************************************************
1331 Check if an IP is the 0.0.0.0.
1332******************************************************************/
1333
1334BOOL is_zero_ip(struct in_addr ip)
1335{
1336        uint32 a;
1337        putip((char *)&a,(char *)&ip);
1338        return(a == 0);
1339}
1340
1341/*******************************************************************
1342 Set an IP to 0.0.0.0.
1343******************************************************************/
1344
1345void zero_ip(struct in_addr *ip)
1346{
1347        static BOOL init;
1348        static struct in_addr ipzero;
1349
1350        if (!init) {
1351                ipzero = *interpret_addr2("0.0.0.0");
1352                init = True;
1353        }
1354
1355        *ip = ipzero;
1356}
1357
1358#if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1359/******************************************************************
1360 Remove any mount options such as -rsize=2048,wsize=2048 etc.
1361 Based on a fix from <Thomas.Hepper@icem.de>.
1362*******************************************************************/
1363
1364static void strip_mount_options( pstring *str)
1365{
1366        if (**str == '-') { 
1367                char *p = *str;
1368                while(*p && !isspace(*p))
1369                        p++;
1370                while(*p && isspace(*p))
1371                        p++;
1372                if(*p) {
1373                        pstring tmp_str;
1374
1375                        pstrcpy(tmp_str, p);
1376                        pstrcpy(*str, tmp_str);
1377                }
1378        }
1379}
1380
1381/*******************************************************************
1382 Patch from jkf@soton.ac.uk
1383 Split Luke's automount_server into YP lookup and string splitter
1384 so can easily implement automount_path().
1385 As we may end up doing both, cache the last YP result.
1386*******************************************************************/
1387
1388#ifdef WITH_NISPLUS_HOME
1389char *automount_lookup(const char *user_name)
1390{
1391        static fstring last_key = "";
1392        static pstring last_value = "";
1393 
1394        char *nis_map = (char *)lp_nis_home_map_name();
1395 
1396        char buffer[NIS_MAXATTRVAL + 1];
1397        nis_result *result;
1398        nis_object *object;
1399        entry_obj  *entry;
1400 
1401        if (strcmp(user_name, last_key)) {
1402                slprintf(buffer, sizeof(buffer)-1, "[key=%s],%s", user_name, nis_map);
1403                DEBUG(5, ("NIS+ querystring: %s\n", buffer));
1404 
1405                if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
1406                        if (result->status != NIS_SUCCESS) {
1407                                DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
1408                                fstrcpy(last_key, ""); pstrcpy(last_value, "");
1409                        } else {
1410                                object = result->objects.objects_val;
1411                                if (object->zo_data.zo_type == ENTRY_OBJ) {
1412                                        entry = &object->zo_data.objdata_u.en_data;
1413                                        DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
1414                                        DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
1415 
1416                                        pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
1417                                        pstring_sub(last_value, "&", user_name);
1418                                        fstrcpy(last_key, user_name);
1419                                }
1420                        }
1421                }
1422                nis_freeresult(result);
1423        }
1424
1425        strip_mount_options(&last_value);
1426
1427        DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
1428        return last_value;
1429}
1430#else /* WITH_NISPLUS_HOME */
1431
1432char *automount_lookup(const char *user_name)
1433{
1434        static fstring last_key = "";
1435        static pstring last_value = "";
1436
1437        int nis_error;        /* returned by yp all functions */
1438        char *nis_result;     /* yp_match inits this */
1439        int nis_result_len;  /* and set this */
1440        char *nis_domain;     /* yp_get_default_domain inits this */
1441        char *nis_map = (char *)lp_nis_home_map_name();
1442
1443        if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
1444                DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
1445                return last_value;
1446        }
1447
1448        DEBUG(5, ("NIS Domain: %s\n", nis_domain));
1449
1450        if (!strcmp(user_name, last_key)) {
1451                nis_result = last_value;
1452                nis_result_len = strlen(last_value);
1453                nis_error = 0;
1454        } else {
1455                if ((nis_error = yp_match(nis_domain, nis_map, user_name, strlen(user_name),
1456                                &nis_result, &nis_result_len)) == 0) {
1457                        fstrcpy(last_key, user_name);
1458                        pstrcpy(last_value, nis_result);
1459                        strip_mount_options(&last_value);
1460
1461                } else if(nis_error == YPERR_KEY) {
1462
1463                        /* If Key lookup fails user home server is not in nis_map
1464                                use default information for server, and home directory */
1465                        last_value[0] = 0;
1466                        DEBUG(3, ("YP Key not found:  while looking up \"%s\" in map \"%s\"\n", 
1467                                        user_name, nis_map));
1468                        DEBUG(3, ("using defaults for server and home directory\n"));
1469                } else {
1470                        DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n", 
1471                                        yperr_string(nis_error), user_name, nis_map));
1472                }
1473        }
1474
1475        DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
1476        return last_value;
1477}
1478#endif /* WITH_NISPLUS_HOME */
1479#endif
1480
1481/*******************************************************************
1482 Are two IPs on the same subnet?
1483********************************************************************/
1484
1485BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
1486{
1487        uint32 net1,net2,nmask;
1488
1489        nmask = ntohl(mask.s_addr);
1490        net1  = ntohl(ip1.s_addr);
1491        net2  = ntohl(ip2.s_addr);
1492           
1493        return((net1 & nmask) == (net2 & nmask));
1494}
1495
1496
1497/****************************************************************************
1498 Check if a process exists. Does this work on all unixes?
1499****************************************************************************/
1500
1501BOOL process_exists(const struct process_id pid)
1502{
1503        if (procid_is_me(&pid)) {
1504                return True;
1505        }
1506
1507        if (!procid_is_local(&pid)) {
1508                /* This *SEVERELY* needs fixing. */
1509                return True;
1510        }
1511
1512        /* Doing kill with a non-positive pid causes messages to be
1513         * sent to places we don't want. */
1514        SMB_ASSERT(pid.pid > 0);
1515        return(kill(pid.pid,0) == 0 || errno != ESRCH);
1516}
1517
1518BOOL process_exists_by_pid(pid_t pid)
1519{
1520        return process_exists(pid_to_procid(pid));
1521}
1522
1523/*******************************************************************
1524 Convert a uid into a user name.
1525********************************************************************/
1526
1527const char *uidtoname(uid_t uid)
1528{
1529        static fstring name;
1530        struct passwd *pass;
1531
1532        pass = getpwuid_alloc(NULL, uid);
1533        if (pass) {
1534                fstrcpy(name, pass->pw_name);
1535                TALLOC_FREE(pass);
1536        } else {
1537                slprintf(name, sizeof(name) - 1, "%ld",(long int)uid);
1538        }
1539        return name;
1540}
1541
1542
1543/*******************************************************************
1544 Convert a gid into a group name.
1545********************************************************************/
1546
1547char *gidtoname(gid_t gid)
1548{
1549        static fstring name;
1550        struct group *grp;
1551
1552        grp = getgrgid(gid);
1553        if (grp)
1554                return(grp->gr_name);
1555        slprintf(name,sizeof(name) - 1, "%d",(int)gid);
1556        return(name);
1557}
1558
1559/*******************************************************************
1560 Convert a user name into a uid.
1561********************************************************************/
1562
1563uid_t nametouid(const char *name)
1564{
1565        struct passwd *pass;
1566        char *p;
1567        uid_t u;
1568
1569        pass = getpwnam_alloc(NULL, name);
1570        if (pass) {
1571                u = pass->pw_uid;
1572                TALLOC_FREE(pass);
1573                return u;
1574        }
1575
1576        u = (uid_t)strtol(name, &p, 0);
1577        if ((p != name) && (*p == '\0'))
1578                return u;
1579
1580        return (uid_t)-1;
1581}
1582
1583/*******************************************************************
1584 Convert a name to a gid_t if possible. Return -1 if not a group.
1585********************************************************************/
1586
1587gid_t nametogid(const char *name)
1588{
1589        struct group *grp;
1590        char *p;
1591        gid_t g;
1592
1593        g = (gid_t)strtol(name, &p, 0);
1594        if ((p != name) && (*p == '\0'))
1595                return g;
1596
1597        grp = sys_getgrnam(name);
1598        if (grp)
1599                return(grp->gr_gid);
1600        return (gid_t)-1;
1601}
1602
1603/*******************************************************************
1604 Something really nasty happened - panic !
1605********************************************************************/
1606
1607void smb_panic(const char *const why)
1608{
1609        char *cmd;
1610        int result;
1611
1612#ifdef DEVELOPER
1613        {
1614
1615                if (global_clobber_region_function) {
1616                        DEBUG(0,("smb_panic: clobber_region() last called from [%s(%u)]\n",
1617                                         global_clobber_region_function,
1618                                         global_clobber_region_line));
1619                } 
1620        }
1621#endif
1622
1623        DEBUG(0,("PANIC (pid %llu): %s\n",
1624                    (unsigned long long)sys_getpid(), why));
1625        log_stack_trace();
1626
1627        cmd = lp_panic_action();
1628        if (cmd && *cmd) {
1629                DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
1630                result = system(cmd);
1631
1632                if (result == -1)
1633                        DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
1634                                          strerror(errno)));
1635                else
1636                        DEBUG(0, ("smb_panic(): action returned status %d\n",
1637                                          WEXITSTATUS(result)));
1638        }
1639
1640        dump_core();
1641}
1642
1643/*******************************************************************
1644 Print a backtrace of the stack to the debug log. This function
1645 DELIBERATELY LEAKS MEMORY. The expectation is that you should
1646 exit shortly after calling it.
1647********************************************************************/
1648
1649#ifdef HAVE_LIBUNWIND_H
1650#include <libunwind.h>
1651#endif
1652
1653#ifdef HAVE_EXECINFO_H
1654#include <execinfo.h>
1655#endif
1656
1657#ifdef HAVE_LIBEXC_H
1658#include <libexc.h>
1659#endif
1660
1661void log_stack_trace(void)
1662{
1663#ifdef HAVE_LIBUNWIND
1664        /* Try to use libunwind before any other technique since on ia64
1665         * libunwind correctly walks the stack in more circumstances than
1666         * backtrace.
1667         */ 
1668        unw_cursor_t cursor;
1669        unw_context_t uc;
1670        unsigned i = 0;
1671
1672        char procname[256];
1673        unw_word_t ip, sp, off;
1674
1675        procname[sizeof(procname) - 1] = '\0';
1676
1677        if (unw_getcontext(&uc) != 0) {
1678                goto libunwind_failed;
1679        }
1680
1681        if (unw_init_local(&cursor, &uc) != 0) {
1682                goto libunwind_failed;
1683        }
1684
1685        DEBUG(0, ("BACKTRACE:\n"));
1686
1687        do {
1688            ip = sp = 0;
1689            unw_get_reg(&cursor, UNW_REG_IP, &ip);
1690            unw_get_reg(&cursor, UNW_REG_SP, &sp);
1691
1692            switch (unw_get_proc_name(&cursor,
1693                        procname, sizeof(procname) - 1, &off) ) {
1694            case 0:
1695                    /* Name found. */
1696            case -UNW_ENOMEM:
1697                    /* Name truncated. */
1698                    DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
1699                            i, procname, (long long)off,
1700                            (long long)ip, (long long) sp));
1701                    break;
1702            default:
1703            /* case -UNW_ENOINFO: */
1704            /* case -UNW_EUNSPEC: */
1705                    /* No symbol name found. */
1706                    DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
1707                            i, "<unknown symbol>",
1708                            (long long)ip, (long long) sp));
1709            }
1710            ++i;
1711        } while (unw_step(&cursor) > 0);
1712
1713        return;
1714
1715libunwind_failed:
1716        DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
1717
1718#elif HAVE_BACKTRACE_SYMBOLS
1719        void *backtrace_stack[BACKTRACE_STACK_SIZE];
1720        size_t backtrace_size;
1721        char **backtrace_strings;
1722
1723        /* get the backtrace (stack frames) */
1724        backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
1725        backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
1726
1727        DEBUG(0, ("BACKTRACE: %lu stack frames:\n", 
1728                  (unsigned long)backtrace_size));
1729       
1730        if (backtrace_strings) {
1731                int i;
1732
1733                for (i = 0; i < backtrace_size; i++)
1734                        DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
1735
1736                /* Leak the backtrace_strings, rather than risk what free() might do */
1737        }
1738
1739#elif HAVE_LIBEXC
1740
1741        /* The IRIX libexc library provides an API for unwinding the stack. See
1742         * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
1743         * since we are about to abort anyway, it hardly matters.
1744         */
1745
1746#define NAMESIZE 32 /* Arbitrary */
1747
1748        __uint64_t      addrs[BACKTRACE_STACK_SIZE];
1749        char *          names[BACKTRACE_STACK_SIZE];
1750        char            namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
1751
1752        int             i;
1753        int             levels;
1754
1755        ZERO_ARRAY(addrs);
1756        ZERO_ARRAY(names);
1757        ZERO_ARRAY(namebuf);
1758
1759        /* We need to be root so we can open our /proc entry to walk
1760         * our stack. It also helps when we want to dump core.
1761         */
1762        become_root();
1763
1764        for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
1765                names[i] = namebuf + (i * NAMESIZE);
1766        }
1767
1768        levels = trace_back_stack(0, addrs, names,
1769                        BACKTRACE_STACK_SIZE, NAMESIZE - 1);
1770
1771        DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
1772        for (i = 0; i < levels; i++) {
1773                DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
1774        }
1775#undef NAMESIZE
1776
1777#else
1778        DEBUG(0, ("unable to produce a stack trace on this platform\n"));
1779#endif
1780}
1781
1782/*******************************************************************
1783  A readdir wrapper which just returns the file name.
1784 ********************************************************************/
1785
1786const char *readdirname(SMB_STRUCT_DIR *p)
1787{
1788        SMB_STRUCT_DIRENT *ptr;
1789        char *dname;
1790
1791        if (!p)
1792                return(NULL);
1793 
1794        ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
1795        if (!ptr)
1796                return(NULL);
1797
1798        dname = ptr->d_name;
1799
1800#ifdef NEXT2
1801        if (telldir(p) < 0)
1802                return(NULL);
1803#endif
1804
1805#ifdef HAVE_BROKEN_READDIR_NAME
1806        /* using /usr/ucb/cc is BAD */
1807        dname = dname - 2;
1808#endif
1809
1810        {
1811                static pstring buf;
1812                int len = NAMLEN(ptr);
1813                memcpy(buf, dname, len);
1814                buf[len] = 0;
1815                dname = buf;
1816        }
1817
1818        return(dname);
1819}
1820
1821/*******************************************************************
1822 Utility function used to decide if the last component
1823 of a path matches a (possibly wildcarded) entry in a namelist.
1824********************************************************************/
1825
1826BOOL is_in_path(const char *name, name_compare_entry *namelist, BOOL case_sensitive)
1827{
1828        pstring last_component;
1829        char *p;
1830
1831        /* if we have no list it's obviously not in the path */
1832        if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
1833                return False;
1834        }
1835
1836        DEBUG(8, ("is_in_path: %s\n", name));
1837
1838        /* Get the last component of the unix name. */
1839        p = strrchr_m(name, '/');
1840        pstrcpy(last_component, p ? ++p : name);
1841
1842        for(; namelist->name != NULL; namelist++) {
1843                if(namelist->is_wild) {
1844                        if (mask_match(last_component, namelist->name, case_sensitive)) {
1845                                DEBUG(8,("is_in_path: mask match succeeded\n"));
1846                                return True;
1847                        }
1848                } else {
1849                        if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
1850                                                (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0))) {
1851                                DEBUG(8,("is_in_path: match succeeded\n"));
1852                                return True;
1853                        }
1854                }
1855        }
1856        DEBUG(8,("is_in_path: match not found\n"));
1857 
1858        return False;
1859}
1860
1861/*******************************************************************
1862 Strip a '/' separated list into an array of
1863 name_compare_enties structures suitable for
1864 passing to is_in_path(). We do this for
1865 speed so we can pre-parse all the names in the list
1866 and don't do it for each call to is_in_path().
1867 namelist is modified here and is assumed to be
1868 a copy owned by the caller.
1869 We also check if the entry contains a wildcard to
1870 remove a potentially expensive call to mask_match
1871 if possible.
1872********************************************************************/
1873 
1874void set_namearray(name_compare_entry **ppname_array, char *namelist)
1875{
1876        char *name_end;
1877        char *nameptr = namelist;
1878        int num_entries = 0;
1879        int i;
1880
1881        (*ppname_array) = NULL;
1882
1883        if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
1884                return;
1885
1886        /* We need to make two passes over the string. The
1887                first to count the number of elements, the second
1888                to split it.
1889        */
1890
1891        while(*nameptr) {
1892                if ( *nameptr == '/' ) {
1893                        /* cope with multiple (useless) /s) */
1894                        nameptr++;
1895                        continue;
1896                }
1897                /* find the next / */
1898                name_end = strchr_m(nameptr, '/');
1899
1900                /* oops - the last check for a / didn't find one. */
1901                if (name_end == NULL)
1902                        break;
1903
1904                /* next segment please */
1905                nameptr = name_end + 1;
1906                num_entries++;
1907        }
1908
1909        if(num_entries == 0)
1910                return;
1911
1912        if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1913                DEBUG(0,("set_namearray: malloc fail\n"));
1914                return;
1915        }
1916
1917        /* Now copy out the names */
1918        nameptr = namelist;
1919        i = 0;
1920        while(*nameptr) {
1921                if ( *nameptr == '/' ) {
1922                        /* cope with multiple (useless) /s) */
1923                        nameptr++;
1924                        continue;
1925                }
1926                /* find the next / */
1927                if ((name_end = strchr_m(nameptr, '/')) != NULL)
1928                        *name_end = 0;
1929
1930                /* oops - the last check for a / didn't find one. */
1931                if(name_end == NULL) 
1932                        break;
1933
1934                (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1935                if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1936                        DEBUG(0,("set_namearray: malloc fail (1)\n"));
1937                        return;
1938                }
1939
1940                /* next segment please */
1941                nameptr = name_end + 1;
1942                i++;
1943        }
1944 
1945        (*ppname_array)[i].name = NULL;
1946
1947        return;
1948}
1949
1950/****************************************************************************
1951 Routine to free a namearray.
1952****************************************************************************/
1953
1954void free_namearray(name_compare_entry *name_array)
1955{
1956        int i;
1957
1958        if(name_array == NULL)
1959                return;
1960
1961        for(i=0; name_array[i].name!=NULL; i++)
1962                SAFE_FREE(name_array[i].name);
1963        SAFE_FREE(name_array);
1964}
1965
1966#undef DBGC_CLASS
1967#define DBGC_CLASS DBGC_LOCKING
1968
1969/****************************************************************************
1970 Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
1971 is dealt with in posix.c
1972 Returns True if the lock was granted, False otherwise.
1973****************************************************************************/
1974
1975BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
1976{
1977        SMB_STRUCT_FLOCK lock;
1978        int ret;
1979
1980        lock.l_type = type;
1981        lock.l_whence = SEEK_SET;
1982        lock.l_start = offset;
1983        lock.l_len = count;
1984        lock.l_pid = 0;
1985#ifdef __OS2__
1986        if (op == SMB_F_GETLK)
1987        {
1988#if 0
1989                lock.l_type = F_UNLCK;
1990                int ret1 = fcntl(fd,F_SETLK,&lock);
1991                lock.l_type = type;
1992#endif
1993                int ret1 = fcntl(fd,F_SETLK,&lock);
1994                DEBUG(8,("!!!! fcntl F_SETLK %d %d %.0f %.0f %d = %d/%d\n",fd,op,(double)offset,(double)count,type, ret1, errno));
1995                lock.l_type = F_UNLCK;
1996                ret = fcntl(fd,F_SETLK,&lock);
1997                DEBUG(8,("!!!! fcntl F_SETLK2 %d %d %.0f %.0f %d = %d/%d\n",fd,op,(double)offset,(double)count,type, ret, errno));
1998                if (ret1 == -1)
1999                {
2000                        return(True);
2001                }
2002                return(False);
2003        }
2004#endif /* __OS2__ */
2005
2006        ret = sys_fcntl_ptr(fd,op,&lock);
2007
2008        DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d = %d/%d\n",fd,op,(double)offset,(double)count,type, ret, errno));
2009
2010        if (ret == -1) {
2011                int sav = errno;
2012                DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
2013                        (double)offset,(double)count,op,type,strerror(errno)));
2014                errno = sav;
2015                return False;
2016        }
2017
2018        /* everything went OK */
2019        DEBUG(8,("fcntl_lock: Lock call successful\n"));
2020
2021        return True;
2022}
2023
2024/****************************************************************************
2025 Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
2026 is dealt with in posix.c
2027 Returns True if we have information regarding this lock region (and returns
2028 F_UNLCK in *ptype if the region is unlocked). False if the call failed.
2029****************************************************************************/
2030
2031BOOL fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
2032{
2033        SMB_STRUCT_FLOCK lock;
2034        int ret;
2035
2036        DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
2037                    fd,(double)*poffset,(double)*pcount,*ptype));
2038
2039        lock.l_type = *ptype;
2040        lock.l_whence = SEEK_SET;
2041        lock.l_start = *poffset;
2042        lock.l_len = *pcount;
2043        lock.l_pid = 0;
2044
2045        ret = sys_fcntl_ptr(fd,SMB_F_GETLK,&lock);
2046
2047        if (ret == -1) {
2048                int sav = errno;
2049                DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
2050                        (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
2051                errno = sav;
2052                return False;
2053        }
2054
2055        *ptype = lock.l_type;
2056        *poffset = lock.l_start;
2057        *pcount = lock.l_len;
2058        *ppid = lock.l_pid;
2059       
2060        DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
2061                        fd, (int)lock.l_type, (unsigned int)lock.l_pid));
2062        return True;
2063}
2064
2065#undef DBGC_CLASS
2066#define DBGC_CLASS DBGC_ALL
2067
2068/*******************************************************************
2069 Is the name specified one of my netbios names.
2070 Returns true if it is equal, false otherwise.
2071********************************************************************/
2072
2073BOOL is_myname(const char *s)
2074{
2075        int n;
2076        BOOL ret = False;
2077
2078        for (n=0; my_netbios_names(n); n++) {
2079                if (strequal(my_netbios_names(n), s)) {
2080                        ret=True;
2081                        break;
2082                }
2083        }
2084        DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
2085        return(ret);
2086}
2087
2088BOOL is_myname_or_ipaddr(const char *s)
2089{
2090        fstring name, dnsname;
2091        char *servername;
2092
2093        if ( !s )
2094                return False;
2095
2096        /* santize the string from '\\name' */
2097
2098        fstrcpy( name, s );
2099
2100        servername = strrchr_m( name, '\\' );
2101        if ( !servername )
2102                servername = name;
2103        else
2104                servername++;
2105
2106        /* optimize for the common case */
2107
2108        if (strequal(servername, global_myname())) 
2109                return True;
2110
2111        /* check for an alias */
2112
2113        if (is_myname(servername))
2114                return True;
2115
2116        /* check for loopback */
2117
2118        if (strequal(servername, "127.0.0.1")) 
2119                return True;
2120
2121        if (strequal(servername, "localhost")) 
2122                return True;
2123
2124        /* maybe it's my dns name */
2125
2126        if ( get_mydnsfullname( dnsname ) )
2127                if ( strequal( servername, dnsname ) )
2128                        return True;
2129               
2130        /* handle possible CNAME records */
2131
2132        if ( !is_ipaddress( servername ) ) {
2133                /* use DNS to resolve the name, but only the first address */
2134                struct hostent *hp;
2135
2136                if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
2137                        struct in_addr return_ip;
2138                        putip( (char*)&return_ip, (char*)hp->h_addr );
2139                        fstrcpy( name, inet_ntoa( return_ip ) );
2140                        servername = name;
2141                }       
2142        }
2143               
2144        /* maybe its an IP address? */
2145        if (is_ipaddress(servername)) {
2146                struct iface_struct nics[MAX_INTERFACES];
2147                int i, n;
2148                uint32 ip;
2149               
2150                ip = interpret_addr(servername);
2151                if ((ip==0) || (ip==0xffffffff))
2152                        return False;
2153                       
2154                n = get_interfaces(nics, MAX_INTERFACES);
2155                for (i=0; i<n; i++) {
2156                        if (ip == nics[i].ip.s_addr)
2157                                return True;
2158                }
2159        }       
2160
2161        /* no match */
2162        return False;
2163}
2164
2165/*******************************************************************
2166 Is the name specified our workgroup/domain.
2167 Returns true if it is equal, false otherwise.
2168********************************************************************/
2169
2170BOOL is_myworkgroup(const char *s)
2171{
2172        BOOL ret = False;
2173
2174        if (strequal(s, lp_workgroup())) {
2175                ret=True;
2176        }
2177
2178        DEBUG(8, ("is_myworkgroup(\"%s\") returns %d\n", s, ret));
2179        return(ret);
2180}
2181
2182/*******************************************************************
2183 we distinguish between 2K and XP by the "Native Lan Manager" string
2184   WinXP => "Windows 2002 5.1"
2185   WinXP 64bit => "Windows XP 5.2"
2186   Win2k => "Windows 2000 5.0"
2187   NT4   => "Windows NT 4.0"
2188   Win9x => "Windows 4.0"
2189 Windows 2003 doesn't set the native lan manager string but
2190 they do set the domain to "Windows 2003 5.2" (probably a bug).
2191********************************************************************/
2192
2193void ra_lanman_string( const char *native_lanman )
2194{       
2195        if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
2196                set_remote_arch( RA_WINXP );
2197        else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
2198                set_remote_arch( RA_WINXP );
2199        else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
2200                set_remote_arch( RA_WIN2K3 );
2201}
2202
2203/*******************************************************************
2204 Set the horrid remote_arch string based on an enum.
2205********************************************************************/
2206
2207void set_remote_arch(enum remote_arch_types type)
2208{
2209        ra_type = type;
2210        switch( type ) {
2211        case RA_WFWG:
2212                fstrcpy(remote_arch, "WfWg");
2213                break;
2214        case RA_OS2:
2215                fstrcpy(remote_arch, "OS2");
2216                break;
2217        case RA_WIN95:
2218                fstrcpy(remote_arch, "Win95");
2219                break;
2220        case RA_WINNT:
2221                fstrcpy(remote_arch, "WinNT");
2222                break;
2223        case RA_WIN2K:
2224                fstrcpy(remote_arch, "Win2K");
2225                break;
2226        case RA_WINXP:
2227                fstrcpy(remote_arch, "WinXP");
2228                break;
2229        case RA_WIN2K3:
2230                fstrcpy(remote_arch, "Win2K3");
2231                break;
2232        case RA_VISTA:
2233                fstrcpy(remote_arch, "Vista");
2234                break;
2235        case RA_SAMBA:
2236                fstrcpy(remote_arch,"Samba");
2237                break;
2238        case RA_CIFSFS:
2239                fstrcpy(remote_arch,"CIFSFS");
2240                break;
2241        default:
2242                ra_type = RA_UNKNOWN;
2243                fstrcpy(remote_arch, "UNKNOWN");
2244                break;
2245        }
2246
2247        DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n", remote_arch));
2248}
2249
2250/*******************************************************************
2251 Get the remote_arch type.
2252********************************************************************/
2253
2254enum remote_arch_types get_remote_arch(void)
2255{
2256        return ra_type;
2257}
2258
2259void print_asc(int level, const unsigned char *buf,int len)
2260{
2261        int i;
2262        for (i=0;i<len;i++)
2263                DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
2264}
2265
2266void dump_data(int level, const char *buf1,int len)
2267{
2268        const unsigned char *buf = (const unsigned char *)buf1;
2269        int i=0;
2270        if (len<=0) return;
2271
2272        if (!DEBUGLVL(level)) return;
2273       
2274        DEBUGADD(level,("[%03X] ",i));
2275        for (i=0;i<len;) {
2276                DEBUGADD(level,("%02X ",(int)buf[i]));
2277                i++;
2278                if (i%8 == 0) DEBUGADD(level,(" "));
2279                if (i%16 == 0) {     
2280                        print_asc(level,&buf[i-16],8); DEBUGADD(level,(" "));
2281                        print_asc(level,&buf[i-8],8); DEBUGADD(level,("\n"));
2282                        if (i<len) DEBUGADD(level,("[%03X] ",i));
2283                }
2284        }
2285        if (i%16) {
2286                int n;
2287                n = 16 - (i%16);
2288                DEBUGADD(level,(" "));
2289                if (n>8) DEBUGADD(level,(" "));
2290                while (n--) DEBUGADD(level,("   "));
2291                n = MIN(8,i%16);
2292                print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,( " " ));
2293                n = (i%16) - n;
2294                if (n>0) print_asc(level,&buf[i-n],n); 
2295                DEBUGADD(level,("\n"));   
2296        }       
2297}
2298
2299void dump_data_pw(const char *msg, const uchar * data, size_t len)
2300{
2301#ifdef DEBUG_PASSWORD
2302        DEBUG(11, ("%s", msg));
2303        if (data != NULL && len > 0)
2304        {
2305                dump_data(11, (const char *)data, len);
2306        }
2307#endif
2308}
2309
2310char *tab_depth(int depth)
2311{
2312        static pstring spaces;
2313        memset(spaces, ' ', depth * 4);
2314        spaces[depth * 4] = 0;
2315        return spaces;
2316}
2317
2318/*****************************************************************************
2319 Provide a checksum on a string
2320
2321 Input:  s - the null-terminated character string for which the checksum
2322             will be calculated.
2323
2324  Output: The checksum value calculated for s.
2325*****************************************************************************/
2326
2327int str_checksum(const char *s)
2328{
2329        int res = 0;
2330        int c;
2331        int i=0;
2332       
2333        while(*s) {
2334                c = *s;
2335                res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
2336                s++;
2337                i++;
2338        }
2339        return(res);
2340}
2341
2342/*****************************************************************
2343 Zero a memory area then free it. Used to catch bugs faster.
2344*****************************************************************/ 
2345
2346void zero_free(void *p, size_t size)
2347{
2348        memset(p, 0, size);
2349        SAFE_FREE(p);
2350}
2351
2352/*****************************************************************
2353 Set our open file limit to a requested max and return the limit.
2354*****************************************************************/ 
2355
2356int set_maxfiles(int requested_max)
2357{
2358#ifndef __OS2__
2359#if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
2360        struct rlimit rlp;
2361        int saved_current_limit;
2362
2363        if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2364                DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
2365                        strerror(errno) ));
2366                /* just guess... */
2367                return requested_max;
2368        }
2369
2370        /*
2371         * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
2372         * account for the extra fd we need
2373         * as well as the log files and standard
2374         * handles etc. Save the limit we want to set in case
2375         * we are running on an OS that doesn't support this limit (AIX)
2376         * which always returns RLIM_INFINITY for rlp.rlim_max.
2377         */
2378
2379        /* Try raising the hard (max) limit to the requested amount. */
2380
2381#if defined(RLIM_INFINITY)
2382        if (rlp.rlim_max != RLIM_INFINITY) {
2383                int orig_max = rlp.rlim_max;
2384
2385                if ( rlp.rlim_max < requested_max )
2386                        rlp.rlim_max = requested_max;
2387
2388                /* This failing is not an error - many systems (Linux) don't
2389                        support our default request of 10,000 open files. JRA. */
2390
2391                if(setrlimit(RLIMIT_NOFILE, &rlp)) {
2392                        DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n", 
2393                                (int)rlp.rlim_max, strerror(errno) ));
2394
2395                        /* Set failed - restore original value from get. */
2396                        rlp.rlim_max = orig_max;
2397                }
2398        }
2399#endif
2400
2401        /* Now try setting the soft (current) limit. */
2402
2403        saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
2404
2405        if(setrlimit(RLIMIT_NOFILE, &rlp)) {
2406                DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n", 
2407                        (int)rlp.rlim_cur, strerror(errno) ));
2408                /* just guess... */
2409                return saved_current_limit;
2410        }
2411
2412        if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2413                DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
2414                        strerror(errno) ));
2415                /* just guess... */
2416                return saved_current_limit;
2417    }
2418
2419#if defined(RLIM_INFINITY)
2420        if(rlp.rlim_cur == RLIM_INFINITY)
2421                return saved_current_limit;
2422#endif
2423
2424        if((int)rlp.rlim_cur > saved_current_limit)
2425                return saved_current_limit;
2426
2427        return rlp.rlim_cur;
2428#else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
2429        /*
2430         * No way to know - just guess...
2431         */
2432        return requested_max;
2433#endif
2434#endif /* __OS2__ */
2435}
2436
2437/*****************************************************************
2438 Possibly replace mkstemp if it is broken.
2439*****************************************************************/ 
2440
2441int smb_mkstemp(char *name_template)
2442{
2443#if HAVE_SECURE_MKSTEMP
2444        return mkstemp(name_template);
2445#else
2446        /* have a reasonable go at emulating it. Hope that
2447           the system mktemp() isn't completly hopeless */
2448        char *p = mktemp(name_template);
2449        if (!p)
2450                return -1;
2451        return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
2452#endif
2453}
2454
2455/*****************************************************************
2456 malloc that aborts with smb_panic on fail or zero size.
2457 *****************************************************************/ 
2458
2459void *smb_xmalloc_array(size_t size, unsigned int count)
2460{
2461        void *p;
2462        if (size == 0)
2463                smb_panic("smb_xmalloc_array: called with zero size.\n");
2464        if (count >= MAX_ALLOC_SIZE/size) {
2465                smb_panic("smb_xmalloc: alloc size too large.\n");
2466        }
2467        if ((p = SMB_MALLOC(size*count)) == NULL) {
2468                DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
2469                        (unsigned long)size, (unsigned long)count));
2470                smb_panic("smb_xmalloc_array: malloc fail.\n");
2471        }
2472        return p;
2473}
2474
2475/**
2476 Memdup with smb_panic on fail.
2477**/
2478
2479void *smb_xmemdup(const void *p, size_t size)
2480{
2481        void *p2;
2482        p2 = SMB_XMALLOC_ARRAY(unsigned char,size);
2483        memcpy(p2, p, size);
2484        return p2;
2485}
2486
2487/**
2488 strdup that aborts on malloc fail.
2489**/
2490
2491char *smb_xstrdup(const char *s)
2492{
2493#if defined(PARANOID_MALLOC_CHECKER)
2494#ifdef strdup
2495#undef strdup
2496#endif
2497#endif
2498
2499#ifndef HAVE_STRDUP
2500#define strdup rep_strdup
2501#endif
2502
2503        char *s1 = strdup(s);
2504#if defined(PARANOID_MALLOC_CHECKER)
2505#ifdef strdup
2506#undef strdup
2507#endif
2508#define strdup(s) __ERROR_DONT_USE_STRDUP_DIRECTLY
2509#endif
2510        if (!s1)
2511                smb_panic("smb_xstrdup: malloc fail\n");
2512        return s1;
2513
2514}
2515
2516/**
2517 strndup that aborts on malloc fail.
2518**/
2519
2520char *smb_xstrndup(const char *s, size_t n)
2521{
2522#if defined(PARANOID_MALLOC_CHECKER)
2523#ifdef strndup
2524#undef strndup
2525#endif
2526#endif
2527
2528#if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP))
2529#undef HAVE_STRNDUP
2530#define strndup rep_strndup
2531#endif
2532
2533        char *s1 = strndup(s, n);
2534#if defined(PARANOID_MALLOC_CHECKER)
2535#ifdef strndup
2536#undef strndup
2537#endif
2538#define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY
2539#endif
2540        if (!s1)
2541                smb_panic("smb_xstrndup: malloc fail\n");
2542        return s1;
2543}
2544
2545/*
2546  vasprintf that aborts on malloc fail
2547*/
2548
2549 int smb_xvasprintf(char **ptr, const char *format, va_list ap)
2550{
2551        int n;
2552        va_list ap2;
2553
2554        VA_COPY(ap2, ap);
2555
2556        n = vasprintf(ptr, format, ap2);
2557        if (n == -1 || ! *ptr)
2558                smb_panic("smb_xvasprintf: out of memory");
2559        return n;
2560}
2561
2562/*****************************************************************
2563 Like strdup but for memory.
2564*****************************************************************/ 
2565
2566void *memdup(const void *p, size_t size)
2567{
2568        void *p2;
2569        if (size == 0)
2570                return NULL;
2571        p2 = SMB_MALLOC(size);
2572        if (!p2)
2573                return NULL;
2574        memcpy(p2, p, size);
2575        return p2;
2576}
2577
2578/*****************************************************************
2579 Get local hostname and cache result.
2580*****************************************************************/ 
2581
2582char *myhostname(void)
2583{
2584        static pstring ret;
2585        if (ret[0] == 0)
2586                get_myname(ret);
2587        return ret;
2588}
2589
2590/*****************************************************************
2591 A useful function for returning a path in the Samba lock directory.
2592*****************************************************************/ 
2593
2594char *lock_path(const char *name)
2595{
2596        static pstring fname;
2597
2598        pstrcpy(fname,lp_lockdir());
2599        trim_char(fname,'\0','/');
2600       
2601        if (!directory_exist(fname,NULL))
2602                mkdir(fname,0755);
2603       
2604        pstrcat(fname,"/");
2605        pstrcat(fname,name);
2606
2607        return fname;
2608}
2609
2610/*****************************************************************
2611 A useful function for returning a path in the Samba pid directory.
2612*****************************************************************/
2613
2614char *pid_path(const char *name)
2615{
2616        static pstring fname;
2617
2618        pstrcpy(fname,lp_piddir());
2619        trim_char(fname,'\0','/');
2620
2621        if (!directory_exist(fname,NULL))
2622                mkdir(fname,0755);
2623
2624        pstrcat(fname,"/");
2625        pstrcat(fname,name);
2626
2627        return fname;
2628}
2629
2630/**
2631 * @brief Returns an absolute path to a file in the Samba lib directory.
2632 *
2633 * @param name File to find, relative to LIBDIR.
2634 *
2635 * @retval Pointer to a static #pstring containing the full path.
2636 **/
2637
2638char *lib_path(const char *name)
2639{
2640        static pstring fname;
2641        fstr_sprintf(fname, "%s/%s", dyn_LIBDIR, name);
2642        return fname;
2643}
2644
2645/**
2646 * @brief Returns the platform specific shared library extension.
2647 *
2648 * @retval Pointer to a static #fstring containing the extension.
2649 **/
2650
2651const char *shlib_ext(void)
2652{
2653  return dyn_SHLIBEXT;
2654}
2655
2656/*******************************************************************
2657 Given a filename - get its directory name
2658 NB: Returned in static storage.  Caveats:
2659 o  Not safe in thread environment.
2660 o  Caller must not free.
2661 o  If caller wishes to preserve, they should copy.
2662********************************************************************/
2663
2664char *parent_dirname(const char *path)
2665{
2666        static pstring dirpath;
2667        char *p;
2668
2669        if (!path)
2670                return(NULL);
2671
2672        pstrcpy(dirpath, path);
2673        p = strrchr_m(dirpath, '/');  /* Find final '/', if any */
2674        if (!p) {
2675                pstrcpy(dirpath, ".");    /* No final "/", so dir is "." */
2676        } else {
2677                if (p == dirpath)
2678                        ++p;    /* For root "/", leave "/" in place */
2679                *p = '\0';
2680        }
2681        return dirpath;
2682}
2683
2684BOOL parent_dirname_talloc(TALLOC_CTX *mem_ctx, const char *dir,
2685                           char **parent, const char **name)
2686{
2687        char *p;
2688        ptrdiff_t len;
2689 
2690        p = strrchr_m(dir, '/'); /* Find final '/', if any */
2691
2692        if (p == NULL) {
2693                if (!(*parent = talloc_strdup(mem_ctx, "."))) {
2694                        return False;
2695                }
2696                if (name) {
2697                        *name = "";
2698                }
2699                return True;
2700        }
2701
2702        len = p-dir;
2703
2704        if (!(*parent = TALLOC_ARRAY(mem_ctx, char, len+1))) {
2705                return False;
2706        }
2707        memcpy(*parent, dir, len);
2708        (*parent)[len] = '\0';
2709
2710        if (name) {
2711                *name = p+1;
2712        }
2713        return True;
2714}
2715
2716/*******************************************************************
2717 Determine if a pattern contains any Microsoft wildcard characters.
2718*******************************************************************/
2719
2720BOOL ms_has_wild(const char *s)
2721{
2722        char c;
2723
2724        if (lp_posix_pathnames()) {
2725                /* With posix pathnames no characters are wild. */
2726                return False;
2727        }
2728
2729        while ((c = *s++)) {
2730                switch (c) {
2731                case '*':
2732                case '?':
2733                case '<':
2734                case '>':
2735                case '"':
2736                        return True;
2737                }
2738        }
2739        return False;
2740}
2741
2742BOOL ms_has_wild_w(const smb_ucs2_t *s)
2743{
2744        smb_ucs2_t c;
2745        if (!s) return False;
2746        while ((c = *s++)) {
2747                switch (c) {
2748                case UCS2_CHAR('*'):
2749                case UCS2_CHAR('?'):
2750                case UCS2_CHAR('<'):
2751                case UCS2_CHAR('>'):
2752                case UCS2_CHAR('"'):
2753                        return True;
2754                }
2755        }
2756        return False;
2757}
2758
2759/*******************************************************************
2760 A wrapper that handles case sensitivity and the special handling
2761 of the ".." name.
2762*******************************************************************/
2763
2764BOOL mask_match(const char *string, char *pattern, BOOL is_case_sensitive)
2765{
2766        if (strcmp(string,"..") == 0)
2767                string = ".";
2768        if (strcmp(pattern,".") == 0)
2769                return False;
2770       
2771        return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
2772}
2773
2774/*******************************************************************
2775 A wrapper that handles case sensitivity and the special handling
2776 of the ".." name. Varient that is only called by old search code which requires
2777 pattern translation.
2778*******************************************************************/
2779
2780BOOL mask_match_search(const char *string, char *pattern, BOOL is_case_sensitive)
2781{
2782        if (strcmp(string,"..") == 0)
2783                string = ".";
2784        if (strcmp(pattern,".") == 0)
2785                return False;
2786       
2787        return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
2788}
2789
2790/*******************************************************************
2791 A wrapper that handles a list of patters and calls mask_match()
2792 on each.  Returns True if any of the patterns match.
2793*******************************************************************/
2794
2795BOOL mask_match_list(const char *string, char **list, int listLen, BOOL is_case_sensitive)
2796{
2797       while (listLen-- > 0) {
2798               if (mask_match(string, *list++, is_case_sensitive))
2799                       return True;
2800       }
2801       return False;
2802}
2803
2804/*********************************************************
2805 Recursive routine that is called by unix_wild_match.
2806*********************************************************/
2807
2808static BOOL unix_do_match(const char *regexp, const char *str)
2809{
2810        const char *p;
2811
2812        for( p = regexp; *p && *str; ) {
2813
2814                switch(*p) {
2815                        case '?':
2816                                str++;
2817                                p++;
2818                                break;
2819
2820                        case '*':
2821
2822                                /*
2823                                 * Look for a character matching
2824                                 * the one after the '*'.
2825                                 */
2826                                p++;
2827                                if(!*p)
2828                                        return True; /* Automatic match */
2829                                while(*str) {
2830
2831                                        while(*str && (*p != *str))
2832                                                str++;
2833
2834                                        /*
2835                                         * Patch from weidel@multichart.de. In the case of the regexp
2836                                         * '*XX*' we want to ensure there are at least 2 'X' characters
2837                                         * in the string after the '*' for a match to be made.
2838                                         */
2839
2840                                        {
2841                                                int matchcount=0;
2842
2843                                                /*
2844                                                 * Eat all the characters that match, but count how many there were.
2845                                                 */
2846
2847                                                while(*str && (*p == *str)) {
2848                                                        str++;
2849                                                        matchcount++;
2850                                                }
2851
2852                                                /*
2853                                                 * Now check that if the regexp had n identical characters that
2854                                                 * matchcount had at least that many matches.
2855                                                 */
2856
2857                                                while ( *(p+1) && (*(p+1) == *p)) {
2858                                                        p++;
2859                                                        matchcount--;
2860                                                }
2861
2862                                                if ( matchcount <= 0 )
2863                                                        return False;
2864                                        }
2865
2866                                        str--; /* We've eaten the match char after the '*' */
2867
2868                                        if(unix_do_match(p, str))
2869                                                return True;
2870
2871                                        if(!*str)
2872                                                return False;
2873                                        else
2874                                                str++;
2875                                }
2876                                return False;
2877
2878                        default:
2879                                if(*str != *p)
2880                                        return False;
2881                                str++;
2882                                p++;
2883                                break;
2884                }
2885        }
2886
2887        if(!*p && !*str)
2888                return True;
2889
2890        if (!*p && str[0] == '.' && str[1] == 0)
2891                return(True);
2892 
2893        if (!*str && *p == '?') {
2894                while (*p == '?')
2895                        p++;
2896                return(!*p);
2897        }
2898
2899        if(!*str && (*p == '*' && p[1] == '\0'))
2900                return True;
2901
2902        return False;
2903}
2904
2905/*******************************************************************
2906 Simple case insensitive interface to a UNIX wildcard matcher.
2907 Returns True if match, False if not.
2908*******************************************************************/
2909
2910BOOL unix_wild_match(const char *pattern, const char *string)
2911{
2912        pstring p2, s2;
2913        char *p;
2914
2915        pstrcpy(p2, pattern);
2916        pstrcpy(s2, string);
2917        strlower_m(p2);
2918        strlower_m(s2);
2919
2920        /* Remove any *? and ** from the pattern as they are meaningless */
2921        for(p = p2; *p; p++)
2922                while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
2923                        pstrcpy( &p[1], &p[2]);
2924 
2925        if (strequal(p2,"*"))
2926                return True;
2927
2928        return unix_do_match(p2, s2);
2929}
2930
2931/**********************************************************************
2932 Converts a name to a fully qualified domain name.
2933 Returns True if lookup succeeded, False if not (then fqdn is set to name)
2934***********************************************************************/
2935                                                                                                                                                   
2936BOOL name_to_fqdn(fstring fqdn, const char *name)
2937{
2938        struct hostent *hp = sys_gethostbyname(name);
2939
2940        if ( hp && hp->h_name && *hp->h_name ) {
2941                char *full = NULL;
2942
2943                /* find out if the fqdn is returned as an alias
2944                 * to cope with /etc/hosts files where the first
2945                 * name is not the fqdn but the short name */
2946                if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
2947                        int i;
2948                        for (i = 0; hp->h_aliases[i]; i++) {
2949                                if (strchr_m(hp->h_aliases[i], '.')) {
2950                                        full = hp->h_aliases[i];
2951                                        break;
2952                                }
2953                        }
2954                }
2955                if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) {
2956                        DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
2957                        DEBUGADD(1, ("    Specifing the machine hostname for address 127.0.0.1 may lead\n"));
2958                        DEBUGADD(1, ("    to Kerberos authentication problems as localhost.localdomain\n"));
2959                        DEBUGADD(1, ("    may end up being used instead of the real machine FQDN.\n"));
2960                        full = hp->h_name;
2961                }
2962                       
2963                if (!full) {
2964                        full = hp->h_name;
2965                }
2966
2967                DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
2968                fstrcpy(fqdn, full);
2969                return True;
2970        } else {
2971                DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
2972                fstrcpy(fqdn, name);
2973                return False;
2974        }
2975}
2976
2977/**********************************************************************
2978 Extension to talloc_get_type: Abort on type mismatch
2979***********************************************************************/
2980
2981void *talloc_check_name_abort(const void *ptr, const char *name)
2982{
2983        void *result;
2984
2985        result = talloc_check_name(ptr, name);
2986        if (result != NULL)
2987                return result;
2988
2989        DEBUG(0, ("Talloc type mismatch, expected %s, got %s\n",
2990                  name, talloc_get_name(ptr)));
2991        smb_panic("aborting");
2992        /* Keep the compiler happy */
2993        return NULL;
2994}
2995
2996
2997#ifdef __INSURE__
2998
2999/*******************************************************************
3000This routine is a trick to immediately catch errors when debugging
3001with insure. A xterm with a gdb is popped up when insure catches
3002a error. It is Linux specific.
3003********************************************************************/
3004
3005int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
3006{
3007        static int (*fn)();
3008        int ret;
3009        char pidstr[10];
3010        /* you can get /usr/bin/backtrace from
3011           http://samba.org/ftp/unpacked/junkcode/backtrace */
3012        pstring cmd = "/usr/bin/backtrace %d";
3013
3014        slprintf(pidstr, sizeof(pidstr)-1, "%d", sys_getpid());
3015        pstring_sub(cmd, "%d", pidstr);
3016
3017        if (!fn) {
3018                static void *h;
3019                h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
3020                fn = dlsym(h, "_Insure_trap_error");
3021
3022                if (!h || h == _Insure_trap_error) {
3023                        h = dlopen("/usr/local/parasoft/lib.linux2/libinsure.so", RTLD_LAZY);
3024                        fn = dlsym(h, "_Insure_trap_error");
3025                }               
3026        }
3027
3028        ret = fn(a1, a2, a3, a4, a5, a6);
3029
3030        system(cmd);
3031
3032        return ret;
3033}
3034#endif
3035
3036uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
3037{
3038        switch (share_access & ~FILE_SHARE_DELETE) {
3039                case FILE_SHARE_NONE:
3040                        return DENY_ALL;
3041                case FILE_SHARE_READ:
3042                        return DENY_WRITE;
3043                case FILE_SHARE_WRITE:
3044                        return DENY_READ;
3045                case FILE_SHARE_READ|FILE_SHARE_WRITE:
3046                        return DENY_NONE;
3047        }
3048        if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
3049                return DENY_DOS;
3050        } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
3051                return DENY_FCB;
3052        }
3053
3054        return (uint32)-1;
3055}
3056
3057pid_t procid_to_pid(const struct process_id *proc)
3058{
3059        return proc->pid;
3060}
3061
3062struct process_id pid_to_procid(pid_t pid)
3063{
3064        struct process_id result;
3065        result.pid = pid;
3066        return result;
3067}
3068
3069struct process_id procid_self(void)
3070{
3071        return pid_to_procid(sys_getpid());
3072}
3073
3074struct server_id server_id_self(void)
3075{
3076        struct server_id id;
3077        id.id = procid_self();
3078        return id;
3079}
3080
3081BOOL procid_equal(const struct process_id *p1, const struct process_id *p2)
3082{
3083        return (p1->pid == p2->pid);
3084}
3085
3086BOOL cluster_id_equal(const struct server_id *id1,
3087                      const struct server_id *id2)
3088{
3089        return procid_equal(&id1->id, &id2->id);
3090}
3091
3092BOOL procid_is_me(const struct process_id *pid)
3093{
3094        return (pid->pid == sys_getpid());
3095}
3096
3097struct process_id interpret_pid(const char *pid_string)
3098{
3099        return pid_to_procid(atoi(pid_string));
3100}
3101
3102char *procid_str_static(const struct process_id *pid)
3103{
3104        static fstring str;
3105        fstr_sprintf(str, "%d", pid->pid);
3106        return str;
3107}
3108
3109char *procid_str(TALLOC_CTX *mem_ctx, const struct process_id *pid)
3110{
3111        return talloc_strdup(mem_ctx, procid_str_static(pid));
3112}
3113
3114BOOL procid_valid(const struct process_id *pid)
3115{
3116        return (pid->pid != -1);
3117}
3118
3119BOOL procid_is_local(const struct process_id *pid)
3120{
3121        return True;
3122}
3123
3124int this_is_smp(void)
3125{
3126#if defined(HAVE_SYSCONF)
3127
3128#if defined(SYSCONF_SC_NPROC_ONLN)
3129        return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0;
3130#elif defined(SYSCONF_SC_NPROCESSORS_ONLN)
3131        return (sysconf(_SC_NPROCESSORS_ONLN) > 1) ? 1 : 0;
3132#else
3133        return 0;
3134#endif
3135
3136#else
3137        return 0;
3138#endif
3139}
3140
3141/****************************************************************
3142 Check if an offset into a buffer is safe.
3143 If this returns True it's safe to indirect into the byte at
3144 pointer ptr+off.
3145****************************************************************/
3146
3147BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
3148{
3149        const char *end_base = buf_base + buf_len;
3150        char *end_ptr = ptr + off;
3151
3152        if (!buf_base || !ptr) {
3153                return False;
3154        }
3155
3156        if (end_base < buf_base || end_ptr < ptr) {
3157                return False; /* wrap. */
3158        }
3159
3160        if (end_ptr < end_base) {
3161                return True;
3162        }
3163        return False;
3164}
3165
3166/****************************************************************
3167 Return a safe pointer into a buffer, or NULL.
3168****************************************************************/
3169
3170char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
3171{
3172        return is_offset_safe(buf_base, buf_len, ptr, off) ?
3173                        ptr + off : NULL;
3174}
3175
3176/****************************************************************
3177 Return a safe pointer into a string within a buffer, or NULL.
3178****************************************************************/
3179
3180char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
3181{
3182        if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
3183                return NULL;
3184        }
3185        /* Check if a valid string exists at this offset. */
3186        if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
3187                return NULL;
3188        }
3189        return ptr + off;
3190}
3191
3192/****************************************************************
3193 Return an SVAL at a pointer, or failval if beyond the end.
3194****************************************************************/
3195
3196int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
3197{
3198        /*
3199         * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
3200         * NOT ptr[2].
3201         */
3202        if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
3203                return failval;
3204        }
3205        return SVAL(ptr,off);
3206}
3207
3208/****************************************************************
3209 Return an IVAL at a pointer, or failval if beyond the end.
3210****************************************************************/
3211
3212int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
3213{
3214        /*
3215         * Note we use off+3 here, not off+4 as IVAL accesses
3216         * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
3217         */
3218        if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
3219                return failval;
3220        }
3221        return IVAL(ptr,off);
3222}
Note: See TracBrowser for help on using the repository browser.