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

Last change on this file since 104 was 62, checked in by Paul Smedley, 18 years ago

Update source to 3.0.25c level

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