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