Fix many const compiler warnings.
[nivanova/samba-autobuild/.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(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  namelist is modified here and is assumed to be 
1318  a copy owned by the caller.
1319  We also check if the entry contains a wildcard to
1320  remove a potentially expensive call to mask_match
1321  if possible.
1322 ********************************************************************/
1323
1324 void set_namearray(name_compare_entry **ppname_array, const char *namelist)
1325 {
1326         char *name_end;
1327         char *nameptr = (char *)namelist;
1328         int num_entries = 0;
1329         int i;
1330
1331         (*ppname_array) = NULL;
1332
1333         if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
1334                 return;
1335
1336         /* We need to make two passes over the string. The
1337                 first to count the number of elements, the second
1338                 to split it.
1339         */
1340
1341         while(*nameptr) {
1342                 if ( *nameptr == '/' ) {
1343                         /* cope with multiple (useless) /s) */
1344                         nameptr++;
1345                         continue;
1346                 }
1347                 /* anything left? */
1348                 if ( *nameptr == '\0' )
1349                         break;
1350
1351                 /* find the next '/' or consume remaining */
1352                 name_end = strchr_m(nameptr, '/');
1353                 if (name_end == NULL)
1354                         name_end = (char *)nameptr + strlen(nameptr);
1355
1356                 /* next segment please */
1357                 nameptr = name_end + 1;
1358                 num_entries++;
1359         }
1360
1361         if(num_entries == 0)
1362                 return;
1363
1364         if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1365                 DEBUG(0,("set_namearray: malloc fail\n"));
1366                 return;
1367         }
1368
1369         /* Now copy out the names */
1370         nameptr = (char *)namelist;
1371         i = 0;
1372         while(*nameptr) {
1373                 if ( *nameptr == '/' ) {
1374                         /* cope with multiple (useless) /s) */
1375                         nameptr++;
1376                         continue;
1377                 }
1378                 /* anything left? */
1379                 if ( *nameptr == '\0' )
1380                         break;
1381
1382                 /* find the next '/' or consume remaining */
1383                 name_end = strchr_m(nameptr, '/');
1384                 if (name_end)
1385                         *name_end = '\0';
1386                 else
1387                         name_end = nameptr + strlen(nameptr);
1388
1389                 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1390                 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1391                         DEBUG(0,("set_namearray: malloc fail (1)\n"));
1392                         return;
1393                 }
1394
1395                 /* next segment please */
1396                 nameptr = name_end + 1;
1397                 i++;
1398         }
1399
1400         (*ppname_array)[i].name = NULL;
1401
1402         return;
1403 }
1404
1405 /****************************************************************************
1406  Routine to free a namearray.
1407 ****************************************************************************/
1408
1409 void free_namearray(name_compare_entry *name_array)
1410 {
1411         int i;
1412
1413         if(name_array == NULL)
1414                 return;
1415
1416         for(i=0; name_array[i].name!=NULL; i++)
1417                 SAFE_FREE(name_array[i].name);
1418         SAFE_FREE(name_array);
1419 }
1420
1421 #undef DBGC_CLASS
1422 #define DBGC_CLASS DBGC_LOCKING
1423
1424 /****************************************************************************
1425  Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
1426  is dealt with in posix.c
1427  Returns True if we have information regarding this lock region (and returns
1428  F_UNLCK in *ptype if the region is unlocked). False if the call failed.
1429 ****************************************************************************/
1430
1431 bool fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
1432 {
1433         SMB_STRUCT_FLOCK lock;
1434         int ret;
1435
1436         DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
1437                     fd,(double)*poffset,(double)*pcount,*ptype));
1438
1439         lock.l_type = *ptype;
1440         lock.l_whence = SEEK_SET;
1441         lock.l_start = *poffset;
1442         lock.l_len = *pcount;
1443         lock.l_pid = 0;
1444
1445         ret = sys_fcntl_ptr(fd,SMB_F_GETLK,&lock);
1446
1447         if (ret == -1) {
1448                 int sav = errno;
1449                 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
1450                         (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
1451                 errno = sav;
1452                 return False;
1453         }
1454
1455         *ptype = lock.l_type;
1456         *poffset = lock.l_start;
1457         *pcount = lock.l_len;
1458         *ppid = lock.l_pid;
1459
1460         DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
1461                         fd, (int)lock.l_type, (unsigned int)lock.l_pid));
1462         return True;
1463 }
1464
1465 #undef DBGC_CLASS
1466 #define DBGC_CLASS DBGC_ALL
1467
1468 /*******************************************************************
1469  Is the name specified one of my netbios names.
1470  Returns true if it is equal, false otherwise.
1471 ********************************************************************/
1472
1473 bool is_myname(const char *s)
1474 {
1475         int n;
1476         bool ret = False;
1477
1478         for (n=0; my_netbios_names(n); n++) {
1479                 if (strequal(my_netbios_names(n), s)) {
1480                         ret=True;
1481                         break;
1482                 }
1483         }
1484         DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1485         return(ret);
1486 }
1487
1488 /*******************************************************************
1489  Is the name specified our workgroup/domain.
1490  Returns true if it is equal, false otherwise.
1491 ********************************************************************/
1492
1493 bool is_myworkgroup(const char *s)
1494 {
1495         bool ret = False;
1496
1497         if (strequal(s, lp_workgroup())) {
1498                 ret=True;
1499         }
1500
1501         DEBUG(8, ("is_myworkgroup(\"%s\") returns %d\n", s, ret));
1502         return(ret);
1503 }
1504
1505 /*******************************************************************
1506  we distinguish between 2K and XP by the "Native Lan Manager" string
1507    WinXP => "Windows 2002 5.1"
1508    WinXP 64bit => "Windows XP 5.2"
1509    Win2k => "Windows 2000 5.0"
1510    NT4   => "Windows NT 4.0"
1511    Win9x => "Windows 4.0"
1512  Windows 2003 doesn't set the native lan manager string but
1513  they do set the domain to "Windows 2003 5.2" (probably a bug).
1514 ********************************************************************/
1515
1516 void ra_lanman_string( const char *native_lanman )
1517 {
1518         if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1519                 set_remote_arch( RA_WINXP );
1520         else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1521                 set_remote_arch( RA_WINXP64 );
1522         else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1523                 set_remote_arch( RA_WIN2K3 );
1524 }
1525
1526 static const char *remote_arch_str;
1527
1528 const char *get_remote_arch_str(void)
1529 {
1530         if (!remote_arch_str) {
1531                 return "UNKNOWN";
1532         }
1533         return remote_arch_str;
1534 }
1535
1536 /*******************************************************************
1537  Set the horrid remote_arch string based on an enum.
1538 ********************************************************************/
1539
1540 void set_remote_arch(enum remote_arch_types type)
1541 {
1542         ra_type = type;
1543         switch( type ) {
1544         case RA_WFWG:
1545                 remote_arch_str = "WfWg";
1546                 break;
1547         case RA_OS2:
1548                 remote_arch_str = "OS2";
1549                 break;
1550         case RA_WIN95:
1551                 remote_arch_str = "Win95";
1552                 break;
1553         case RA_WINNT:
1554                 remote_arch_str = "WinNT";
1555                 break;
1556         case RA_WIN2K:
1557                 remote_arch_str = "Win2K";
1558                 break;
1559         case RA_WINXP:
1560                 remote_arch_str = "WinXP";
1561                 break;
1562         case RA_WINXP64:
1563                 remote_arch_str = "WinXP64";
1564                 break;
1565         case RA_WIN2K3:
1566                 remote_arch_str = "Win2K3";
1567                 break;
1568         case RA_VISTA:
1569                 remote_arch_str = "Vista";
1570                 break;
1571         case RA_SAMBA:
1572                 remote_arch_str = "Samba";
1573                 break;
1574         case RA_CIFSFS:
1575                 remote_arch_str = "CIFSFS";
1576                 break;
1577         case RA_OSX:
1578                 remote_arch_str = "OSX";
1579                 break;
1580         default:
1581                 ra_type = RA_UNKNOWN;
1582                 remote_arch_str = "UNKNOWN";
1583                 break;
1584         }
1585
1586         DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1587                                 remote_arch_str));
1588 }
1589
1590 /*******************************************************************
1591  Get the remote_arch type.
1592 ********************************************************************/
1593
1594 enum remote_arch_types get_remote_arch(void)
1595 {
1596         return ra_type;
1597 }
1598
1599 const char *tab_depth(int level, int depth)
1600 {
1601         if( CHECK_DEBUGLVL(level) ) {
1602                 dbgtext("%*s", depth*4, "");
1603         }
1604         return "";
1605 }
1606
1607 /*****************************************************************************
1608  Provide a checksum on a string
1609
1610  Input:  s - the null-terminated character string for which the checksum
1611              will be calculated.
1612
1613   Output: The checksum value calculated for s.
1614 *****************************************************************************/
1615
1616 int str_checksum(const char *s)
1617 {
1618         TDB_DATA key = string_tdb_data(s);
1619         return tdb_jenkins_hash(&key);
1620 }
1621
1622 /*****************************************************************
1623  Zero a memory area then free it. Used to catch bugs faster.
1624 *****************************************************************/  
1625
1626 void zero_free(void *p, size_t size)
1627 {
1628         memset(p, 0, size);
1629         SAFE_FREE(p);
1630 }
1631
1632 /*****************************************************************
1633  Set our open file limit to a requested max and return the limit.
1634 *****************************************************************/  
1635
1636 int set_maxfiles(int requested_max)
1637 {
1638 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1639         struct rlimit rlp;
1640         int saved_current_limit;
1641
1642         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1643                 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1644                         strerror(errno) ));
1645                 /* just guess... */
1646                 return requested_max;
1647         }
1648
1649         /* 
1650          * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1651          * account for the extra fd we need 
1652          * as well as the log files and standard
1653          * handles etc. Save the limit we want to set in case
1654          * we are running on an OS that doesn't support this limit (AIX)
1655          * which always returns RLIM_INFINITY for rlp.rlim_max.
1656          */
1657
1658         /* Try raising the hard (max) limit to the requested amount. */
1659
1660 #if defined(RLIM_INFINITY)
1661         if (rlp.rlim_max != RLIM_INFINITY) {
1662                 int orig_max = rlp.rlim_max;
1663
1664                 if ( rlp.rlim_max < requested_max )
1665                         rlp.rlim_max = requested_max;
1666
1667                 /* This failing is not an error - many systems (Linux) don't
1668                         support our default request of 10,000 open files. JRA. */
1669
1670                 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1671                         DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n", 
1672                                 (int)rlp.rlim_max, strerror(errno) ));
1673
1674                         /* Set failed - restore original value from get. */
1675                         rlp.rlim_max = orig_max;
1676                 }
1677         }
1678 #endif
1679
1680         /* Now try setting the soft (current) limit. */
1681
1682         saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1683
1684         if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1685                 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n", 
1686                         (int)rlp.rlim_cur, strerror(errno) ));
1687                 /* just guess... */
1688                 return saved_current_limit;
1689         }
1690
1691         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1692                 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1693                         strerror(errno) ));
1694                 /* just guess... */
1695                 return saved_current_limit;
1696     }
1697
1698 #if defined(RLIM_INFINITY)
1699         if(rlp.rlim_cur == RLIM_INFINITY)
1700                 return saved_current_limit;
1701 #endif
1702
1703         if((int)rlp.rlim_cur > saved_current_limit)
1704                 return saved_current_limit;
1705
1706         return rlp.rlim_cur;
1707 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1708         /*
1709          * No way to know - just guess...
1710          */
1711         return requested_max;
1712 #endif
1713 }
1714
1715 /*****************************************************************
1716  malloc that aborts with smb_panic on fail or zero size.
1717  *****************************************************************/  
1718
1719 void *smb_xmalloc_array(size_t size, unsigned int count)
1720 {
1721         void *p;
1722         if (size == 0) {
1723                 smb_panic("smb_xmalloc_array: called with zero size");
1724         }
1725         if (count >= MAX_ALLOC_SIZE/size) {
1726                 smb_panic("smb_xmalloc_array: alloc size too large");
1727         }
1728         if ((p = SMB_MALLOC(size*count)) == NULL) {
1729                 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1730                         (unsigned long)size, (unsigned long)count));
1731                 smb_panic("smb_xmalloc_array: malloc failed");
1732         }
1733         return p;
1734 }
1735
1736 /*
1737   vasprintf that aborts on malloc fail
1738 */
1739
1740  int smb_xvasprintf(char **ptr, const char *format, va_list ap)
1741 {
1742         int n;
1743         va_list ap2;
1744
1745         va_copy(ap2, ap);
1746
1747         n = vasprintf(ptr, format, ap2);
1748         va_end(ap2);
1749         if (n == -1 || ! *ptr) {
1750                 smb_panic("smb_xvasprintf: out of memory");
1751         }
1752         return n;
1753 }
1754
1755 /*****************************************************************
1756  Get local hostname and cache result.
1757 *****************************************************************/
1758
1759 char *myhostname(void)
1760 {
1761         static char *ret;
1762         if (ret == NULL) {
1763                 ret = get_myname(NULL);
1764         }
1765         return ret;
1766 }
1767
1768 /**
1769  * @brief Returns an absolute path to a file concatenating the provided
1770  * @a rootpath and @a basename
1771  *
1772  * @param name Filename, relative to @a rootpath
1773  *
1774  * @retval Pointer to a string containing the full path.
1775  **/
1776
1777 static char *xx_path(const char *name, const char *rootpath)
1778 {
1779         char *fname = NULL;
1780
1781         fname = talloc_strdup(talloc_tos(), rootpath);
1782         if (!fname) {
1783                 return NULL;
1784         }
1785         trim_string(fname,"","/");
1786
1787         if (!directory_exist(fname)) {
1788                 if (!mkdir(fname,0755))
1789                         DEBUG(1, ("Unable to create directory %s for file %s. "
1790                               "Error was %s\n", fname, name, strerror(errno)));
1791         }
1792
1793         return talloc_asprintf(talloc_tos(),
1794                                 "%s/%s",
1795                                 fname,
1796                                 name);
1797 }
1798
1799 /**
1800  * @brief Returns an absolute path to a file in the Samba lock directory.
1801  *
1802  * @param name File to find, relative to LOCKDIR.
1803  *
1804  * @retval Pointer to a talloc'ed string containing the full path.
1805  **/
1806
1807 char *lock_path(const char *name)
1808 {
1809         return xx_path(name, lp_lockdir());
1810 }
1811
1812 /**
1813  * @brief Returns an absolute path to a file in the Samba pid directory.
1814  *
1815  * @param name File to find, relative to PIDDIR.
1816  *
1817  * @retval Pointer to a talloc'ed string containing the full path.
1818  **/
1819
1820 char *pid_path(const char *name)
1821 {
1822         return xx_path(name, lp_piddir());
1823 }
1824
1825 /**
1826  * @brief Returns an absolute path to a file in the Samba lib directory.
1827  *
1828  * @param name File to find, relative to LIBDIR.
1829  *
1830  * @retval Pointer to a string containing the full path.
1831  **/
1832
1833 char *lib_path(const char *name)
1834 {
1835         return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_LIBDIR(), name);
1836 }
1837
1838 /**
1839  * @brief Returns an absolute path to a file in the Samba modules directory.
1840  *
1841  * @param name File to find, relative to MODULESDIR.
1842  *
1843  * @retval Pointer to a string containing the full path.
1844  **/
1845
1846 char *modules_path(const char *name)
1847 {
1848         return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_MODULESDIR(), name);
1849 }
1850
1851 /**
1852  * @brief Returns an absolute path to a file in the Samba data directory.
1853  *
1854  * @param name File to find, relative to CODEPAGEDIR.
1855  *
1856  * @retval Pointer to a talloc'ed string containing the full path.
1857  **/
1858
1859 char *data_path(const char *name)
1860 {
1861         return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_CODEPAGEDIR(), name);
1862 }
1863
1864 /**
1865  * @brief Returns an absolute path to a file in the Samba state directory.
1866  *
1867  * @param name File to find, relative to STATEDIR.
1868  *
1869  * @retval Pointer to a talloc'ed string containing the full path.
1870  **/
1871
1872 char *state_path(const char *name)
1873 {
1874         return xx_path(name, lp_statedir());
1875 }
1876
1877 /**
1878  * @brief Returns an absolute path to a file in the Samba cache directory.
1879  *
1880  * @param name File to find, relative to CACHEDIR.
1881  *
1882  * @retval Pointer to a talloc'ed string containing the full path.
1883  **/
1884
1885 char *cache_path(const char *name)
1886 {
1887         return xx_path(name, lp_cachedir());
1888 }
1889
1890 /**
1891  * @brief Returns the platform specific shared library extension.
1892  *
1893  * @retval Pointer to a const char * containing the extension.
1894  **/
1895
1896 const char *shlib_ext(void)
1897 {
1898         return get_dyn_SHLIBEXT();
1899 }
1900
1901 /*******************************************************************
1902  Given a filename - get its directory name
1903 ********************************************************************/
1904
1905 bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
1906                     const char **name)
1907 {
1908         char *p;
1909         ptrdiff_t len;
1910
1911         p = strrchr_m(dir, '/'); /* Find final '/', if any */
1912
1913         if (p == NULL) {
1914                 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
1915                         return False;
1916                 }
1917                 if (name) {
1918                         *name = dir;
1919                 }
1920                 return True;
1921         }
1922
1923         len = p-dir;
1924
1925         if (!(*parent = (char *)TALLOC_MEMDUP(mem_ctx, dir, len+1))) {
1926                 return False;
1927         }
1928         (*parent)[len] = '\0';
1929
1930         if (name) {
1931                 *name = p+1;
1932         }
1933         return True;
1934 }
1935
1936 /*******************************************************************
1937  Determine if a pattern contains any Microsoft wildcard characters.
1938 *******************************************************************/
1939
1940 bool ms_has_wild(const char *s)
1941 {
1942         char c;
1943
1944         if (lp_posix_pathnames()) {
1945                 /* With posix pathnames no characters are wild. */
1946                 return False;
1947         }
1948
1949         while ((c = *s++)) {
1950                 switch (c) {
1951                 case '*':
1952                 case '?':
1953                 case '<':
1954                 case '>':
1955                 case '"':
1956                         return True;
1957                 }
1958         }
1959         return False;
1960 }
1961
1962 bool ms_has_wild_w(const smb_ucs2_t *s)
1963 {
1964         smb_ucs2_t c;
1965         if (!s) return False;
1966         while ((c = *s++)) {
1967                 switch (c) {
1968                 case UCS2_CHAR('*'):
1969                 case UCS2_CHAR('?'):
1970                 case UCS2_CHAR('<'):
1971                 case UCS2_CHAR('>'):
1972                 case UCS2_CHAR('"'):
1973                         return True;
1974                 }
1975         }
1976         return False;
1977 }
1978
1979 /*******************************************************************
1980  A wrapper that handles case sensitivity and the special handling
1981  of the ".." name.
1982 *******************************************************************/
1983
1984 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
1985 {
1986         if (ISDOTDOT(string))
1987                 string = ".";
1988         if (ISDOT(pattern))
1989                 return False;
1990
1991         return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
1992 }
1993
1994 /*******************************************************************
1995  A wrapper that handles case sensitivity and the special handling
1996  of the ".." name. Varient that is only called by old search code which requires
1997  pattern translation.
1998 *******************************************************************/
1999
2000 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
2001 {
2002         if (ISDOTDOT(string))
2003                 string = ".";
2004         if (ISDOT(pattern))
2005                 return False;
2006
2007         return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
2008 }
2009
2010 /*******************************************************************
2011  A wrapper that handles a list of patters and calls mask_match()
2012  on each.  Returns True if any of the patterns match.
2013 *******************************************************************/
2014
2015 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
2016 {
2017        while (listLen-- > 0) {
2018                if (mask_match(string, *list++, is_case_sensitive))
2019                        return True;
2020        }
2021        return False;
2022 }
2023
2024 /*********************************************************
2025  Recursive routine that is called by unix_wild_match.
2026 *********************************************************/
2027
2028 static bool unix_do_match(const char *regexp, const char *str)
2029 {
2030         const char *p;
2031
2032         for( p = regexp; *p && *str; ) {
2033
2034                 switch(*p) {
2035                         case '?':
2036                                 str++;
2037                                 p++;
2038                                 break;
2039
2040                         case '*':
2041
2042                                 /*
2043                                  * Look for a character matching 
2044                                  * the one after the '*'.
2045                                  */
2046                                 p++;
2047                                 if(!*p)
2048                                         return true; /* Automatic match */
2049                                 while(*str) {
2050
2051                                         while(*str && (*p != *str))
2052                                                 str++;
2053
2054                                         /*
2055                                          * Patch from weidel@multichart.de. In the case of the regexp
2056                                          * '*XX*' we want to ensure there are at least 2 'X' characters
2057                                          * in the string after the '*' for a match to be made.
2058                                          */
2059
2060                                         {
2061                                                 int matchcount=0;
2062
2063                                                 /*
2064                                                  * Eat all the characters that match, but count how many there were.
2065                                                  */
2066
2067                                                 while(*str && (*p == *str)) {
2068                                                         str++;
2069                                                         matchcount++;
2070                                                 }
2071
2072                                                 /*
2073                                                  * Now check that if the regexp had n identical characters that
2074                                                  * matchcount had at least that many matches.
2075                                                  */
2076
2077                                                 while ( *(p+1) && (*(p+1) == *p)) {
2078                                                         p++;
2079                                                         matchcount--;
2080                                                 }
2081
2082                                                 if ( matchcount <= 0 )
2083                                                         return false;
2084                                         }
2085
2086                                         str--; /* We've eaten the match char after the '*' */
2087
2088                                         if(unix_do_match(p, str))
2089                                                 return true;
2090
2091                                         if(!*str)
2092                                                 return false;
2093                                         else
2094                                                 str++;
2095                                 }
2096                                 return false;
2097
2098                         default:
2099                                 if(*str != *p)
2100                                         return false;
2101                                 str++;
2102                                 p++;
2103                                 break;
2104                 }
2105         }
2106
2107         if(!*p && !*str)
2108                 return true;
2109
2110         if (!*p && str[0] == '.' && str[1] == 0)
2111                 return true;
2112
2113         if (!*str && *p == '?') {
2114                 while (*p == '?')
2115                         p++;
2116                 return(!*p);
2117         }
2118
2119         if(!*str && (*p == '*' && p[1] == '\0'))
2120                 return true;
2121
2122         return false;
2123 }
2124
2125 /*******************************************************************
2126  Simple case insensitive interface to a UNIX wildcard matcher.
2127  Returns True if match, False if not.
2128 *******************************************************************/
2129
2130 bool unix_wild_match(const char *pattern, const char *string)
2131 {
2132         TALLOC_CTX *ctx = talloc_stackframe();
2133         char *p2;
2134         char *s2;
2135         char *p;
2136         bool ret = false;
2137
2138         p2 = talloc_strdup(ctx,pattern);
2139         s2 = talloc_strdup(ctx,string);
2140         if (!p2 || !s2) {
2141                 TALLOC_FREE(ctx);
2142                 return false;
2143         }
2144         strlower_m(p2);
2145         strlower_m(s2);
2146
2147         /* Remove any *? and ** from the pattern as they are meaningless */
2148         for(p = p2; *p; p++) {
2149                 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
2150                         memmove(&p[1], &p[2], strlen(&p[2])+1);
2151                 }
2152         }
2153
2154         if (strequal(p2,"*")) {
2155                 TALLOC_FREE(ctx);
2156                 return true;
2157         }
2158
2159         ret = unix_do_match(p2, s2);
2160         TALLOC_FREE(ctx);
2161         return ret;
2162 }
2163
2164 /**********************************************************************
2165  Converts a name to a fully qualified domain name.
2166  Returns true if lookup succeeded, false if not (then fqdn is set to name)
2167  Note we deliberately use gethostbyname here, not getaddrinfo as we want
2168  to examine the h_aliases and I don't know how to do that with getaddrinfo.
2169 ***********************************************************************/
2170
2171 bool name_to_fqdn(fstring fqdn, const char *name)
2172 {
2173         char *full = NULL;
2174         struct hostent *hp = gethostbyname(name);
2175
2176         if (!hp || !hp->h_name || !*hp->h_name) {
2177                 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
2178                 fstrcpy(fqdn, name);
2179                 return false;
2180         }
2181
2182         /* Find out if the fqdn is returned as an alias
2183          * to cope with /etc/hosts files where the first
2184          * name is not the fqdn but the short name */
2185         if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
2186                 int i;
2187                 for (i = 0; hp->h_aliases[i]; i++) {
2188                         if (strchr_m(hp->h_aliases[i], '.')) {
2189                                 full = hp->h_aliases[i];
2190                                 break;
2191                         }
2192                 }
2193         }
2194         if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) {
2195                 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
2196                 DEBUGADD(1, ("    Specifing the machine hostname for address 127.0.0.1 may lead\n"));
2197                 DEBUGADD(1, ("    to Kerberos authentication problems as localhost.localdomain\n"));
2198                 DEBUGADD(1, ("    may end up being used instead of the real machine FQDN.\n"));
2199                 full = hp->h_name;
2200         }
2201         if (!full) {
2202                 full = hp->h_name;
2203         }
2204
2205         DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
2206         fstrcpy(fqdn, full);
2207         return true;
2208 }
2209
2210 /**********************************************************************
2211  Append a DATA_BLOB to a talloc'ed object
2212 ***********************************************************************/
2213
2214 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
2215 {
2216         size_t old_size = 0;
2217         char *result;
2218
2219         if (blob.length == 0) {
2220                 return buf;
2221         }
2222
2223         if (buf != NULL) {
2224                 old_size = talloc_get_size(buf);
2225         }
2226
2227         result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
2228         if (result == NULL) {
2229                 return NULL;
2230         }
2231
2232         memcpy(result + old_size, blob.data, blob.length);
2233         return result;
2234 }
2235
2236 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
2237 {
2238         switch (share_access & ~FILE_SHARE_DELETE) {
2239                 case FILE_SHARE_NONE:
2240                         return DENY_ALL;
2241                 case FILE_SHARE_READ:
2242                         return DENY_WRITE;
2243                 case FILE_SHARE_WRITE:
2244                         return DENY_READ;
2245                 case FILE_SHARE_READ|FILE_SHARE_WRITE:
2246                         return DENY_NONE;
2247         }
2248         if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
2249                 return DENY_DOS;
2250         } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
2251                 return DENY_FCB;
2252         }
2253
2254         return (uint32)-1;
2255 }
2256
2257 pid_t procid_to_pid(const struct server_id *proc)
2258 {
2259         return proc->pid;
2260 }
2261
2262 static uint32 my_vnn = NONCLUSTER_VNN;
2263
2264 void set_my_vnn(uint32 vnn)
2265 {
2266         DEBUG(10, ("vnn pid %d = %u\n", (int)sys_getpid(), (unsigned int)vnn));
2267         my_vnn = vnn;
2268 }
2269
2270 uint32 get_my_vnn(void)
2271 {
2272         return my_vnn;
2273 }
2274
2275 static uint64_t my_unique_id = 0;
2276
2277 void set_my_unique_id(uint64_t unique_id)
2278 {
2279         my_unique_id = unique_id;
2280 }
2281
2282 struct server_id pid_to_procid(pid_t pid)
2283 {
2284         struct server_id result;
2285         result.pid = pid;
2286         result.unique_id = my_unique_id;
2287         result.vnn = my_vnn;
2288         return result;
2289 }
2290
2291 struct server_id procid_self(void)
2292 {
2293         return pid_to_procid(sys_getpid());
2294 }
2295
2296 bool procid_equal(const struct server_id *p1, const struct server_id *p2)
2297 {
2298         if (p1->pid != p2->pid)
2299                 return False;
2300         if (p1->vnn != p2->vnn)
2301                 return False;
2302         return True;
2303 }
2304
2305 bool cluster_id_equal(const struct server_id *id1,
2306                       const struct server_id *id2)
2307 {
2308         return procid_equal(id1, id2);
2309 }
2310
2311 bool procid_is_me(const struct server_id *pid)
2312 {
2313         if (pid->pid != sys_getpid())
2314                 return False;
2315         if (pid->vnn != my_vnn)
2316                 return False;
2317         return True;
2318 }
2319
2320 struct server_id interpret_pid(const char *pid_string)
2321 {
2322         struct server_id result;
2323         int pid;
2324         unsigned int vnn;
2325         if (sscanf(pid_string, "%u:%d", &vnn, &pid) == 2) {
2326                 result.vnn = vnn;
2327                 result.pid = pid;
2328         }
2329         else if (sscanf(pid_string, "%d", &pid) == 1) {
2330                 result.vnn = get_my_vnn();
2331                 result.pid = pid;
2332         }
2333         else {
2334                 result.vnn = NONCLUSTER_VNN;
2335                 result.pid = -1;
2336         }
2337         /* Assigning to result.pid may have overflowed
2338            Map negative pid to -1: i.e. error */
2339         if (result.pid < 0) {
2340                 result.pid = -1;
2341         }
2342         result.unique_id = 0;
2343         return result;
2344 }
2345
2346 char *procid_str(TALLOC_CTX *mem_ctx, const struct server_id *pid)
2347 {
2348         if (pid->vnn == NONCLUSTER_VNN) {
2349                 return talloc_asprintf(mem_ctx,
2350                                 "%d",
2351                                 (int)pid->pid);
2352         }
2353         else {
2354                 return talloc_asprintf(mem_ctx,
2355                                         "%u:%d",
2356                                         (unsigned)pid->vnn,
2357                                         (int)pid->pid);
2358         }
2359 }
2360
2361 char *procid_str_static(const struct server_id *pid)
2362 {
2363         return procid_str(talloc_tos(), pid);
2364 }
2365
2366 bool procid_valid(const struct server_id *pid)
2367 {
2368         return (pid->pid != -1);
2369 }
2370
2371 bool procid_is_local(const struct server_id *pid)
2372 {
2373         return pid->vnn == my_vnn;
2374 }
2375
2376 /****************************************************************
2377  Check if offset/length fit into bufsize. Should probably be
2378  merged with is_offset_safe, but this would require a rewrite
2379  of lanman.c. Later :-)
2380 ****************************************************************/
2381
2382 bool trans_oob(uint32_t bufsize, uint32_t offset, uint32_t length)
2383 {
2384         if ((offset + length < offset) || (offset + length < length)) {
2385                 /* wrap */
2386                 return true;
2387         }
2388         if ((offset > bufsize) || (offset + length > bufsize)) {
2389                 /* overflow */
2390                 return true;
2391         }
2392         return false;
2393 }
2394
2395 /****************************************************************
2396  Check if an offset into a buffer is safe.
2397  If this returns True it's safe to indirect into the byte at
2398  pointer ptr+off.
2399 ****************************************************************/
2400
2401 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2402 {
2403         const char *end_base = buf_base + buf_len;
2404         char *end_ptr = ptr + off;
2405
2406         if (!buf_base || !ptr) {
2407                 return False;
2408         }
2409
2410         if (end_base < buf_base || end_ptr < ptr) {
2411                 return False; /* wrap. */
2412         }
2413
2414         if (end_ptr < end_base) {
2415                 return True;
2416         }
2417         return False;
2418 }
2419
2420 /****************************************************************
2421  Return a safe pointer into a buffer, or NULL.
2422 ****************************************************************/
2423
2424 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2425 {
2426         return is_offset_safe(buf_base, buf_len, ptr, off) ?
2427                         ptr + off : NULL;
2428 }
2429
2430 /****************************************************************
2431  Return a safe pointer into a string within a buffer, or NULL.
2432 ****************************************************************/
2433
2434 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2435 {
2436         if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2437                 return NULL;
2438         }
2439         /* Check if a valid string exists at this offset. */
2440         if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2441                 return NULL;
2442         }
2443         return ptr + off;
2444 }
2445
2446 /****************************************************************
2447  Return an SVAL at a pointer, or failval if beyond the end.
2448 ****************************************************************/
2449
2450 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2451 {
2452         /*
2453          * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2454          * NOT ptr[2].
2455          */
2456         if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2457                 return failval;
2458         }
2459         return SVAL(ptr,off);
2460 }
2461
2462 /****************************************************************
2463  Return an IVAL at a pointer, or failval if beyond the end.
2464 ****************************************************************/
2465
2466 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2467 {
2468         /*
2469          * Note we use off+3 here, not off+4 as IVAL accesses 
2470          * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2471          */
2472         if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2473                 return failval;
2474         }
2475         return IVAL(ptr,off);
2476 }
2477
2478 /****************************************************************
2479  Split DOM\user into DOM and user. Do not mix with winbind variants of that
2480  call (they take care of winbind separator and other winbind specific settings).
2481 ****************************************************************/
2482
2483 void split_domain_user(TALLOC_CTX *mem_ctx,
2484                        const char *full_name,
2485                        char **domain,
2486                        char **user)
2487 {
2488         const char *p = NULL;
2489
2490         p = strchr_m(full_name, '\\');
2491
2492         if (p != NULL) {
2493                 *domain = talloc_strndup(mem_ctx, full_name,
2494                                          PTR_DIFF(p, full_name));
2495                 *user = talloc_strdup(mem_ctx, p+1);
2496         } else {
2497                 *domain = talloc_strdup(mem_ctx, "");
2498                 *user = talloc_strdup(mem_ctx, full_name);
2499         }
2500 }
2501
2502 #if 0
2503
2504 Disable these now we have checked all code paths and ensured
2505 NULL returns on zero request. JRA.
2506
2507 /****************************************************************
2508  talloc wrapper functions that guarentee a null pointer return
2509  if size == 0.
2510 ****************************************************************/
2511
2512 #ifndef MAX_TALLOC_SIZE
2513 #define MAX_TALLOC_SIZE 0x10000000
2514 #endif
2515
2516 /*
2517  *    talloc and zero memory.
2518  *    - returns NULL if size is zero.
2519  */
2520
2521 void *_talloc_zero_zeronull(const void *ctx, size_t size, const char *name)
2522 {
2523         void *p;
2524
2525         if (size == 0) {
2526                 return NULL;
2527         }
2528
2529         p = talloc_named_const(ctx, size, name);
2530
2531         if (p) {
2532                 memset(p, '\0', size);
2533         }
2534
2535         return p;
2536 }
2537
2538 /*
2539  *   memdup with a talloc.
2540  *   - returns NULL if size is zero.
2541  */
2542
2543 void *_talloc_memdup_zeronull(const void *t, const void *p, size_t size, const char *name)
2544 {
2545         void *newp;
2546
2547         if (size == 0) {
2548                 return NULL;
2549         }
2550
2551         newp = talloc_named_const(t, size, name);
2552         if (newp) {
2553                 memcpy(newp, p, size);
2554         }
2555
2556         return newp;
2557 }
2558
2559 /*
2560  *   alloc an array, checking for integer overflow in the array size.
2561  *   - returns NULL if count or el_size are zero.
2562  */
2563
2564 void *_talloc_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
2565 {
2566         if (count >= MAX_TALLOC_SIZE/el_size) {
2567                 return NULL;
2568         }
2569
2570         if (el_size == 0 || count == 0) {
2571                 return NULL;
2572         }
2573
2574         return talloc_named_const(ctx, el_size * count, name);
2575 }
2576
2577 /*
2578  *   alloc an zero array, checking for integer overflow in the array size
2579  *   - returns NULL if count or el_size are zero.
2580  */
2581
2582 void *_talloc_zero_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
2583 {
2584         if (count >= MAX_TALLOC_SIZE/el_size) {
2585                 return NULL;
2586         }
2587
2588         if (el_size == 0 || count == 0) {
2589                 return NULL;
2590         }
2591
2592         return _talloc_zero(ctx, el_size * count, name);
2593 }
2594
2595 /*
2596  *   Talloc wrapper that returns NULL if size == 0.
2597  */
2598 void *talloc_zeronull(const void *context, size_t size, const char *name)
2599 {
2600         if (size == 0) {
2601                 return NULL;
2602         }
2603         return talloc_named_const(context, size, name);
2604 }
2605 #endif
2606
2607 /****************************************************************
2608  strip off leading '\\' from a hostname
2609 ****************************************************************/
2610
2611 const char *strip_hostname(const char *s)
2612 {
2613         if (!s) {
2614                 return NULL;
2615         }
2616
2617         if (strlen_m(s) < 3) {
2618                 return s;
2619         }
2620
2621         if (s[0] == '\\') s++;
2622         if (s[0] == '\\') s++;
2623
2624         return s;
2625 }
2626
2627 bool tevent_req_poll_ntstatus(struct tevent_req *req,
2628                               struct tevent_context *ev,
2629                               NTSTATUS *status)
2630 {
2631         bool ret = tevent_req_poll(req, ev);
2632         if (!ret) {
2633                 *status = map_nt_error_from_unix(errno);
2634         }
2635         return ret;
2636 }
2637
2638 bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result)
2639 {
2640         if (!NT_STATUS_IS_OK(err1)) {
2641                 *result = err1;
2642                 return true;
2643         }
2644         if (!NT_STATUS_IS_OK(err2)) {
2645                 *result = err2;
2646                 return true;
2647         }
2648         return false;
2649 }
2650
2651 int timeval_to_msec(struct timeval t)
2652 {
2653         return t.tv_sec * 1000 + (t.tv_usec+999) / 1000;
2654 }
2655
2656 /*******************************************************************
2657  Check a given DOS pathname is valid for a share.
2658 ********************************************************************/
2659
2660 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
2661 {
2662         char *ptr = NULL;
2663
2664         if (!dos_pathname) {
2665                 return NULL;
2666         }
2667
2668         ptr = talloc_strdup(ctx, dos_pathname);
2669         if (!ptr) {
2670                 return NULL;
2671         }
2672         /* Convert any '\' paths to '/' */
2673         unix_format(ptr);
2674         ptr = unix_clean_name(ctx, ptr);
2675         if (!ptr) {
2676                 return NULL;
2677         }
2678
2679         /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
2680         if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
2681                 ptr += 2;
2682
2683         /* Only absolute paths allowed. */
2684         if (*ptr != '/')
2685                 return NULL;
2686
2687         return ptr;
2688 }