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

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

Fixes for Tickets #69 and #71 (by diver) in 3.2 branch

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