r23055: Rewrite messages.c to use auto-generated marshalling in the tdb. I'm
[samba.git] / source / 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-2002
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 2 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, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26
27 extern fstring local_machine;
28 extern char *global_clobber_region_function;
29 extern unsigned int global_clobber_region_line;
30 extern fstring remote_arch;
31
32 /* Max allowable allococation - 256mb - 0x10000000 */
33 #define MAX_ALLOC_SIZE (1024*1024*256)
34
35 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
36 #ifdef WITH_NISPLUS_HOME
37 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
38 /*
39  * The following lines are needed due to buggy include files
40  * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
41  * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
42  * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
43  * an enum in /usr/include/rpcsvc/nis.h.
44  */
45
46 #if defined(GROUP)
47 #undef GROUP
48 #endif
49
50 #if defined(GROUP_OBJ)
51 #undef GROUP_OBJ
52 #endif
53
54 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
55
56 #include <rpcsvc/nis.h>
57
58 #endif /* WITH_NISPLUS_HOME */
59 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
60
61 enum protocol_types Protocol = PROTOCOL_COREPLUS;
62
63 /* a default finfo structure to ensure all fields are sensible */
64 file_info def_finfo;
65
66 /* this is used by the chaining code */
67 int chain_size = 0;
68
69 int trans_num = 0;
70
71 static enum remote_arch_types ra_type = RA_UNKNOWN;
72 pstring user_socket_options=DEFAULT_SOCKET_OPTIONS;   
73
74 /***********************************************************************
75  Definitions for all names.
76 ***********************************************************************/
77
78 static char *smb_myname;
79 static char *smb_myworkgroup;
80 static char *smb_scope;
81 static int smb_num_netbios_names;
82 static char **smb_my_netbios_names;
83
84 /***********************************************************************
85  Allocate and set myname. Ensure upper case.
86 ***********************************************************************/
87
88 BOOL set_global_myname(const char *myname)
89 {
90         SAFE_FREE(smb_myname);
91         smb_myname = SMB_STRDUP(myname);
92         if (!smb_myname)
93                 return False;
94         strupper_m(smb_myname);
95         return True;
96 }
97
98 const char *global_myname(void)
99 {
100         return smb_myname;
101 }
102
103 /***********************************************************************
104  Allocate and set myworkgroup. Ensure upper case.
105 ***********************************************************************/
106
107 BOOL set_global_myworkgroup(const char *myworkgroup)
108 {
109         SAFE_FREE(smb_myworkgroup);
110         smb_myworkgroup = SMB_STRDUP(myworkgroup);
111         if (!smb_myworkgroup)
112                 return False;
113         strupper_m(smb_myworkgroup);
114         return True;
115 }
116
117 const char *lp_workgroup(void)
118 {
119         return smb_myworkgroup;
120 }
121
122 /***********************************************************************
123  Allocate and set scope. Ensure upper case.
124 ***********************************************************************/
125
126 BOOL set_global_scope(const char *scope)
127 {
128         SAFE_FREE(smb_scope);
129         smb_scope = SMB_STRDUP(scope);
130         if (!smb_scope)
131                 return False;
132         strupper_m(smb_scope);
133         return True;
134 }
135
136 /*********************************************************************
137  Ensure scope is never null string.
138 *********************************************************************/
139
140 const char *global_scope(void)
141 {
142         if (!smb_scope)
143                 set_global_scope("");
144         return smb_scope;
145 }
146
147 static void free_netbios_names_array(void)
148 {
149         int i;
150
151         for (i = 0; i < smb_num_netbios_names; i++)
152                 SAFE_FREE(smb_my_netbios_names[i]);
153
154         SAFE_FREE(smb_my_netbios_names);
155         smb_num_netbios_names = 0;
156 }
157
158 static BOOL allocate_my_netbios_names_array(size_t number)
159 {
160         free_netbios_names_array();
161
162         smb_num_netbios_names = number + 1;
163         smb_my_netbios_names = SMB_MALLOC_ARRAY( char *, smb_num_netbios_names );
164
165         if (!smb_my_netbios_names)
166                 return False;
167
168         memset(smb_my_netbios_names, '\0', sizeof(char *) * smb_num_netbios_names);
169         return True;
170 }
171
172 static BOOL set_my_netbios_names(const char *name, int i)
173 {
174         SAFE_FREE(smb_my_netbios_names[i]);
175
176         smb_my_netbios_names[i] = SMB_STRDUP(name);
177         if (!smb_my_netbios_names[i])
178                 return False;
179         strupper_m(smb_my_netbios_names[i]);
180         return True;
181 }
182
183 /***********************************************************************
184  Free memory allocated to global objects
185 ***********************************************************************/
186
187 void gfree_names(void)
188 {
189         SAFE_FREE( smb_myname );
190         SAFE_FREE( smb_myworkgroup );
191         SAFE_FREE( smb_scope );
192         free_netbios_names_array();
193 }
194
195 void gfree_all( void )
196 {
197         gfree_names();  
198         gfree_loadparm();
199         gfree_case_tables();
200         gfree_debugsyms();
201         gfree_charcnv();
202         gfree_interfaces();
203
204         /* release the talloc null_context memory last */
205         talloc_disable_null_tracking();
206 }
207
208 const char *my_netbios_names(int i)
209 {
210         return smb_my_netbios_names[i];
211 }
212
213 BOOL set_netbios_aliases(const char **str_array)
214 {
215         size_t namecount;
216
217         /* Work out the max number of netbios aliases that we have */
218         for( namecount=0; str_array && (str_array[namecount] != NULL); namecount++ )
219                 ;
220
221         if ( global_myname() && *global_myname())
222                 namecount++;
223
224         /* Allocate space for the netbios aliases */
225         if (!allocate_my_netbios_names_array(namecount))
226                 return False;
227
228         /* Use the global_myname string first */
229         namecount=0;
230         if ( global_myname() && *global_myname()) {
231                 set_my_netbios_names( global_myname(), namecount );
232                 namecount++;
233         }
234
235         if (str_array) {
236                 size_t i;
237                 for ( i = 0; str_array[i] != NULL; i++) {
238                         size_t n;
239                         BOOL duplicate = False;
240
241                         /* Look for duplicates */
242                         for( n=0; n<namecount; n++ ) {
243                                 if( strequal( str_array[i], my_netbios_names(n) ) ) {
244                                         duplicate = True;
245                                         break;
246                                 }
247                         }
248                         if (!duplicate) {
249                                 if (!set_my_netbios_names(str_array[i], namecount))
250                                         return False;
251                                 namecount++;
252                         }
253                 }
254         }
255         return True;
256 }
257
258 /****************************************************************************
259   Common name initialization code.
260 ****************************************************************************/
261
262 BOOL init_names(void)
263 {
264         char *p;
265         int n;
266
267         if (global_myname() == NULL || *global_myname() == '\0') {
268                 if (!set_global_myname(myhostname())) {
269                         DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
270                         return False;
271                 }
272         }
273
274         if (!set_netbios_aliases(lp_netbios_aliases())) {
275                 DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
276                 return False;
277         }                       
278
279         fstrcpy( local_machine, global_myname() );
280         trim_char( local_machine, ' ', ' ' );
281         p = strchr( local_machine, ' ' );
282         if (p)
283                 *p = 0;
284         strlower_m( local_machine );
285
286         DEBUG( 5, ("Netbios name list:-\n") );
287         for( n=0; my_netbios_names(n); n++ )
288                 DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names(n) ) );
289
290         return( True );
291 }
292
293 /**************************************************************************n
294  Find a suitable temporary directory. The result should be copied immediately
295  as it may be overwritten by a subsequent call.
296 ****************************************************************************/
297
298 const char *tmpdir(void)
299 {
300         char *p;
301         if ((p = getenv("TMPDIR")))
302                 return p;
303         return "/tmp";
304 }
305
306 /****************************************************************************
307  Add a gid to an array of gids if it's not already there.
308 ****************************************************************************/
309
310 BOOL add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
311                              gid_t **gids, size_t *num_gids)
312 {
313         int i;
314
315         if ((*num_gids != 0) && (*gids == NULL)) {
316                 /*
317                  * A former call to this routine has failed to allocate memory
318                  */
319                 return False;
320         }
321
322         for (i=0; i<*num_gids; i++) {
323                 if ((*gids)[i] == gid) {
324                         return True;
325                 }
326         }
327
328         *gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1);
329         if (*gids == NULL) {
330                 *num_gids = 0;
331                 return False;
332         }
333
334         (*gids)[*num_gids] = gid;
335         *num_gids += 1;
336         return True;
337 }
338
339 /****************************************************************************
340  Like atoi but gets the value up to the separator character.
341 ****************************************************************************/
342
343 static const char *Atoic(const char *p, int *n, const char *c)
344 {
345         if (!isdigit((int)*p)) {
346                 DEBUG(5, ("Atoic: malformed number\n"));
347                 return NULL;
348         }
349
350         (*n) = atoi(p);
351
352         while ((*p) && isdigit((int)*p))
353                 p++;
354
355         if (strchr_m(c, *p) == NULL) {
356                 DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c));
357                 return NULL;
358         }
359
360         return p;
361 }
362
363 /*************************************************************************
364  Reads a list of numbers.
365  *************************************************************************/
366
367 const char *get_numlist(const char *p, uint32 **num, int *count)
368 {
369         int val;
370
371         if (num == NULL || count == NULL)
372                 return NULL;
373
374         (*count) = 0;
375         (*num  ) = NULL;
376
377         while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':') {
378                 *num = SMB_REALLOC_ARRAY((*num), uint32, (*count)+1);
379                 if (!(*num)) {
380                         return NULL;
381                 }
382                 (*num)[(*count)] = val;
383                 (*count)++;
384                 p++;
385         }
386
387         return p;
388 }
389
390 /*******************************************************************
391  Check if a file exists - call vfs_file_exist for samba files.
392 ********************************************************************/
393
394 BOOL file_exist(const char *fname,SMB_STRUCT_STAT *sbuf)
395 {
396         SMB_STRUCT_STAT st;
397         if (!sbuf)
398                 sbuf = &st;
399   
400         if (sys_stat(fname,sbuf) != 0) 
401                 return(False);
402
403         return((S_ISREG(sbuf->st_mode)) || (S_ISFIFO(sbuf->st_mode)));
404 }
405
406 /*******************************************************************
407  Check a files mod time.
408 ********************************************************************/
409
410 time_t file_modtime(const char *fname)
411 {
412         SMB_STRUCT_STAT st;
413   
414         if (sys_stat(fname,&st) != 0) 
415                 return(0);
416
417         return(st.st_mtime);
418 }
419
420 /*******************************************************************
421  Check if a directory exists.
422 ********************************************************************/
423
424 BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
425 {
426         SMB_STRUCT_STAT st2;
427         BOOL ret;
428
429         if (!st)
430                 st = &st2;
431
432         if (sys_stat(dname,st) != 0) 
433                 return(False);
434
435         ret = S_ISDIR(st->st_mode);
436         if(!ret)
437                 errno = ENOTDIR;
438         return ret;
439 }
440
441 /*******************************************************************
442  Returns the size in bytes of the named file.
443 ********************************************************************/
444
445 SMB_OFF_T get_file_size(char *file_name)
446 {
447         SMB_STRUCT_STAT buf;
448         buf.st_size = 0;
449         if(sys_stat(file_name,&buf) != 0)
450                 return (SMB_OFF_T)-1;
451         return(buf.st_size);
452 }
453
454 /*******************************************************************
455  Return a string representing an attribute for a file.
456 ********************************************************************/
457
458 char *attrib_string(uint16 mode)
459 {
460         static fstring attrstr;
461
462         attrstr[0] = 0;
463
464         if (mode & aVOLID) fstrcat(attrstr,"V");
465         if (mode & aDIR) fstrcat(attrstr,"D");
466         if (mode & aARCH) fstrcat(attrstr,"A");
467         if (mode & aHIDDEN) fstrcat(attrstr,"H");
468         if (mode & aSYSTEM) fstrcat(attrstr,"S");
469         if (mode & aRONLY) fstrcat(attrstr,"R");          
470
471         return(attrstr);
472 }
473
474 /*******************************************************************
475  Show a smb message structure.
476 ********************************************************************/
477
478 void show_msg(char *buf)
479 {
480         int i;
481         int bcc=0;
482
483         if (!DEBUGLVL(5))
484                 return;
485         
486         DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
487                         smb_len(buf),
488                         (int)CVAL(buf,smb_com),
489                         (int)CVAL(buf,smb_rcls),
490                         (int)CVAL(buf,smb_reh),
491                         (int)SVAL(buf,smb_err),
492                         (int)CVAL(buf,smb_flg),
493                         (int)SVAL(buf,smb_flg2)));
494         DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
495                         (int)SVAL(buf,smb_tid),
496                         (int)SVAL(buf,smb_pid),
497                         (int)SVAL(buf,smb_uid),
498                         (int)SVAL(buf,smb_mid)));
499         DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
500
501         for (i=0;i<(int)CVAL(buf,smb_wct);i++)
502                 DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
503                         SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
504         
505         bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
506
507         DEBUGADD(5,("smb_bcc=%d\n",bcc));
508
509         if (DEBUGLEVEL < 10)
510                 return;
511
512         if (DEBUGLEVEL < 50)
513                 bcc = MIN(bcc, 512);
514
515         dump_data(10, (uint8 *)smb_buf(buf), bcc);      
516 }
517
518 /*******************************************************************
519  Set the length and marker of an encrypted smb packet.
520 ********************************************************************/
521
522 void smb_set_enclen(char *buf,int len,uint16 enc_ctx_num)
523 {
524         _smb_setlen(buf,len);
525
526         SCVAL(buf,4,0xFF);
527         SCVAL(buf,5,'E');
528         SSVAL(buf,6,enc_ctx_num);
529 }
530
531 /*******************************************************************
532  Set the length and marker of an smb packet.
533 ********************************************************************/
534
535 void smb_setlen(const char *frombuf, char *buf, int len)
536 {
537         _smb_setlen(buf,len);
538
539         if (frombuf) {
540                 if (buf != frombuf) {
541                         memcpy(buf+4, frombuf+4, 4);
542                 }
543         } else {
544                 SCVAL(buf,4,0xFF);
545                 SCVAL(buf,5,'S');
546                 SCVAL(buf,6,'M');
547                 SCVAL(buf,7,'B');
548         }
549 }
550
551 /*******************************************************************
552  Setup the word count and byte count for a smb message.
553 ********************************************************************/
554
555 int set_message(const char *frombuf, char *buf,int num_words,int num_bytes,BOOL zero)
556 {
557         if (zero && (num_words || num_bytes)) {
558                 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
559         }
560         SCVAL(buf,smb_wct,num_words);
561         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);  
562         smb_setlen(frombuf, buf,smb_size + num_words*2 + num_bytes - 4);
563         return (smb_size + num_words*2 + num_bytes);
564 }
565
566 /*******************************************************************
567  Setup only the byte count for a smb message.
568 ********************************************************************/
569
570 int set_message_bcc(const char *frombuf, char *buf,int num_bytes)
571 {
572         int num_words = CVAL(buf,smb_wct);
573         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);  
574         smb_setlen(frombuf, buf,smb_size + num_words*2 + num_bytes - 4);
575         return (smb_size + num_words*2 + num_bytes);
576 }
577
578 /*******************************************************************
579  Setup only the byte count for a smb message, using the end of the
580  message as a marker.
581 ********************************************************************/
582
583 int set_message_end(const char *frombuf, void *outbuf,void *end_ptr)
584 {
585         return set_message_bcc(frombuf,
586                         (char *)outbuf,
587                         PTR_DIFF(end_ptr,smb_buf((char *)outbuf)));
588 }
589
590 /*******************************************************************
591  Reduce a file name, removing .. elements.
592 ********************************************************************/
593
594 void dos_clean_name(char *s)
595 {
596         char *p=NULL;
597
598         DEBUG(3,("dos_clean_name [%s]\n",s));
599
600         /* remove any double slashes */
601         all_string_sub(s, "\\\\", "\\", 0);
602
603         /* Remove leading .\\ characters */
604         if(strncmp(s, ".\\", 2) == 0) {
605                 trim_string(s, ".\\", NULL);
606                 if(*s == 0)
607                         pstrcpy(s,".\\");
608         }
609
610         while ((p = strstr_m(s,"\\..\\")) != NULL) {
611                 pstring s1;
612
613                 *p = 0;
614                 pstrcpy(s1,p+3);
615
616                 if ((p=strrchr_m(s,'\\')) != NULL)
617                         *p = 0;
618                 else
619                         *s = 0;
620                 pstrcat(s,s1);
621         }  
622
623         trim_string(s,NULL,"\\..");
624         all_string_sub(s, "\\.\\", "\\", 0);
625 }
626
627 /*******************************************************************
628  Reduce a file name, removing .. elements. 
629 ********************************************************************/
630
631 void unix_clean_name(char *s)
632 {
633         char *p=NULL;
634
635         DEBUG(3,("unix_clean_name [%s]\n",s));
636
637         /* remove any double slashes */
638         all_string_sub(s, "//","/", 0);
639
640         /* Remove leading ./ characters */
641         if(strncmp(s, "./", 2) == 0) {
642                 trim_string(s, "./", NULL);
643                 if(*s == 0)
644                         pstrcpy(s,"./");
645         }
646
647         while ((p = strstr_m(s,"/../")) != NULL) {
648                 pstring s1;
649
650                 *p = 0;
651                 pstrcpy(s1,p+3);
652
653                 if ((p=strrchr_m(s,'/')) != NULL)
654                         *p = 0;
655                 else
656                         *s = 0;
657                 pstrcat(s,s1);
658         }  
659
660         trim_string(s,NULL,"/..");
661         all_string_sub(s, "/./", "/", 0);
662 }
663
664 void clean_name(char *s)
665 {
666         dos_clean_name(s);
667         unix_clean_name(s);
668 }
669
670 /*******************************************************************
671  Close the low 3 fd's and open dev/null in their place.
672 ********************************************************************/
673
674 void close_low_fds(BOOL stderr_too)
675 {
676 #ifndef VALGRIND
677         int fd;
678         int i;
679
680         close(0);
681         close(1); 
682
683         if (stderr_too)
684                 close(2);
685
686         /* try and use up these file descriptors, so silly
687                 library routines writing to stdout etc won't cause havoc */
688         for (i=0;i<3;i++) {
689                 if (i == 2 && !stderr_too)
690                         continue;
691
692                 fd = sys_open("/dev/null",O_RDWR,0);
693                 if (fd < 0)
694                         fd = sys_open("/dev/null",O_WRONLY,0);
695                 if (fd < 0) {
696                         DEBUG(0,("Can't open /dev/null\n"));
697                         return;
698                 }
699                 if (fd != i) {
700                         DEBUG(0,("Didn't get file descriptor %d\n",i));
701                         return;
702                 }
703         }
704 #endif
705 }
706
707 /*******************************************************************
708  Write data into an fd at a given offset. Ignore seek errors.
709 ********************************************************************/
710
711 ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos)
712 {
713         size_t total=0;
714         ssize_t ret;
715
716         if (pos == (SMB_OFF_T)-1) {
717                 return write_data(fd, buffer, N);
718         }
719 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
720         while (total < N) {
721                 ret = sys_pwrite(fd,buffer + total,N - total, pos);
722                 if (ret == -1 && errno == ESPIPE) {
723                         return write_data(fd, buffer + total,N - total);
724                 }
725                 if (ret == -1) {
726                         DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
727                         return -1;
728                 }
729                 if (ret == 0) {
730                         return total;
731                 }
732                 total += ret;
733                 pos += ret;
734         }
735         return (ssize_t)total;
736 #else
737         /* Use lseek and write_data. */
738         if (sys_lseek(fd, pos, SEEK_SET) == -1) {
739                 if (errno != ESPIPE) {
740                         return -1;
741                 }
742         }
743         return write_data(fd, buffer, N);
744 #endif
745 }
746
747 /****************************************************************************
748  Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
749  else
750   if SYSV use O_NDELAY
751   if BSD use FNDELAY
752 ****************************************************************************/
753
754 int set_blocking(int fd, BOOL set)
755 {
756         int val;
757 #ifdef O_NONBLOCK
758 #define FLAG_TO_SET O_NONBLOCK
759 #else
760 #ifdef SYSV
761 #define FLAG_TO_SET O_NDELAY
762 #else /* BSD */
763 #define FLAG_TO_SET FNDELAY
764 #endif
765 #endif
766
767         if((val = sys_fcntl_long(fd, F_GETFL, 0)) == -1)
768                 return -1;
769         if(set) /* Turn blocking on - ie. clear nonblock flag */
770                 val &= ~FLAG_TO_SET;
771         else
772                 val |= FLAG_TO_SET;
773         return sys_fcntl_long( fd, F_SETFL, val);
774 #undef FLAG_TO_SET
775 }
776
777 /****************************************************************************
778  Transfer some data between two fd's.
779 ****************************************************************************/
780
781 #ifndef TRANSFER_BUF_SIZE
782 #define TRANSFER_BUF_SIZE 65536
783 #endif
784
785 ssize_t transfer_file_internal(int infd, int outfd, size_t n, ssize_t (*read_fn)(int, void *, size_t),
786                                                 ssize_t (*write_fn)(int, const void *, size_t))
787 {
788         char *buf;
789         size_t total = 0;
790         ssize_t read_ret;
791         ssize_t write_ret;
792         size_t num_to_read_thistime;
793         size_t num_written = 0;
794
795         if ((buf = SMB_MALLOC_ARRAY(char, TRANSFER_BUF_SIZE)) == NULL)
796                 return -1;
797
798         while (total < n) {
799                 num_to_read_thistime = MIN((n - total), TRANSFER_BUF_SIZE);
800
801                 read_ret = (*read_fn)(infd, buf, num_to_read_thistime);
802                 if (read_ret == -1) {
803                         DEBUG(0,("transfer_file_internal: read failure. Error = %s\n", strerror(errno) ));
804                         SAFE_FREE(buf);
805                         return -1;
806                 }
807                 if (read_ret == 0)
808                         break;
809
810                 num_written = 0;
811  
812                 while (num_written < read_ret) {
813                         write_ret = (*write_fn)(outfd,buf + num_written, read_ret - num_written);
814  
815                         if (write_ret == -1) {
816                                 DEBUG(0,("transfer_file_internal: write failure. Error = %s\n", strerror(errno) ));
817                                 SAFE_FREE(buf);
818                                 return -1;
819                         }
820                         if (write_ret == 0)
821                                 return (ssize_t)total;
822  
823                         num_written += (size_t)write_ret;
824                 }
825
826                 total += (size_t)read_ret;
827         }
828
829         SAFE_FREE(buf);
830         return (ssize_t)total;          
831 }
832
833 SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n)
834 {
835         return (SMB_OFF_T)transfer_file_internal(infd, outfd, (size_t)n, sys_read, sys_write);
836 }
837
838 /*******************************************************************
839  Sleep for a specified number of milliseconds.
840 ********************************************************************/
841
842 void smb_msleep(unsigned int t)
843 {
844 #if defined(HAVE_NANOSLEEP)
845         struct timespec tval;
846         int ret;
847
848         tval.tv_sec = t/1000;
849         tval.tv_nsec = 1000000*(t%1000);
850
851         do {
852                 errno = 0;
853                 ret = nanosleep(&tval, &tval);
854         } while (ret < 0 && errno == EINTR && (tval.tv_sec > 0 || tval.tv_nsec > 0));
855 #else
856         unsigned int tdiff=0;
857         struct timeval tval,t1,t2;  
858         fd_set fds;
859
860         GetTimeOfDay(&t1);
861         t2 = t1;
862   
863         while (tdiff < t) {
864                 tval.tv_sec = (t-tdiff)/1000;
865                 tval.tv_usec = 1000*((t-tdiff)%1000);
866
867                 /* Never wait for more than 1 sec. */
868                 if (tval.tv_sec > 1) {
869                         tval.tv_sec = 1; 
870                         tval.tv_usec = 0;
871                 }
872
873                 FD_ZERO(&fds);
874                 errno = 0;
875                 sys_select_intr(0,&fds,NULL,NULL,&tval);
876
877                 GetTimeOfDay(&t2);
878                 if (t2.tv_sec < t1.tv_sec) {
879                         /* Someone adjusted time... */
880                         t1 = t2;
881                 }
882
883                 tdiff = TvalDiff(&t1,&t2);
884         }
885 #endif
886 }
887
888 /****************************************************************************
889  Become a daemon, discarding the controlling terminal.
890 ****************************************************************************/
891
892 void become_daemon(BOOL Fork, BOOL no_process_group)
893 {
894         if (Fork) {
895                 if (sys_fork()) {
896                         _exit(0);
897                 }
898         }
899
900   /* detach from the terminal */
901 #ifdef HAVE_SETSID
902         if (!no_process_group) setsid();
903 #elif defined(TIOCNOTTY)
904         if (!no_process_group) {
905                 int i = sys_open("/dev/tty", O_RDWR, 0);
906                 if (i != -1) {
907                         ioctl(i, (int) TIOCNOTTY, (char *)0);      
908                         close(i);
909                 }
910         }
911 #endif /* HAVE_SETSID */
912
913         /* Close fd's 0,1,2. Needed if started by rsh */
914         close_low_fds(False);  /* Don't close stderr, let the debug system
915                                   attach it to the logfile */
916 }
917
918 /****************************************************************************
919  Put up a yes/no prompt.
920 ****************************************************************************/
921
922 BOOL yesno(char *p)
923 {
924         pstring ans;
925         printf("%s",p);
926
927         if (!fgets(ans,sizeof(ans)-1,stdin))
928                 return(False);
929
930         if (*ans == 'y' || *ans == 'Y')
931                 return(True);
932
933         return(False);
934 }
935
936 #if defined(PARANOID_MALLOC_CHECKER)
937
938 /****************************************************************************
939  Internal malloc wrapper. Externally visible.
940 ****************************************************************************/
941
942 void *malloc_(size_t size)
943 {
944         if (size == 0) {
945                 return NULL;
946         }
947 #undef malloc
948         return malloc(size);
949 #define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
950 }
951
952 /****************************************************************************
953  Internal calloc wrapper. Not externally visible.
954 ****************************************************************************/
955
956 static void *calloc_(size_t count, size_t size)
957 {
958         if (size == 0 || count == 0) {
959                 return NULL;
960         }
961 #undef calloc
962         return calloc(count, size);
963 #define calloc(n,s) __ERROR_DONT_USE_CALLOC_DIRECTLY
964 }
965
966 /****************************************************************************
967  Internal realloc wrapper. Not externally visible.
968 ****************************************************************************/
969
970 static void *realloc_(void *ptr, size_t size)
971 {
972 #undef realloc
973         return realloc(ptr, size);
974 #define realloc(p,s) __ERROR_DONT_USE_RELLOC_DIRECTLY
975 }
976
977 #endif /* PARANOID_MALLOC_CHECKER */
978
979 /****************************************************************************
980  Type-safe malloc.
981 ****************************************************************************/
982
983 void *malloc_array(size_t el_size, unsigned int count)
984 {
985         if (count >= MAX_ALLOC_SIZE/el_size) {
986                 return NULL;
987         }
988
989         if (el_size == 0 || count == 0) {
990                 return NULL;
991         }
992 #if defined(PARANOID_MALLOC_CHECKER)
993         return malloc_(el_size*count);
994 #else
995         return malloc(el_size*count);
996 #endif
997 }
998
999 /****************************************************************************
1000  Type-safe memalign
1001 ****************************************************************************/
1002
1003 void *memalign_array(size_t el_size, size_t align, unsigned int count)
1004 {
1005         if (count >= MAX_ALLOC_SIZE/el_size) {
1006                 return NULL;
1007         }
1008
1009         return sys_memalign(align, el_size*count);
1010 }
1011
1012 /****************************************************************************
1013  Type-safe calloc.
1014 ****************************************************************************/
1015
1016 void *calloc_array(size_t size, size_t nmemb)
1017 {
1018         if (nmemb >= MAX_ALLOC_SIZE/size) {
1019                 return NULL;
1020         }
1021         if (size == 0 || nmemb == 0) {
1022                 return NULL;
1023         }
1024 #if defined(PARANOID_MALLOC_CHECKER)
1025         return calloc_(nmemb, size);
1026 #else
1027         return calloc(nmemb, size);
1028 #endif
1029 }
1030
1031 /****************************************************************************
1032  Expand a pointer to be a particular size.
1033  Note that this version of Realloc has an extra parameter that decides
1034  whether to free the passed in storage on allocation failure or if the
1035  new size is zero.
1036
1037  This is designed for use in the typical idiom of :
1038
1039  p = SMB_REALLOC(p, size)
1040  if (!p) {
1041     return error;
1042  }
1043
1044  and not to have to keep track of the old 'p' contents to free later, nor
1045  to worry if the size parameter was zero. In the case where NULL is returned
1046  we guarentee that p has been freed.
1047
1048  If free later semantics are desired, then pass 'free_old_on_error' as False which
1049  guarentees that the old contents are not freed on error, even if size == 0. To use
1050  this idiom use :
1051
1052  tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
1053  if (!tmp) {
1054     SAFE_FREE(p);
1055     return error;
1056  } else {
1057     p = tmp;
1058  }
1059
1060  Changes were instigated by Coverity error checking. JRA.
1061 ****************************************************************************/
1062
1063 void *Realloc(void *p, size_t size, BOOL free_old_on_error)
1064 {
1065         void *ret=NULL;
1066
1067         if (size == 0) {
1068                 if (free_old_on_error) {
1069                         SAFE_FREE(p);
1070                 }
1071                 DEBUG(2,("Realloc asked for 0 bytes\n"));
1072                 return NULL;
1073         }
1074
1075 #if defined(PARANOID_MALLOC_CHECKER)
1076         if (!p) {
1077                 ret = (void *)malloc_(size);
1078         } else {
1079                 ret = (void *)realloc_(p,size);
1080         }
1081 #else
1082         if (!p) {
1083                 ret = (void *)malloc(size);
1084         } else {
1085                 ret = (void *)realloc(p,size);
1086         }
1087 #endif
1088
1089         if (!ret) {
1090                 if (free_old_on_error && p) {
1091                         SAFE_FREE(p);
1092                 }
1093                 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
1094         }
1095
1096         return(ret);
1097 }
1098
1099 /****************************************************************************
1100  Type-safe realloc.
1101 ****************************************************************************/
1102
1103 void *realloc_array(void *p, size_t el_size, unsigned int count, BOOL free_old_on_error)
1104 {
1105         if (count >= MAX_ALLOC_SIZE/el_size) {
1106                 if (free_old_on_error) {
1107                         SAFE_FREE(p);
1108                 }
1109                 return NULL;
1110         }
1111         return Realloc(p, el_size*count, free_old_on_error);
1112 }
1113
1114 /****************************************************************************
1115  (Hopefully) efficient array append.
1116 ****************************************************************************/
1117
1118 void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
1119                         void *element, void *_array, uint32 *num_elements,
1120                         ssize_t *array_size)
1121 {
1122         void **array = (void **)_array;
1123
1124         if (*array_size < 0) {
1125                 return;
1126         }
1127
1128         if (*array == NULL) {
1129                 if (*array_size == 0) {
1130                         *array_size = 128;
1131                 }
1132
1133                 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
1134                         goto error;
1135                 }
1136
1137                 *array = TALLOC(mem_ctx, element_size * (*array_size));
1138                 if (*array == NULL) {
1139                         goto error;
1140                 }
1141         }
1142
1143         if (*num_elements == *array_size) {
1144                 *array_size *= 2;
1145
1146                 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
1147                         goto error;
1148                 }
1149
1150                 *array = TALLOC_REALLOC(mem_ctx, *array,
1151                                         element_size * (*array_size));
1152
1153                 if (*array == NULL) {
1154                         goto error;
1155                 }
1156         }
1157
1158         memcpy((char *)(*array) + element_size*(*num_elements),
1159                element, element_size);
1160         *num_elements += 1;
1161
1162         return;
1163
1164  error:
1165         *num_elements = 0;
1166         *array_size = -1;
1167 }
1168
1169 /****************************************************************************
1170  Free memory, checks for NULL.
1171  Use directly SAFE_FREE()
1172  Exists only because we need to pass a function pointer somewhere --SSS
1173 ****************************************************************************/
1174
1175 void safe_free(void *p)
1176 {
1177         SAFE_FREE(p);
1178 }
1179
1180 /****************************************************************************
1181  Get my own name and IP.
1182 ****************************************************************************/
1183
1184 BOOL get_myname(char *my_name)
1185 {
1186         pstring hostname;
1187
1188         *hostname = 0;
1189
1190         /* get my host name */
1191         if (gethostname(hostname, sizeof(hostname)) == -1) {
1192                 DEBUG(0,("gethostname failed\n"));
1193                 return False;
1194         } 
1195
1196         /* Ensure null termination. */
1197         hostname[sizeof(hostname)-1] = '\0';
1198
1199         if (my_name) {
1200                 /* split off any parts after an initial . */
1201                 char *p = strchr_m(hostname,'.');
1202
1203                 if (p)
1204                         *p = 0;
1205                 
1206                 fstrcpy(my_name,hostname);
1207         }
1208         
1209         return(True);
1210 }
1211
1212 /****************************************************************************
1213  Get my own canonical name, including domain.
1214 ****************************************************************************/
1215
1216 BOOL get_mydnsfullname(fstring my_dnsname)
1217 {
1218         static fstring dnshostname;
1219         struct hostent *hp;
1220
1221         if (!*dnshostname) {
1222                 /* get my host name */
1223                 if (gethostname(dnshostname, sizeof(dnshostname)) == -1) {
1224                         *dnshostname = '\0';
1225                         DEBUG(0,("gethostname failed\n"));
1226                         return False;
1227                 } 
1228
1229                 /* Ensure null termination. */
1230                 dnshostname[sizeof(dnshostname)-1] = '\0';
1231
1232                 /* Ensure we get the cannonical name. */
1233                 if (!(hp = sys_gethostbyname(dnshostname))) {
1234                         *dnshostname = '\0';
1235                         return False;
1236                 }
1237                 fstrcpy(dnshostname, hp->h_name);
1238         }
1239         fstrcpy(my_dnsname, dnshostname);
1240         return True;
1241 }
1242
1243 /****************************************************************************
1244  Get my own domain name.
1245 ****************************************************************************/
1246
1247 BOOL get_mydnsdomname(fstring my_domname)
1248 {
1249         fstring domname;
1250         char *p;
1251
1252         *my_domname = '\0';
1253         if (!get_mydnsfullname(domname)) {
1254                 return False;
1255         }       
1256         p = strchr_m(domname, '.');
1257         if (p) {
1258                 p++;
1259                 fstrcpy(my_domname, p);
1260         }
1261
1262         return False;
1263 }
1264
1265 /****************************************************************************
1266  Interpret a protocol description string, with a default.
1267 ****************************************************************************/
1268
1269 int interpret_protocol(const char *str,int def)
1270 {
1271         if (strequal(str,"NT1"))
1272                 return(PROTOCOL_NT1);
1273         if (strequal(str,"LANMAN2"))
1274                 return(PROTOCOL_LANMAN2);
1275         if (strequal(str,"LANMAN1"))
1276                 return(PROTOCOL_LANMAN1);
1277         if (strequal(str,"CORE"))
1278                 return(PROTOCOL_CORE);
1279         if (strequal(str,"COREPLUS"))
1280                 return(PROTOCOL_COREPLUS);
1281         if (strequal(str,"CORE+"))
1282                 return(PROTOCOL_COREPLUS);
1283   
1284         DEBUG(0,("Unrecognised protocol level %s\n",str));
1285   
1286         return(def);
1287 }
1288
1289 /****************************************************************************
1290  Return true if a string could be a pure IP address.
1291 ****************************************************************************/
1292
1293 BOOL is_ipaddress(const char *str)
1294 {
1295         BOOL pure_address = True;
1296         int i;
1297   
1298         for (i=0; pure_address && str[i]; i++)
1299                 if (!(isdigit((int)str[i]) || str[i] == '.'))
1300                         pure_address = False;
1301
1302         /* Check that a pure number is not misinterpreted as an IP */
1303         pure_address = pure_address && (strchr_m(str, '.') != NULL);
1304
1305         return pure_address;
1306 }
1307
1308 /****************************************************************************
1309  Interpret an internet address or name into an IP address in 4 byte form.
1310 ****************************************************************************/
1311
1312 uint32 interpret_addr(const char *str)
1313 {
1314         struct hostent *hp;
1315         uint32 res;
1316
1317         if (strcmp(str,"0.0.0.0") == 0)
1318                 return(0);
1319         if (strcmp(str,"255.255.255.255") == 0)
1320                 return(0xFFFFFFFF);
1321
1322   /* if it's in the form of an IP address then get the lib to interpret it */
1323         if (is_ipaddress(str)) {
1324                 res = inet_addr(str);
1325         } else {
1326                 /* otherwise assume it's a network name of some sort and use 
1327                         sys_gethostbyname */
1328                 if ((hp = sys_gethostbyname(str)) == 0) {
1329                         DEBUG(3,("sys_gethostbyname: Unknown host. %s\n",str));
1330                         return 0;
1331                 }
1332
1333                 if(hp->h_addr == NULL) {
1334                         DEBUG(3,("sys_gethostbyname: host address is invalid for host %s\n",str));
1335                         return 0;
1336                 }
1337                 putip((char *)&res,(char *)hp->h_addr);
1338         }
1339
1340         if (res == (uint32)-1)
1341                 return(0);
1342
1343         return(res);
1344 }
1345
1346 /*******************************************************************
1347  A convenient addition to interpret_addr().
1348 ******************************************************************/
1349
1350 struct in_addr *interpret_addr2(const char *str)
1351 {
1352         static struct in_addr ret;
1353         uint32 a = interpret_addr(str);
1354         ret.s_addr = a;
1355         return(&ret);
1356 }
1357
1358 /*******************************************************************
1359  Check if an IP is the 0.0.0.0.
1360 ******************************************************************/
1361
1362 BOOL is_zero_ip(struct in_addr ip)
1363 {
1364         uint32 a;
1365         putip((char *)&a,(char *)&ip);
1366         return(a == 0);
1367 }
1368
1369 /*******************************************************************
1370  Set an IP to 0.0.0.0.
1371 ******************************************************************/
1372
1373 void zero_ip(struct in_addr *ip)
1374 {
1375         static BOOL init;
1376         static struct in_addr ipzero;
1377
1378         if (!init) {
1379                 ipzero = *interpret_addr2("0.0.0.0");
1380                 init = True;
1381         }
1382
1383         *ip = ipzero;
1384 }
1385
1386 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1387 /******************************************************************
1388  Remove any mount options such as -rsize=2048,wsize=2048 etc.
1389  Based on a fix from <Thomas.Hepper@icem.de>.
1390 *******************************************************************/
1391
1392 static void strip_mount_options( pstring *str)
1393 {
1394         if (**str == '-') { 
1395                 char *p = *str;
1396                 while(*p && !isspace(*p))
1397                         p++;
1398                 while(*p && isspace(*p))
1399                         p++;
1400                 if(*p) {
1401                         pstring tmp_str;
1402
1403                         pstrcpy(tmp_str, p);
1404                         pstrcpy(*str, tmp_str);
1405                 }
1406         }
1407 }
1408
1409 /*******************************************************************
1410  Patch from jkf@soton.ac.uk
1411  Split Luke's automount_server into YP lookup and string splitter
1412  so can easily implement automount_path(). 
1413  As we may end up doing both, cache the last YP result. 
1414 *******************************************************************/
1415
1416 #ifdef WITH_NISPLUS_HOME
1417 char *automount_lookup(const char *user_name)
1418 {
1419         static fstring last_key = "";
1420         static pstring last_value = "";
1421  
1422         char *nis_map = (char *)lp_nis_home_map_name();
1423  
1424         char buffer[NIS_MAXATTRVAL + 1];
1425         nis_result *result;
1426         nis_object *object;
1427         entry_obj  *entry;
1428  
1429         if (strcmp(user_name, last_key)) {
1430                 slprintf(buffer, sizeof(buffer)-1, "[key=%s],%s", user_name, nis_map);
1431                 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
1432  
1433                 if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
1434                         if (result->status != NIS_SUCCESS) {
1435                                 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
1436                                 fstrcpy(last_key, ""); pstrcpy(last_value, "");
1437                         } else {
1438                                 object = result->objects.objects_val;
1439                                 if (object->zo_data.zo_type == ENTRY_OBJ) {
1440                                         entry = &object->zo_data.objdata_u.en_data;
1441                                         DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
1442                                         DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
1443  
1444                                         pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
1445                                         pstring_sub(last_value, "&", user_name);
1446                                         fstrcpy(last_key, user_name);
1447                                 }
1448                         }
1449                 }
1450                 nis_freeresult(result);
1451         }
1452
1453         strip_mount_options(&last_value);
1454
1455         DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
1456         return last_value;
1457 }
1458 #else /* WITH_NISPLUS_HOME */
1459
1460 char *automount_lookup(const char *user_name)
1461 {
1462         static fstring last_key = "";
1463         static pstring last_value = "";
1464
1465         int nis_error;        /* returned by yp all functions */
1466         char *nis_result;     /* yp_match inits this */
1467         int nis_result_len;  /* and set this */
1468         char *nis_domain;     /* yp_get_default_domain inits this */
1469         char *nis_map = (char *)lp_nis_home_map_name();
1470
1471         if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
1472                 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
1473                 return last_value;
1474         }
1475
1476         DEBUG(5, ("NIS Domain: %s\n", nis_domain));
1477
1478         if (!strcmp(user_name, last_key)) {
1479                 nis_result = last_value;
1480                 nis_result_len = strlen(last_value);
1481                 nis_error = 0;
1482         } else {
1483                 if ((nis_error = yp_match(nis_domain, nis_map, user_name, strlen(user_name),
1484                                 &nis_result, &nis_result_len)) == 0) {
1485                         fstrcpy(last_key, user_name);
1486                         pstrcpy(last_value, nis_result);
1487                         strip_mount_options(&last_value);
1488
1489                 } else if(nis_error == YPERR_KEY) {
1490
1491                         /* If Key lookup fails user home server is not in nis_map 
1492                                 use default information for server, and home directory */
1493                         last_value[0] = 0;
1494                         DEBUG(3, ("YP Key not found:  while looking up \"%s\" in map \"%s\"\n", 
1495                                         user_name, nis_map));
1496                         DEBUG(3, ("using defaults for server and home directory\n"));
1497                 } else {
1498                         DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n", 
1499                                         yperr_string(nis_error), user_name, nis_map));
1500                 }
1501         }
1502
1503         DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
1504         return last_value;
1505 }
1506 #endif /* WITH_NISPLUS_HOME */
1507 #endif
1508
1509 /*******************************************************************
1510  Are two IPs on the same subnet?
1511 ********************************************************************/
1512
1513 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
1514 {
1515         uint32 net1,net2,nmask;
1516
1517         nmask = ntohl(mask.s_addr);
1518         net1  = ntohl(ip1.s_addr);
1519         net2  = ntohl(ip2.s_addr);
1520             
1521         return((net1 & nmask) == (net2 & nmask));
1522 }
1523
1524
1525 /****************************************************************************
1526  Check if a process exists. Does this work on all unixes?
1527 ****************************************************************************/
1528
1529 BOOL process_exists(const struct server_id pid)
1530 {
1531         if (procid_is_me(&pid)) {
1532                 return True;
1533         }
1534
1535         if (!procid_is_local(&pid)) {
1536                 /* This *SEVERELY* needs fixing. */
1537                 return True;
1538         }
1539
1540         /* Doing kill with a non-positive pid causes messages to be
1541          * sent to places we don't want. */
1542         SMB_ASSERT(pid.pid > 0);
1543         return(kill(pid.pid,0) == 0 || errno != ESRCH);
1544 }
1545
1546 BOOL process_exists_by_pid(pid_t pid)
1547 {
1548         return process_exists(pid_to_procid(pid));
1549 }
1550
1551 /*******************************************************************
1552  Convert a uid into a user name.
1553 ********************************************************************/
1554
1555 const char *uidtoname(uid_t uid)
1556 {
1557         static fstring name;
1558         struct passwd *pass;
1559
1560         pass = getpwuid_alloc(NULL, uid);
1561         if (pass) {
1562                 fstrcpy(name, pass->pw_name);
1563                 TALLOC_FREE(pass);
1564         } else {
1565                 slprintf(name, sizeof(name) - 1, "%ld",(long int)uid);
1566         }
1567         return name;
1568 }
1569
1570
1571 /*******************************************************************
1572  Convert a gid into a group name.
1573 ********************************************************************/
1574
1575 char *gidtoname(gid_t gid)
1576 {
1577         static fstring name;
1578         struct group *grp;
1579
1580         grp = getgrgid(gid);
1581         if (grp)
1582                 return(grp->gr_name);
1583         slprintf(name,sizeof(name) - 1, "%d",(int)gid);
1584         return(name);
1585 }
1586
1587 /*******************************************************************
1588  Convert a user name into a uid. 
1589 ********************************************************************/
1590
1591 uid_t nametouid(const char *name)
1592 {
1593         struct passwd *pass;
1594         char *p;
1595         uid_t u;
1596
1597         pass = getpwnam_alloc(NULL, name);
1598         if (pass) {
1599                 u = pass->pw_uid;
1600                 TALLOC_FREE(pass);
1601                 return u;
1602         }
1603
1604         u = (uid_t)strtol(name, &p, 0);
1605         if ((p != name) && (*p == '\0'))
1606                 return u;
1607
1608         return (uid_t)-1;
1609 }
1610
1611 /*******************************************************************
1612  Convert a name to a gid_t if possible. Return -1 if not a group. 
1613 ********************************************************************/
1614
1615 gid_t nametogid(const char *name)
1616 {
1617         struct group *grp;
1618         char *p;
1619         gid_t g;
1620
1621         g = (gid_t)strtol(name, &p, 0);
1622         if ((p != name) && (*p == '\0'))
1623                 return g;
1624
1625         grp = sys_getgrnam(name);
1626         if (grp)
1627                 return(grp->gr_gid);
1628         return (gid_t)-1;
1629 }
1630
1631 /*******************************************************************
1632  Something really nasty happened - panic !
1633 ********************************************************************/
1634
1635 void smb_panic(const char *const why)
1636 {
1637         char *cmd;
1638         int result;
1639
1640 #ifdef DEVELOPER
1641         {
1642
1643                 if (global_clobber_region_function) {
1644                         DEBUG(0,("smb_panic: clobber_region() last called from [%s(%u)]\n",
1645                                          global_clobber_region_function,
1646                                          global_clobber_region_line));
1647                 } 
1648         }
1649 #endif
1650
1651         DEBUG(0,("PANIC (pid %llu): %s\n",
1652                     (unsigned long long)sys_getpid(), why));
1653         log_stack_trace();
1654
1655         cmd = lp_panic_action();
1656         if (cmd && *cmd) {
1657                 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
1658                 result = system(cmd);
1659
1660                 if (result == -1)
1661                         DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
1662                                           strerror(errno)));
1663                 else
1664                         DEBUG(0, ("smb_panic(): action returned status %d\n",
1665                                           WEXITSTATUS(result)));
1666         }
1667
1668         dump_core();
1669 }
1670
1671 /*******************************************************************
1672  Print a backtrace of the stack to the debug log. This function
1673  DELIBERATELY LEAKS MEMORY. The expectation is that you should
1674  exit shortly after calling it.
1675 ********************************************************************/
1676
1677 #ifdef HAVE_LIBUNWIND_H
1678 #include <libunwind.h>
1679 #endif
1680
1681 #ifdef HAVE_EXECINFO_H
1682 #include <execinfo.h>
1683 #endif
1684
1685 #ifdef HAVE_LIBEXC_H
1686 #include <libexc.h>
1687 #endif
1688
1689 void log_stack_trace(void)
1690 {
1691 #ifdef HAVE_LIBUNWIND
1692         /* Try to use libunwind before any other technique since on ia64
1693          * libunwind correctly walks the stack in more circumstances than
1694          * backtrace.
1695          */ 
1696         unw_cursor_t cursor;
1697         unw_context_t uc;
1698         unsigned i = 0;
1699
1700         char procname[256];
1701         unw_word_t ip, sp, off;
1702
1703         procname[sizeof(procname) - 1] = '\0';
1704
1705         if (unw_getcontext(&uc) != 0) {
1706                 goto libunwind_failed;
1707         }
1708
1709         if (unw_init_local(&cursor, &uc) != 0) {
1710                 goto libunwind_failed;
1711         }
1712
1713         DEBUG(0, ("BACKTRACE:\n"));
1714
1715         do {
1716             ip = sp = 0;
1717             unw_get_reg(&cursor, UNW_REG_IP, &ip);
1718             unw_get_reg(&cursor, UNW_REG_SP, &sp);
1719
1720             switch (unw_get_proc_name(&cursor,
1721                         procname, sizeof(procname) - 1, &off) ) {
1722             case 0:
1723                     /* Name found. */
1724             case -UNW_ENOMEM:
1725                     /* Name truncated. */
1726                     DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
1727                             i, procname, (long long)off,
1728                             (long long)ip, (long long) sp));
1729                     break;
1730             default:
1731             /* case -UNW_ENOINFO: */
1732             /* case -UNW_EUNSPEC: */
1733                     /* No symbol name found. */
1734                     DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
1735                             i, "<unknown symbol>",
1736                             (long long)ip, (long long) sp));
1737             }
1738             ++i;
1739         } while (unw_step(&cursor) > 0);
1740
1741         return;
1742
1743 libunwind_failed:
1744         DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
1745
1746 #elif HAVE_BACKTRACE_SYMBOLS
1747         void *backtrace_stack[BACKTRACE_STACK_SIZE];
1748         size_t backtrace_size;
1749         char **backtrace_strings;
1750
1751         /* get the backtrace (stack frames) */
1752         backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
1753         backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
1754
1755         DEBUG(0, ("BACKTRACE: %lu stack frames:\n", 
1756                   (unsigned long)backtrace_size));
1757         
1758         if (backtrace_strings) {
1759                 int i;
1760
1761                 for (i = 0; i < backtrace_size; i++)
1762                         DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
1763
1764                 /* Leak the backtrace_strings, rather than risk what free() might do */
1765         }
1766
1767 #elif HAVE_LIBEXC
1768
1769         /* The IRIX libexc library provides an API for unwinding the stack. See
1770          * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
1771          * since we are about to abort anyway, it hardly matters.
1772          */
1773
1774 #define NAMESIZE 32 /* Arbitrary */
1775
1776         __uint64_t      addrs[BACKTRACE_STACK_SIZE];
1777         char *          names[BACKTRACE_STACK_SIZE];
1778         char            namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
1779
1780         int             i;
1781         int             levels;
1782
1783         ZERO_ARRAY(addrs);
1784         ZERO_ARRAY(names);
1785         ZERO_ARRAY(namebuf);
1786
1787         /* We need to be root so we can open our /proc entry to walk
1788          * our stack. It also helps when we want to dump core.
1789          */
1790         become_root();
1791
1792         for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
1793                 names[i] = namebuf + (i * NAMESIZE);
1794         }
1795
1796         levels = trace_back_stack(0, addrs, names,
1797                         BACKTRACE_STACK_SIZE, NAMESIZE - 1);
1798
1799         DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
1800         for (i = 0; i < levels; i++) {
1801                 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
1802         }
1803 #undef NAMESIZE
1804
1805 #else
1806         DEBUG(0, ("unable to produce a stack trace on this platform\n"));
1807 #endif
1808 }
1809
1810 /*******************************************************************
1811   A readdir wrapper which just returns the file name.
1812  ********************************************************************/
1813
1814 const char *readdirname(SMB_STRUCT_DIR *p)
1815 {
1816         SMB_STRUCT_DIRENT *ptr;
1817         char *dname;
1818
1819         if (!p)
1820                 return(NULL);
1821   
1822         ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
1823         if (!ptr)
1824                 return(NULL);
1825
1826         dname = ptr->d_name;
1827
1828 #ifdef NEXT2
1829         if (telldir(p) < 0)
1830                 return(NULL);
1831 #endif
1832
1833 #ifdef HAVE_BROKEN_READDIR_NAME
1834         /* using /usr/ucb/cc is BAD */
1835         dname = dname - 2;
1836 #endif
1837
1838         {
1839                 static pstring buf;
1840                 int len = NAMLEN(ptr);
1841                 memcpy(buf, dname, len);
1842                 buf[len] = 0;
1843                 dname = buf;
1844         }
1845
1846         return(dname);
1847 }
1848
1849 /*******************************************************************
1850  Utility function used to decide if the last component 
1851  of a path matches a (possibly wildcarded) entry in a namelist.
1852 ********************************************************************/
1853
1854 BOOL is_in_path(const char *name, name_compare_entry *namelist, BOOL case_sensitive)
1855 {
1856         pstring last_component;
1857         char *p;
1858
1859         /* if we have no list it's obviously not in the path */
1860         if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
1861                 return False;
1862         }
1863
1864         DEBUG(8, ("is_in_path: %s\n", name));
1865
1866         /* Get the last component of the unix name. */
1867         p = strrchr_m(name, '/');
1868         pstrcpy(last_component, p ? ++p : name);
1869
1870         for(; namelist->name != NULL; namelist++) {
1871                 if(namelist->is_wild) {
1872                         if (mask_match(last_component, namelist->name, case_sensitive)) {
1873                                 DEBUG(8,("is_in_path: mask match succeeded\n"));
1874                                 return True;
1875                         }
1876                 } else {
1877                         if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
1878                                                 (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0))) {
1879                                 DEBUG(8,("is_in_path: match succeeded\n"));
1880                                 return True;
1881                         }
1882                 }
1883         }
1884         DEBUG(8,("is_in_path: match not found\n"));
1885  
1886         return False;
1887 }
1888
1889 /*******************************************************************
1890  Strip a '/' separated list into an array of 
1891  name_compare_enties structures suitable for 
1892  passing to is_in_path(). We do this for
1893  speed so we can pre-parse all the names in the list 
1894  and don't do it for each call to is_in_path().
1895  namelist is modified here and is assumed to be 
1896  a copy owned by the caller.
1897  We also check if the entry contains a wildcard to
1898  remove a potentially expensive call to mask_match
1899  if possible.
1900 ********************************************************************/
1901  
1902 void set_namearray(name_compare_entry **ppname_array, char *namelist)
1903 {
1904         char *name_end;
1905         char *nameptr = namelist;
1906         int num_entries = 0;
1907         int i;
1908
1909         (*ppname_array) = NULL;
1910
1911         if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
1912                 return;
1913
1914         /* We need to make two passes over the string. The
1915                 first to count the number of elements, the second
1916                 to split it.
1917         */
1918
1919         while(*nameptr) {
1920                 if ( *nameptr == '/' ) {
1921                         /* cope with multiple (useless) /s) */
1922                         nameptr++;
1923                         continue;
1924                 }
1925                 /* find the next / */
1926                 name_end = strchr_m(nameptr, '/');
1927
1928                 /* oops - the last check for a / didn't find one. */
1929                 if (name_end == NULL)
1930                         break;
1931
1932                 /* next segment please */
1933                 nameptr = name_end + 1;
1934                 num_entries++;
1935         }
1936
1937         if(num_entries == 0)
1938                 return;
1939
1940         if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1941                 DEBUG(0,("set_namearray: malloc fail\n"));
1942                 return;
1943         }
1944
1945         /* Now copy out the names */
1946         nameptr = namelist;
1947         i = 0;
1948         while(*nameptr) {
1949                 if ( *nameptr == '/' ) {
1950                         /* cope with multiple (useless) /s) */
1951                         nameptr++;
1952                         continue;
1953                 }
1954                 /* find the next / */
1955                 if ((name_end = strchr_m(nameptr, '/')) != NULL)
1956                         *name_end = 0;
1957
1958                 /* oops - the last check for a / didn't find one. */
1959                 if(name_end == NULL) 
1960                         break;
1961
1962                 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1963                 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1964                         DEBUG(0,("set_namearray: malloc fail (1)\n"));
1965                         return;
1966                 }
1967
1968                 /* next segment please */
1969                 nameptr = name_end + 1;
1970                 i++;
1971         }
1972   
1973         (*ppname_array)[i].name = NULL;
1974
1975         return;
1976 }
1977
1978 /****************************************************************************
1979  Routine to free a namearray.
1980 ****************************************************************************/
1981
1982 void free_namearray(name_compare_entry *name_array)
1983 {
1984         int i;
1985
1986         if(name_array == NULL)
1987                 return;
1988
1989         for(i=0; name_array[i].name!=NULL; i++)
1990                 SAFE_FREE(name_array[i].name);
1991         SAFE_FREE(name_array);
1992 }
1993
1994 #undef DBGC_CLASS
1995 #define DBGC_CLASS DBGC_LOCKING
1996
1997 /****************************************************************************
1998  Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
1999  is dealt with in posix.c
2000  Returns True if the lock was granted, False otherwise.
2001 ****************************************************************************/
2002
2003 BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
2004 {
2005         SMB_STRUCT_FLOCK lock;
2006         int ret;
2007
2008         DEBUG(8,("fcntl_lock fd=%d op=%d offset=%.0f count=%.0f type=%d\n",
2009                 fd,op,(double)offset,(double)count,type));
2010
2011         lock.l_type = type;
2012         lock.l_whence = SEEK_SET;
2013         lock.l_start = offset;
2014         lock.l_len = count;
2015         lock.l_pid = 0;
2016
2017         ret = sys_fcntl_ptr(fd,op,&lock);
2018
2019         if (ret == -1) {
2020                 int sav = errno;
2021                 DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
2022                         (double)offset,(double)count,op,type,strerror(errno)));
2023                 errno = sav;
2024                 return False;
2025         }
2026
2027         /* everything went OK */
2028         DEBUG(8,("fcntl_lock: Lock call successful\n"));
2029
2030         return True;
2031 }
2032
2033 /****************************************************************************
2034  Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
2035  is dealt with in posix.c
2036  Returns True if we have information regarding this lock region (and returns
2037  F_UNLCK in *ptype if the region is unlocked). False if the call failed.
2038 ****************************************************************************/
2039
2040 BOOL fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
2041 {
2042         SMB_STRUCT_FLOCK lock;
2043         int ret;
2044
2045         DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
2046                     fd,(double)*poffset,(double)*pcount,*ptype));
2047
2048         lock.l_type = *ptype;
2049         lock.l_whence = SEEK_SET;
2050         lock.l_start = *poffset;
2051         lock.l_len = *pcount;
2052         lock.l_pid = 0;
2053
2054         ret = sys_fcntl_ptr(fd,SMB_F_GETLK,&lock);
2055
2056         if (ret == -1) {
2057                 int sav = errno;
2058                 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
2059                         (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
2060                 errno = sav;
2061                 return False;
2062         }
2063
2064         *ptype = lock.l_type;
2065         *poffset = lock.l_start;
2066         *pcount = lock.l_len;
2067         *ppid = lock.l_pid;
2068         
2069         DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
2070                         fd, (int)lock.l_type, (unsigned int)lock.l_pid));
2071         return True;
2072 }
2073
2074 #undef DBGC_CLASS
2075 #define DBGC_CLASS DBGC_ALL
2076
2077 /*******************************************************************
2078  Is the name specified one of my netbios names.
2079  Returns true if it is equal, false otherwise.
2080 ********************************************************************/
2081
2082 BOOL is_myname(const char *s)
2083 {
2084         int n;
2085         BOOL ret = False;
2086
2087         for (n=0; my_netbios_names(n); n++) {
2088                 if (strequal(my_netbios_names(n), s)) {
2089                         ret=True;
2090                         break;
2091                 }
2092         }
2093         DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
2094         return(ret);
2095 }
2096
2097 BOOL is_myname_or_ipaddr(const char *s)
2098 {
2099         fstring name, dnsname;
2100         char *servername;
2101
2102         if ( !s )
2103                 return False;
2104
2105         /* santize the string from '\\name' */
2106
2107         fstrcpy( name, s );
2108
2109         servername = strrchr_m( name, '\\' );
2110         if ( !servername )
2111                 servername = name;
2112         else
2113                 servername++;
2114
2115         /* optimize for the common case */
2116
2117         if (strequal(servername, global_myname())) 
2118                 return True;
2119
2120         /* check for an alias */
2121
2122         if (is_myname(servername))
2123                 return True;
2124
2125         /* check for loopback */
2126
2127         if (strequal(servername, "127.0.0.1")) 
2128                 return True;
2129
2130         if (strequal(servername, "localhost")) 
2131                 return True;
2132
2133         /* maybe it's my dns name */
2134
2135         if ( get_mydnsfullname( dnsname ) )
2136                 if ( strequal( servername, dnsname ) )
2137                         return True;
2138                 
2139         /* handle possible CNAME records */
2140
2141         if ( !is_ipaddress( servername ) ) {
2142                 /* use DNS to resolve the name, but only the first address */
2143                 struct hostent *hp;
2144
2145                 if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
2146                         struct in_addr return_ip;
2147                         putip( (char*)&return_ip, (char*)hp->h_addr );
2148                         fstrcpy( name, inet_ntoa( return_ip ) );
2149                         servername = name;
2150                 }       
2151         }
2152                 
2153         /* maybe its an IP address? */
2154         if (is_ipaddress(servername)) {
2155                 struct iface_struct nics[MAX_INTERFACES];
2156                 int i, n;
2157                 uint32 ip;
2158                 
2159                 ip = interpret_addr(servername);
2160                 if ((ip==0) || (ip==0xffffffff))
2161                         return False;
2162                         
2163                 n = get_interfaces(nics, MAX_INTERFACES);
2164                 for (i=0; i<n; i++) {
2165                         if (ip == nics[i].ip.s_addr)
2166                                 return True;
2167                 }
2168         }       
2169
2170         /* no match */
2171         return False;
2172 }
2173
2174 /*******************************************************************
2175  Is the name specified our workgroup/domain.
2176  Returns true if it is equal, false otherwise.
2177 ********************************************************************/
2178
2179 BOOL is_myworkgroup(const char *s)
2180 {
2181         BOOL ret = False;
2182
2183         if (strequal(s, lp_workgroup())) {
2184                 ret=True;
2185         }
2186
2187         DEBUG(8, ("is_myworkgroup(\"%s\") returns %d\n", s, ret));
2188         return(ret);
2189 }
2190
2191 /*******************************************************************
2192  we distinguish between 2K and XP by the "Native Lan Manager" string
2193    WinXP => "Windows 2002 5.1"
2194    WinXP 64bit => "Windows XP 5.2"
2195    Win2k => "Windows 2000 5.0"
2196    NT4   => "Windows NT 4.0" 
2197    Win9x => "Windows 4.0"
2198  Windows 2003 doesn't set the native lan manager string but 
2199  they do set the domain to "Windows 2003 5.2" (probably a bug).
2200 ********************************************************************/
2201
2202 void ra_lanman_string( const char *native_lanman )
2203 {       
2204         if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
2205                 set_remote_arch( RA_WINXP );
2206         else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
2207                 set_remote_arch( RA_WINXP );
2208         else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
2209                 set_remote_arch( RA_WIN2K3 );
2210 }
2211
2212 /*******************************************************************
2213  Set the horrid remote_arch string based on an enum.
2214 ********************************************************************/
2215
2216 void set_remote_arch(enum remote_arch_types type)
2217 {
2218         ra_type = type;
2219         switch( type ) {
2220         case RA_WFWG:
2221                 fstrcpy(remote_arch, "WfWg");
2222                 break;
2223         case RA_OS2:
2224                 fstrcpy(remote_arch, "OS2");
2225                 break;
2226         case RA_WIN95:
2227                 fstrcpy(remote_arch, "Win95");
2228                 break;
2229         case RA_WINNT:
2230                 fstrcpy(remote_arch, "WinNT");
2231                 break;
2232         case RA_WIN2K:
2233                 fstrcpy(remote_arch, "Win2K");
2234                 break;
2235         case RA_WINXP:
2236                 fstrcpy(remote_arch, "WinXP");
2237                 break;
2238         case RA_WIN2K3:
2239                 fstrcpy(remote_arch, "Win2K3");
2240                 break;
2241         case RA_VISTA:
2242                 fstrcpy(remote_arch, "Vista");
2243                 break;
2244         case RA_SAMBA:
2245                 fstrcpy(remote_arch,"Samba");
2246                 break;
2247         case RA_CIFSFS:
2248                 fstrcpy(remote_arch,"CIFSFS");
2249                 break;
2250         default:
2251                 ra_type = RA_UNKNOWN;
2252                 fstrcpy(remote_arch, "UNKNOWN");
2253                 break;
2254         }
2255
2256         DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n", remote_arch));
2257 }
2258
2259 /*******************************************************************
2260  Get the remote_arch type.
2261 ********************************************************************/
2262
2263 enum remote_arch_types get_remote_arch(void)
2264 {
2265         return ra_type;
2266 }
2267
2268 void print_asc(int level, const unsigned char *buf,int len)
2269 {
2270         int i;
2271         for (i=0;i<len;i++)
2272                 DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
2273 }
2274
2275 void dump_data(int level, const unsigned char *buf,int len)
2276 {
2277         int i=0;
2278         if (len<=0) return;
2279
2280         if (!DEBUGLVL(level)) return;
2281         
2282         DEBUGADD(level,("[%03X] ",i));
2283         for (i=0;i<len;) {
2284                 DEBUGADD(level,("%02X ",(int)buf[i]));
2285                 i++;
2286                 if (i%8 == 0) DEBUGADD(level,(" "));
2287                 if (i%16 == 0) {      
2288                         print_asc(level,&buf[i-16],8); DEBUGADD(level,(" "));
2289                         print_asc(level,&buf[i-8],8); DEBUGADD(level,("\n"));
2290                         if (i<len) DEBUGADD(level,("[%03X] ",i));
2291                 }
2292         }
2293         if (i%16) {
2294                 int n;
2295                 n = 16 - (i%16);
2296                 DEBUGADD(level,(" "));
2297                 if (n>8) DEBUGADD(level,(" "));
2298                 while (n--) DEBUGADD(level,("   "));
2299                 n = MIN(8,i%16);
2300                 print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,( " " ));
2301                 n = (i%16) - n;
2302                 if (n>0) print_asc(level,&buf[i-n],n); 
2303                 DEBUGADD(level,("\n"));    
2304         }       
2305 }
2306
2307 void dump_data_pw(const char *msg, const uchar * data, size_t len)
2308 {
2309 #ifdef DEBUG_PASSWORD
2310         DEBUG(11, ("%s", msg));
2311         if (data != NULL && len > 0)
2312         {
2313                 dump_data(11, data, len);
2314         }
2315 #endif
2316 }
2317
2318 char *tab_depth(int depth)
2319 {
2320         static pstring spaces;
2321         memset(spaces, ' ', depth * 4);
2322         spaces[depth * 4] = 0;
2323         return spaces;
2324 }
2325
2326 /*****************************************************************************
2327  Provide a checksum on a string
2328
2329  Input:  s - the null-terminated character string for which the checksum
2330              will be calculated.
2331
2332   Output: The checksum value calculated for s.
2333 *****************************************************************************/
2334
2335 int str_checksum(const char *s)
2336 {
2337         int res = 0;
2338         int c;
2339         int i=0;
2340         
2341         while(*s) {
2342                 c = *s;
2343                 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
2344                 s++;
2345                 i++;
2346         }
2347         return(res);
2348 }
2349
2350 /*****************************************************************
2351  Zero a memory area then free it. Used to catch bugs faster.
2352 *****************************************************************/  
2353
2354 void zero_free(void *p, size_t size)
2355 {
2356         memset(p, 0, size);
2357         SAFE_FREE(p);
2358 }
2359
2360 /*****************************************************************
2361  Set our open file limit to a requested max and return the limit.
2362 *****************************************************************/  
2363
2364 int set_maxfiles(int requested_max)
2365 {
2366 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
2367         struct rlimit rlp;
2368         int saved_current_limit;
2369
2370         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2371                 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
2372                         strerror(errno) ));
2373                 /* just guess... */
2374                 return requested_max;
2375         }
2376
2377         /* 
2378          * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
2379          * account for the extra fd we need 
2380          * as well as the log files and standard
2381          * handles etc. Save the limit we want to set in case
2382          * we are running on an OS that doesn't support this limit (AIX)
2383          * which always returns RLIM_INFINITY for rlp.rlim_max.
2384          */
2385
2386         /* Try raising the hard (max) limit to the requested amount. */
2387
2388 #if defined(RLIM_INFINITY)
2389         if (rlp.rlim_max != RLIM_INFINITY) {
2390                 int orig_max = rlp.rlim_max;
2391
2392                 if ( rlp.rlim_max < requested_max )
2393                         rlp.rlim_max = requested_max;
2394
2395                 /* This failing is not an error - many systems (Linux) don't
2396                         support our default request of 10,000 open files. JRA. */
2397
2398                 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
2399                         DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n", 
2400                                 (int)rlp.rlim_max, strerror(errno) ));
2401
2402                         /* Set failed - restore original value from get. */
2403                         rlp.rlim_max = orig_max;
2404                 }
2405         }
2406 #endif
2407
2408         /* Now try setting the soft (current) limit. */
2409
2410         saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
2411
2412         if(setrlimit(RLIMIT_NOFILE, &rlp)) {
2413                 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n", 
2414                         (int)rlp.rlim_cur, strerror(errno) ));
2415                 /* just guess... */
2416                 return saved_current_limit;
2417         }
2418
2419         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2420                 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
2421                         strerror(errno) ));
2422                 /* just guess... */
2423                 return saved_current_limit;
2424     }
2425
2426 #if defined(RLIM_INFINITY)
2427         if(rlp.rlim_cur == RLIM_INFINITY)
2428                 return saved_current_limit;
2429 #endif
2430
2431         if((int)rlp.rlim_cur > saved_current_limit)
2432                 return saved_current_limit;
2433
2434         return rlp.rlim_cur;
2435 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
2436         /*
2437          * No way to know - just guess...
2438          */
2439         return requested_max;
2440 #endif
2441 }
2442
2443 /*****************************************************************
2444  Possibly replace mkstemp if it is broken.
2445 *****************************************************************/  
2446
2447 int smb_mkstemp(char *name_template)
2448 {
2449 #if HAVE_SECURE_MKSTEMP
2450         return mkstemp(name_template);
2451 #else
2452         /* have a reasonable go at emulating it. Hope that
2453            the system mktemp() isn't completly hopeless */
2454         char *p = mktemp(name_template);
2455         if (!p)
2456                 return -1;
2457         return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
2458 #endif
2459 }
2460
2461 /*****************************************************************
2462  malloc that aborts with smb_panic on fail or zero size.
2463  *****************************************************************/  
2464
2465 void *smb_xmalloc_array(size_t size, unsigned int count)
2466 {
2467         void *p;
2468         if (size == 0)
2469                 smb_panic("smb_xmalloc_array: called with zero size.\n");
2470         if (count >= MAX_ALLOC_SIZE/size) {
2471                 smb_panic("smb_xmalloc: alloc size too large.\n");
2472         }
2473         if ((p = SMB_MALLOC(size*count)) == NULL) {
2474                 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
2475                         (unsigned long)size, (unsigned long)count));
2476                 smb_panic("smb_xmalloc_array: malloc fail.\n");
2477         }
2478         return p;
2479 }
2480
2481 /**
2482  Memdup with smb_panic on fail.
2483 **/
2484
2485 void *smb_xmemdup(const void *p, size_t size)
2486 {
2487         void *p2;
2488         p2 = SMB_XMALLOC_ARRAY(unsigned char,size);
2489         memcpy(p2, p, size);
2490         return p2;
2491 }
2492
2493 /**
2494  strdup that aborts on malloc fail.
2495 **/
2496
2497 char *smb_xstrdup(const char *s)
2498 {
2499 #if defined(PARANOID_MALLOC_CHECKER)
2500 #ifdef strdup
2501 #undef strdup
2502 #endif
2503 #endif
2504
2505 #ifndef HAVE_STRDUP
2506 #define strdup rep_strdup
2507 #endif
2508
2509         char *s1 = strdup(s);
2510 #if defined(PARANOID_MALLOC_CHECKER)
2511 #ifdef strdup
2512 #undef strdup
2513 #endif
2514 #define strdup(s) __ERROR_DONT_USE_STRDUP_DIRECTLY
2515 #endif
2516         if (!s1)
2517                 smb_panic("smb_xstrdup: malloc fail\n");
2518         return s1;
2519
2520 }
2521
2522 /**
2523  strndup that aborts on malloc fail.
2524 **/
2525
2526 char *smb_xstrndup(const char *s, size_t n)
2527 {
2528 #if defined(PARANOID_MALLOC_CHECKER)
2529 #ifdef strndup
2530 #undef strndup
2531 #endif
2532 #endif
2533
2534 #if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP))
2535 #undef HAVE_STRNDUP
2536 #define strndup rep_strndup
2537 #endif
2538
2539         char *s1 = strndup(s, n);
2540 #if defined(PARANOID_MALLOC_CHECKER)
2541 #ifdef strndup
2542 #undef strndup
2543 #endif
2544 #define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY
2545 #endif
2546         if (!s1)
2547                 smb_panic("smb_xstrndup: malloc fail\n");
2548         return s1;
2549 }
2550
2551 /*
2552   vasprintf that aborts on malloc fail
2553 */
2554
2555  int smb_xvasprintf(char **ptr, const char *format, va_list ap)
2556 {
2557         int n;
2558         va_list ap2;
2559
2560         VA_COPY(ap2, ap);
2561
2562         n = vasprintf(ptr, format, ap2);
2563         if (n == -1 || ! *ptr)
2564                 smb_panic("smb_xvasprintf: out of memory");
2565         return n;
2566 }
2567
2568 /*****************************************************************
2569  Like strdup but for memory.
2570 *****************************************************************/  
2571
2572 void *memdup(const void *p, size_t size)
2573 {
2574         void *p2;
2575         if (size == 0)
2576                 return NULL;
2577         p2 = SMB_MALLOC(size);
2578         if (!p2)
2579                 return NULL;
2580         memcpy(p2, p, size);
2581         return p2;
2582 }
2583
2584 /*****************************************************************
2585  Get local hostname and cache result.
2586 *****************************************************************/  
2587
2588 char *myhostname(void)
2589 {
2590         static pstring ret;
2591         if (ret[0] == 0)
2592                 get_myname(ret);
2593         return ret;
2594 }
2595
2596 /*****************************************************************
2597  A useful function for returning a path in the Samba lock directory.
2598 *****************************************************************/  
2599
2600 char *lock_path(const char *name)
2601 {
2602         static pstring fname;
2603
2604         pstrcpy(fname,lp_lockdir());
2605         trim_char(fname,'\0','/');
2606         
2607         if (!directory_exist(fname,NULL))
2608                 mkdir(fname,0755);
2609         
2610         pstrcat(fname,"/");
2611         pstrcat(fname,name);
2612
2613         return fname;
2614 }
2615
2616 /*****************************************************************
2617  A useful function for returning a path in the Samba pid directory.
2618 *****************************************************************/
2619
2620 char *pid_path(const char *name)
2621 {
2622         static pstring fname;
2623
2624         pstrcpy(fname,lp_piddir());
2625         trim_char(fname,'\0','/');
2626
2627         if (!directory_exist(fname,NULL))
2628                 mkdir(fname,0755);
2629
2630         pstrcat(fname,"/");
2631         pstrcat(fname,name);
2632
2633         return fname;
2634 }
2635
2636 /**
2637  * @brief Returns an absolute path to a file in the Samba lib directory.
2638  *
2639  * @param name File to find, relative to LIBDIR.
2640  *
2641  * @retval Pointer to a static #pstring containing the full path.
2642  **/
2643
2644 char *lib_path(const char *name)
2645 {
2646         static pstring fname;
2647         fstr_sprintf(fname, "%s/%s", dyn_LIBDIR, name);
2648         return fname;
2649 }
2650
2651 /**
2652  * @brief Returns the platform specific shared library extension.
2653  *
2654  * @retval Pointer to a static #fstring containing the extension.
2655  **/
2656
2657 const char *shlib_ext(void)
2658 {
2659   return dyn_SHLIBEXT;
2660 }
2661
2662 /*******************************************************************
2663  Given a filename - get its directory name
2664  NB: Returned in static storage.  Caveats:
2665  o  Not safe in thread environment.
2666  o  Caller must not free.
2667  o  If caller wishes to preserve, they should copy.
2668 ********************************************************************/
2669
2670 char *parent_dirname(const char *path)
2671 {
2672         static pstring dirpath;
2673         char *p;
2674
2675         if (!path)
2676                 return(NULL);
2677
2678         pstrcpy(dirpath, path);
2679         p = strrchr_m(dirpath, '/');  /* Find final '/', if any */
2680         if (!p) {
2681                 pstrcpy(dirpath, ".");    /* No final "/", so dir is "." */
2682         } else {
2683                 if (p == dirpath)
2684                         ++p;    /* For root "/", leave "/" in place */
2685                 *p = '\0';
2686         }
2687         return dirpath;
2688 }
2689
2690 BOOL parent_dirname_talloc(TALLOC_CTX *mem_ctx, const char *dir,
2691                            char **parent, const char **name)
2692 {
2693         char *p;
2694         ptrdiff_t len;
2695  
2696         p = strrchr_m(dir, '/'); /* Find final '/', if any */
2697
2698         if (p == NULL) {
2699                 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
2700                         return False;
2701                 }
2702                 if (name) {
2703                         *name = "";
2704                 }
2705                 return True;
2706         }
2707
2708         len = p-dir;
2709
2710         if (!(*parent = TALLOC_ARRAY(mem_ctx, char, len+1))) {
2711                 return False;
2712         }
2713         memcpy(*parent, dir, len);
2714         (*parent)[len] = '\0';
2715
2716         if (name) {
2717                 *name = p+1;
2718         }
2719         return True;
2720 }
2721
2722 /*******************************************************************
2723  Determine if a pattern contains any Microsoft wildcard characters.
2724 *******************************************************************/
2725
2726 BOOL ms_has_wild(const char *s)
2727 {
2728         char c;
2729
2730         if (lp_posix_pathnames()) {
2731                 /* With posix pathnames no characters are wild. */
2732                 return False;
2733         }
2734
2735         while ((c = *s++)) {
2736                 switch (c) {
2737                 case '*':
2738                 case '?':
2739                 case '<':
2740                 case '>':
2741                 case '"':
2742                         return True;
2743                 }
2744         }
2745         return False;
2746 }
2747
2748 BOOL ms_has_wild_w(const smb_ucs2_t *s)
2749 {
2750         smb_ucs2_t c;
2751         if (!s) return False;
2752         while ((c = *s++)) {
2753                 switch (c) {
2754                 case UCS2_CHAR('*'):
2755                 case UCS2_CHAR('?'):
2756                 case UCS2_CHAR('<'):
2757                 case UCS2_CHAR('>'):
2758                 case UCS2_CHAR('"'):
2759                         return True;
2760                 }
2761         }
2762         return False;
2763 }
2764
2765 /*******************************************************************
2766  A wrapper that handles case sensitivity and the special handling
2767  of the ".." name.
2768 *******************************************************************/
2769
2770 BOOL mask_match(const char *string, char *pattern, BOOL is_case_sensitive)
2771 {
2772         if (strcmp(string,"..") == 0)
2773                 string = ".";
2774         if (strcmp(pattern,".") == 0)
2775                 return False;
2776         
2777         return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
2778 }
2779
2780 /*******************************************************************
2781  A wrapper that handles case sensitivity and the special handling
2782  of the ".." name. Varient that is only called by old search code which requires
2783  pattern translation.
2784 *******************************************************************/
2785
2786 BOOL mask_match_search(const char *string, char *pattern, BOOL is_case_sensitive)
2787 {
2788         if (strcmp(string,"..") == 0)
2789                 string = ".";
2790         if (strcmp(pattern,".") == 0)
2791                 return False;
2792         
2793         return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
2794 }
2795
2796 /*******************************************************************
2797  A wrapper that handles a list of patters and calls mask_match()
2798  on each.  Returns True if any of the patterns match.
2799 *******************************************************************/
2800
2801 BOOL mask_match_list(const char *string, char **list, int listLen, BOOL is_case_sensitive)
2802 {
2803        while (listLen-- > 0) {
2804                if (mask_match(string, *list++, is_case_sensitive))
2805                        return True;
2806        }
2807        return False;
2808 }
2809
2810 /*********************************************************
2811  Recursive routine that is called by unix_wild_match.
2812 *********************************************************/
2813
2814 static BOOL unix_do_match(const char *regexp, const char *str)
2815 {
2816         const char *p;
2817
2818         for( p = regexp; *p && *str; ) {
2819
2820                 switch(*p) {
2821                         case '?':
2822                                 str++;
2823                                 p++;
2824                                 break;
2825
2826                         case '*':
2827
2828                                 /*
2829                                  * Look for a character matching 
2830                                  * the one after the '*'.
2831                                  */
2832                                 p++;
2833                                 if(!*p)
2834                                         return True; /* Automatic match */
2835                                 while(*str) {
2836
2837                                         while(*str && (*p != *str))
2838                                                 str++;
2839
2840                                         /*
2841                                          * Patch from weidel@multichart.de. In the case of the regexp
2842                                          * '*XX*' we want to ensure there are at least 2 'X' characters
2843                                          * in the string after the '*' for a match to be made.
2844                                          */
2845
2846                                         {
2847                                                 int matchcount=0;
2848
2849                                                 /*
2850                                                  * Eat all the characters that match, but count how many there were.
2851                                                  */
2852
2853                                                 while(*str && (*p == *str)) {
2854                                                         str++;
2855                                                         matchcount++;
2856                                                 }
2857
2858                                                 /*
2859                                                  * Now check that if the regexp had n identical characters that
2860                                                  * matchcount had at least that many matches.
2861                                                  */
2862
2863                                                 while ( *(p+1) && (*(p+1) == *p)) {
2864                                                         p++;
2865                                                         matchcount--;
2866                                                 }
2867
2868                                                 if ( matchcount <= 0 )
2869                                                         return False;
2870                                         }
2871
2872                                         str--; /* We've eaten the match char after the '*' */
2873
2874                                         if(unix_do_match(p, str))
2875                                                 return True;
2876
2877                                         if(!*str)
2878                                                 return False;
2879                                         else
2880                                                 str++;
2881                                 }
2882                                 return False;
2883
2884                         default:
2885                                 if(*str != *p)
2886                                         return False;
2887                                 str++;
2888                                 p++;
2889                                 break;
2890                 }
2891         }
2892
2893         if(!*p && !*str)
2894                 return True;
2895
2896         if (!*p && str[0] == '.' && str[1] == 0)
2897                 return(True);
2898   
2899         if (!*str && *p == '?') {
2900                 while (*p == '?')
2901                         p++;
2902                 return(!*p);
2903         }
2904
2905         if(!*str && (*p == '*' && p[1] == '\0'))
2906                 return True;
2907
2908         return False;
2909 }
2910
2911 /*******************************************************************
2912  Simple case insensitive interface to a UNIX wildcard matcher.
2913  Returns True if match, False if not.
2914 *******************************************************************/
2915
2916 BOOL unix_wild_match(const char *pattern, const char *string)
2917 {
2918         pstring p2, s2;
2919         char *p;
2920
2921         pstrcpy(p2, pattern);
2922         pstrcpy(s2, string);
2923         strlower_m(p2);
2924         strlower_m(s2);
2925
2926         /* Remove any *? and ** from the pattern as they are meaningless */
2927         for(p = p2; *p; p++)
2928                 while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
2929                         pstrcpy( &p[1], &p[2]);
2930  
2931         if (strequal(p2,"*"))
2932                 return True;
2933
2934         return unix_do_match(p2, s2);
2935 }
2936
2937 /**********************************************************************
2938  Converts a name to a fully qualified domain name.
2939  Returns True if lookup succeeded, False if not (then fqdn is set to name)
2940 ***********************************************************************/
2941                                                                                                                                                    
2942 BOOL name_to_fqdn(fstring fqdn, const char *name)
2943 {
2944         struct hostent *hp = sys_gethostbyname(name);
2945
2946         if ( hp && hp->h_name && *hp->h_name ) {
2947                 char *full = NULL;
2948
2949                 /* find out if the fqdn is returned as an alias
2950                  * to cope with /etc/hosts files where the first
2951                  * name is not the fqdn but the short name */
2952                 if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
2953                         int i;
2954                         for (i = 0; hp->h_aliases[i]; i++) {
2955                                 if (strchr_m(hp->h_aliases[i], '.')) {
2956                                         full = hp->h_aliases[i];
2957                                         break;
2958                                 }
2959                         }
2960                 }
2961                 if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) {
2962                         DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
2963                         DEBUGADD(1, ("    Specifing the machine hostname for address 127.0.0.1 may lead\n"));
2964                         DEBUGADD(1, ("    to Kerberos authentication problems as localhost.localdomain\n"));
2965                         DEBUGADD(1, ("    may end up being used instead of the real machine FQDN.\n"));
2966                         full = hp->h_name;
2967                 }
2968                         
2969                 if (!full) {
2970                         full = hp->h_name;
2971                 }
2972
2973                 DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
2974                 fstrcpy(fqdn, full);
2975                 return True;
2976         } else {
2977                 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
2978                 fstrcpy(fqdn, name);
2979                 return False;
2980         }
2981 }
2982
2983 /**********************************************************************
2984  Extension to talloc_get_type: Abort on type mismatch
2985 ***********************************************************************/
2986
2987 void *talloc_check_name_abort(const void *ptr, const char *name)
2988 {
2989         void *result;
2990
2991         result = talloc_check_name(ptr, name);
2992         if (result != NULL)
2993                 return result;
2994
2995         DEBUG(0, ("Talloc type mismatch, expected %s, got %s\n",
2996                   name, talloc_get_name(ptr)));
2997         smb_panic("aborting");
2998         /* Keep the compiler happy */
2999         return NULL;
3000 }
3001
3002
3003 #ifdef __INSURE__
3004
3005 /*******************************************************************
3006 This routine is a trick to immediately catch errors when debugging
3007 with insure. A xterm with a gdb is popped up when insure catches
3008 a error. It is Linux specific.
3009 ********************************************************************/
3010
3011 int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
3012 {
3013         static int (*fn)();
3014         int ret;
3015         char pidstr[10];
3016         /* you can get /usr/bin/backtrace from 
3017            http://samba.org/ftp/unpacked/junkcode/backtrace */
3018         pstring cmd = "/usr/bin/backtrace %d";
3019
3020         slprintf(pidstr, sizeof(pidstr)-1, "%d", sys_getpid());
3021         pstring_sub(cmd, "%d", pidstr);
3022
3023         if (!fn) {
3024                 static void *h;
3025                 h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
3026                 fn = dlsym(h, "_Insure_trap_error");
3027
3028                 if (!h || h == _Insure_trap_error) {
3029                         h = dlopen("/usr/local/parasoft/lib.linux2/libinsure.so", RTLD_LAZY);
3030                         fn = dlsym(h, "_Insure_trap_error");
3031                 }               
3032         }
3033
3034         ret = fn(a1, a2, a3, a4, a5, a6);
3035
3036         system(cmd);
3037
3038         return ret;
3039 }
3040 #endif
3041
3042 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
3043 {
3044         switch (share_access & ~FILE_SHARE_DELETE) {
3045                 case FILE_SHARE_NONE:
3046                         return DENY_ALL;
3047                 case FILE_SHARE_READ:
3048                         return DENY_WRITE;
3049                 case FILE_SHARE_WRITE:
3050                         return DENY_READ;
3051                 case FILE_SHARE_READ|FILE_SHARE_WRITE:
3052                         return DENY_NONE;
3053         }
3054         if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
3055                 return DENY_DOS;
3056         } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
3057                 return DENY_FCB;
3058         }
3059
3060         return (uint32)-1;
3061 }
3062
3063 pid_t procid_to_pid(const struct server_id *proc)
3064 {
3065         return proc->pid;
3066 }
3067
3068 struct server_id pid_to_procid(pid_t pid)
3069 {
3070         struct server_id result;
3071         result.pid = pid;
3072         return result;
3073 }
3074
3075 struct server_id procid_self(void)
3076 {
3077         return pid_to_procid(sys_getpid());
3078 }
3079
3080 struct server_id server_id_self(void)
3081 {
3082         return procid_self();
3083 }
3084
3085 BOOL procid_equal(const struct server_id *p1, const struct server_id *p2)
3086 {
3087         return (p1->pid == p2->pid);
3088 }
3089
3090 BOOL cluster_id_equal(const struct server_id *id1,
3091                       const struct server_id *id2)
3092 {
3093         return procid_equal(id1, id2);
3094 }
3095
3096 BOOL procid_is_me(const struct server_id *pid)
3097 {
3098         return (pid->pid == sys_getpid());
3099 }
3100
3101 struct server_id interpret_pid(const char *pid_string)
3102 {
3103         return pid_to_procid(atoi(pid_string));
3104 }
3105
3106 char *procid_str_static(const struct server_id *pid)
3107 {
3108         static fstring str;
3109         fstr_sprintf(str, "%d", pid->pid);
3110         return str;
3111 }
3112
3113 char *procid_str(TALLOC_CTX *mem_ctx, const struct server_id *pid)
3114 {
3115         return talloc_strdup(mem_ctx, procid_str_static(pid));
3116 }
3117
3118 BOOL procid_valid(const struct server_id *pid)
3119 {
3120         return (pid->pid != -1);
3121 }
3122
3123 BOOL procid_is_local(const struct server_id *pid)
3124 {
3125         return True;
3126 }
3127
3128 int this_is_smp(void)
3129 {
3130 #if defined(HAVE_SYSCONF)
3131
3132 #if defined(SYSCONF_SC_NPROC_ONLN)
3133         return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0;
3134 #elif defined(SYSCONF_SC_NPROCESSORS_ONLN)
3135         return (sysconf(_SC_NPROCESSORS_ONLN) > 1) ? 1 : 0;
3136 #else
3137         return 0;
3138 #endif
3139
3140 #else
3141         return 0;
3142 #endif
3143 }
3144
3145 /****************************************************************
3146  Check if an offset into a buffer is safe.
3147  If this returns True it's safe to indirect into the byte at
3148  pointer ptr+off.
3149 ****************************************************************/
3150
3151 BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
3152 {
3153         const char *end_base = buf_base + buf_len;
3154         char *end_ptr = ptr + off;
3155
3156         if (!buf_base || !ptr) {
3157                 return False;
3158         }
3159
3160         if (end_base < buf_base || end_ptr < ptr) {
3161                 return False; /* wrap. */
3162         }
3163
3164         if (end_ptr < end_base) {
3165                 return True;
3166         }
3167         return False;
3168 }
3169
3170 /****************************************************************
3171  Return a safe pointer into a buffer, or NULL.
3172 ****************************************************************/
3173
3174 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
3175 {
3176         return is_offset_safe(buf_base, buf_len, ptr, off) ?
3177                         ptr + off : NULL;
3178 }
3179
3180 /****************************************************************
3181  Return a safe pointer into a string within a buffer, or NULL.
3182 ****************************************************************/
3183
3184 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
3185 {
3186         if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
3187                 return NULL;
3188         }
3189         /* Check if a valid string exists at this offset. */
3190         if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
3191                 return NULL;
3192         }
3193         return ptr + off;
3194 }
3195
3196 /****************************************************************
3197  Return an SVAL at a pointer, or failval if beyond the end.
3198 ****************************************************************/
3199
3200 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
3201 {
3202         /*
3203          * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
3204          * NOT ptr[2].
3205          */
3206         if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
3207                 return failval;
3208         }
3209         return SVAL(ptr,off);
3210 }
3211
3212 /****************************************************************
3213  Return an IVAL at a pointer, or failval if beyond the end.
3214 ****************************************************************/
3215
3216 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
3217 {
3218         /*
3219          * Note we use off+3 here, not off+4 as IVAL accesses 
3220          * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
3221          */
3222         if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
3223                 return failval;
3224         }
3225         return IVAL(ptr,off);
3226 }
3227
3228 /****************************************************************
3229  talloc wrapper functions that guarentee a null pointer return
3230  if size == 0.
3231 ****************************************************************/
3232
3233 #ifndef MAX_TALLOC_SIZE
3234 #define MAX_TALLOC_SIZE 0x10000000
3235 #endif
3236
3237 /*
3238  *    talloc and zero memory.
3239  *    - returns NULL if size is zero.
3240  */
3241
3242 void *_talloc_zero_zeronull(const void *ctx, size_t size, const char *name)
3243 {
3244         void *p;
3245
3246         if (size == 0) {
3247                 return NULL;
3248         }
3249
3250         p = talloc_named_const(ctx, size, name);
3251
3252         if (p) {
3253                 memset(p, '\0', size);
3254         }
3255
3256         return p;
3257 }
3258
3259 /*
3260  *   memdup with a talloc.
3261  *   - returns NULL if size is zero.
3262  */
3263
3264 void *_talloc_memdup_zeronull(const void *t, const void *p, size_t size, const char *name)
3265 {
3266         void *newp;
3267
3268         if (size == 0) {
3269                 return NULL;
3270         }
3271
3272         newp = talloc_named_const(t, size, name);
3273         if (newp) {
3274                 memcpy(newp, p, size);
3275         }
3276
3277         return newp;
3278 }
3279
3280 /*
3281  *   alloc an array, checking for integer overflow in the array size.
3282  *   - returns NULL if count or el_size are zero.
3283  */
3284
3285 void *_talloc_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
3286 {
3287         if (count >= MAX_TALLOC_SIZE/el_size) {
3288                 return NULL;
3289         }
3290
3291         if (el_size == 0 || count == 0) {
3292                 return NULL;
3293         }
3294
3295         return talloc_named_const(ctx, el_size * count, name);
3296 }
3297
3298 /*
3299  *   alloc an zero array, checking for integer overflow in the array size
3300  *   - returns NULL if count or el_size are zero.
3301  */
3302
3303 void *_talloc_zero_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
3304 {
3305         if (count >= MAX_TALLOC_SIZE/el_size) {
3306                 return NULL;
3307         }
3308
3309         if (el_size == 0 || count == 0) {
3310                 return NULL;
3311         }
3312
3313         return _talloc_zero(ctx, el_size * count, name);
3314 }
3315
3316 /*
3317  *   Talloc wrapper that returns NULL if size == 0.
3318  */
3319 void *talloc_zeronull(const void *context, size_t size, const char *name)
3320 {
3321         if (size == 0) {
3322                 return NULL;
3323         }
3324         return talloc_named_const(context, size, name);
3325 }