Make use of TALLOC_MEMDUP in parent_dirname_talloc()
[obnox/samba-ctdb.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                        bool parent_longlived)
953 {
954         NTSTATUS status;
955
956         /* Reset the state of the random
957          * number generation system, so
958          * children do not get the same random
959          * numbers as each other */
960         set_need_random_reseed();
961
962         /* tdb needs special fork handling */
963         if (tdb_reopen_all(parent_longlived ? 1 : 0) == -1) {
964                 DEBUG(0,("tdb_reopen_all failed.\n"));
965                 return false;
966         }
967
968         /*
969          * For clustering, we need to re-init our ctdbd connection after the
970          * fork
971          */
972         status = messaging_reinit(msg_ctx);
973         if (!NT_STATUS_IS_OK(status)) {
974                 DEBUG(0,("messaging_reinit() failed: %s\n",
975                          nt_errstr(status)));
976                 return false;
977         }
978
979         return true;
980 }
981
982 /****************************************************************************
983  Put up a yes/no prompt.
984 ****************************************************************************/
985
986 bool yesno(const char *p)
987 {
988         char ans[20];
989         printf("%s",p);
990
991         if (!fgets(ans,sizeof(ans)-1,stdin))
992                 return(False);
993
994         if (*ans == 'y' || *ans == 'Y')
995                 return(True);
996
997         return(False);
998 }
999
1000 #if defined(PARANOID_MALLOC_CHECKER)
1001
1002 /****************************************************************************
1003  Internal malloc wrapper. Externally visible.
1004 ****************************************************************************/
1005
1006 void *malloc_(size_t size)
1007 {
1008         if (size == 0) {
1009                 return NULL;
1010         }
1011 #undef malloc
1012         return malloc(size);
1013 #define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
1014 }
1015
1016 /****************************************************************************
1017  Internal calloc wrapper. Not externally visible.
1018 ****************************************************************************/
1019
1020 static void *calloc_(size_t count, size_t size)
1021 {
1022         if (size == 0 || count == 0) {
1023                 return NULL;
1024         }
1025 #undef calloc
1026         return calloc(count, size);
1027 #define calloc(n,s) __ERROR_DONT_USE_CALLOC_DIRECTLY
1028 }
1029
1030 /****************************************************************************
1031  Internal realloc wrapper. Not externally visible.
1032 ****************************************************************************/
1033
1034 static void *realloc_(void *ptr, size_t size)
1035 {
1036 #undef realloc
1037         return realloc(ptr, size);
1038 #define realloc(p,s) __ERROR_DONT_USE_RELLOC_DIRECTLY
1039 }
1040
1041 #endif /* PARANOID_MALLOC_CHECKER */
1042
1043 /****************************************************************************
1044  Type-safe memalign
1045 ****************************************************************************/
1046
1047 void *memalign_array(size_t el_size, size_t align, unsigned int count)
1048 {
1049         if (count >= MAX_ALLOC_SIZE/el_size) {
1050                 return NULL;
1051         }
1052
1053         return sys_memalign(align, el_size*count);
1054 }
1055
1056 /****************************************************************************
1057  Type-safe calloc.
1058 ****************************************************************************/
1059
1060 void *calloc_array(size_t size, size_t nmemb)
1061 {
1062         if (nmemb >= MAX_ALLOC_SIZE/size) {
1063                 return NULL;
1064         }
1065         if (size == 0 || nmemb == 0) {
1066                 return NULL;
1067         }
1068 #if defined(PARANOID_MALLOC_CHECKER)
1069         return calloc_(nmemb, size);
1070 #else
1071         return calloc(nmemb, size);
1072 #endif
1073 }
1074
1075 /****************************************************************************
1076  Expand a pointer to be a particular size.
1077  Note that this version of Realloc has an extra parameter that decides
1078  whether to free the passed in storage on allocation failure or if the
1079  new size is zero.
1080
1081  This is designed for use in the typical idiom of :
1082
1083  p = SMB_REALLOC(p, size)
1084  if (!p) {
1085     return error;
1086  }
1087
1088  and not to have to keep track of the old 'p' contents to free later, nor
1089  to worry if the size parameter was zero. In the case where NULL is returned
1090  we guarentee that p has been freed.
1091
1092  If free later semantics are desired, then pass 'free_old_on_error' as False which
1093  guarentees that the old contents are not freed on error, even if size == 0. To use
1094  this idiom use :
1095
1096  tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
1097  if (!tmp) {
1098     SAFE_FREE(p);
1099     return error;
1100  } else {
1101     p = tmp;
1102  }
1103
1104  Changes were instigated by Coverity error checking. JRA.
1105 ****************************************************************************/
1106
1107 void *Realloc(void *p, size_t size, bool free_old_on_error)
1108 {
1109         void *ret=NULL;
1110
1111         if (size == 0) {
1112                 if (free_old_on_error) {
1113                         SAFE_FREE(p);
1114                 }
1115                 DEBUG(2,("Realloc asked for 0 bytes\n"));
1116                 return NULL;
1117         }
1118
1119 #if defined(PARANOID_MALLOC_CHECKER)
1120         if (!p) {
1121                 ret = (void *)malloc_(size);
1122         } else {
1123                 ret = (void *)realloc_(p,size);
1124         }
1125 #else
1126         if (!p) {
1127                 ret = (void *)malloc(size);
1128         } else {
1129                 ret = (void *)realloc(p,size);
1130         }
1131 #endif
1132
1133         if (!ret) {
1134                 if (free_old_on_error && p) {
1135                         SAFE_FREE(p);
1136                 }
1137                 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
1138         }
1139
1140         return(ret);
1141 }
1142
1143 /****************************************************************************
1144  (Hopefully) efficient array append.
1145 ****************************************************************************/
1146
1147 void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
1148                         void *element, void *_array, uint32 *num_elements,
1149                         ssize_t *array_size)
1150 {
1151         void **array = (void **)_array;
1152
1153         if (*array_size < 0) {
1154                 return;
1155         }
1156
1157         if (*array == NULL) {
1158                 if (*array_size == 0) {
1159                         *array_size = 128;
1160                 }
1161
1162                 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
1163                         goto error;
1164                 }
1165
1166                 *array = TALLOC(mem_ctx, element_size * (*array_size));
1167                 if (*array == NULL) {
1168                         goto error;
1169                 }
1170         }
1171
1172         if (*num_elements == *array_size) {
1173                 *array_size *= 2;
1174
1175                 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
1176                         goto error;
1177                 }
1178
1179                 *array = TALLOC_REALLOC(mem_ctx, *array,
1180                                         element_size * (*array_size));
1181
1182                 if (*array == NULL) {
1183                         goto error;
1184                 }
1185         }
1186
1187         memcpy((char *)(*array) + element_size*(*num_elements),
1188                element, element_size);
1189         *num_elements += 1;
1190
1191         return;
1192
1193  error:
1194         *num_elements = 0;
1195         *array_size = -1;
1196 }
1197
1198 /****************************************************************************
1199  Get my own name and IP.
1200 ****************************************************************************/
1201
1202 char *talloc_get_myname(TALLOC_CTX *ctx)
1203 {
1204         char *p;
1205         char hostname[HOST_NAME_MAX];
1206
1207         *hostname = 0;
1208
1209         /* get my host name */
1210         if (gethostname(hostname, sizeof(hostname)) == -1) {
1211                 DEBUG(0,("gethostname failed\n"));
1212                 return False;
1213         }
1214
1215         /* Ensure null termination. */
1216         hostname[sizeof(hostname)-1] = '\0';
1217
1218         /* split off any parts after an initial . */
1219         p = strchr_m(hostname,'.');
1220         if (p) {
1221                 *p = 0;
1222         }
1223
1224         return talloc_strdup(ctx, hostname);
1225 }
1226
1227 /****************************************************************************
1228  Get my own domain name, or "" if we have none.
1229 ****************************************************************************/
1230
1231 char *get_mydnsdomname(TALLOC_CTX *ctx)
1232 {
1233         const char *domname;
1234         char *p;
1235
1236         domname = get_mydnsfullname();
1237         if (!domname) {
1238                 return NULL;
1239         }
1240
1241         p = strchr_m(domname, '.');
1242         if (p) {
1243                 p++;
1244                 return talloc_strdup(ctx, p);
1245         } else {
1246                 return talloc_strdup(ctx, "");
1247         }
1248 }
1249
1250 /****************************************************************************
1251  Interpret a protocol description string, with a default.
1252 ****************************************************************************/
1253
1254 int interpret_protocol(const char *str,int def)
1255 {
1256         if (strequal(str,"NT1"))
1257                 return(PROTOCOL_NT1);
1258         if (strequal(str,"LANMAN2"))
1259                 return(PROTOCOL_LANMAN2);
1260         if (strequal(str,"LANMAN1"))
1261                 return(PROTOCOL_LANMAN1);
1262         if (strequal(str,"CORE"))
1263                 return(PROTOCOL_CORE);
1264         if (strequal(str,"COREPLUS"))
1265                 return(PROTOCOL_COREPLUS);
1266         if (strequal(str,"CORE+"))
1267                 return(PROTOCOL_COREPLUS);
1268   
1269         DEBUG(0,("Unrecognised protocol level %s\n",str));
1270   
1271         return(def);
1272 }
1273
1274
1275 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1276 /******************************************************************
1277  Remove any mount options such as -rsize=2048,wsize=2048 etc.
1278  Based on a fix from <Thomas.Hepper@icem.de>.
1279  Returns a malloc'ed string.
1280 *******************************************************************/
1281
1282 static char *strip_mount_options(TALLOC_CTX *ctx, const char *str)
1283 {
1284         if (*str == '-') {
1285                 const char *p = str;
1286                 while(*p && !isspace(*p))
1287                         p++;
1288                 while(*p && isspace(*p))
1289                         p++;
1290                 if(*p) {
1291                         return talloc_strdup(ctx, p);
1292                 }
1293         }
1294         return NULL;
1295 }
1296
1297 /*******************************************************************
1298  Patch from jkf@soton.ac.uk
1299  Split Luke's automount_server into YP lookup and string splitter
1300  so can easily implement automount_path().
1301  Returns a malloc'ed string.
1302 *******************************************************************/
1303
1304 #ifdef WITH_NISPLUS_HOME
1305 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
1306 {
1307         char *value = NULL;
1308
1309         char *nis_map = (char *)lp_nis_home_map_name();
1310
1311         char buffer[NIS_MAXATTRVAL + 1];
1312         nis_result *result;
1313         nis_object *object;
1314         entry_obj  *entry;
1315
1316         snprintf(buffer, sizeof(buffer), "[key=%s],%s", user_name, nis_map);
1317         DEBUG(5, ("NIS+ querystring: %s\n", buffer));
1318
1319         if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
1320                 if (result->status != NIS_SUCCESS) {
1321                         DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
1322                 } else {
1323                         object = result->objects.objects_val;
1324                         if (object->zo_data.zo_type == ENTRY_OBJ) {
1325                                 entry = &object->zo_data.objdata_u.en_data;
1326                                 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
1327                                 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
1328
1329                                 value = talloc_strdup(ctx,
1330                                                 entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
1331                                 if (!value) {
1332                                         nis_freeresult(result);
1333                                         return NULL;
1334                                 }
1335                                 value = talloc_string_sub(ctx,
1336                                                 value,
1337                                                 "&",
1338                                                 user_name);
1339                         }
1340                 }
1341         }
1342         nis_freeresult(result);
1343
1344         if (value) {
1345                 value = strip_mount_options(ctx, value);
1346                 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n",
1347                                         user_name, value));
1348         }
1349         return value;
1350 }
1351 #else /* WITH_NISPLUS_HOME */
1352
1353 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
1354 {
1355         char *value = NULL;
1356
1357         int nis_error;        /* returned by yp all functions */
1358         char *nis_result;     /* yp_match inits this */
1359         int nis_result_len;  /* and set this */
1360         char *nis_domain;     /* yp_get_default_domain inits this */
1361         char *nis_map = (char *)lp_nis_home_map_name();
1362
1363         if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
1364                 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
1365                 return NULL;
1366         }
1367
1368         DEBUG(5, ("NIS Domain: %s\n", nis_domain));
1369
1370         if ((nis_error = yp_match(nis_domain, nis_map, user_name,
1371                                         strlen(user_name), &nis_result,
1372                                         &nis_result_len)) == 0) {
1373                 value = talloc_strdup(ctx, nis_result);
1374                 if (!value) {
1375                         return NULL;
1376                 }
1377                 value = strip_mount_options(ctx, value);
1378         } else if(nis_error == YPERR_KEY) {
1379                 DEBUG(3, ("YP Key not found:  while looking up \"%s\" in map \"%s\"\n", 
1380                                 user_name, nis_map));
1381                 DEBUG(3, ("using defaults for server and home directory\n"));
1382         } else {
1383                 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n", 
1384                                 yperr_string(nis_error), user_name, nis_map));
1385         }
1386
1387         if (value) {
1388                 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, value));
1389         }
1390         return value;
1391 }
1392 #endif /* WITH_NISPLUS_HOME */
1393 #endif
1394
1395 /****************************************************************************
1396  Check if a process exists. Does this work on all unixes?
1397 ****************************************************************************/
1398
1399 bool process_exists(const struct server_id pid)
1400 {
1401         if (procid_is_me(&pid)) {
1402                 return True;
1403         }
1404
1405         if (procid_is_local(&pid)) {
1406                 return (kill(pid.pid,0) == 0 || errno != ESRCH);
1407         }
1408
1409 #ifdef CLUSTER_SUPPORT
1410         return ctdbd_process_exists(messaging_ctdbd_connection(), pid.vnn,
1411                                     pid.pid);
1412 #else
1413         return False;
1414 #endif
1415 }
1416
1417 /*******************************************************************
1418  Convert a uid into a user name.
1419 ********************************************************************/
1420
1421 const char *uidtoname(uid_t uid)
1422 {
1423         TALLOC_CTX *ctx = talloc_tos();
1424         char *name = NULL;
1425         struct passwd *pass = NULL;
1426
1427         pass = getpwuid_alloc(ctx,uid);
1428         if (pass) {
1429                 name = talloc_strdup(ctx,pass->pw_name);
1430                 TALLOC_FREE(pass);
1431         } else {
1432                 name = talloc_asprintf(ctx,
1433                                 "%ld",
1434                                 (long int)uid);
1435         }
1436         return name;
1437 }
1438
1439 /*******************************************************************
1440  Convert a gid into a group name.
1441 ********************************************************************/
1442
1443 char *gidtoname(gid_t gid)
1444 {
1445         struct group *grp;
1446
1447         grp = getgrgid(gid);
1448         if (grp) {
1449                 return talloc_strdup(talloc_tos(), grp->gr_name);
1450         }
1451         else {
1452                 return talloc_asprintf(talloc_tos(),
1453                                         "%d",
1454                                         (int)gid);
1455         }
1456 }
1457
1458 /*******************************************************************
1459  Convert a user name into a uid.
1460 ********************************************************************/
1461
1462 uid_t nametouid(const char *name)
1463 {
1464         struct passwd *pass;
1465         char *p;
1466         uid_t u;
1467
1468         pass = getpwnam_alloc(talloc_autofree_context(), name);
1469         if (pass) {
1470                 u = pass->pw_uid;
1471                 TALLOC_FREE(pass);
1472                 return u;
1473         }
1474
1475         u = (uid_t)strtol(name, &p, 0);
1476         if ((p != name) && (*p == '\0'))
1477                 return u;
1478
1479         return (uid_t)-1;
1480 }
1481
1482 /*******************************************************************
1483  Convert a name to a gid_t if possible. Return -1 if not a group. 
1484 ********************************************************************/
1485
1486 gid_t nametogid(const char *name)
1487 {
1488         struct group *grp;
1489         char *p;
1490         gid_t g;
1491
1492         g = (gid_t)strtol(name, &p, 0);
1493         if ((p != name) && (*p == '\0'))
1494                 return g;
1495
1496         grp = sys_getgrnam(name);
1497         if (grp)
1498                 return(grp->gr_gid);
1499         return (gid_t)-1;
1500 }
1501
1502 /*******************************************************************
1503  Something really nasty happened - panic !
1504 ********************************************************************/
1505
1506 void smb_panic(const char *const why)
1507 {
1508         char *cmd;
1509         int result;
1510
1511 #ifdef DEVELOPER
1512         {
1513
1514                 if (global_clobber_region_function) {
1515                         DEBUG(0,("smb_panic: clobber_region() last called from [%s(%u)]\n",
1516                                          global_clobber_region_function,
1517                                          global_clobber_region_line));
1518                 } 
1519         }
1520 #endif
1521
1522         DEBUG(0,("PANIC (pid %llu): %s\n",
1523                     (unsigned long long)sys_getpid(), why));
1524         log_stack_trace();
1525
1526         cmd = lp_panic_action();
1527         if (cmd && *cmd) {
1528                 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
1529                 result = system(cmd);
1530
1531                 if (result == -1)
1532                         DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
1533                                           strerror(errno)));
1534                 else
1535                         DEBUG(0, ("smb_panic(): action returned status %d\n",
1536                                           WEXITSTATUS(result)));
1537         }
1538
1539         dump_core();
1540 }
1541
1542 /*******************************************************************
1543  Print a backtrace of the stack to the debug log. This function
1544  DELIBERATELY LEAKS MEMORY. The expectation is that you should
1545  exit shortly after calling it.
1546 ********************************************************************/
1547
1548 #ifdef HAVE_LIBUNWIND_H
1549 #include <libunwind.h>
1550 #endif
1551
1552 #ifdef HAVE_EXECINFO_H
1553 #include <execinfo.h>
1554 #endif
1555
1556 #ifdef HAVE_LIBEXC_H
1557 #include <libexc.h>
1558 #endif
1559
1560 void log_stack_trace(void)
1561 {
1562 #ifdef HAVE_LIBUNWIND
1563         /* Try to use libunwind before any other technique since on ia64
1564          * libunwind correctly walks the stack in more circumstances than
1565          * backtrace.
1566          */ 
1567         unw_cursor_t cursor;
1568         unw_context_t uc;
1569         unsigned i = 0;
1570
1571         char procname[256];
1572         unw_word_t ip, sp, off;
1573
1574         procname[sizeof(procname) - 1] = '\0';
1575
1576         if (unw_getcontext(&uc) != 0) {
1577                 goto libunwind_failed;
1578         }
1579
1580         if (unw_init_local(&cursor, &uc) != 0) {
1581                 goto libunwind_failed;
1582         }
1583
1584         DEBUG(0, ("BACKTRACE:\n"));
1585
1586         do {
1587             ip = sp = 0;
1588             unw_get_reg(&cursor, UNW_REG_IP, &ip);
1589             unw_get_reg(&cursor, UNW_REG_SP, &sp);
1590
1591             switch (unw_get_proc_name(&cursor,
1592                         procname, sizeof(procname) - 1, &off) ) {
1593             case 0:
1594                     /* Name found. */
1595             case -UNW_ENOMEM:
1596                     /* Name truncated. */
1597                     DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
1598                             i, procname, (long long)off,
1599                             (long long)ip, (long long) sp));
1600                     break;
1601             default:
1602             /* case -UNW_ENOINFO: */
1603             /* case -UNW_EUNSPEC: */
1604                     /* No symbol name found. */
1605                     DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
1606                             i, "<unknown symbol>",
1607                             (long long)ip, (long long) sp));
1608             }
1609             ++i;
1610         } while (unw_step(&cursor) > 0);
1611
1612         return;
1613
1614 libunwind_failed:
1615         DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
1616
1617 #elif HAVE_BACKTRACE_SYMBOLS
1618         void *backtrace_stack[BACKTRACE_STACK_SIZE];
1619         size_t backtrace_size;
1620         char **backtrace_strings;
1621
1622         /* get the backtrace (stack frames) */
1623         backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
1624         backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
1625
1626         DEBUG(0, ("BACKTRACE: %lu stack frames:\n", 
1627                   (unsigned long)backtrace_size));
1628         
1629         if (backtrace_strings) {
1630                 int i;
1631
1632                 for (i = 0; i < backtrace_size; i++)
1633                         DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
1634
1635                 /* Leak the backtrace_strings, rather than risk what free() might do */
1636         }
1637
1638 #elif HAVE_LIBEXC
1639
1640         /* The IRIX libexc library provides an API for unwinding the stack. See
1641          * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
1642          * since we are about to abort anyway, it hardly matters.
1643          */
1644
1645 #define NAMESIZE 32 /* Arbitrary */
1646
1647         __uint64_t      addrs[BACKTRACE_STACK_SIZE];
1648         char *          names[BACKTRACE_STACK_SIZE];
1649         char            namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
1650
1651         int             i;
1652         int             levels;
1653
1654         ZERO_ARRAY(addrs);
1655         ZERO_ARRAY(names);
1656         ZERO_ARRAY(namebuf);
1657
1658         /* We need to be root so we can open our /proc entry to walk
1659          * our stack. It also helps when we want to dump core.
1660          */
1661         become_root();
1662
1663         for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
1664                 names[i] = namebuf + (i * NAMESIZE);
1665         }
1666
1667         levels = trace_back_stack(0, addrs, names,
1668                         BACKTRACE_STACK_SIZE, NAMESIZE - 1);
1669
1670         DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
1671         for (i = 0; i < levels; i++) {
1672                 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
1673         }
1674 #undef NAMESIZE
1675
1676 #else
1677         DEBUG(0, ("unable to produce a stack trace on this platform\n"));
1678 #endif
1679 }
1680
1681 /*******************************************************************
1682   A readdir wrapper which just returns the file name.
1683  ********************************************************************/
1684
1685 const char *readdirname(SMB_STRUCT_DIR *p)
1686 {
1687         SMB_STRUCT_DIRENT *ptr;
1688         char *dname;
1689
1690         if (!p)
1691                 return(NULL);
1692   
1693         ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
1694         if (!ptr)
1695                 return(NULL);
1696
1697         dname = ptr->d_name;
1698
1699 #ifdef NEXT2
1700         if (telldir(p) < 0)
1701                 return(NULL);
1702 #endif
1703
1704 #ifdef HAVE_BROKEN_READDIR_NAME
1705         /* using /usr/ucb/cc is BAD */
1706         dname = dname - 2;
1707 #endif
1708
1709         return talloc_strdup(talloc_tos(), dname);
1710 }
1711
1712 /*******************************************************************
1713  Utility function used to decide if the last component 
1714  of a path matches a (possibly wildcarded) entry in a namelist.
1715 ********************************************************************/
1716
1717 bool is_in_path(const char *name, name_compare_entry *namelist, bool case_sensitive)
1718 {
1719         const char *last_component;
1720
1721         /* if we have no list it's obviously not in the path */
1722         if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
1723                 return False;
1724         }
1725
1726         DEBUG(8, ("is_in_path: %s\n", name));
1727
1728         /* Get the last component of the unix name. */
1729         last_component = strrchr_m(name, '/');
1730         if (!last_component) {
1731                 last_component = name;
1732         } else {
1733                 last_component++; /* Go past '/' */
1734         }
1735
1736         for(; namelist->name != NULL; namelist++) {
1737                 if(namelist->is_wild) {
1738                         if (mask_match(last_component, namelist->name, case_sensitive)) {
1739                                 DEBUG(8,("is_in_path: mask match succeeded\n"));
1740                                 return True;
1741                         }
1742                 } else {
1743                         if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
1744                                                 (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0))) {
1745                                 DEBUG(8,("is_in_path: match succeeded\n"));
1746                                 return True;
1747                         }
1748                 }
1749         }
1750         DEBUG(8,("is_in_path: match not found\n"));
1751         return False;
1752 }
1753
1754 /*******************************************************************
1755  Strip a '/' separated list into an array of 
1756  name_compare_enties structures suitable for 
1757  passing to is_in_path(). We do this for
1758  speed so we can pre-parse all the names in the list 
1759  and don't do it for each call to is_in_path().
1760  namelist is modified here and is assumed to be 
1761  a copy owned by the caller.
1762  We also check if the entry contains a wildcard to
1763  remove a potentially expensive call to mask_match
1764  if possible.
1765 ********************************************************************/
1766  
1767 void set_namearray(name_compare_entry **ppname_array, const char *namelist)
1768 {
1769         char *name_end;
1770         const char *nameptr = namelist;
1771         int num_entries = 0;
1772         int i;
1773
1774         (*ppname_array) = NULL;
1775
1776         if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
1777                 return;
1778
1779         /* We need to make two passes over the string. The
1780                 first to count the number of elements, the second
1781                 to split it.
1782         */
1783
1784         while(*nameptr) {
1785                 if ( *nameptr == '/' ) {
1786                         /* cope with multiple (useless) /s) */
1787                         nameptr++;
1788                         continue;
1789                 }
1790                 /* find the next / */
1791                 name_end = strchr_m(nameptr, '/');
1792
1793                 /* oops - the last check for a / didn't find one. */
1794                 if (name_end == NULL)
1795                         break;
1796
1797                 /* next segment please */
1798                 nameptr = name_end + 1;
1799                 num_entries++;
1800         }
1801
1802         if(num_entries == 0)
1803                 return;
1804
1805         if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1806                 DEBUG(0,("set_namearray: malloc fail\n"));
1807                 return;
1808         }
1809
1810         /* Now copy out the names */
1811         nameptr = namelist;
1812         i = 0;
1813         while(*nameptr) {
1814                 if ( *nameptr == '/' ) {
1815                         /* cope with multiple (useless) /s) */
1816                         nameptr++;
1817                         continue;
1818                 }
1819                 /* find the next / */
1820                 if ((name_end = strchr_m(nameptr, '/')) != NULL)
1821                         *name_end = 0;
1822
1823                 /* oops - the last check for a / didn't find one. */
1824                 if(name_end == NULL) 
1825                         break;
1826
1827                 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1828                 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1829                         DEBUG(0,("set_namearray: malloc fail (1)\n"));
1830                         return;
1831                 }
1832
1833                 /* next segment please */
1834                 nameptr = name_end + 1;
1835                 i++;
1836         }
1837   
1838         (*ppname_array)[i].name = NULL;
1839
1840         return;
1841 }
1842
1843 /****************************************************************************
1844  Routine to free a namearray.
1845 ****************************************************************************/
1846
1847 void free_namearray(name_compare_entry *name_array)
1848 {
1849         int i;
1850
1851         if(name_array == NULL)
1852                 return;
1853
1854         for(i=0; name_array[i].name!=NULL; i++)
1855                 SAFE_FREE(name_array[i].name);
1856         SAFE_FREE(name_array);
1857 }
1858
1859 #undef DBGC_CLASS
1860 #define DBGC_CLASS DBGC_LOCKING
1861
1862 /****************************************************************************
1863  Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
1864  is dealt with in posix.c
1865  Returns True if we have information regarding this lock region (and returns
1866  F_UNLCK in *ptype if the region is unlocked). False if the call failed.
1867 ****************************************************************************/
1868
1869 bool fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
1870 {
1871         SMB_STRUCT_FLOCK lock;
1872         int ret;
1873
1874         DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
1875                     fd,(double)*poffset,(double)*pcount,*ptype));
1876
1877         lock.l_type = *ptype;
1878         lock.l_whence = SEEK_SET;
1879         lock.l_start = *poffset;
1880         lock.l_len = *pcount;
1881         lock.l_pid = 0;
1882
1883         ret = sys_fcntl_ptr(fd,SMB_F_GETLK,&lock);
1884
1885         if (ret == -1) {
1886                 int sav = errno;
1887                 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
1888                         (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
1889                 errno = sav;
1890                 return False;
1891         }
1892
1893         *ptype = lock.l_type;
1894         *poffset = lock.l_start;
1895         *pcount = lock.l_len;
1896         *ppid = lock.l_pid;
1897         
1898         DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
1899                         fd, (int)lock.l_type, (unsigned int)lock.l_pid));
1900         return True;
1901 }
1902
1903 #undef DBGC_CLASS
1904 #define DBGC_CLASS DBGC_ALL
1905
1906 /*******************************************************************
1907  Is the name specified one of my netbios names.
1908  Returns true if it is equal, false otherwise.
1909 ********************************************************************/
1910
1911 bool is_myname(const char *s)
1912 {
1913         int n;
1914         bool ret = False;
1915
1916         for (n=0; my_netbios_names(n); n++) {
1917                 if (strequal(my_netbios_names(n), s)) {
1918                         ret=True;
1919                         break;
1920                 }
1921         }
1922         DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1923         return(ret);
1924 }
1925
1926 /*******************************************************************
1927  Is the name specified our workgroup/domain.
1928  Returns true if it is equal, false otherwise.
1929 ********************************************************************/
1930
1931 bool is_myworkgroup(const char *s)
1932 {
1933         bool ret = False;
1934
1935         if (strequal(s, lp_workgroup())) {
1936                 ret=True;
1937         }
1938
1939         DEBUG(8, ("is_myworkgroup(\"%s\") returns %d\n", s, ret));
1940         return(ret);
1941 }
1942
1943 /*******************************************************************
1944  we distinguish between 2K and XP by the "Native Lan Manager" string
1945    WinXP => "Windows 2002 5.1"
1946    WinXP 64bit => "Windows XP 5.2"
1947    Win2k => "Windows 2000 5.0"
1948    NT4   => "Windows NT 4.0"
1949    Win9x => "Windows 4.0"
1950  Windows 2003 doesn't set the native lan manager string but
1951  they do set the domain to "Windows 2003 5.2" (probably a bug).
1952 ********************************************************************/
1953
1954 void ra_lanman_string( const char *native_lanman )
1955 {
1956         if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1957                 set_remote_arch( RA_WINXP );
1958         else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1959                 set_remote_arch( RA_WINXP64 );
1960         else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1961                 set_remote_arch( RA_WIN2K3 );
1962 }
1963
1964 static const char *remote_arch_str;
1965
1966 const char *get_remote_arch_str(void)
1967 {
1968         if (!remote_arch_str) {
1969                 return "UNKNOWN";
1970         }
1971         return remote_arch_str;
1972 }
1973
1974 /*******************************************************************
1975  Set the horrid remote_arch string based on an enum.
1976 ********************************************************************/
1977
1978 void set_remote_arch(enum remote_arch_types type)
1979 {
1980         ra_type = type;
1981         switch( type ) {
1982         case RA_WFWG:
1983                 remote_arch_str = "WfWg";
1984                 break;
1985         case RA_OS2:
1986                 remote_arch_str = "OS2";
1987                 break;
1988         case RA_WIN95:
1989                 remote_arch_str = "Win95";
1990                 break;
1991         case RA_WINNT:
1992                 remote_arch_str = "WinNT";
1993                 break;
1994         case RA_WIN2K:
1995                 remote_arch_str = "Win2K";
1996                 break;
1997         case RA_WINXP:
1998                 remote_arch_str = "WinXP";
1999                 break;
2000         case RA_WINXP64:
2001                 remote_arch_str = "WinXP64";
2002                 break;
2003         case RA_WIN2K3:
2004                 remote_arch_str = "Win2K3";
2005                 break;
2006         case RA_VISTA:
2007                 remote_arch_str = "Vista";
2008                 break;
2009         case RA_SAMBA:
2010                 remote_arch_str = "Samba";
2011                 break;
2012         case RA_CIFSFS:
2013                 remote_arch_str = "CIFSFS";
2014                 break;
2015         default:
2016                 ra_type = RA_UNKNOWN;
2017                 remote_arch_str = "UNKNOWN";
2018                 break;
2019         }
2020
2021         DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
2022                                 remote_arch_str));
2023 }
2024
2025 /*******************************************************************
2026  Get the remote_arch type.
2027 ********************************************************************/
2028
2029 enum remote_arch_types get_remote_arch(void)
2030 {
2031         return ra_type;
2032 }
2033
2034 const char *tab_depth(int level, int depth)
2035 {
2036         if( CHECK_DEBUGLVL(level) ) {
2037                 dbgtext("%*s", depth*4, "");
2038         }
2039         return "";
2040 }
2041
2042 /*****************************************************************************
2043  Provide a checksum on a string
2044
2045  Input:  s - the null-terminated character string for which the checksum
2046              will be calculated.
2047
2048   Output: The checksum value calculated for s.
2049 *****************************************************************************/
2050
2051 int str_checksum(const char *s)
2052 {
2053         int res = 0;
2054         int c;
2055         int i=0;
2056
2057         while(*s) {
2058                 c = *s;
2059                 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
2060                 s++;
2061                 i++;
2062         }
2063         return(res);
2064 }
2065
2066 /*****************************************************************
2067  Zero a memory area then free it. Used to catch bugs faster.
2068 *****************************************************************/  
2069
2070 void zero_free(void *p, size_t size)
2071 {
2072         memset(p, 0, size);
2073         SAFE_FREE(p);
2074 }
2075
2076 /*****************************************************************
2077  Set our open file limit to a requested max and return the limit.
2078 *****************************************************************/  
2079
2080 int set_maxfiles(int requested_max)
2081 {
2082 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
2083         struct rlimit rlp;
2084         int saved_current_limit;
2085
2086         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2087                 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
2088                         strerror(errno) ));
2089                 /* just guess... */
2090                 return requested_max;
2091         }
2092
2093         /* 
2094          * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
2095          * account for the extra fd we need 
2096          * as well as the log files and standard
2097          * handles etc. Save the limit we want to set in case
2098          * we are running on an OS that doesn't support this limit (AIX)
2099          * which always returns RLIM_INFINITY for rlp.rlim_max.
2100          */
2101
2102         /* Try raising the hard (max) limit to the requested amount. */
2103
2104 #if defined(RLIM_INFINITY)
2105         if (rlp.rlim_max != RLIM_INFINITY) {
2106                 int orig_max = rlp.rlim_max;
2107
2108                 if ( rlp.rlim_max < requested_max )
2109                         rlp.rlim_max = requested_max;
2110
2111                 /* This failing is not an error - many systems (Linux) don't
2112                         support our default request of 10,000 open files. JRA. */
2113
2114                 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
2115                         DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n", 
2116                                 (int)rlp.rlim_max, strerror(errno) ));
2117
2118                         /* Set failed - restore original value from get. */
2119                         rlp.rlim_max = orig_max;
2120                 }
2121         }
2122 #endif
2123
2124         /* Now try setting the soft (current) limit. */
2125
2126         saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
2127
2128         if(setrlimit(RLIMIT_NOFILE, &rlp)) {
2129                 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n", 
2130                         (int)rlp.rlim_cur, strerror(errno) ));
2131                 /* just guess... */
2132                 return saved_current_limit;
2133         }
2134
2135         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2136                 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
2137                         strerror(errno) ));
2138                 /* just guess... */
2139                 return saved_current_limit;
2140     }
2141
2142 #if defined(RLIM_INFINITY)
2143         if(rlp.rlim_cur == RLIM_INFINITY)
2144                 return saved_current_limit;
2145 #endif
2146
2147         if((int)rlp.rlim_cur > saved_current_limit)
2148                 return saved_current_limit;
2149
2150         return rlp.rlim_cur;
2151 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
2152         /*
2153          * No way to know - just guess...
2154          */
2155         return requested_max;
2156 #endif
2157 }
2158
2159 /*****************************************************************
2160  Possibly replace mkstemp if it is broken.
2161 *****************************************************************/  
2162
2163 int smb_mkstemp(char *name_template)
2164 {
2165 #if HAVE_SECURE_MKSTEMP
2166         return mkstemp(name_template);
2167 #else
2168         /* have a reasonable go at emulating it. Hope that
2169            the system mktemp() isn't completly hopeless */
2170         char *p = mktemp(name_template);
2171         if (!p)
2172                 return -1;
2173         return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
2174 #endif
2175 }
2176
2177 /*****************************************************************
2178  malloc that aborts with smb_panic on fail or zero size.
2179  *****************************************************************/  
2180
2181 void *smb_xmalloc_array(size_t size, unsigned int count)
2182 {
2183         void *p;
2184         if (size == 0) {
2185                 smb_panic("smb_xmalloc_array: called with zero size");
2186         }
2187         if (count >= MAX_ALLOC_SIZE/size) {
2188                 smb_panic("smb_xmalloc_array: alloc size too large");
2189         }
2190         if ((p = SMB_MALLOC(size*count)) == NULL) {
2191                 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
2192                         (unsigned long)size, (unsigned long)count));
2193                 smb_panic("smb_xmalloc_array: malloc failed");
2194         }
2195         return p;
2196 }
2197
2198 /*
2199   vasprintf that aborts on malloc fail
2200 */
2201
2202  int smb_xvasprintf(char **ptr, const char *format, va_list ap)
2203 {
2204         int n;
2205         va_list ap2;
2206
2207         va_copy(ap2, ap);
2208
2209         n = vasprintf(ptr, format, ap2);
2210         if (n == -1 || ! *ptr) {
2211                 smb_panic("smb_xvasprintf: out of memory");
2212         }
2213         va_end(ap2);
2214         return n;
2215 }
2216
2217 /*****************************************************************
2218  Get local hostname and cache result.
2219 *****************************************************************/
2220
2221 char *myhostname(void)
2222 {
2223         static char *ret;
2224         if (ret == NULL) {
2225                 /* This is cached forever so
2226                  * use talloc_autofree_context() ctx. */
2227                 ret = talloc_get_myname(talloc_autofree_context());
2228         }
2229         return ret;
2230 }
2231
2232 /*****************************************************************
2233  A useful function for returning a path in the Samba pid directory.
2234 *****************************************************************/
2235
2236 static char *xx_path(const char *name, const char *rootpath)
2237 {
2238         char *fname = NULL;
2239
2240         fname = talloc_strdup(talloc_tos(), rootpath);
2241         if (!fname) {
2242                 return NULL;
2243         }
2244         trim_string(fname,"","/");
2245
2246         if (!directory_exist(fname)) {
2247                 mkdir(fname,0755);
2248         }
2249
2250         return talloc_asprintf(talloc_tos(),
2251                                 "%s/%s",
2252                                 fname,
2253                                 name);
2254 }
2255
2256 /*****************************************************************
2257  A useful function for returning a path in the Samba lock directory.
2258 *****************************************************************/
2259
2260 char *lock_path(const char *name)
2261 {
2262         return xx_path(name, lp_lockdir());
2263 }
2264
2265 /*****************************************************************
2266  A useful function for returning a path in the Samba pid directory.
2267 *****************************************************************/
2268
2269 char *pid_path(const char *name)
2270 {
2271         return xx_path(name, lp_piddir());
2272 }
2273
2274 /**
2275  * @brief Returns an absolute path to a file in the Samba lib directory.
2276  *
2277  * @param name File to find, relative to LIBDIR.
2278  *
2279  * @retval Pointer to a string containing the full path.
2280  **/
2281
2282 char *lib_path(const char *name)
2283 {
2284         return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_LIBDIR(), name);
2285 }
2286
2287 /**
2288  * @brief Returns an absolute path to a file in the Samba modules directory.
2289  *
2290  * @param name File to find, relative to MODULESDIR.
2291  *
2292  * @retval Pointer to a string containing the full path.
2293  **/
2294
2295 char *modules_path(const char *name)
2296 {
2297         return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_MODULESDIR(), name);
2298 }
2299
2300 /**
2301  * @brief Returns an absolute path to a file in the Samba data directory.
2302  *
2303  * @param name File to find, relative to CODEPAGEDIR.
2304  *
2305  * @retval Pointer to a talloc'ed string containing the full path.
2306  **/
2307
2308 char *data_path(const char *name)
2309 {
2310         return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_CODEPAGEDIR(), name);
2311 }
2312
2313 /*****************************************************************
2314 a useful function for returning a path in the Samba state directory
2315  *****************************************************************/
2316
2317 char *state_path(const char *name)
2318 {
2319         return xx_path(name, get_dyn_STATEDIR());
2320 }
2321
2322 /**
2323  * @brief Returns the platform specific shared library extension.
2324  *
2325  * @retval Pointer to a const char * containing the extension.
2326  **/
2327
2328 const char *shlib_ext(void)
2329 {
2330         return get_dyn_SHLIBEXT();
2331 }
2332
2333 /*******************************************************************
2334  Given a filename - get its directory name
2335  NB: Returned in static storage.  Caveats:
2336  o  If caller wishes to preserve, they should copy.
2337 ********************************************************************/
2338
2339 char *parent_dirname(const char *path)
2340 {
2341         char *parent;
2342
2343         if (!parent_dirname_talloc(talloc_tos(), path, &parent, NULL)) {
2344                 return NULL;
2345         }
2346
2347         return parent;
2348 }
2349
2350 bool parent_dirname_talloc(TALLOC_CTX *mem_ctx, const char *dir,
2351                            char **parent, const char **name)
2352 {
2353         char *p;
2354         ptrdiff_t len;
2355  
2356         p = strrchr_m(dir, '/'); /* Find final '/', if any */
2357
2358         if (p == NULL) {
2359                 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
2360                         return False;
2361                 }
2362                 if (name) {
2363                         *name = "";
2364                 }
2365                 return True;
2366         }
2367
2368         len = p-dir;
2369
2370         if (!(*parent = (char *)TALLOC_MEMDUP(mem_ctx, dir, len+1))) {
2371                 return False;
2372         }
2373         (*parent)[len] = '\0';
2374
2375         if (name) {
2376                 *name = p+1;
2377         }
2378         return True;
2379 }
2380
2381 /*******************************************************************
2382  Determine if a pattern contains any Microsoft wildcard characters.
2383 *******************************************************************/
2384
2385 bool ms_has_wild(const char *s)
2386 {
2387         char c;
2388
2389         if (lp_posix_pathnames()) {
2390                 /* With posix pathnames no characters are wild. */
2391                 return False;
2392         }
2393
2394         while ((c = *s++)) {
2395                 switch (c) {
2396                 case '*':
2397                 case '?':
2398                 case '<':
2399                 case '>':
2400                 case '"':
2401                         return True;
2402                 }
2403         }
2404         return False;
2405 }
2406
2407 bool ms_has_wild_w(const smb_ucs2_t *s)
2408 {
2409         smb_ucs2_t c;
2410         if (!s) return False;
2411         while ((c = *s++)) {
2412                 switch (c) {
2413                 case UCS2_CHAR('*'):
2414                 case UCS2_CHAR('?'):
2415                 case UCS2_CHAR('<'):
2416                 case UCS2_CHAR('>'):
2417                 case UCS2_CHAR('"'):
2418                         return True;
2419                 }
2420         }
2421         return False;
2422 }
2423
2424 /*******************************************************************
2425  A wrapper that handles case sensitivity and the special handling
2426  of the ".." name.
2427 *******************************************************************/
2428
2429 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
2430 {
2431         if (strcmp(string,"..") == 0)
2432                 string = ".";
2433         if (strcmp(pattern,".") == 0)
2434                 return False;
2435         
2436         return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
2437 }
2438
2439 /*******************************************************************
2440  A wrapper that handles case sensitivity and the special handling
2441  of the ".." name. Varient that is only called by old search code which requires
2442  pattern translation.
2443 *******************************************************************/
2444
2445 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
2446 {
2447         if (strcmp(string,"..") == 0)
2448                 string = ".";
2449         if (strcmp(pattern,".") == 0)
2450                 return False;
2451         
2452         return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
2453 }
2454
2455 /*******************************************************************
2456  A wrapper that handles a list of patters and calls mask_match()
2457  on each.  Returns True if any of the patterns match.
2458 *******************************************************************/
2459
2460 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
2461 {
2462        while (listLen-- > 0) {
2463                if (mask_match(string, *list++, is_case_sensitive))
2464                        return True;
2465        }
2466        return False;
2467 }
2468
2469 /*********************************************************
2470  Recursive routine that is called by unix_wild_match.
2471 *********************************************************/
2472
2473 static bool unix_do_match(const char *regexp, const char *str)
2474 {
2475         const char *p;
2476
2477         for( p = regexp; *p && *str; ) {
2478
2479                 switch(*p) {
2480                         case '?':
2481                                 str++;
2482                                 p++;
2483                                 break;
2484
2485                         case '*':
2486
2487                                 /*
2488                                  * Look for a character matching 
2489                                  * the one after the '*'.
2490                                  */
2491                                 p++;
2492                                 if(!*p)
2493                                         return true; /* Automatic match */
2494                                 while(*str) {
2495
2496                                         while(*str && (*p != *str))
2497                                                 str++;
2498
2499                                         /*
2500                                          * Patch from weidel@multichart.de. In the case of the regexp
2501                                          * '*XX*' we want to ensure there are at least 2 'X' characters
2502                                          * in the string after the '*' for a match to be made.
2503                                          */
2504
2505                                         {
2506                                                 int matchcount=0;
2507
2508                                                 /*
2509                                                  * Eat all the characters that match, but count how many there were.
2510                                                  */
2511
2512                                                 while(*str && (*p == *str)) {
2513                                                         str++;
2514                                                         matchcount++;
2515                                                 }
2516
2517                                                 /*
2518                                                  * Now check that if the regexp had n identical characters that
2519                                                  * matchcount had at least that many matches.
2520                                                  */
2521
2522                                                 while ( *(p+1) && (*(p+1) == *p)) {
2523                                                         p++;
2524                                                         matchcount--;
2525                                                 }
2526
2527                                                 if ( matchcount <= 0 )
2528                                                         return false;
2529                                         }
2530
2531                                         str--; /* We've eaten the match char after the '*' */
2532
2533                                         if(unix_do_match(p, str))
2534                                                 return true;
2535
2536                                         if(!*str)
2537                                                 return false;
2538                                         else
2539                                                 str++;
2540                                 }
2541                                 return false;
2542
2543                         default:
2544                                 if(*str != *p)
2545                                         return false;
2546                                 str++;
2547                                 p++;
2548                                 break;
2549                 }
2550         }
2551
2552         if(!*p && !*str)
2553                 return true;
2554
2555         if (!*p && str[0] == '.' && str[1] == 0)
2556                 return true;
2557
2558         if (!*str && *p == '?') {
2559                 while (*p == '?')
2560                         p++;
2561                 return(!*p);
2562         }
2563
2564         if(!*str && (*p == '*' && p[1] == '\0'))
2565                 return true;
2566
2567         return false;
2568 }
2569
2570 /*******************************************************************
2571  Simple case insensitive interface to a UNIX wildcard matcher.
2572  Returns True if match, False if not.
2573 *******************************************************************/
2574
2575 bool unix_wild_match(const char *pattern, const char *string)
2576 {
2577         TALLOC_CTX *ctx = talloc_stackframe();
2578         char *p2;
2579         char *s2;
2580         char *p;
2581         bool ret = false;
2582
2583         p2 = talloc_strdup(ctx,pattern);
2584         s2 = talloc_strdup(ctx,string);
2585         if (!p2 || !s2) {
2586                 TALLOC_FREE(ctx);
2587                 return false;
2588         }
2589         strlower_m(p2);
2590         strlower_m(s2);
2591
2592         /* Remove any *? and ** from the pattern as they are meaningless */
2593         for(p = p2; *p; p++) {
2594                 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
2595                         memmove(&p[1], &p[2], strlen(&p[2])+1);
2596                 }
2597         }
2598
2599         if (strequal(p2,"*")) {
2600                 TALLOC_FREE(ctx);
2601                 return true;
2602         }
2603
2604         ret = unix_do_match(p2, s2);
2605         TALLOC_FREE(ctx);
2606         return ret;
2607 }
2608
2609 /**********************************************************************
2610  Converts a name to a fully qualified domain name.
2611  Returns true if lookup succeeded, false if not (then fqdn is set to name)
2612  Note we deliberately use gethostbyname here, not getaddrinfo as we want
2613  to examine the h_aliases and I don't know how to do that with getaddrinfo.
2614 ***********************************************************************/
2615
2616 bool name_to_fqdn(fstring fqdn, const char *name)
2617 {
2618         char *full = NULL;
2619         struct hostent *hp = gethostbyname(name);
2620
2621         if (!hp || !hp->h_name || !*hp->h_name) {
2622                 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
2623                 fstrcpy(fqdn, name);
2624                 return false;
2625         }
2626
2627         /* Find out if the fqdn is returned as an alias
2628          * to cope with /etc/hosts files where the first
2629          * name is not the fqdn but the short name */
2630         if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
2631                 int i;
2632                 for (i = 0; hp->h_aliases[i]; i++) {
2633                         if (strchr_m(hp->h_aliases[i], '.')) {
2634                                 full = hp->h_aliases[i];
2635                                 break;
2636                         }
2637                 }
2638         }
2639         if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) {
2640                 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
2641                 DEBUGADD(1, ("    Specifing the machine hostname for address 127.0.0.1 may lead\n"));
2642                 DEBUGADD(1, ("    to Kerberos authentication problems as localhost.localdomain\n"));
2643                 DEBUGADD(1, ("    may end up being used instead of the real machine FQDN.\n"));
2644                 full = hp->h_name;
2645         }
2646         if (!full) {
2647                 full = hp->h_name;
2648         }
2649
2650         DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
2651         fstrcpy(fqdn, full);
2652         return true;
2653 }
2654
2655 /**********************************************************************
2656  Append a DATA_BLOB to a talloc'ed object
2657 ***********************************************************************/
2658
2659 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
2660 {
2661         size_t old_size = 0;
2662         char *result;
2663
2664         if (blob.length == 0) {
2665                 return buf;
2666         }
2667
2668         if (buf != NULL) {
2669                 old_size = talloc_get_size(buf);
2670         }
2671
2672         result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
2673         if (result == NULL) {
2674                 return NULL;
2675         }
2676
2677         memcpy(result + old_size, blob.data, blob.length);
2678         return result;
2679 }
2680
2681 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
2682 {
2683         switch (share_access & ~FILE_SHARE_DELETE) {
2684                 case FILE_SHARE_NONE:
2685                         return DENY_ALL;
2686                 case FILE_SHARE_READ:
2687                         return DENY_WRITE;
2688                 case FILE_SHARE_WRITE:
2689                         return DENY_READ;
2690                 case FILE_SHARE_READ|FILE_SHARE_WRITE:
2691                         return DENY_NONE;
2692         }
2693         if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
2694                 return DENY_DOS;
2695         } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
2696                 return DENY_FCB;
2697         }
2698
2699         return (uint32)-1;
2700 }
2701
2702 pid_t procid_to_pid(const struct server_id *proc)
2703 {
2704         return proc->pid;
2705 }
2706
2707 static uint32 my_vnn = NONCLUSTER_VNN;
2708
2709 void set_my_vnn(uint32 vnn)
2710 {
2711         DEBUG(10, ("vnn pid %d = %u\n", (int)sys_getpid(), (unsigned int)vnn));
2712         my_vnn = vnn;
2713 }
2714
2715 uint32 get_my_vnn(void)
2716 {
2717         return my_vnn;
2718 }
2719
2720 struct server_id pid_to_procid(pid_t pid)
2721 {
2722         struct server_id result;
2723         result.pid = pid;
2724 #ifdef CLUSTER_SUPPORT
2725         result.vnn = my_vnn;
2726 #endif
2727         return result;
2728 }
2729
2730 struct server_id procid_self(void)
2731 {
2732         return pid_to_procid(sys_getpid());
2733 }
2734
2735 struct server_id server_id_self(void)
2736 {
2737         return procid_self();
2738 }
2739
2740 bool procid_equal(const struct server_id *p1, const struct server_id *p2)
2741 {
2742         if (p1->pid != p2->pid)
2743                 return False;
2744 #ifdef CLUSTER_SUPPORT
2745         if (p1->vnn != p2->vnn)
2746                 return False;
2747 #endif
2748         return True;
2749 }
2750
2751 bool cluster_id_equal(const struct server_id *id1,
2752                       const struct server_id *id2)
2753 {
2754         return procid_equal(id1, id2);
2755 }
2756
2757 bool procid_is_me(const struct server_id *pid)
2758 {
2759         if (pid->pid != sys_getpid())
2760                 return False;
2761 #ifdef CLUSTER_SUPPORT
2762         if (pid->vnn != my_vnn)
2763                 return False;
2764 #endif
2765         return True;
2766 }
2767
2768 struct server_id interpret_pid(const char *pid_string)
2769 {
2770 #ifdef CLUSTER_SUPPORT
2771         unsigned int vnn, pid;
2772         struct server_id result;
2773         if (sscanf(pid_string, "%u:%u", &vnn, &pid) == 2) {
2774                 result.vnn = vnn;
2775                 result.pid = pid;
2776         }
2777         else if (sscanf(pid_string, "%u", &pid) == 1) {
2778                 result.vnn = get_my_vnn();
2779                 result.pid = pid;
2780         }
2781         else {
2782                 result.vnn = NONCLUSTER_VNN;
2783                 result.pid = -1;
2784         }
2785         return result;
2786 #else
2787         return pid_to_procid(atoi(pid_string));
2788 #endif
2789 }
2790
2791 char *procid_str(TALLOC_CTX *mem_ctx, const struct server_id *pid)
2792 {
2793 #ifdef CLUSTER_SUPPORT
2794         if (pid->vnn == NONCLUSTER_VNN) {
2795                 return talloc_asprintf(mem_ctx,
2796                                 "%d",
2797                                 (int)pid->pid);
2798         }
2799         else {
2800                 return talloc_asprintf(mem_ctx,
2801                                         "%u:%d",
2802                                         (unsigned)pid->vnn,
2803                                         (int)pid->pid);
2804         }
2805 #else
2806         return talloc_asprintf(mem_ctx,
2807                         "%d",
2808                         (int)pid->pid);
2809 #endif
2810 }
2811
2812 char *procid_str_static(const struct server_id *pid)
2813 {
2814         return procid_str(talloc_tos(), pid);
2815 }
2816
2817 bool procid_valid(const struct server_id *pid)
2818 {
2819         return (pid->pid != -1);
2820 }
2821
2822 bool procid_is_local(const struct server_id *pid)
2823 {
2824 #ifdef CLUSTER_SUPPORT
2825         return pid->vnn == my_vnn;
2826 #else
2827         return True;
2828 #endif
2829 }
2830
2831 int this_is_smp(void)
2832 {
2833 #if defined(HAVE_SYSCONF)
2834
2835 #if defined(SYSCONF_SC_NPROC_ONLN)
2836         return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0;
2837 #elif defined(SYSCONF_SC_NPROCESSORS_ONLN)
2838         return (sysconf(_SC_NPROCESSORS_ONLN) > 1) ? 1 : 0;
2839 #else
2840         return 0;
2841 #endif
2842
2843 #else
2844         return 0;
2845 #endif
2846 }
2847
2848 /****************************************************************
2849  Check if offset/length fit into bufsize. Should probably be
2850  merged with is_offset_safe, but this would require a rewrite
2851  of lanman.c. Later :-)
2852 ****************************************************************/
2853
2854 bool trans_oob(uint32_t bufsize, uint32_t offset, uint32_t length)
2855 {
2856         if ((offset + length < offset) || (offset + length < length)) {
2857                 /* wrap */
2858                 return true;
2859         }
2860         if ((offset > bufsize) || (offset + length > bufsize)) {
2861                 /* overflow */
2862                 return true;
2863         }
2864         return false;
2865 }
2866
2867 /****************************************************************
2868  Check if an offset into a buffer is safe.
2869  If this returns True it's safe to indirect into the byte at
2870  pointer ptr+off.
2871 ****************************************************************/
2872
2873 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2874 {
2875         const char *end_base = buf_base + buf_len;
2876         char *end_ptr = ptr + off;
2877
2878         if (!buf_base || !ptr) {
2879                 return False;
2880         }
2881
2882         if (end_base < buf_base || end_ptr < ptr) {
2883                 return False; /* wrap. */
2884         }
2885
2886         if (end_ptr < end_base) {
2887                 return True;
2888         }
2889         return False;
2890 }
2891
2892 /****************************************************************
2893  Return a safe pointer into a buffer, or NULL.
2894 ****************************************************************/
2895
2896 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2897 {
2898         return is_offset_safe(buf_base, buf_len, ptr, off) ?
2899                         ptr + off : NULL;
2900 }
2901
2902 /****************************************************************
2903  Return a safe pointer into a string within a buffer, or NULL.
2904 ****************************************************************/
2905
2906 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2907 {
2908         if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2909                 return NULL;
2910         }
2911         /* Check if a valid string exists at this offset. */
2912         if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2913                 return NULL;
2914         }
2915         return ptr + off;
2916 }
2917
2918 /****************************************************************
2919  Return an SVAL at a pointer, or failval if beyond the end.
2920 ****************************************************************/
2921
2922 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2923 {
2924         /*
2925          * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2926          * NOT ptr[2].
2927          */
2928         if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2929                 return failval;
2930         }
2931         return SVAL(ptr,off);
2932 }
2933
2934 /****************************************************************
2935  Return an IVAL at a pointer, or failval if beyond the end.
2936 ****************************************************************/
2937
2938 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2939 {
2940         /*
2941          * Note we use off+3 here, not off+4 as IVAL accesses 
2942          * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2943          */
2944         if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2945                 return failval;
2946         }
2947         return IVAL(ptr,off);
2948 }
2949
2950 /****************************************************************
2951  Split DOM\user into DOM and user. Do not mix with winbind variants of that
2952  call (they take care of winbind separator and other winbind specific settings).
2953 ****************************************************************/
2954
2955 void split_domain_user(TALLOC_CTX *mem_ctx,
2956                        const char *full_name,
2957                        char **domain,
2958                        char **user)
2959 {
2960         const char *p = NULL;
2961
2962         p = strchr_m(full_name, '\\');
2963
2964         if (p != NULL) {
2965                 *domain = talloc_strndup(mem_ctx, full_name,
2966                                          PTR_DIFF(p, full_name));
2967                 *user = talloc_strdup(mem_ctx, p+1);
2968         } else {
2969                 *domain = talloc_strdup(mem_ctx, "");
2970                 *user = talloc_strdup(mem_ctx, full_name);
2971         }
2972 }
2973
2974 #if 0
2975
2976 Disable these now we have checked all code paths and ensured
2977 NULL returns on zero request. JRA.
2978
2979 /****************************************************************
2980  talloc wrapper functions that guarentee a null pointer return
2981  if size == 0.
2982 ****************************************************************/
2983
2984 #ifndef MAX_TALLOC_SIZE
2985 #define MAX_TALLOC_SIZE 0x10000000
2986 #endif
2987
2988 /*
2989  *    talloc and zero memory.
2990  *    - returns NULL if size is zero.
2991  */
2992
2993 void *_talloc_zero_zeronull(const void *ctx, size_t size, const char *name)
2994 {
2995         void *p;
2996
2997         if (size == 0) {
2998                 return NULL;
2999         }
3000
3001         p = talloc_named_const(ctx, size, name);
3002
3003         if (p) {
3004                 memset(p, '\0', size);
3005         }
3006
3007         return p;
3008 }
3009
3010 /*
3011  *   memdup with a talloc.
3012  *   - returns NULL if size is zero.
3013  */
3014
3015 void *_talloc_memdup_zeronull(const void *t, const void *p, size_t size, const char *name)
3016 {
3017         void *newp;
3018
3019         if (size == 0) {
3020                 return NULL;
3021         }
3022
3023         newp = talloc_named_const(t, size, name);
3024         if (newp) {
3025                 memcpy(newp, p, size);
3026         }
3027
3028         return newp;
3029 }
3030
3031 /*
3032  *   alloc an array, checking for integer overflow in the array size.
3033  *   - returns NULL if count or el_size are zero.
3034  */
3035
3036 void *_talloc_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
3037 {
3038         if (count >= MAX_TALLOC_SIZE/el_size) {
3039                 return NULL;
3040         }
3041
3042         if (el_size == 0 || count == 0) {
3043                 return NULL;
3044         }
3045
3046         return talloc_named_const(ctx, el_size * count, name);
3047 }
3048
3049 /*
3050  *   alloc an zero array, checking for integer overflow in the array size
3051  *   - returns NULL if count or el_size are zero.
3052  */
3053
3054 void *_talloc_zero_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
3055 {
3056         if (count >= MAX_TALLOC_SIZE/el_size) {
3057                 return NULL;
3058         }
3059
3060         if (el_size == 0 || count == 0) {
3061                 return NULL;
3062         }
3063
3064         return _talloc_zero(ctx, el_size * count, name);
3065 }
3066
3067 /*
3068  *   Talloc wrapper that returns NULL if size == 0.
3069  */
3070 void *talloc_zeronull(const void *context, size_t size, const char *name)
3071 {
3072         if (size == 0) {
3073                 return NULL;
3074         }
3075         return talloc_named_const(context, size, name);
3076 }
3077 #endif
3078
3079 /* Split a path name into filename and stream name components. Canonicalise
3080  * such that an implicit $DATA token is always explicit.
3081  *
3082  * The "specification" of this function can be found in the
3083  * run_local_stream_name() function in torture.c, I've tried those
3084  * combinations against a W2k3 server.
3085  */
3086
3087 NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
3088                                 char **pbase, char **pstream)
3089 {
3090         char *base = NULL;
3091         char *stream = NULL;
3092         char *sname; /* stream name */
3093         const char *stype; /* stream type */
3094
3095         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
3096
3097         sname = strchr_m(fname, ':');
3098
3099         if (lp_posix_pathnames() || (sname == NULL)) {
3100                 if (pbase != NULL) {
3101                         base = talloc_strdup(mem_ctx, fname);
3102                         NT_STATUS_HAVE_NO_MEMORY(base);
3103                 }
3104                 goto done;
3105         }
3106
3107         if (pbase != NULL) {
3108                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
3109                 NT_STATUS_HAVE_NO_MEMORY(base);
3110         }
3111
3112         sname += 1;
3113
3114         stype = strchr_m(sname, ':');
3115
3116         if (stype == NULL) {
3117                 sname = talloc_strdup(mem_ctx, sname);
3118                 stype = "$DATA";
3119         }
3120         else {
3121                 if (StrCaseCmp(stype, ":$DATA") != 0) {
3122                         /*
3123                          * If there is an explicit stream type, so far we only
3124                          * allow $DATA. Is there anything else allowed? -- vl
3125                          */
3126                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
3127                         TALLOC_FREE(base);
3128                         return NT_STATUS_OBJECT_NAME_INVALID;
3129                 }
3130                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
3131                 stype += 1;
3132         }
3133
3134         if (sname == NULL) {
3135                 TALLOC_FREE(base);
3136                 return NT_STATUS_NO_MEMORY;
3137         }
3138
3139         if (sname[0] == '\0') {
3140                 /*
3141                  * no stream name, so no stream
3142                  */
3143                 goto done;
3144         }
3145
3146         if (pstream != NULL) {
3147                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
3148                 if (stream == NULL) {
3149                         TALLOC_FREE(sname);
3150                         TALLOC_FREE(base);
3151                         return NT_STATUS_NO_MEMORY;
3152                 }
3153                 /*
3154                  * upper-case the type field
3155                  */
3156                 strupper_m(strchr_m(stream, ':')+1);
3157         }
3158
3159  done:
3160         if (pbase != NULL) {
3161                 *pbase = base;
3162         }
3163         if (pstream != NULL) {
3164                 *pstream = stream;
3165         }
3166         return NT_STATUS_OK;
3167 }
3168
3169 bool is_valid_policy_hnd(const POLICY_HND *hnd)
3170 {
3171         POLICY_HND tmp;
3172         ZERO_STRUCT(tmp);
3173         return (memcmp(&tmp, hnd, sizeof(tmp)) != 0);
3174 }
3175
3176 bool policy_hnd_equal(const struct policy_handle *hnd1,
3177                       const struct policy_handle *hnd2)
3178 {
3179         if (!hnd1 || !hnd2) {
3180                 return false;
3181         }
3182
3183         return (memcmp(hnd1, hnd2, sizeof(*hnd1)) == 0);
3184 }
3185
3186 /****************************************************************
3187  strip off leading '\\' from a hostname
3188 ****************************************************************/
3189
3190 const char *strip_hostname(const char *s)
3191 {
3192         if (!s) {
3193                 return NULL;
3194         }
3195
3196         if (strlen_m(s) < 3) {
3197                 return s;
3198         }
3199
3200         if (s[0] == '\\') s++;
3201         if (s[0] == '\\') s++;
3202
3203         return s;
3204 }