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