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