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