source: branches/samba-3.0/source/lib/util.c@ 363

Last change on this file since 363 was 170, checked in by Herwig Bauernfeind, 16 years ago

Fix for Ticket #69 and #71

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