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