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