VERSION: Bump version up to 3.6.20.
[Samba.git] / source3 / lib / util.c
blob23bb11c37855b5c3a748baab67bd29d3578f0e58
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
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.
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.
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/>.
24 #include "includes.h"
25 #include "system/passwd.h"
26 #include "system/filesys.h"
27 #include "util_tdb.h"
28 #include "ctdbd_conn.h"
29 #include "../lib/util/util_pw.h"
30 #include "messages.h"
31 #include "libcli/security/security.h"
33 extern char *global_clobber_region_function;
34 extern unsigned int global_clobber_region_line;
36 /* Max allowable allococation - 256mb - 0x10000000 */
37 #define MAX_ALLOC_SIZE (1024*1024*256)
39 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
40 #ifdef WITH_NISPLUS_HOME
41 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
43 * The following lines are needed due to buggy include files
44 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
45 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
46 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
47 * an enum in /usr/include/rpcsvc/nis.h.
50 #if defined(GROUP)
51 #undef GROUP
52 #endif
54 #if defined(GROUP_OBJ)
55 #undef GROUP_OBJ
56 #endif
58 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
60 #include <rpcsvc/nis.h>
62 #endif /* WITH_NISPLUS_HOME */
63 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
65 static enum protocol_types Protocol = PROTOCOL_COREPLUS;
67 enum protocol_types get_Protocol(void)
69 return Protocol;
72 void set_Protocol(enum protocol_types p)
74 Protocol = p;
77 static enum remote_arch_types ra_type = RA_UNKNOWN;
79 /***********************************************************************
80 Definitions for all names.
81 ***********************************************************************/
83 static char *smb_scope;
84 static int smb_num_netbios_names;
85 static char **smb_my_netbios_names;
87 /***********************************************************************
88 Allocate and set scope. Ensure upper case.
89 ***********************************************************************/
91 bool set_global_scope(const char *scope)
93 SAFE_FREE(smb_scope);
94 smb_scope = SMB_STRDUP(scope);
95 if (!smb_scope)
96 return False;
97 strupper_m(smb_scope);
98 return True;
101 /*********************************************************************
102 Ensure scope is never null string.
103 *********************************************************************/
105 const char *global_scope(void)
107 if (!smb_scope)
108 set_global_scope("");
109 return smb_scope;
112 static void free_netbios_names_array(void)
114 int i;
116 for (i = 0; i < smb_num_netbios_names; i++)
117 SAFE_FREE(smb_my_netbios_names[i]);
119 SAFE_FREE(smb_my_netbios_names);
120 smb_num_netbios_names = 0;
123 static bool allocate_my_netbios_names_array(size_t number)
125 free_netbios_names_array();
127 smb_num_netbios_names = number + 1;
128 smb_my_netbios_names = SMB_MALLOC_ARRAY( char *, smb_num_netbios_names );
130 if (!smb_my_netbios_names)
131 return False;
133 memset(smb_my_netbios_names, '\0', sizeof(char *) * smb_num_netbios_names);
134 return True;
137 static bool set_my_netbios_names(const char *name, int i)
139 SAFE_FREE(smb_my_netbios_names[i]);
141 smb_my_netbios_names[i] = SMB_STRDUP(name);
142 if (!smb_my_netbios_names[i])
143 return False;
144 strupper_m(smb_my_netbios_names[i]);
145 return True;
148 /***********************************************************************
149 Free memory allocated to global objects
150 ***********************************************************************/
152 void gfree_names(void)
154 gfree_netbios_names();
155 SAFE_FREE( smb_scope );
156 free_netbios_names_array();
157 free_local_machine_name();
160 void gfree_all( void )
162 gfree_names();
163 gfree_loadparm();
164 gfree_case_tables();
165 gfree_charcnv();
166 gfree_interfaces();
167 gfree_debugsyms();
170 const char *my_netbios_names(int i)
172 return smb_my_netbios_names[i];
175 bool set_netbios_aliases(const char **str_array)
177 size_t namecount;
179 /* Work out the max number of netbios aliases that we have */
180 for( namecount=0; str_array && (str_array[namecount] != NULL); namecount++ )
183 if ( global_myname() && *global_myname())
184 namecount++;
186 /* Allocate space for the netbios aliases */
187 if (!allocate_my_netbios_names_array(namecount))
188 return False;
190 /* Use the global_myname string first */
191 namecount=0;
192 if ( global_myname() && *global_myname()) {
193 set_my_netbios_names( global_myname(), namecount );
194 namecount++;
197 if (str_array) {
198 size_t i;
199 for ( i = 0; str_array[i] != NULL; i++) {
200 size_t n;
201 bool duplicate = False;
203 /* Look for duplicates */
204 for( n=0; n<namecount; n++ ) {
205 if( strequal( str_array[i], my_netbios_names(n) ) ) {
206 duplicate = True;
207 break;
210 if (!duplicate) {
211 if (!set_my_netbios_names(str_array[i], namecount))
212 return False;
213 namecount++;
217 return True;
220 /****************************************************************************
221 Common name initialization code.
222 ****************************************************************************/
224 bool init_names(void)
226 int n;
228 if (global_myname() == NULL || *global_myname() == '\0') {
229 if (!set_global_myname(myhostname())) {
230 DEBUG( 0, ( "init_names: malloc fail.\n" ) );
231 return False;
235 if (!set_netbios_aliases(lp_netbios_aliases())) {
236 DEBUG( 0, ( "init_names: malloc fail.\n" ) );
237 return False;
240 set_local_machine_name(global_myname(),false);
242 DEBUG( 5, ("Netbios name list:-\n") );
243 for( n=0; my_netbios_names(n); n++ ) {
244 DEBUGADD( 5, ("my_netbios_names[%d]=\"%s\"\n",
245 n, my_netbios_names(n) ) );
248 return( True );
251 /*******************************************************************
252 Check if a file exists - call vfs_file_exist for samba files.
253 ********************************************************************/
255 bool file_exist_stat(const char *fname,SMB_STRUCT_STAT *sbuf,
256 bool fake_dir_create_times)
258 SMB_STRUCT_STAT st;
259 if (!sbuf)
260 sbuf = &st;
262 if (sys_stat(fname, sbuf, fake_dir_create_times) != 0)
263 return(False);
265 return((S_ISREG(sbuf->st_ex_mode)) || (S_ISFIFO(sbuf->st_ex_mode)));
268 /*******************************************************************
269 Check if a unix domain socket exists - call vfs_file_exist for samba files.
270 ********************************************************************/
272 bool socket_exist(const char *fname)
274 SMB_STRUCT_STAT st;
275 if (sys_stat(fname, &st, false) != 0)
276 return(False);
278 return S_ISSOCK(st.st_ex_mode);
281 /*******************************************************************
282 Returns the size in bytes of the named given the stat struct.
283 ********************************************************************/
285 uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf)
287 return sbuf->st_ex_size;
290 /*******************************************************************
291 Returns the size in bytes of the named file.
292 ********************************************************************/
294 SMB_OFF_T get_file_size(char *file_name)
296 SMB_STRUCT_STAT buf;
297 buf.st_ex_size = 0;
298 if (sys_stat(file_name, &buf, false) != 0)
299 return (SMB_OFF_T)-1;
300 return get_file_size_stat(&buf);
303 /*******************************************************************
304 Return a string representing an attribute for a file.
305 ********************************************************************/
307 char *attrib_string(uint16 mode)
309 fstring attrstr;
311 attrstr[0] = 0;
313 if (mode & FILE_ATTRIBUTE_VOLUME) fstrcat(attrstr,"V");
314 if (mode & FILE_ATTRIBUTE_DIRECTORY) fstrcat(attrstr,"D");
315 if (mode & FILE_ATTRIBUTE_ARCHIVE) fstrcat(attrstr,"A");
316 if (mode & FILE_ATTRIBUTE_HIDDEN) fstrcat(attrstr,"H");
317 if (mode & FILE_ATTRIBUTE_SYSTEM) fstrcat(attrstr,"S");
318 if (mode & FILE_ATTRIBUTE_READONLY) fstrcat(attrstr,"R");
320 return talloc_strdup(talloc_tos(), attrstr);
323 /*******************************************************************
324 Show a smb message structure.
325 ********************************************************************/
327 void show_msg(char *buf)
329 int i;
330 int bcc=0;
332 if (!DEBUGLVL(5))
333 return;
335 DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
336 smb_len(buf),
337 (int)CVAL(buf,smb_com),
338 (int)CVAL(buf,smb_rcls),
339 (int)CVAL(buf,smb_reh),
340 (int)SVAL(buf,smb_err),
341 (int)CVAL(buf,smb_flg),
342 (int)SVAL(buf,smb_flg2)));
343 DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
344 (int)SVAL(buf,smb_tid),
345 (int)SVAL(buf,smb_pid),
346 (int)SVAL(buf,smb_uid),
347 (int)SVAL(buf,smb_mid)));
348 DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
350 for (i=0;i<(int)CVAL(buf,smb_wct);i++)
351 DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
352 SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
354 bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
356 DEBUGADD(5,("smb_bcc=%d\n",bcc));
358 if (DEBUGLEVEL < 10)
359 return;
361 if (DEBUGLEVEL < 50)
362 bcc = MIN(bcc, 512);
364 dump_data(10, (uint8 *)smb_buf(buf), bcc);
367 /*******************************************************************
368 Set the length and marker of an encrypted smb packet.
369 ********************************************************************/
371 void smb_set_enclen(char *buf,int len,uint16 enc_ctx_num)
373 _smb_setlen(buf,len);
375 SCVAL(buf,4,0xFF);
376 SCVAL(buf,5,'E');
377 SSVAL(buf,6,enc_ctx_num);
380 /*******************************************************************
381 Set the length and marker of an smb packet.
382 ********************************************************************/
384 void smb_setlen(char *buf,int len)
386 _smb_setlen_large(buf,len);
388 SCVAL(buf,4,0xFF);
389 SCVAL(buf,5,'S');
390 SCVAL(buf,6,'M');
391 SCVAL(buf,7,'B');
394 /*******************************************************************
395 Setup only the byte count for a smb message.
396 ********************************************************************/
398 int set_message_bcc(char *buf,int num_bytes)
400 int num_words = CVAL(buf,smb_wct);
401 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
402 _smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
403 return (smb_size + num_words*2 + num_bytes);
406 /*******************************************************************
407 Add a data blob to the end of a smb_buf, adjusting bcc and smb_len.
408 Return the bytes added
409 ********************************************************************/
411 ssize_t message_push_blob(uint8 **outbuf, DATA_BLOB blob)
413 size_t newlen = smb_len(*outbuf) + 4 + blob.length;
414 uint8 *tmp;
416 if (!(tmp = TALLOC_REALLOC_ARRAY(NULL, *outbuf, uint8, newlen))) {
417 DEBUG(0, ("talloc failed\n"));
418 return -1;
420 *outbuf = tmp;
422 memcpy(tmp + smb_len(tmp) + 4, blob.data, blob.length);
423 set_message_bcc((char *)tmp, smb_buflen(tmp) + blob.length);
424 return blob.length;
427 /*******************************************************************
428 Reduce a file name, removing .. elements.
429 ********************************************************************/
431 static char *dos_clean_name(TALLOC_CTX *ctx, const char *s)
433 char *p = NULL;
434 char *str = NULL;
436 DEBUG(3,("dos_clean_name [%s]\n",s));
438 /* remove any double slashes */
439 str = talloc_all_string_sub(ctx, s, "\\\\", "\\");
440 if (!str) {
441 return NULL;
444 /* Remove leading .\\ characters */
445 if(strncmp(str, ".\\", 2) == 0) {
446 trim_string(str, ".\\", NULL);
447 if(*str == 0) {
448 str = talloc_strdup(ctx, ".\\");
449 if (!str) {
450 return NULL;
455 while ((p = strstr_m(str,"\\..\\")) != NULL) {
456 char *s1;
458 *p = 0;
459 s1 = p+3;
461 if ((p=strrchr_m(str,'\\')) != NULL) {
462 *p = 0;
463 } else {
464 *str = 0;
466 str = talloc_asprintf(ctx,
467 "%s%s",
468 str,
469 s1);
470 if (!str) {
471 return NULL;
475 trim_string(str,NULL,"\\..");
476 return talloc_all_string_sub(ctx, str, "\\.\\", "\\");
479 /*******************************************************************
480 Reduce a file name, removing .. elements.
481 ********************************************************************/
483 char *unix_clean_name(TALLOC_CTX *ctx, const char *s)
485 char *p = NULL;
486 char *str = NULL;
488 DEBUG(3,("unix_clean_name [%s]\n",s));
490 /* remove any double slashes */
491 str = talloc_all_string_sub(ctx, s, "//","/");
492 if (!str) {
493 return NULL;
496 /* Remove leading ./ characters */
497 if(strncmp(str, "./", 2) == 0) {
498 trim_string(str, "./", NULL);
499 if(*str == 0) {
500 str = talloc_strdup(ctx, "./");
501 if (!str) {
502 return NULL;
507 while ((p = strstr_m(str,"/../")) != NULL) {
508 char *s1;
510 *p = 0;
511 s1 = p+3;
513 if ((p=strrchr_m(str,'/')) != NULL) {
514 *p = 0;
515 } else {
516 *str = 0;
518 str = talloc_asprintf(ctx,
519 "%s%s",
520 str,
521 s1);
522 if (!str) {
523 return NULL;
527 trim_string(str,NULL,"/..");
528 return talloc_all_string_sub(ctx, str, "/./", "/");
531 char *clean_name(TALLOC_CTX *ctx, const char *s)
533 char *str = dos_clean_name(ctx, s);
534 if (!str) {
535 return NULL;
537 return unix_clean_name(ctx, str);
540 /*******************************************************************
541 Write data into an fd at a given offset. Ignore seek errors.
542 ********************************************************************/
544 ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos)
546 size_t total=0;
547 ssize_t ret;
549 if (pos == (SMB_OFF_T)-1) {
550 return write_data(fd, buffer, N);
552 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
553 while (total < N) {
554 ret = sys_pwrite(fd,buffer + total,N - total, pos);
555 if (ret == -1 && errno == ESPIPE) {
556 return write_data(fd, buffer + total,N - total);
558 if (ret == -1) {
559 DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
560 return -1;
562 if (ret == 0) {
563 return total;
565 total += ret;
566 pos += ret;
568 return (ssize_t)total;
569 #else
570 /* Use lseek and write_data. */
571 if (sys_lseek(fd, pos, SEEK_SET) == -1) {
572 if (errno != ESPIPE) {
573 return -1;
576 return write_data(fd, buffer, N);
577 #endif
581 NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
582 struct event_context *ev_ctx,
583 struct server_id id,
584 bool parent_longlived)
586 NTSTATUS status = NT_STATUS_OK;
588 /* Reset the state of the random
589 * number generation system, so
590 * children do not get the same random
591 * numbers as each other */
592 set_need_random_reseed();
594 /* tdb needs special fork handling */
595 if (tdb_reopen_all(parent_longlived ? 1 : 0) == -1) {
596 DEBUG(0,("tdb_reopen_all failed.\n"));
597 status = NT_STATUS_OPEN_FAILED;
598 goto done;
601 if (ev_ctx && tevent_re_initialise(ev_ctx) != 0) {
602 smb_panic(__location__ ": Failed to re-initialise event context");
605 if (msg_ctx) {
607 * For clustering, we need to re-init our ctdbd connection after the
608 * fork
610 status = messaging_reinit(msg_ctx, id);
611 if (!NT_STATUS_IS_OK(status)) {
612 DEBUG(0,("messaging_reinit() failed: %s\n",
613 nt_errstr(status)));
616 done:
617 return status;
620 #if defined(PARANOID_MALLOC_CHECKER)
622 /****************************************************************************
623 Internal malloc wrapper. Externally visible.
624 ****************************************************************************/
626 void *malloc_(size_t size)
628 if (size == 0) {
629 return NULL;
631 #undef malloc
632 return malloc(size);
633 #define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
636 /****************************************************************************
637 Internal calloc wrapper. Not externally visible.
638 ****************************************************************************/
640 static void *calloc_(size_t count, size_t size)
642 if (size == 0 || count == 0) {
643 return NULL;
645 #undef calloc
646 return calloc(count, size);
647 #define calloc(n,s) __ERROR_DONT_USE_CALLOC_DIRECTLY
650 /****************************************************************************
651 Internal realloc wrapper. Not externally visible.
652 ****************************************************************************/
654 static void *realloc_(void *ptr, size_t size)
656 #undef realloc
657 return realloc(ptr, size);
658 #define realloc(p,s) __ERROR_DONT_USE_RELLOC_DIRECTLY
661 #endif /* PARANOID_MALLOC_CHECKER */
663 /****************************************************************************
664 Type-safe memalign
665 ****************************************************************************/
667 void *memalign_array(size_t el_size, size_t align, unsigned int count)
669 if (count >= MAX_ALLOC_SIZE/el_size) {
670 return NULL;
673 return sys_memalign(align, el_size*count);
676 /****************************************************************************
677 Type-safe calloc.
678 ****************************************************************************/
680 void *calloc_array(size_t size, size_t nmemb)
682 if (nmemb >= MAX_ALLOC_SIZE/size) {
683 return NULL;
685 if (size == 0 || nmemb == 0) {
686 return NULL;
688 #if defined(PARANOID_MALLOC_CHECKER)
689 return calloc_(nmemb, size);
690 #else
691 return calloc(nmemb, size);
692 #endif
695 /****************************************************************************
696 Expand a pointer to be a particular size.
697 Note that this version of Realloc has an extra parameter that decides
698 whether to free the passed in storage on allocation failure or if the
699 new size is zero.
701 This is designed for use in the typical idiom of :
703 p = SMB_REALLOC(p, size)
704 if (!p) {
705 return error;
708 and not to have to keep track of the old 'p' contents to free later, nor
709 to worry if the size parameter was zero. In the case where NULL is returned
710 we guarentee that p has been freed.
712 If free later semantics are desired, then pass 'free_old_on_error' as False which
713 guarentees that the old contents are not freed on error, even if size == 0. To use
714 this idiom use :
716 tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
717 if (!tmp) {
718 SAFE_FREE(p);
719 return error;
720 } else {
721 p = tmp;
724 Changes were instigated by Coverity error checking. JRA.
725 ****************************************************************************/
727 void *Realloc(void *p, size_t size, bool free_old_on_error)
729 void *ret=NULL;
731 if (size == 0) {
732 if (free_old_on_error) {
733 SAFE_FREE(p);
735 DEBUG(2,("Realloc asked for 0 bytes\n"));
736 return NULL;
739 #if defined(PARANOID_MALLOC_CHECKER)
740 if (!p) {
741 ret = (void *)malloc_(size);
742 } else {
743 ret = (void *)realloc_(p,size);
745 #else
746 if (!p) {
747 ret = (void *)malloc(size);
748 } else {
749 ret = (void *)realloc(p,size);
751 #endif
753 if (!ret) {
754 if (free_old_on_error && p) {
755 SAFE_FREE(p);
757 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
760 return(ret);
763 /****************************************************************************
764 (Hopefully) efficient array append.
765 ****************************************************************************/
767 void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
768 void *element, void *_array, uint32 *num_elements,
769 ssize_t *array_size)
771 void **array = (void **)_array;
773 if (*array_size < 0) {
774 return;
777 if (*array == NULL) {
778 if (*array_size == 0) {
779 *array_size = 128;
782 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
783 goto error;
786 *array = TALLOC(mem_ctx, element_size * (*array_size));
787 if (*array == NULL) {
788 goto error;
792 if (*num_elements == *array_size) {
793 *array_size *= 2;
795 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
796 goto error;
799 *array = TALLOC_REALLOC(mem_ctx, *array,
800 element_size * (*array_size));
802 if (*array == NULL) {
803 goto error;
807 memcpy((char *)(*array) + element_size*(*num_elements),
808 element, element_size);
809 *num_elements += 1;
811 return;
813 error:
814 *num_elements = 0;
815 *array_size = -1;
818 /****************************************************************************
819 Get my own domain name, or "" if we have none.
820 ****************************************************************************/
822 char *get_mydnsdomname(TALLOC_CTX *ctx)
824 const char *domname;
825 char *p;
827 domname = get_mydnsfullname();
828 if (!domname) {
829 return NULL;
832 p = strchr_m(domname, '.');
833 if (p) {
834 p++;
835 return talloc_strdup(ctx, p);
836 } else {
837 return talloc_strdup(ctx, "");
841 /****************************************************************************
842 Interpret a protocol description string, with a default.
843 ****************************************************************************/
845 int interpret_protocol(const char *str,int def)
847 if (strequal(str,"NT1"))
848 return(PROTOCOL_NT1);
849 if (strequal(str,"LANMAN2"))
850 return(PROTOCOL_LANMAN2);
851 if (strequal(str,"LANMAN1"))
852 return(PROTOCOL_LANMAN1);
853 if (strequal(str,"CORE"))
854 return(PROTOCOL_CORE);
855 if (strequal(str,"COREPLUS"))
856 return(PROTOCOL_COREPLUS);
857 if (strequal(str,"CORE+"))
858 return(PROTOCOL_COREPLUS);
860 DEBUG(0,("Unrecognised protocol level %s\n",str));
862 return(def);
866 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
867 /******************************************************************
868 Remove any mount options such as -rsize=2048,wsize=2048 etc.
869 Based on a fix from <Thomas.Hepper@icem.de>.
870 Returns a malloc'ed string.
871 *******************************************************************/
873 static char *strip_mount_options(TALLOC_CTX *ctx, const char *str)
875 if (*str == '-') {
876 const char *p = str;
877 while(*p && !isspace(*p))
878 p++;
879 while(*p && isspace(*p))
880 p++;
881 if(*p) {
882 return talloc_strdup(ctx, p);
885 return NULL;
888 /*******************************************************************
889 Patch from jkf@soton.ac.uk
890 Split Luke's automount_server into YP lookup and string splitter
891 so can easily implement automount_path().
892 Returns a malloc'ed string.
893 *******************************************************************/
895 #ifdef WITH_NISPLUS_HOME
896 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
898 char *value = NULL;
900 char *nis_map = (char *)lp_nis_home_map_name();
902 char buffer[NIS_MAXATTRVAL + 1];
903 nis_result *result;
904 nis_object *object;
905 entry_obj *entry;
907 snprintf(buffer, sizeof(buffer), "[key=%s],%s", user_name, nis_map);
908 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
910 if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
911 if (result->status != NIS_SUCCESS) {
912 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
913 } else {
914 object = result->objects.objects_val;
915 if (object->zo_data.zo_type == ENTRY_OBJ) {
916 entry = &object->zo_data.objdata_u.en_data;
917 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
918 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
920 value = talloc_strdup(ctx,
921 entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
922 if (!value) {
923 nis_freeresult(result);
924 return NULL;
926 value = talloc_string_sub(ctx,
927 value,
928 "&",
929 user_name);
933 nis_freeresult(result);
935 if (value) {
936 value = strip_mount_options(ctx, value);
937 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n",
938 user_name, value));
940 return value;
942 #else /* WITH_NISPLUS_HOME */
944 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
946 char *value = NULL;
948 int nis_error; /* returned by yp all functions */
949 char *nis_result; /* yp_match inits this */
950 int nis_result_len; /* and set this */
951 char *nis_domain; /* yp_get_default_domain inits this */
952 char *nis_map = (char *)lp_nis_home_map_name();
954 if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
955 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
956 return NULL;
959 DEBUG(5, ("NIS Domain: %s\n", nis_domain));
961 if ((nis_error = yp_match(nis_domain, nis_map, user_name,
962 strlen(user_name), &nis_result,
963 &nis_result_len)) == 0) {
964 if (nis_result_len > 0 && nis_result[nis_result_len] == '\n') {
965 nis_result[nis_result_len] = '\0';
967 value = talloc_strdup(ctx, nis_result);
968 if (!value) {
969 return NULL;
971 value = strip_mount_options(ctx, value);
972 } else if(nis_error == YPERR_KEY) {
973 DEBUG(3, ("YP Key not found: while looking up \"%s\" in map \"%s\"\n",
974 user_name, nis_map));
975 DEBUG(3, ("using defaults for server and home directory\n"));
976 } else {
977 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
978 yperr_string(nis_error), user_name, nis_map));
981 if (value) {
982 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, value));
984 return value;
986 #endif /* WITH_NISPLUS_HOME */
987 #endif
989 /****************************************************************************
990 Check if a process exists. Does this work on all unixes?
991 ****************************************************************************/
993 bool process_exists(const struct server_id pid)
995 if (procid_is_me(&pid)) {
996 return True;
999 if (procid_is_local(&pid)) {
1000 return (kill(pid.pid,0) == 0 || errno != ESRCH);
1003 #ifdef CLUSTER_SUPPORT
1004 return ctdbd_process_exists(messaging_ctdbd_connection(),
1005 pid.vnn, pid.pid);
1006 #else
1007 return False;
1008 #endif
1011 /*******************************************************************
1012 Convert a uid into a user name.
1013 ********************************************************************/
1015 const char *uidtoname(uid_t uid)
1017 TALLOC_CTX *ctx = talloc_tos();
1018 char *name = NULL;
1019 struct passwd *pass = NULL;
1021 pass = getpwuid_alloc(ctx,uid);
1022 if (pass) {
1023 name = talloc_strdup(ctx,pass->pw_name);
1024 TALLOC_FREE(pass);
1025 } else {
1026 name = talloc_asprintf(ctx,
1027 "%ld",
1028 (long int)uid);
1030 return name;
1033 /*******************************************************************
1034 Convert a gid into a group name.
1035 ********************************************************************/
1037 char *gidtoname(gid_t gid)
1039 struct group *grp;
1041 grp = getgrgid(gid);
1042 if (grp) {
1043 return talloc_strdup(talloc_tos(), grp->gr_name);
1045 else {
1046 return talloc_asprintf(talloc_tos(),
1047 "%d",
1048 (int)gid);
1052 /*******************************************************************
1053 Convert a user name into a uid.
1054 ********************************************************************/
1056 uid_t nametouid(const char *name)
1058 struct passwd *pass;
1059 char *p;
1060 uid_t u;
1062 pass = Get_Pwnam_alloc(talloc_tos(), name);
1063 if (pass) {
1064 u = pass->pw_uid;
1065 TALLOC_FREE(pass);
1066 return u;
1069 u = (uid_t)strtol(name, &p, 0);
1070 if ((p != name) && (*p == '\0'))
1071 return u;
1073 return (uid_t)-1;
1076 /*******************************************************************
1077 Convert a name to a gid_t if possible. Return -1 if not a group.
1078 ********************************************************************/
1080 gid_t nametogid(const char *name)
1082 struct group *grp;
1083 char *p;
1084 gid_t g;
1086 g = (gid_t)strtol(name, &p, 0);
1087 if ((p != name) && (*p == '\0'))
1088 return g;
1090 grp = sys_getgrnam(name);
1091 if (grp)
1092 return(grp->gr_gid);
1093 return (gid_t)-1;
1096 /*******************************************************************
1097 Something really nasty happened - panic !
1098 ********************************************************************/
1100 void smb_panic(const char *const why)
1102 char *cmd;
1103 int result;
1105 #ifdef DEVELOPER
1108 if (global_clobber_region_function) {
1109 DEBUG(0,("smb_panic: clobber_region() last called from [%s(%u)]\n",
1110 global_clobber_region_function,
1111 global_clobber_region_line));
1114 #endif
1116 DEBUG(0,("PANIC (pid %llu): %s\n",
1117 (unsigned long long)sys_getpid(), why));
1118 log_stack_trace();
1120 cmd = lp_panic_action();
1121 if (cmd && *cmd) {
1122 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
1123 result = system(cmd);
1125 if (result == -1)
1126 DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
1127 strerror(errno)));
1128 else
1129 DEBUG(0, ("smb_panic(): action returned status %d\n",
1130 WEXITSTATUS(result)));
1133 dump_core();
1136 /*******************************************************************
1137 Print a backtrace of the stack to the debug log. This function
1138 DELIBERATELY LEAKS MEMORY. The expectation is that you should
1139 exit shortly after calling it.
1140 ********************************************************************/
1142 #ifdef HAVE_LIBUNWIND_H
1143 #include <libunwind.h>
1144 #endif
1146 #ifdef HAVE_EXECINFO_H
1147 #include <execinfo.h>
1148 #endif
1150 #ifdef HAVE_LIBEXC_H
1151 #include <libexc.h>
1152 #endif
1154 void log_stack_trace(void)
1156 #ifdef HAVE_LIBUNWIND
1157 /* Try to use libunwind before any other technique since on ia64
1158 * libunwind correctly walks the stack in more circumstances than
1159 * backtrace.
1161 unw_cursor_t cursor;
1162 unw_context_t uc;
1163 unsigned i = 0;
1165 char procname[256];
1166 unw_word_t ip, sp, off;
1168 procname[sizeof(procname) - 1] = '\0';
1170 if (unw_getcontext(&uc) != 0) {
1171 goto libunwind_failed;
1174 if (unw_init_local(&cursor, &uc) != 0) {
1175 goto libunwind_failed;
1178 DEBUG(0, ("BACKTRACE:\n"));
1180 do {
1181 ip = sp = 0;
1182 unw_get_reg(&cursor, UNW_REG_IP, &ip);
1183 unw_get_reg(&cursor, UNW_REG_SP, &sp);
1185 switch (unw_get_proc_name(&cursor,
1186 procname, sizeof(procname) - 1, &off) ) {
1187 case 0:
1188 /* Name found. */
1189 case -UNW_ENOMEM:
1190 /* Name truncated. */
1191 DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
1192 i, procname, (long long)off,
1193 (long long)ip, (long long) sp));
1194 break;
1195 default:
1196 /* case -UNW_ENOINFO: */
1197 /* case -UNW_EUNSPEC: */
1198 /* No symbol name found. */
1199 DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
1200 i, "<unknown symbol>",
1201 (long long)ip, (long long) sp));
1203 ++i;
1204 } while (unw_step(&cursor) > 0);
1206 return;
1208 libunwind_failed:
1209 DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
1211 #elif HAVE_BACKTRACE_SYMBOLS
1212 void *backtrace_stack[BACKTRACE_STACK_SIZE];
1213 size_t backtrace_size;
1214 char **backtrace_strings;
1216 /* get the backtrace (stack frames) */
1217 backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
1218 backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
1220 DEBUG(0, ("BACKTRACE: %lu stack frames:\n",
1221 (unsigned long)backtrace_size));
1223 if (backtrace_strings) {
1224 int i;
1226 for (i = 0; i < backtrace_size; i++)
1227 DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
1229 /* Leak the backtrace_strings, rather than risk what free() might do */
1232 #elif HAVE_LIBEXC
1234 /* The IRIX libexc library provides an API for unwinding the stack. See
1235 * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
1236 * since we are about to abort anyway, it hardly matters.
1239 #define NAMESIZE 32 /* Arbitrary */
1241 __uint64_t addrs[BACKTRACE_STACK_SIZE];
1242 char * names[BACKTRACE_STACK_SIZE];
1243 char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
1245 int i;
1246 int levels;
1248 ZERO_ARRAY(addrs);
1249 ZERO_ARRAY(names);
1250 ZERO_ARRAY(namebuf);
1252 /* We need to be root so we can open our /proc entry to walk
1253 * our stack. It also helps when we want to dump core.
1255 become_root();
1257 for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
1258 names[i] = namebuf + (i * NAMESIZE);
1261 levels = trace_back_stack(0, addrs, names,
1262 BACKTRACE_STACK_SIZE, NAMESIZE - 1);
1264 DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
1265 for (i = 0; i < levels; i++) {
1266 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
1268 #undef NAMESIZE
1270 #else
1271 DEBUG(0, ("unable to produce a stack trace on this platform\n"));
1272 #endif
1275 /*******************************************************************
1276 A readdir wrapper which just returns the file name.
1277 ********************************************************************/
1279 const char *readdirname(SMB_STRUCT_DIR *p)
1281 SMB_STRUCT_DIRENT *ptr;
1282 char *dname;
1284 if (!p)
1285 return(NULL);
1287 ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
1288 if (!ptr)
1289 return(NULL);
1291 dname = ptr->d_name;
1293 #ifdef NEXT2
1294 if (telldir(p) < 0)
1295 return(NULL);
1296 #endif
1298 #ifdef HAVE_BROKEN_READDIR_NAME
1299 /* using /usr/ucb/cc is BAD */
1300 dname = dname - 2;
1301 #endif
1303 return talloc_strdup(talloc_tos(), dname);
1306 /*******************************************************************
1307 Utility function used to decide if the last component
1308 of a path matches a (possibly wildcarded) entry in a namelist.
1309 ********************************************************************/
1311 bool is_in_path(const char *name, name_compare_entry *namelist, bool case_sensitive)
1313 const char *last_component;
1315 /* if we have no list it's obviously not in the path */
1316 if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
1317 return False;
1320 DEBUG(8, ("is_in_path: %s\n", name));
1322 /* Get the last component of the unix name. */
1323 last_component = strrchr_m(name, '/');
1324 if (!last_component) {
1325 last_component = name;
1326 } else {
1327 last_component++; /* Go past '/' */
1330 for(; namelist->name != NULL; namelist++) {
1331 if(namelist->is_wild) {
1332 if (mask_match(last_component, namelist->name, case_sensitive)) {
1333 DEBUG(8,("is_in_path: mask match succeeded\n"));
1334 return True;
1336 } else {
1337 if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
1338 (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0))) {
1339 DEBUG(8,("is_in_path: match succeeded\n"));
1340 return True;
1344 DEBUG(8,("is_in_path: match not found\n"));
1345 return False;
1348 /*******************************************************************
1349 Strip a '/' separated list into an array of
1350 name_compare_enties structures suitable for
1351 passing to is_in_path(). We do this for
1352 speed so we can pre-parse all the names in the list
1353 and don't do it for each call to is_in_path().
1354 namelist is modified here and is assumed to be
1355 a copy owned by the caller.
1356 We also check if the entry contains a wildcard to
1357 remove a potentially expensive call to mask_match
1358 if possible.
1359 ********************************************************************/
1361 void set_namearray(name_compare_entry **ppname_array, const char *namelist)
1363 char *name_end;
1364 char *nameptr = (char *)namelist;
1365 int num_entries = 0;
1366 int i;
1368 (*ppname_array) = NULL;
1370 if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0')))
1371 return;
1373 /* We need to make two passes over the string. The
1374 first to count the number of elements, the second
1375 to split it.
1378 while(*nameptr) {
1379 if ( *nameptr == '/' ) {
1380 /* cope with multiple (useless) /s) */
1381 nameptr++;
1382 continue;
1384 /* anything left? */
1385 if ( *nameptr == '\0' )
1386 break;
1388 /* find the next '/' or consume remaining */
1389 name_end = strchr_m(nameptr, '/');
1390 if (name_end == NULL)
1391 name_end = (char *)nameptr + strlen(nameptr);
1393 /* next segment please */
1394 nameptr = name_end + 1;
1395 num_entries++;
1398 if(num_entries == 0)
1399 return;
1401 if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1402 DEBUG(0,("set_namearray: malloc fail\n"));
1403 return;
1406 /* Now copy out the names */
1407 nameptr = (char *)namelist;
1408 i = 0;
1409 while(*nameptr) {
1410 if ( *nameptr == '/' ) {
1411 /* cope with multiple (useless) /s) */
1412 nameptr++;
1413 continue;
1415 /* anything left? */
1416 if ( *nameptr == '\0' )
1417 break;
1419 /* find the next '/' or consume remaining */
1420 name_end = strchr_m(nameptr, '/');
1421 if (name_end)
1422 *name_end = '\0';
1423 else
1424 name_end = nameptr + strlen(nameptr);
1426 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1427 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1428 DEBUG(0,("set_namearray: malloc fail (1)\n"));
1429 return;
1432 /* next segment please */
1433 nameptr = name_end + 1;
1434 i++;
1437 (*ppname_array)[i].name = NULL;
1439 return;
1442 /****************************************************************************
1443 Routine to free a namearray.
1444 ****************************************************************************/
1446 void free_namearray(name_compare_entry *name_array)
1448 int i;
1450 if(name_array == NULL)
1451 return;
1453 for(i=0; name_array[i].name!=NULL; i++)
1454 SAFE_FREE(name_array[i].name);
1455 SAFE_FREE(name_array);
1458 #undef DBGC_CLASS
1459 #define DBGC_CLASS DBGC_LOCKING
1461 /****************************************************************************
1462 Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
1463 is dealt with in posix.c
1464 Returns True if we have information regarding this lock region (and returns
1465 F_UNLCK in *ptype if the region is unlocked). False if the call failed.
1466 ****************************************************************************/
1468 bool fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
1470 SMB_STRUCT_FLOCK lock;
1471 int ret;
1473 DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
1474 fd,(double)*poffset,(double)*pcount,*ptype));
1476 lock.l_type = *ptype;
1477 lock.l_whence = SEEK_SET;
1478 lock.l_start = *poffset;
1479 lock.l_len = *pcount;
1480 lock.l_pid = 0;
1482 ret = sys_fcntl_ptr(fd,SMB_F_GETLK,&lock);
1484 if (ret == -1) {
1485 int sav = errno;
1486 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
1487 (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
1488 errno = sav;
1489 return False;
1492 *ptype = lock.l_type;
1493 *poffset = lock.l_start;
1494 *pcount = lock.l_len;
1495 *ppid = lock.l_pid;
1497 DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
1498 fd, (int)lock.l_type, (unsigned int)lock.l_pid));
1499 return True;
1502 #undef DBGC_CLASS
1503 #define DBGC_CLASS DBGC_ALL
1505 /*******************************************************************
1506 Is the name specified one of my netbios names.
1507 Returns true if it is equal, false otherwise.
1508 ********************************************************************/
1510 bool is_myname(const char *s)
1512 int n;
1513 bool ret = False;
1515 for (n=0; my_netbios_names(n); n++) {
1516 if (strequal(my_netbios_names(n), s)) {
1517 ret=True;
1518 break;
1521 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1522 return(ret);
1525 /*******************************************************************
1526 Is the name specified our workgroup/domain.
1527 Returns true if it is equal, false otherwise.
1528 ********************************************************************/
1530 bool is_myworkgroup(const char *s)
1532 bool ret = False;
1534 if (strequal(s, lp_workgroup())) {
1535 ret=True;
1538 DEBUG(8, ("is_myworkgroup(\"%s\") returns %d\n", s, ret));
1539 return(ret);
1542 /*******************************************************************
1543 we distinguish between 2K and XP by the "Native Lan Manager" string
1544 WinXP => "Windows 2002 5.1"
1545 WinXP 64bit => "Windows XP 5.2"
1546 Win2k => "Windows 2000 5.0"
1547 NT4 => "Windows NT 4.0"
1548 Win9x => "Windows 4.0"
1549 Windows 2003 doesn't set the native lan manager string but
1550 they do set the domain to "Windows 2003 5.2" (probably a bug).
1551 ********************************************************************/
1553 void ra_lanman_string( const char *native_lanman )
1555 if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1556 set_remote_arch( RA_WINXP );
1557 else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1558 set_remote_arch( RA_WINXP64 );
1559 else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1560 set_remote_arch( RA_WIN2K3 );
1563 static const char *remote_arch_str;
1565 const char *get_remote_arch_str(void)
1567 if (!remote_arch_str) {
1568 return "UNKNOWN";
1570 return remote_arch_str;
1573 /*******************************************************************
1574 Set the horrid remote_arch string based on an enum.
1575 ********************************************************************/
1577 void set_remote_arch(enum remote_arch_types type)
1579 ra_type = type;
1580 switch( type ) {
1581 case RA_WFWG:
1582 remote_arch_str = "WfWg";
1583 break;
1584 case RA_OS2:
1585 remote_arch_str = "OS2";
1586 break;
1587 case RA_WIN95:
1588 remote_arch_str = "Win95";
1589 break;
1590 case RA_WINNT:
1591 remote_arch_str = "WinNT";
1592 break;
1593 case RA_WIN2K:
1594 remote_arch_str = "Win2K";
1595 break;
1596 case RA_WINXP:
1597 remote_arch_str = "WinXP";
1598 break;
1599 case RA_WINXP64:
1600 remote_arch_str = "WinXP64";
1601 break;
1602 case RA_WIN2K3:
1603 remote_arch_str = "Win2K3";
1604 break;
1605 case RA_VISTA:
1606 remote_arch_str = "Vista";
1607 break;
1608 case RA_SAMBA:
1609 remote_arch_str = "Samba";
1610 break;
1611 case RA_CIFSFS:
1612 remote_arch_str = "CIFSFS";
1613 break;
1614 case RA_OSX:
1615 remote_arch_str = "OSX";
1616 break;
1617 default:
1618 ra_type = RA_UNKNOWN;
1619 remote_arch_str = "UNKNOWN";
1620 break;
1623 DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1624 remote_arch_str));
1627 /*******************************************************************
1628 Get the remote_arch type.
1629 ********************************************************************/
1631 enum remote_arch_types get_remote_arch(void)
1633 return ra_type;
1636 const char *tab_depth(int level, int depth)
1638 if( CHECK_DEBUGLVL(level) ) {
1639 dbgtext("%*s", depth*4, "");
1641 return "";
1644 /*****************************************************************************
1645 Provide a checksum on a string
1647 Input: s - the null-terminated character string for which the checksum
1648 will be calculated.
1650 Output: The checksum value calculated for s.
1651 *****************************************************************************/
1653 int str_checksum(const char *s)
1655 TDB_DATA key = string_tdb_data(s);
1656 return tdb_jenkins_hash(&key);
1659 /*****************************************************************
1660 Zero a memory area then free it. Used to catch bugs faster.
1661 *****************************************************************/
1663 void zero_free(void *p, size_t size)
1665 memset(p, 0, size);
1666 SAFE_FREE(p);
1669 /*****************************************************************
1670 Set our open file limit to a requested max and return the limit.
1671 *****************************************************************/
1673 int set_maxfiles(int requested_max)
1675 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1676 struct rlimit rlp;
1677 int saved_current_limit;
1679 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1680 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1681 strerror(errno) ));
1682 /* just guess... */
1683 return requested_max;
1687 * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1688 * account for the extra fd we need
1689 * as well as the log files and standard
1690 * handles etc. Save the limit we want to set in case
1691 * we are running on an OS that doesn't support this limit (AIX)
1692 * which always returns RLIM_INFINITY for rlp.rlim_max.
1695 /* Try raising the hard (max) limit to the requested amount. */
1697 #if defined(RLIM_INFINITY)
1698 if (rlp.rlim_max != RLIM_INFINITY) {
1699 int orig_max = rlp.rlim_max;
1701 if ( rlp.rlim_max < requested_max )
1702 rlp.rlim_max = requested_max;
1704 /* This failing is not an error - many systems (Linux) don't
1705 support our default request of 10,000 open files. JRA. */
1707 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1708 DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n",
1709 (int)rlp.rlim_max, strerror(errno) ));
1711 /* Set failed - restore original value from get. */
1712 rlp.rlim_max = orig_max;
1715 #endif
1717 /* Now try setting the soft (current) limit. */
1719 saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1721 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1722 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
1723 (int)rlp.rlim_cur, strerror(errno) ));
1724 /* just guess... */
1725 return saved_current_limit;
1728 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1729 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1730 strerror(errno) ));
1731 /* just guess... */
1732 return saved_current_limit;
1735 #if defined(RLIM_INFINITY)
1736 if(rlp.rlim_cur == RLIM_INFINITY)
1737 return saved_current_limit;
1738 #endif
1740 if((int)rlp.rlim_cur > saved_current_limit)
1741 return saved_current_limit;
1743 return rlp.rlim_cur;
1744 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1746 * No way to know - just guess...
1748 return requested_max;
1749 #endif
1752 /*****************************************************************
1753 malloc that aborts with smb_panic on fail or zero size.
1754 *****************************************************************/
1756 void *smb_xmalloc_array(size_t size, unsigned int count)
1758 void *p;
1759 if (size == 0) {
1760 smb_panic("smb_xmalloc_array: called with zero size");
1762 if (count >= MAX_ALLOC_SIZE/size) {
1763 smb_panic("smb_xmalloc_array: alloc size too large");
1765 if ((p = SMB_MALLOC(size*count)) == NULL) {
1766 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1767 (unsigned long)size, (unsigned long)count));
1768 smb_panic("smb_xmalloc_array: malloc failed");
1770 return p;
1774 vasprintf that aborts on malloc fail
1777 int smb_xvasprintf(char **ptr, const char *format, va_list ap)
1779 int n;
1780 va_list ap2;
1782 va_copy(ap2, ap);
1784 n = vasprintf(ptr, format, ap2);
1785 va_end(ap2);
1786 if (n == -1 || ! *ptr) {
1787 smb_panic("smb_xvasprintf: out of memory");
1789 return n;
1792 /*****************************************************************
1793 Get local hostname and cache result.
1794 *****************************************************************/
1796 char *myhostname(void)
1798 static char *ret;
1799 if (ret == NULL) {
1800 ret = get_myname(NULL);
1802 return ret;
1806 * @brief Returns an absolute path to a file concatenating the provided
1807 * @a rootpath and @a basename
1809 * @param name Filename, relative to @a rootpath
1811 * @retval Pointer to a string containing the full path.
1814 static char *xx_path(const char *name, const char *rootpath)
1816 char *fname = NULL;
1818 fname = talloc_strdup(talloc_tos(), rootpath);
1819 if (!fname) {
1820 return NULL;
1822 trim_string(fname,"","/");
1824 if (!directory_exist(fname)) {
1825 if (!mkdir(fname,0755))
1826 DEBUG(1, ("Unable to create directory %s for file %s. "
1827 "Error was %s\n", fname, name, strerror(errno)));
1830 return talloc_asprintf(talloc_tos(),
1831 "%s/%s",
1832 fname,
1833 name);
1837 * @brief Returns an absolute path to a file in the Samba lock directory.
1839 * @param name File to find, relative to LOCKDIR.
1841 * @retval Pointer to a talloc'ed string containing the full path.
1844 char *lock_path(const char *name)
1846 return xx_path(name, lp_lockdir());
1850 * @brief Returns an absolute path to a file in the Samba pid directory.
1852 * @param name File to find, relative to PIDDIR.
1854 * @retval Pointer to a talloc'ed string containing the full path.
1857 char *pid_path(const char *name)
1859 return xx_path(name, lp_piddir());
1863 * @brief Returns an absolute path to a file in the Samba lib directory.
1865 * @param name File to find, relative to LIBDIR.
1867 * @retval Pointer to a string containing the full path.
1870 char *lib_path(const char *name)
1872 return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_LIBDIR(), name);
1876 * @brief Returns an absolute path to a file in the Samba modules directory.
1878 * @param name File to find, relative to MODULESDIR.
1880 * @retval Pointer to a string containing the full path.
1883 char *modules_path(const char *name)
1885 return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_MODULESDIR(), name);
1889 * @brief Returns an absolute path to a file in the Samba data directory.
1891 * @param name File to find, relative to CODEPAGEDIR.
1893 * @retval Pointer to a talloc'ed string containing the full path.
1896 char *data_path(const char *name)
1898 return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_CODEPAGEDIR(), name);
1902 * @brief Returns an absolute path to a file in the Samba state directory.
1904 * @param name File to find, relative to STATEDIR.
1906 * @retval Pointer to a talloc'ed string containing the full path.
1909 char *state_path(const char *name)
1911 return xx_path(name, lp_statedir());
1915 * @brief Returns an absolute path to a file in the Samba cache directory.
1917 * @param name File to find, relative to CACHEDIR.
1919 * @retval Pointer to a talloc'ed string containing the full path.
1922 char *cache_path(const char *name)
1924 return xx_path(name, lp_cachedir());
1928 * @brief Returns the platform specific shared library extension.
1930 * @retval Pointer to a const char * containing the extension.
1933 const char *shlib_ext(void)
1935 return get_dyn_SHLIBEXT();
1938 /*******************************************************************
1939 Given a filename - get its directory name
1940 ********************************************************************/
1942 bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
1943 const char **name)
1945 char *p;
1946 ptrdiff_t len;
1948 p = strrchr_m(dir, '/'); /* Find final '/', if any */
1950 if (p == NULL) {
1951 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
1952 return False;
1954 if (name) {
1955 *name = dir;
1957 return True;
1960 len = p-dir;
1962 if (!(*parent = (char *)TALLOC_MEMDUP(mem_ctx, dir, len+1))) {
1963 return False;
1965 (*parent)[len] = '\0';
1967 if (name) {
1968 *name = p+1;
1970 return True;
1973 /*******************************************************************
1974 Determine if a pattern contains any Microsoft wildcard characters.
1975 *******************************************************************/
1977 bool ms_has_wild(const char *s)
1979 char c;
1981 if (lp_posix_pathnames()) {
1982 /* With posix pathnames no characters are wild. */
1983 return False;
1986 while ((c = *s++)) {
1987 switch (c) {
1988 case '*':
1989 case '?':
1990 case '<':
1991 case '>':
1992 case '"':
1993 return True;
1996 return False;
1999 bool ms_has_wild_w(const smb_ucs2_t *s)
2001 smb_ucs2_t c;
2002 if (!s) return False;
2003 while ((c = *s++)) {
2004 switch (c) {
2005 case UCS2_CHAR('*'):
2006 case UCS2_CHAR('?'):
2007 case UCS2_CHAR('<'):
2008 case UCS2_CHAR('>'):
2009 case UCS2_CHAR('"'):
2010 return True;
2013 return False;
2016 /*******************************************************************
2017 A wrapper that handles case sensitivity and the special handling
2018 of the ".." name.
2019 *******************************************************************/
2021 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
2023 if (ISDOTDOT(string))
2024 string = ".";
2025 if (ISDOT(pattern))
2026 return False;
2028 return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
2031 /*******************************************************************
2032 A wrapper that handles case sensitivity and the special handling
2033 of the ".." name. Varient that is only called by old search code which requires
2034 pattern translation.
2035 *******************************************************************/
2037 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
2039 if (ISDOTDOT(string))
2040 string = ".";
2041 if (ISDOT(pattern))
2042 return False;
2044 return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
2047 /*******************************************************************
2048 A wrapper that handles a list of patters and calls mask_match()
2049 on each. Returns True if any of the patterns match.
2050 *******************************************************************/
2052 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
2054 while (listLen-- > 0) {
2055 if (mask_match(string, *list++, is_case_sensitive))
2056 return True;
2058 return False;
2061 /*********************************************************
2062 Recursive routine that is called by unix_wild_match.
2063 *********************************************************/
2065 static bool unix_do_match(const char *regexp, const char *str)
2067 const char *p;
2069 for( p = regexp; *p && *str; ) {
2071 switch(*p) {
2072 case '?':
2073 str++;
2074 p++;
2075 break;
2077 case '*':
2080 * Look for a character matching
2081 * the one after the '*'.
2083 p++;
2084 if(!*p)
2085 return true; /* Automatic match */
2086 while(*str) {
2088 while(*str && (*p != *str))
2089 str++;
2092 * Patch from weidel@multichart.de. In the case of the regexp
2093 * '*XX*' we want to ensure there are at least 2 'X' characters
2094 * in the string after the '*' for a match to be made.
2098 int matchcount=0;
2101 * Eat all the characters that match, but count how many there were.
2104 while(*str && (*p == *str)) {
2105 str++;
2106 matchcount++;
2110 * Now check that if the regexp had n identical characters that
2111 * matchcount had at least that many matches.
2114 while ( *(p+1) && (*(p+1) == *p)) {
2115 p++;
2116 matchcount--;
2119 if ( matchcount <= 0 )
2120 return false;
2123 str--; /* We've eaten the match char after the '*' */
2125 if(unix_do_match(p, str))
2126 return true;
2128 if(!*str)
2129 return false;
2130 else
2131 str++;
2133 return false;
2135 default:
2136 if(*str != *p)
2137 return false;
2138 str++;
2139 p++;
2140 break;
2144 if(!*p && !*str)
2145 return true;
2147 if (!*p && str[0] == '.' && str[1] == 0)
2148 return true;
2150 if (!*str && *p == '?') {
2151 while (*p == '?')
2152 p++;
2153 return(!*p);
2156 if(!*str && (*p == '*' && p[1] == '\0'))
2157 return true;
2159 return false;
2162 /*******************************************************************
2163 Simple case insensitive interface to a UNIX wildcard matcher.
2164 Returns True if match, False if not.
2165 *******************************************************************/
2167 bool unix_wild_match(const char *pattern, const char *string)
2169 TALLOC_CTX *ctx = talloc_stackframe();
2170 char *p2;
2171 char *s2;
2172 char *p;
2173 bool ret = false;
2175 p2 = talloc_strdup(ctx,pattern);
2176 s2 = talloc_strdup(ctx,string);
2177 if (!p2 || !s2) {
2178 TALLOC_FREE(ctx);
2179 return false;
2181 strlower_m(p2);
2182 strlower_m(s2);
2184 /* Remove any *? and ** from the pattern as they are meaningless */
2185 for(p = p2; *p; p++) {
2186 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
2187 memmove(&p[1], &p[2], strlen(&p[2])+1);
2191 if (strequal(p2,"*")) {
2192 TALLOC_FREE(ctx);
2193 return true;
2196 ret = unix_do_match(p2, s2);
2197 TALLOC_FREE(ctx);
2198 return ret;
2201 /**********************************************************************
2202 Converts a name to a fully qualified domain name.
2203 Returns true if lookup succeeded, false if not (then fqdn is set to name)
2204 Note we deliberately use gethostbyname here, not getaddrinfo as we want
2205 to examine the h_aliases and I don't know how to do that with getaddrinfo.
2206 ***********************************************************************/
2208 bool name_to_fqdn(fstring fqdn, const char *name)
2210 char *full = NULL;
2211 struct hostent *hp = gethostbyname(name);
2213 if (!hp || !hp->h_name || !*hp->h_name) {
2214 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
2215 fstrcpy(fqdn, name);
2216 return false;
2219 /* Find out if the fqdn is returned as an alias
2220 * to cope with /etc/hosts files where the first
2221 * name is not the fqdn but the short name */
2222 if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
2223 int i;
2224 for (i = 0; hp->h_aliases[i]; i++) {
2225 if (strchr_m(hp->h_aliases[i], '.')) {
2226 full = hp->h_aliases[i];
2227 break;
2231 if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) {
2232 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
2233 DEBUGADD(1, (" Specifing the machine hostname for address 127.0.0.1 may lead\n"));
2234 DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n"));
2235 DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n"));
2236 full = hp->h_name;
2238 if (!full) {
2239 full = hp->h_name;
2242 DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
2243 fstrcpy(fqdn, full);
2244 return true;
2247 /**********************************************************************
2248 Append a DATA_BLOB to a talloc'ed object
2249 ***********************************************************************/
2251 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
2253 size_t old_size = 0;
2254 char *result;
2256 if (blob.length == 0) {
2257 return buf;
2260 if (buf != NULL) {
2261 old_size = talloc_get_size(buf);
2264 result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
2265 if (result == NULL) {
2266 return NULL;
2269 memcpy(result + old_size, blob.data, blob.length);
2270 return result;
2273 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
2275 switch (share_access & ~FILE_SHARE_DELETE) {
2276 case FILE_SHARE_NONE:
2277 return DENY_ALL;
2278 case FILE_SHARE_READ:
2279 return DENY_WRITE;
2280 case FILE_SHARE_WRITE:
2281 return DENY_READ;
2282 case FILE_SHARE_READ|FILE_SHARE_WRITE:
2283 return DENY_NONE;
2285 if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
2286 return DENY_DOS;
2287 } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
2288 return DENY_FCB;
2291 return (uint32)-1;
2294 pid_t procid_to_pid(const struct server_id *proc)
2296 return proc->pid;
2299 static uint32 my_vnn = NONCLUSTER_VNN;
2301 void set_my_vnn(uint32 vnn)
2303 DEBUG(10, ("vnn pid %d = %u\n", (int)sys_getpid(), (unsigned int)vnn));
2304 my_vnn = vnn;
2307 uint32 get_my_vnn(void)
2309 return my_vnn;
2312 static uint64_t my_unique_id = 0;
2314 void set_my_unique_id(uint64_t unique_id)
2316 my_unique_id = unique_id;
2319 struct server_id pid_to_procid(pid_t pid)
2321 struct server_id result;
2322 result.pid = pid;
2323 result.unique_id = my_unique_id;
2324 result.vnn = my_vnn;
2325 return result;
2328 struct server_id procid_self(void)
2330 return pid_to_procid(sys_getpid());
2333 bool procid_equal(const struct server_id *p1, const struct server_id *p2)
2335 if (p1->pid != p2->pid)
2336 return False;
2337 if (p1->vnn != p2->vnn)
2338 return False;
2339 return True;
2342 bool cluster_id_equal(const struct server_id *id1,
2343 const struct server_id *id2)
2345 return procid_equal(id1, id2);
2348 bool procid_is_me(const struct server_id *pid)
2350 if (pid->pid != sys_getpid())
2351 return False;
2352 if (pid->vnn != my_vnn)
2353 return False;
2354 return True;
2357 struct server_id interpret_pid(const char *pid_string)
2359 struct server_id result;
2360 int pid;
2361 unsigned int vnn;
2362 if (sscanf(pid_string, "%u:%d", &vnn, &pid) == 2) {
2363 result.vnn = vnn;
2364 result.pid = pid;
2366 else if (sscanf(pid_string, "%d", &pid) == 1) {
2367 result.vnn = get_my_vnn();
2368 result.pid = pid;
2370 else {
2371 result.vnn = NONCLUSTER_VNN;
2372 result.pid = -1;
2374 /* Assigning to result.pid may have overflowed
2375 Map negative pid to -1: i.e. error */
2376 if (result.pid < 0) {
2377 result.pid = -1;
2379 result.unique_id = 0;
2380 return result;
2383 char *procid_str(TALLOC_CTX *mem_ctx, const struct server_id *pid)
2385 if (pid->vnn == NONCLUSTER_VNN) {
2386 return talloc_asprintf(mem_ctx,
2387 "%d",
2388 (int)pid->pid);
2390 else {
2391 return talloc_asprintf(mem_ctx,
2392 "%u:%d",
2393 (unsigned)pid->vnn,
2394 (int)pid->pid);
2398 char *procid_str_static(const struct server_id *pid)
2400 return procid_str(talloc_tos(), pid);
2403 bool procid_valid(const struct server_id *pid)
2405 return (pid->pid != -1);
2408 bool procid_is_local(const struct server_id *pid)
2410 return pid->vnn == my_vnn;
2413 /****************************************************************
2414 Check if offset/length fit into bufsize. Should probably be
2415 merged with is_offset_safe, but this would require a rewrite
2416 of lanman.c. Later :-)
2417 ****************************************************************/
2419 bool trans_oob(uint32_t bufsize, uint32_t offset, uint32_t length)
2421 if ((offset + length < offset) || (offset + length < length)) {
2422 /* wrap */
2423 return true;
2425 if ((offset > bufsize) || (offset + length > bufsize)) {
2426 /* overflow */
2427 return true;
2429 return false;
2432 /****************************************************************
2433 Check if an offset into a buffer is safe.
2434 If this returns True it's safe to indirect into the byte at
2435 pointer ptr+off.
2436 ****************************************************************/
2438 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2440 const char *end_base = buf_base + buf_len;
2441 char *end_ptr = ptr + off;
2443 if (!buf_base || !ptr) {
2444 return False;
2447 if (end_base < buf_base || end_ptr < ptr) {
2448 return False; /* wrap. */
2451 if (end_ptr < end_base) {
2452 return True;
2454 return False;
2457 /****************************************************************
2458 Return a safe pointer into a buffer, or NULL.
2459 ****************************************************************/
2461 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2463 return is_offset_safe(buf_base, buf_len, ptr, off) ?
2464 ptr + off : NULL;
2467 /****************************************************************
2468 Return a safe pointer into a string within a buffer, or NULL.
2469 ****************************************************************/
2471 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2473 if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2474 return NULL;
2476 /* Check if a valid string exists at this offset. */
2477 if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2478 return NULL;
2480 return ptr + off;
2483 /****************************************************************
2484 Return an SVAL at a pointer, or failval if beyond the end.
2485 ****************************************************************/
2487 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2490 * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2491 * NOT ptr[2].
2493 if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2494 return failval;
2496 return SVAL(ptr,off);
2499 /****************************************************************
2500 Return an IVAL at a pointer, or failval if beyond the end.
2501 ****************************************************************/
2503 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2506 * Note we use off+3 here, not off+4 as IVAL accesses
2507 * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2509 if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2510 return failval;
2512 return IVAL(ptr,off);
2515 /****************************************************************
2516 Split DOM\user into DOM and user. Do not mix with winbind variants of that
2517 call (they take care of winbind separator and other winbind specific settings).
2518 ****************************************************************/
2520 void split_domain_user(TALLOC_CTX *mem_ctx,
2521 const char *full_name,
2522 char **domain,
2523 char **user)
2525 const char *p = NULL;
2527 p = strchr_m(full_name, '\\');
2529 if (p != NULL) {
2530 *domain = talloc_strndup(mem_ctx, full_name,
2531 PTR_DIFF(p, full_name));
2532 *user = talloc_strdup(mem_ctx, p+1);
2533 } else {
2534 *domain = talloc_strdup(mem_ctx, "");
2535 *user = talloc_strdup(mem_ctx, full_name);
2539 #if 0
2541 Disable these now we have checked all code paths and ensured
2542 NULL returns on zero request. JRA.
2544 /****************************************************************
2545 talloc wrapper functions that guarentee a null pointer return
2546 if size == 0.
2547 ****************************************************************/
2549 #ifndef MAX_TALLOC_SIZE
2550 #define MAX_TALLOC_SIZE 0x10000000
2551 #endif
2554 * talloc and zero memory.
2555 * - returns NULL if size is zero.
2558 void *_talloc_zero_zeronull(const void *ctx, size_t size, const char *name)
2560 void *p;
2562 if (size == 0) {
2563 return NULL;
2566 p = talloc_named_const(ctx, size, name);
2568 if (p) {
2569 memset(p, '\0', size);
2572 return p;
2576 * memdup with a talloc.
2577 * - returns NULL if size is zero.
2580 void *_talloc_memdup_zeronull(const void *t, const void *p, size_t size, const char *name)
2582 void *newp;
2584 if (size == 0) {
2585 return NULL;
2588 newp = talloc_named_const(t, size, name);
2589 if (newp) {
2590 memcpy(newp, p, size);
2593 return newp;
2597 * alloc an array, checking for integer overflow in the array size.
2598 * - returns NULL if count or el_size are zero.
2601 void *_talloc_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
2603 if (count >= MAX_TALLOC_SIZE/el_size) {
2604 return NULL;
2607 if (el_size == 0 || count == 0) {
2608 return NULL;
2611 return talloc_named_const(ctx, el_size * count, name);
2615 * alloc an zero array, checking for integer overflow in the array size
2616 * - returns NULL if count or el_size are zero.
2619 void *_talloc_zero_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
2621 if (count >= MAX_TALLOC_SIZE/el_size) {
2622 return NULL;
2625 if (el_size == 0 || count == 0) {
2626 return NULL;
2629 return _talloc_zero(ctx, el_size * count, name);
2633 * Talloc wrapper that returns NULL if size == 0.
2635 void *talloc_zeronull(const void *context, size_t size, const char *name)
2637 if (size == 0) {
2638 return NULL;
2640 return talloc_named_const(context, size, name);
2642 #endif
2644 /****************************************************************
2645 strip off leading '\\' from a hostname
2646 ****************************************************************/
2648 const char *strip_hostname(const char *s)
2650 if (!s) {
2651 return NULL;
2654 if (strlen_m(s) < 3) {
2655 return s;
2658 if (s[0] == '\\') s++;
2659 if (s[0] == '\\') s++;
2661 return s;
2664 bool tevent_req_poll_ntstatus(struct tevent_req *req,
2665 struct tevent_context *ev,
2666 NTSTATUS *status)
2668 bool ret = tevent_req_poll(req, ev);
2669 if (!ret) {
2670 *status = map_nt_error_from_unix(errno);
2672 return ret;
2675 bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result)
2677 if (!NT_STATUS_IS_OK(err1)) {
2678 *result = err1;
2679 return true;
2681 if (!NT_STATUS_IS_OK(err2)) {
2682 *result = err2;
2683 return true;
2685 return false;
2688 int timeval_to_msec(struct timeval t)
2690 return t.tv_sec * 1000 + (t.tv_usec+999) / 1000;
2693 /*******************************************************************
2694 Check a given DOS pathname is valid for a share.
2695 ********************************************************************/
2697 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
2699 char *ptr = NULL;
2701 if (!dos_pathname) {
2702 return NULL;
2705 ptr = talloc_strdup(ctx, dos_pathname);
2706 if (!ptr) {
2707 return NULL;
2709 /* Convert any '\' paths to '/' */
2710 unix_format(ptr);
2711 ptr = unix_clean_name(ctx, ptr);
2712 if (!ptr) {
2713 return NULL;
2716 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
2717 if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
2718 ptr += 2;
2720 /* Only absolute paths allowed. */
2721 if (*ptr != '/')
2722 return NULL;
2724 return ptr;
2727 /*******************************************************************
2728 Return True if the filename is one of the special executable types.
2729 ********************************************************************/
2731 bool is_executable(const char *fname)
2733 if ((fname = strrchr_m(fname,'.'))) {
2734 if (strequal(fname,".com") ||
2735 strequal(fname,".dll") ||
2736 strequal(fname,".exe") ||
2737 strequal(fname,".sym")) {
2738 return True;
2741 return False;
2744 /****************************************************************************
2745 Open a file with a share mode - old openX method - map into NTCreate.
2746 ****************************************************************************/
2748 bool map_open_params_to_ntcreate(const char *smb_base_fname,
2749 int deny_mode, int open_func,
2750 uint32 *paccess_mask,
2751 uint32 *pshare_mode,
2752 uint32 *pcreate_disposition,
2753 uint32 *pcreate_options,
2754 uint32_t *pprivate_flags)
2756 uint32 access_mask;
2757 uint32 share_mode;
2758 uint32 create_disposition;
2759 uint32 create_options = FILE_NON_DIRECTORY_FILE;
2760 uint32_t private_flags = 0;
2762 DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
2763 "open_func = 0x%x\n",
2764 smb_base_fname, (unsigned int)deny_mode,
2765 (unsigned int)open_func ));
2767 /* Create the NT compatible access_mask. */
2768 switch (GET_OPENX_MODE(deny_mode)) {
2769 case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
2770 case DOS_OPEN_RDONLY:
2771 access_mask = FILE_GENERIC_READ;
2772 break;
2773 case DOS_OPEN_WRONLY:
2774 access_mask = FILE_GENERIC_WRITE;
2775 break;
2776 case DOS_OPEN_RDWR:
2777 case DOS_OPEN_FCB:
2778 access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
2779 break;
2780 default:
2781 DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
2782 (unsigned int)GET_OPENX_MODE(deny_mode)));
2783 return False;
2786 /* Create the NT compatible create_disposition. */
2787 switch (open_func) {
2788 case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
2789 create_disposition = FILE_CREATE;
2790 break;
2792 case OPENX_FILE_EXISTS_OPEN:
2793 create_disposition = FILE_OPEN;
2794 break;
2796 case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
2797 create_disposition = FILE_OPEN_IF;
2798 break;
2800 case OPENX_FILE_EXISTS_TRUNCATE:
2801 create_disposition = FILE_OVERWRITE;
2802 break;
2804 case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
2805 create_disposition = FILE_OVERWRITE_IF;
2806 break;
2808 default:
2809 /* From samba4 - to be confirmed. */
2810 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
2811 create_disposition = FILE_CREATE;
2812 break;
2814 DEBUG(10,("map_open_params_to_ntcreate: bad "
2815 "open_func 0x%x\n", (unsigned int)open_func));
2816 return False;
2819 /* Create the NT compatible share modes. */
2820 switch (GET_DENY_MODE(deny_mode)) {
2821 case DENY_ALL:
2822 share_mode = FILE_SHARE_NONE;
2823 break;
2825 case DENY_WRITE:
2826 share_mode = FILE_SHARE_READ;
2827 break;
2829 case DENY_READ:
2830 share_mode = FILE_SHARE_WRITE;
2831 break;
2833 case DENY_NONE:
2834 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2835 break;
2837 case DENY_DOS:
2838 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
2839 if (is_executable(smb_base_fname)) {
2840 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2841 } else {
2842 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
2843 share_mode = FILE_SHARE_READ;
2844 } else {
2845 share_mode = FILE_SHARE_NONE;
2848 break;
2850 case DENY_FCB:
2851 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
2852 share_mode = FILE_SHARE_NONE;
2853 break;
2855 default:
2856 DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
2857 (unsigned int)GET_DENY_MODE(deny_mode) ));
2858 return False;
2861 DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
2862 "share_mode = 0x%x, create_disposition = 0x%x, "
2863 "create_options = 0x%x private_flags = 0x%x\n",
2864 smb_base_fname,
2865 (unsigned int)access_mask,
2866 (unsigned int)share_mode,
2867 (unsigned int)create_disposition,
2868 (unsigned int)create_options,
2869 (unsigned int)private_flags));
2871 if (paccess_mask) {
2872 *paccess_mask = access_mask;
2874 if (pshare_mode) {
2875 *pshare_mode = share_mode;
2877 if (pcreate_disposition) {
2878 *pcreate_disposition = create_disposition;
2880 if (pcreate_options) {
2881 *pcreate_options = create_options;
2883 if (pprivate_flags) {
2884 *pprivate_flags = private_flags;
2887 return True;