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