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