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