s3: remove POLICY_HND.
[samba.git] / source3 / lib / util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 2001-2007
6    Copyright (C) Simo Sorce 2001
7    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
8    Copyright (C) James Peach 2006
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25
26 extern char *global_clobber_region_function;
27 extern unsigned int global_clobber_region_line;
28
29 /* Max allowable allococation - 256mb - 0x10000000 */
30 #define MAX_ALLOC_SIZE (1024*1024*256)
31
32 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
33 #ifdef WITH_NISPLUS_HOME
34 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
35 /*
36  * The following lines are needed due to buggy include files
37  * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
38  * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
39  * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
40  * an enum in /usr/include/rpcsvc/nis.h.
41  */
42
43 #if defined(GROUP)
44 #undef GROUP
45 #endif
46
47 #if defined(GROUP_OBJ)
48 #undef GROUP_OBJ
49 #endif
50
51 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
52
53 #include <rpcsvc/nis.h>
54
55 #endif /* WITH_NISPLUS_HOME */
56 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
57
58 enum protocol_types Protocol = PROTOCOL_COREPLUS;
59
60 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  Possibly replace mkstemp if it is broken.
2118 *****************************************************************/  
2119
2120 int smb_mkstemp(char *name_template)
2121 {
2122 #if HAVE_SECURE_MKSTEMP
2123         return mkstemp(name_template);
2124 #else
2125         /* have a reasonable go at emulating it. Hope that
2126            the system mktemp() isn't completly hopeless */
2127         char *p = mktemp(name_template);
2128         if (!p)
2129                 return -1;
2130         return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
2131 #endif
2132 }
2133
2134 /*****************************************************************
2135  malloc that aborts with smb_panic on fail or zero size.
2136  *****************************************************************/  
2137
2138 void *smb_xmalloc_array(size_t size, unsigned int count)
2139 {
2140         void *p;
2141         if (size == 0) {
2142                 smb_panic("smb_xmalloc_array: called with zero size");
2143         }
2144         if (count >= MAX_ALLOC_SIZE/size) {
2145                 smb_panic("smb_xmalloc_array: alloc size too large");
2146         }
2147         if ((p = SMB_MALLOC(size*count)) == NULL) {
2148                 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
2149                         (unsigned long)size, (unsigned long)count));
2150                 smb_panic("smb_xmalloc_array: malloc failed");
2151         }
2152         return p;
2153 }
2154
2155 /*
2156   vasprintf that aborts on malloc fail
2157 */
2158
2159  int smb_xvasprintf(char **ptr, const char *format, va_list ap)
2160 {
2161         int n;
2162         va_list ap2;
2163
2164         va_copy(ap2, ap);
2165
2166         n = vasprintf(ptr, format, ap2);
2167         if (n == -1 || ! *ptr) {
2168                 smb_panic("smb_xvasprintf: out of memory");
2169         }
2170         va_end(ap2);
2171         return n;
2172 }
2173
2174 /*****************************************************************
2175  Get local hostname and cache result.
2176 *****************************************************************/
2177
2178 char *myhostname(void)
2179 {
2180         static char *ret;
2181         if (ret == NULL) {
2182                 /* This is cached forever so
2183                  * use talloc_autofree_context() ctx. */
2184                 ret = get_myname(talloc_autofree_context());
2185         }
2186         return ret;
2187 }
2188
2189 /**
2190  * @brief Returns an absolute path to a file concatenating the provided
2191  * @a rootpath and @a basename
2192  *
2193  * @param name Filename, relative to @a rootpath
2194  *
2195  * @retval Pointer to a string containing the full path.
2196  **/
2197
2198 static char *xx_path(const char *name, const char *rootpath)
2199 {
2200         char *fname = NULL;
2201
2202         fname = talloc_strdup(talloc_tos(), rootpath);
2203         if (!fname) {
2204                 return NULL;
2205         }
2206         trim_string(fname,"","/");
2207
2208         if (!directory_exist(fname)) {
2209                 if (!mkdir(fname,0755))
2210                         DEBUG(1, ("Unable to create directory %s for file %s. "
2211                               "Error was %s\n", fname, name, strerror(errno)));
2212         }
2213
2214         return talloc_asprintf(talloc_tos(),
2215                                 "%s/%s",
2216                                 fname,
2217                                 name);
2218 }
2219
2220 /**
2221  * @brief Returns an absolute path to a file in the Samba lock directory.
2222  *
2223  * @param name File to find, relative to LOCKDIR.
2224  *
2225  * @retval Pointer to a talloc'ed string containing the full path.
2226  **/
2227
2228 char *lock_path(const char *name)
2229 {
2230         return xx_path(name, lp_lockdir());
2231 }
2232
2233 /**
2234  * @brief Returns an absolute path to a file in the Samba pid directory.
2235  *
2236  * @param name File to find, relative to PIDDIR.
2237  *
2238  * @retval Pointer to a talloc'ed string containing the full path.
2239  **/
2240
2241 char *pid_path(const char *name)
2242 {
2243         return xx_path(name, lp_piddir());
2244 }
2245
2246 /**
2247  * @brief Returns an absolute path to a file in the Samba lib directory.
2248  *
2249  * @param name File to find, relative to LIBDIR.
2250  *
2251  * @retval Pointer to a string containing the full path.
2252  **/
2253
2254 char *lib_path(const char *name)
2255 {
2256         return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_LIBDIR(), name);
2257 }
2258
2259 /**
2260  * @brief Returns an absolute path to a file in the Samba modules directory.
2261  *
2262  * @param name File to find, relative to MODULESDIR.
2263  *
2264  * @retval Pointer to a string containing the full path.
2265  **/
2266
2267 char *modules_path(const char *name)
2268 {
2269         return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_MODULESDIR(), name);
2270 }
2271
2272 /**
2273  * @brief Returns an absolute path to a file in the Samba data directory.
2274  *
2275  * @param name File to find, relative to CODEPAGEDIR.
2276  *
2277  * @retval Pointer to a talloc'ed string containing the full path.
2278  **/
2279
2280 char *data_path(const char *name)
2281 {
2282         return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_CODEPAGEDIR(), name);
2283 }
2284
2285 /**
2286  * @brief Returns an absolute path to a file in the Samba state directory.
2287  *
2288  * @param name File to find, relative to STATEDIR.
2289  *
2290  * @retval Pointer to a talloc'ed string containing the full path.
2291  **/
2292
2293 char *state_path(const char *name)
2294 {
2295         return xx_path(name, lp_statedir());
2296 }
2297
2298 /**
2299  * @brief Returns an absolute path to a file in the Samba cache directory.
2300  *
2301  * @param name File to find, relative to CACHEDIR.
2302  *
2303  * @retval Pointer to a talloc'ed string containing the full path.
2304  **/
2305
2306 char *cache_path(const char *name)
2307 {
2308         return xx_path(name, lp_cachedir());
2309 }
2310
2311 /**
2312  * @brief Returns the platform specific shared library extension.
2313  *
2314  * @retval Pointer to a const char * containing the extension.
2315  **/
2316
2317 const char *shlib_ext(void)
2318 {
2319         return get_dyn_SHLIBEXT();
2320 }
2321
2322 /*******************************************************************
2323  Given a filename - get its directory name
2324 ********************************************************************/
2325
2326 bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
2327                     const char **name)
2328 {
2329         char *p;
2330         ptrdiff_t len;
2331  
2332         p = strrchr_m(dir, '/'); /* Find final '/', if any */
2333
2334         if (p == NULL) {
2335                 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
2336                         return False;
2337                 }
2338                 if (name) {
2339                         *name = "";
2340                 }
2341                 return True;
2342         }
2343
2344         len = p-dir;
2345
2346         if (!(*parent = (char *)TALLOC_MEMDUP(mem_ctx, dir, len+1))) {
2347                 return False;
2348         }
2349         (*parent)[len] = '\0';
2350
2351         if (name) {
2352                 *name = p+1;
2353         }
2354         return True;
2355 }
2356
2357 /*******************************************************************
2358  Determine if a pattern contains any Microsoft wildcard characters.
2359 *******************************************************************/
2360
2361 bool ms_has_wild(const char *s)
2362 {
2363         char c;
2364
2365         if (lp_posix_pathnames()) {
2366                 /* With posix pathnames no characters are wild. */
2367                 return False;
2368         }
2369
2370         while ((c = *s++)) {
2371                 switch (c) {
2372                 case '*':
2373                 case '?':
2374                 case '<':
2375                 case '>':
2376                 case '"':
2377                         return True;
2378                 }
2379         }
2380         return False;
2381 }
2382
2383 bool ms_has_wild_w(const smb_ucs2_t *s)
2384 {
2385         smb_ucs2_t c;
2386         if (!s) return False;
2387         while ((c = *s++)) {
2388                 switch (c) {
2389                 case UCS2_CHAR('*'):
2390                 case UCS2_CHAR('?'):
2391                 case UCS2_CHAR('<'):
2392                 case UCS2_CHAR('>'):
2393                 case UCS2_CHAR('"'):
2394                         return True;
2395                 }
2396         }
2397         return False;
2398 }
2399
2400 /*******************************************************************
2401  A wrapper that handles case sensitivity and the special handling
2402  of the ".." name.
2403 *******************************************************************/
2404
2405 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
2406 {
2407         if (strcmp(string,"..") == 0)
2408                 string = ".";
2409         if (strcmp(pattern,".") == 0)
2410                 return False;
2411         
2412         return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
2413 }
2414
2415 /*******************************************************************
2416  A wrapper that handles case sensitivity and the special handling
2417  of the ".." name. Varient that is only called by old search code which requires
2418  pattern translation.
2419 *******************************************************************/
2420
2421 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
2422 {
2423         if (strcmp(string,"..") == 0)
2424                 string = ".";
2425         if (strcmp(pattern,".") == 0)
2426                 return False;
2427         
2428         return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
2429 }
2430
2431 /*******************************************************************
2432  A wrapper that handles a list of patters and calls mask_match()
2433  on each.  Returns True if any of the patterns match.
2434 *******************************************************************/
2435
2436 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
2437 {
2438        while (listLen-- > 0) {
2439                if (mask_match(string, *list++, is_case_sensitive))
2440                        return True;
2441        }
2442        return False;
2443 }
2444
2445 /*********************************************************
2446  Recursive routine that is called by unix_wild_match.
2447 *********************************************************/
2448
2449 static bool unix_do_match(const char *regexp, const char *str)
2450 {
2451         const char *p;
2452
2453         for( p = regexp; *p && *str; ) {
2454
2455                 switch(*p) {
2456                         case '?':
2457                                 str++;
2458                                 p++;
2459                                 break;
2460
2461                         case '*':
2462
2463                                 /*
2464                                  * Look for a character matching 
2465                                  * the one after the '*'.
2466                                  */
2467                                 p++;
2468                                 if(!*p)
2469                                         return true; /* Automatic match */
2470                                 while(*str) {
2471
2472                                         while(*str && (*p != *str))
2473                                                 str++;
2474
2475                                         /*
2476                                          * Patch from weidel@multichart.de. In the case of the regexp
2477                                          * '*XX*' we want to ensure there are at least 2 'X' characters
2478                                          * in the string after the '*' for a match to be made.
2479                                          */
2480
2481                                         {
2482                                                 int matchcount=0;
2483
2484                                                 /*
2485                                                  * Eat all the characters that match, but count how many there were.
2486                                                  */
2487
2488                                                 while(*str && (*p == *str)) {
2489                                                         str++;
2490                                                         matchcount++;
2491                                                 }
2492
2493                                                 /*
2494                                                  * Now check that if the regexp had n identical characters that
2495                                                  * matchcount had at least that many matches.
2496                                                  */
2497
2498                                                 while ( *(p+1) && (*(p+1) == *p)) {
2499                                                         p++;
2500                                                         matchcount--;
2501                                                 }
2502
2503                                                 if ( matchcount <= 0 )
2504                                                         return false;
2505                                         }
2506
2507                                         str--; /* We've eaten the match char after the '*' */
2508
2509                                         if(unix_do_match(p, str))
2510                                                 return true;
2511
2512                                         if(!*str)
2513                                                 return false;
2514                                         else
2515                                                 str++;
2516                                 }
2517                                 return false;
2518
2519                         default:
2520                                 if(*str != *p)
2521                                         return false;
2522                                 str++;
2523                                 p++;
2524                                 break;
2525                 }
2526         }
2527
2528         if(!*p && !*str)
2529                 return true;
2530
2531         if (!*p && str[0] == '.' && str[1] == 0)
2532                 return true;
2533
2534         if (!*str && *p == '?') {
2535                 while (*p == '?')
2536                         p++;
2537                 return(!*p);
2538         }
2539
2540         if(!*str && (*p == '*' && p[1] == '\0'))
2541                 return true;
2542
2543         return false;
2544 }
2545
2546 /*******************************************************************
2547  Simple case insensitive interface to a UNIX wildcard matcher.
2548  Returns True if match, False if not.
2549 *******************************************************************/
2550
2551 bool unix_wild_match(const char *pattern, const char *string)
2552 {
2553         TALLOC_CTX *ctx = talloc_stackframe();
2554         char *p2;
2555         char *s2;
2556         char *p;
2557         bool ret = false;
2558
2559         p2 = talloc_strdup(ctx,pattern);
2560         s2 = talloc_strdup(ctx,string);
2561         if (!p2 || !s2) {
2562                 TALLOC_FREE(ctx);
2563                 return false;
2564         }
2565         strlower_m(p2);
2566         strlower_m(s2);
2567
2568         /* Remove any *? and ** from the pattern as they are meaningless */
2569         for(p = p2; *p; p++) {
2570                 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
2571                         memmove(&p[1], &p[2], strlen(&p[2])+1);
2572                 }
2573         }
2574
2575         if (strequal(p2,"*")) {
2576                 TALLOC_FREE(ctx);
2577                 return true;
2578         }
2579
2580         ret = unix_do_match(p2, s2);
2581         TALLOC_FREE(ctx);
2582         return ret;
2583 }
2584
2585 /**********************************************************************
2586  Converts a name to a fully qualified domain name.
2587  Returns true if lookup succeeded, false if not (then fqdn is set to name)
2588  Note we deliberately use gethostbyname here, not getaddrinfo as we want
2589  to examine the h_aliases and I don't know how to do that with getaddrinfo.
2590 ***********************************************************************/
2591
2592 bool name_to_fqdn(fstring fqdn, const char *name)
2593 {
2594         char *full = NULL;
2595         struct hostent *hp = gethostbyname(name);
2596
2597         if (!hp || !hp->h_name || !*hp->h_name) {
2598                 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
2599                 fstrcpy(fqdn, name);
2600                 return false;
2601         }
2602
2603         /* Find out if the fqdn is returned as an alias
2604          * to cope with /etc/hosts files where the first
2605          * name is not the fqdn but the short name */
2606         if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
2607                 int i;
2608                 for (i = 0; hp->h_aliases[i]; i++) {
2609                         if (strchr_m(hp->h_aliases[i], '.')) {
2610                                 full = hp->h_aliases[i];
2611                                 break;
2612                         }
2613                 }
2614         }
2615         if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) {
2616                 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
2617                 DEBUGADD(1, ("    Specifing the machine hostname for address 127.0.0.1 may lead\n"));
2618                 DEBUGADD(1, ("    to Kerberos authentication problems as localhost.localdomain\n"));
2619                 DEBUGADD(1, ("    may end up being used instead of the real machine FQDN.\n"));
2620                 full = hp->h_name;
2621         }
2622         if (!full) {
2623                 full = hp->h_name;
2624         }
2625
2626         DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
2627         fstrcpy(fqdn, full);
2628         return true;
2629 }
2630
2631 /**********************************************************************
2632  Append a DATA_BLOB to a talloc'ed object
2633 ***********************************************************************/
2634
2635 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
2636 {
2637         size_t old_size = 0;
2638         char *result;
2639
2640         if (blob.length == 0) {
2641                 return buf;
2642         }
2643
2644         if (buf != NULL) {
2645                 old_size = talloc_get_size(buf);
2646         }
2647
2648         result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
2649         if (result == NULL) {
2650                 return NULL;
2651         }
2652
2653         memcpy(result + old_size, blob.data, blob.length);
2654         return result;
2655 }
2656
2657 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
2658 {
2659         switch (share_access & ~FILE_SHARE_DELETE) {
2660                 case FILE_SHARE_NONE:
2661                         return DENY_ALL;
2662                 case FILE_SHARE_READ:
2663                         return DENY_WRITE;
2664                 case FILE_SHARE_WRITE:
2665                         return DENY_READ;
2666                 case FILE_SHARE_READ|FILE_SHARE_WRITE:
2667                         return DENY_NONE;
2668         }
2669         if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
2670                 return DENY_DOS;
2671         } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
2672                 return DENY_FCB;
2673         }
2674
2675         return (uint32)-1;
2676 }
2677
2678 pid_t procid_to_pid(const struct server_id *proc)
2679 {
2680         return proc->pid;
2681 }
2682
2683 static uint32 my_vnn = NONCLUSTER_VNN;
2684
2685 void set_my_vnn(uint32 vnn)
2686 {
2687         DEBUG(10, ("vnn pid %d = %u\n", (int)sys_getpid(), (unsigned int)vnn));
2688         my_vnn = vnn;
2689 }
2690
2691 uint32 get_my_vnn(void)
2692 {
2693         return my_vnn;
2694 }
2695
2696 struct server_id pid_to_procid(pid_t pid)
2697 {
2698         struct server_id result;
2699         result.pid = pid;
2700 #ifdef CLUSTER_SUPPORT
2701         result.vnn = my_vnn;
2702 #endif
2703         return result;
2704 }
2705
2706 struct server_id procid_self(void)
2707 {
2708         return pid_to_procid(sys_getpid());
2709 }
2710
2711 struct server_id server_id_self(void)
2712 {
2713         return procid_self();
2714 }
2715
2716 bool procid_equal(const struct server_id *p1, const struct server_id *p2)
2717 {
2718         if (p1->pid != p2->pid)
2719                 return False;
2720 #ifdef CLUSTER_SUPPORT
2721         if (p1->vnn != p2->vnn)
2722                 return False;
2723 #endif
2724         return True;
2725 }
2726
2727 bool cluster_id_equal(const struct server_id *id1,
2728                       const struct server_id *id2)
2729 {
2730         return procid_equal(id1, id2);
2731 }
2732
2733 bool procid_is_me(const struct server_id *pid)
2734 {
2735         if (pid->pid != sys_getpid())
2736                 return False;
2737 #ifdef CLUSTER_SUPPORT
2738         if (pid->vnn != my_vnn)
2739                 return False;
2740 #endif
2741         return True;
2742 }
2743
2744 struct server_id interpret_pid(const char *pid_string)
2745 {
2746 #ifdef CLUSTER_SUPPORT
2747         unsigned int vnn, pid;
2748         struct server_id result;
2749         if (sscanf(pid_string, "%u:%u", &vnn, &pid) == 2) {
2750                 result.vnn = vnn;
2751                 result.pid = pid;
2752         }
2753         else if (sscanf(pid_string, "%u", &pid) == 1) {
2754                 result.vnn = get_my_vnn();
2755                 result.pid = pid;
2756         }
2757         else {
2758                 result.vnn = NONCLUSTER_VNN;
2759                 result.pid = -1;
2760         }
2761         return result;
2762 #else
2763         return pid_to_procid(atoi(pid_string));
2764 #endif
2765 }
2766
2767 char *procid_str(TALLOC_CTX *mem_ctx, const struct server_id *pid)
2768 {
2769 #ifdef CLUSTER_SUPPORT
2770         if (pid->vnn == NONCLUSTER_VNN) {
2771                 return talloc_asprintf(mem_ctx,
2772                                 "%d",
2773                                 (int)pid->pid);
2774         }
2775         else {
2776                 return talloc_asprintf(mem_ctx,
2777                                         "%u:%d",
2778                                         (unsigned)pid->vnn,
2779                                         (int)pid->pid);
2780         }
2781 #else
2782         return talloc_asprintf(mem_ctx,
2783                         "%d",
2784                         (int)pid->pid);
2785 #endif
2786 }
2787
2788 char *procid_str_static(const struct server_id *pid)
2789 {
2790         return procid_str(talloc_tos(), pid);
2791 }
2792
2793 bool procid_valid(const struct server_id *pid)
2794 {
2795         return (pid->pid != -1);
2796 }
2797
2798 bool procid_is_local(const struct server_id *pid)
2799 {
2800 #ifdef CLUSTER_SUPPORT
2801         return pid->vnn == my_vnn;
2802 #else
2803         return True;
2804 #endif
2805 }
2806
2807 int this_is_smp(void)
2808 {
2809 #if defined(HAVE_SYSCONF)
2810
2811 #if defined(SYSCONF_SC_NPROC_ONLN)
2812         return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0;
2813 #elif defined(SYSCONF_SC_NPROCESSORS_ONLN)
2814         return (sysconf(_SC_NPROCESSORS_ONLN) > 1) ? 1 : 0;
2815 #else
2816         return 0;
2817 #endif
2818
2819 #else
2820         return 0;
2821 #endif
2822 }
2823
2824 /****************************************************************
2825  Check if offset/length fit into bufsize. Should probably be
2826  merged with is_offset_safe, but this would require a rewrite
2827  of lanman.c. Later :-)
2828 ****************************************************************/
2829
2830 bool trans_oob(uint32_t bufsize, uint32_t offset, uint32_t length)
2831 {
2832         if ((offset + length < offset) || (offset + length < length)) {
2833                 /* wrap */
2834                 return true;
2835         }
2836         if ((offset > bufsize) || (offset + length > bufsize)) {
2837                 /* overflow */
2838                 return true;
2839         }
2840         return false;
2841 }
2842
2843 /****************************************************************
2844  Check if an offset into a buffer is safe.
2845  If this returns True it's safe to indirect into the byte at
2846  pointer ptr+off.
2847 ****************************************************************/
2848
2849 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2850 {
2851         const char *end_base = buf_base + buf_len;
2852         char *end_ptr = ptr + off;
2853
2854         if (!buf_base || !ptr) {
2855                 return False;
2856         }
2857
2858         if (end_base < buf_base || end_ptr < ptr) {
2859                 return False; /* wrap. */
2860         }
2861
2862         if (end_ptr < end_base) {
2863                 return True;
2864         }
2865         return False;
2866 }
2867
2868 /****************************************************************
2869  Return a safe pointer into a buffer, or NULL.
2870 ****************************************************************/
2871
2872 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2873 {
2874         return is_offset_safe(buf_base, buf_len, ptr, off) ?
2875                         ptr + off : NULL;
2876 }
2877
2878 /****************************************************************
2879  Return a safe pointer into a string within a buffer, or NULL.
2880 ****************************************************************/
2881
2882 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2883 {
2884         if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2885                 return NULL;
2886         }
2887         /* Check if a valid string exists at this offset. */
2888         if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2889                 return NULL;
2890         }
2891         return ptr + off;
2892 }
2893
2894 /****************************************************************
2895  Return an SVAL at a pointer, or failval if beyond the end.
2896 ****************************************************************/
2897
2898 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2899 {
2900         /*
2901          * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2902          * NOT ptr[2].
2903          */
2904         if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2905                 return failval;
2906         }
2907         return SVAL(ptr,off);
2908 }
2909
2910 /****************************************************************
2911  Return an IVAL at a pointer, or failval if beyond the end.
2912 ****************************************************************/
2913
2914 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2915 {
2916         /*
2917          * Note we use off+3 here, not off+4 as IVAL accesses 
2918          * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2919          */
2920         if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2921                 return failval;
2922         }
2923         return IVAL(ptr,off);
2924 }
2925
2926 /****************************************************************
2927  Split DOM\user into DOM and user. Do not mix with winbind variants of that
2928  call (they take care of winbind separator and other winbind specific settings).
2929 ****************************************************************/
2930
2931 void split_domain_user(TALLOC_CTX *mem_ctx,
2932                        const char *full_name,
2933                        char **domain,
2934                        char **user)
2935 {
2936         const char *p = NULL;
2937
2938         p = strchr_m(full_name, '\\');
2939
2940         if (p != NULL) {
2941                 *domain = talloc_strndup(mem_ctx, full_name,
2942                                          PTR_DIFF(p, full_name));
2943                 *user = talloc_strdup(mem_ctx, p+1);
2944         } else {
2945                 *domain = talloc_strdup(mem_ctx, "");
2946                 *user = talloc_strdup(mem_ctx, full_name);
2947         }
2948 }
2949
2950 #if 0
2951
2952 Disable these now we have checked all code paths and ensured
2953 NULL returns on zero request. JRA.
2954
2955 /****************************************************************
2956  talloc wrapper functions that guarentee a null pointer return
2957  if size == 0.
2958 ****************************************************************/
2959
2960 #ifndef MAX_TALLOC_SIZE
2961 #define MAX_TALLOC_SIZE 0x10000000
2962 #endif
2963
2964 /*
2965  *    talloc and zero memory.
2966  *    - returns NULL if size is zero.
2967  */
2968
2969 void *_talloc_zero_zeronull(const void *ctx, size_t size, const char *name)
2970 {
2971         void *p;
2972
2973         if (size == 0) {
2974                 return NULL;
2975         }
2976
2977         p = talloc_named_const(ctx, size, name);
2978
2979         if (p) {
2980                 memset(p, '\0', size);
2981         }
2982
2983         return p;
2984 }
2985
2986 /*
2987  *   memdup with a talloc.
2988  *   - returns NULL if size is zero.
2989  */
2990
2991 void *_talloc_memdup_zeronull(const void *t, const void *p, size_t size, const char *name)
2992 {
2993         void *newp;
2994
2995         if (size == 0) {
2996                 return NULL;
2997         }
2998
2999         newp = talloc_named_const(t, size, name);
3000         if (newp) {
3001                 memcpy(newp, p, size);
3002         }
3003
3004         return newp;
3005 }
3006
3007 /*
3008  *   alloc an array, checking for integer overflow in the array size.
3009  *   - returns NULL if count or el_size are zero.
3010  */
3011
3012 void *_talloc_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_named_const(ctx, el_size * count, name);
3023 }
3024
3025 /*
3026  *   alloc an zero array, checking for integer overflow in the array size
3027  *   - returns NULL if count or el_size are zero.
3028  */
3029
3030 void *_talloc_zero_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
3031 {
3032         if (count >= MAX_TALLOC_SIZE/el_size) {
3033                 return NULL;
3034         }
3035
3036         if (el_size == 0 || count == 0) {
3037                 return NULL;
3038         }
3039
3040         return _talloc_zero(ctx, el_size * count, name);
3041 }
3042
3043 /*
3044  *   Talloc wrapper that returns NULL if size == 0.
3045  */
3046 void *talloc_zeronull(const void *context, size_t size, const char *name)
3047 {
3048         if (size == 0) {
3049                 return NULL;
3050         }
3051         return talloc_named_const(context, size, name);
3052 }
3053 #endif
3054
3055 /* Split a path name into filename and stream name components. Canonicalise
3056  * such that an implicit $DATA token is always explicit.
3057  *
3058  * The "specification" of this function can be found in the
3059  * run_local_stream_name() function in torture.c, I've tried those
3060  * combinations against a W2k3 server.
3061  */
3062
3063 NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
3064                                 char **pbase, char **pstream)
3065 {
3066         char *base = NULL;
3067         char *stream = NULL;
3068         char *sname; /* stream name */
3069         const char *stype; /* stream type */
3070
3071         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
3072
3073         sname = strchr_m(fname, ':');
3074
3075         if (lp_posix_pathnames() || (sname == NULL)) {
3076                 if (pbase != NULL) {
3077                         base = talloc_strdup(mem_ctx, fname);
3078                         NT_STATUS_HAVE_NO_MEMORY(base);
3079                 }
3080                 goto done;
3081         }
3082
3083         if (pbase != NULL) {
3084                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
3085                 NT_STATUS_HAVE_NO_MEMORY(base);
3086         }
3087
3088         sname += 1;
3089
3090         stype = strchr_m(sname, ':');
3091
3092         if (stype == NULL) {
3093                 sname = talloc_strdup(mem_ctx, sname);
3094                 stype = "$DATA";
3095         }
3096         else {
3097                 if (StrCaseCmp(stype, ":$DATA") != 0) {
3098                         /*
3099                          * If there is an explicit stream type, so far we only
3100                          * allow $DATA. Is there anything else allowed? -- vl
3101                          */
3102                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
3103                         TALLOC_FREE(base);
3104                         return NT_STATUS_OBJECT_NAME_INVALID;
3105                 }
3106                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
3107                 stype += 1;
3108         }
3109
3110         if (sname == NULL) {
3111                 TALLOC_FREE(base);
3112                 return NT_STATUS_NO_MEMORY;
3113         }
3114
3115         if (sname[0] == '\0') {
3116                 /*
3117                  * no stream name, so no stream
3118                  */
3119                 goto done;
3120         }
3121
3122         if (pstream != NULL) {
3123                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
3124                 if (stream == NULL) {
3125                         TALLOC_FREE(sname);
3126                         TALLOC_FREE(base);
3127                         return NT_STATUS_NO_MEMORY;
3128                 }
3129                 /*
3130                  * upper-case the type field
3131                  */
3132                 strupper_m(strchr_m(stream, ':')+1);
3133         }
3134
3135  done:
3136         if (pbase != NULL) {
3137                 *pbase = base;
3138         }
3139         if (pstream != NULL) {
3140                 *pstream = stream;
3141         }
3142         return NT_STATUS_OK;
3143 }
3144
3145 bool is_valid_policy_hnd(const struct policy_handle *hnd)
3146 {
3147         struct policy_handle tmp;
3148         ZERO_STRUCT(tmp);
3149         return (memcmp(&tmp, hnd, sizeof(tmp)) != 0);
3150 }
3151
3152 bool policy_hnd_equal(const struct policy_handle *hnd1,
3153                       const struct policy_handle *hnd2)
3154 {
3155         if (!hnd1 || !hnd2) {
3156                 return false;
3157         }
3158
3159         return (memcmp(hnd1, hnd2, sizeof(*hnd1)) == 0);
3160 }
3161
3162 /****************************************************************
3163  strip off leading '\\' from a hostname
3164 ****************************************************************/
3165
3166 const char *strip_hostname(const char *s)
3167 {
3168         if (!s) {
3169                 return NULL;
3170         }
3171
3172         if (strlen_m(s) < 3) {
3173                 return s;
3174         }
3175
3176         if (s[0] == '\\') s++;
3177         if (s[0] == '\\') s++;
3178
3179         return s;
3180 }