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