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