source: branches/samba-3.3.x/source/lib/util.c@ 223

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

Import Samba 3.3 branch at 3.0.0 level (psmedley's port)

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