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

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

Update source to 3.0.27a

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