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