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