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