source: branches/samba-3.2.x/source/lib/util.c@ 216

Last change on this file since 216 was 149, checked in by Paul Smedley, 17 years ago

Update trunk to v3.2.2

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