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