Add 'make randomized-test' rule.
[Samba.git] / source3 / lib / util.c
blob7b2afa8073c1187ae818c8e86cf4ff053299190f
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 <ccan/hash/hash.h>
32 #include "libcli/security/security.h"
33 #include "serverid.h"
35 #ifdef HAVE_SYS_PRCTL_H
36 #include <sys/prctl.h>
37 #endif
39 /* Max allowable allococation - 256mb - 0x10000000 */
40 #define MAX_ALLOC_SIZE (1024*1024*256)
42 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
43 #ifdef WITH_NISPLUS_HOME
44 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
46 * The following lines are needed due to buggy include files
47 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
48 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
49 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
50 * an enum in /usr/include/rpcsvc/nis.h.
53 #if defined(GROUP)
54 #undef GROUP
55 #endif
57 #if defined(GROUP_OBJ)
58 #undef GROUP_OBJ
59 #endif
61 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
63 #include <rpcsvc/nis.h>
65 #endif /* WITH_NISPLUS_HOME */
66 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
68 static enum protocol_types Protocol = PROTOCOL_COREPLUS;
70 enum protocol_types get_Protocol(void)
72 return Protocol;
75 void set_Protocol(enum protocol_types p)
77 Protocol = p;
80 static enum remote_arch_types ra_type = RA_UNKNOWN;
82 void gfree_all( void )
84 gfree_names();
85 gfree_loadparm();
86 gfree_charcnv();
87 gfree_interfaces();
88 gfree_debugsyms();
91 /*******************************************************************
92 Check if a file exists - call vfs_file_exist for samba files.
93 ********************************************************************/
95 bool file_exist_stat(const char *fname,SMB_STRUCT_STAT *sbuf,
96 bool fake_dir_create_times)
98 SMB_STRUCT_STAT st;
99 if (!sbuf)
100 sbuf = &st;
102 if (sys_stat(fname, sbuf, fake_dir_create_times) != 0)
103 return(False);
105 return((S_ISREG(sbuf->st_ex_mode)) || (S_ISFIFO(sbuf->st_ex_mode)));
108 /*******************************************************************
109 Check if a unix domain socket exists - call vfs_file_exist for samba files.
110 ********************************************************************/
112 bool socket_exist(const char *fname)
114 SMB_STRUCT_STAT st;
115 if (sys_stat(fname, &st, false) != 0)
116 return(False);
118 return S_ISSOCK(st.st_ex_mode);
121 /*******************************************************************
122 Returns the size in bytes of the named given the stat struct.
123 ********************************************************************/
125 uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf)
127 return sbuf->st_ex_size;
130 /****************************************************************************
131 Check two stats have identical dev and ino fields.
132 ****************************************************************************/
134 bool check_same_dev_ino(const SMB_STRUCT_STAT *sbuf1,
135 const SMB_STRUCT_STAT *sbuf2)
137 if (sbuf1->st_ex_dev != sbuf2->st_ex_dev ||
138 sbuf1->st_ex_ino != sbuf2->st_ex_ino) {
139 return false;
141 return true;
144 /****************************************************************************
145 Check if a stat struct is identical for use.
146 ****************************************************************************/
148 bool check_same_stat(const SMB_STRUCT_STAT *sbuf1,
149 const SMB_STRUCT_STAT *sbuf2)
151 if (sbuf1->st_ex_uid != sbuf2->st_ex_uid ||
152 sbuf1->st_ex_gid != sbuf2->st_ex_gid ||
153 !check_same_dev_ino(sbuf1, sbuf2)) {
154 return false;
156 return true;
159 /*******************************************************************
160 Show a smb message structure.
161 ********************************************************************/
163 void show_msg(const char *buf)
165 int i;
166 int bcc=0;
168 if (!DEBUGLVL(5))
169 return;
171 DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
172 smb_len(buf),
173 (int)CVAL(buf,smb_com),
174 (int)CVAL(buf,smb_rcls),
175 (int)CVAL(buf,smb_reh),
176 (int)SVAL(buf,smb_err),
177 (int)CVAL(buf,smb_flg),
178 (int)SVAL(buf,smb_flg2)));
179 DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
180 (int)SVAL(buf,smb_tid),
181 (int)SVAL(buf,smb_pid),
182 (int)SVAL(buf,smb_uid),
183 (int)SVAL(buf,smb_mid)));
184 DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
186 for (i=0;i<(int)CVAL(buf,smb_wct);i++)
187 DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
188 SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
190 bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
192 DEBUGADD(5,("smb_bcc=%d\n",bcc));
194 if (DEBUGLEVEL < 10)
195 return;
197 if (DEBUGLEVEL < 50)
198 bcc = MIN(bcc, 512);
200 dump_data(10, (const uint8 *)smb_buf_const(buf), bcc);
203 /*******************************************************************
204 Setup only the byte count for a smb message.
205 ********************************************************************/
207 int set_message_bcc(char *buf,int num_bytes)
209 int num_words = CVAL(buf,smb_wct);
210 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
211 _smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
212 return (smb_size + num_words*2 + num_bytes);
215 /*******************************************************************
216 Add a data blob to the end of a smb_buf, adjusting bcc and smb_len.
217 Return the bytes added
218 ********************************************************************/
220 ssize_t message_push_blob(uint8 **outbuf, DATA_BLOB blob)
222 size_t newlen = smb_len(*outbuf) + 4 + blob.length;
223 uint8 *tmp;
225 if (!(tmp = talloc_realloc(NULL, *outbuf, uint8, newlen))) {
226 DEBUG(0, ("talloc failed\n"));
227 return -1;
229 *outbuf = tmp;
231 memcpy(tmp + smb_len(tmp) + 4, blob.data, blob.length);
232 set_message_bcc((char *)tmp, smb_buflen(tmp) + blob.length);
233 return blob.length;
236 /*******************************************************************
237 Reduce a file name, removing .. elements.
238 ********************************************************************/
240 static char *dos_clean_name(TALLOC_CTX *ctx, const char *s)
242 char *p = NULL;
243 char *str = NULL;
245 DEBUG(3,("dos_clean_name [%s]\n",s));
247 /* remove any double slashes */
248 str = talloc_all_string_sub(ctx, s, "\\\\", "\\");
249 if (!str) {
250 return NULL;
253 /* Remove leading .\\ characters */
254 if(strncmp(str, ".\\", 2) == 0) {
255 trim_string(str, ".\\", NULL);
256 if(*str == 0) {
257 str = talloc_strdup(ctx, ".\\");
258 if (!str) {
259 return NULL;
264 while ((p = strstr_m(str,"\\..\\")) != NULL) {
265 char *s1;
267 *p = 0;
268 s1 = p+3;
270 if ((p=strrchr_m(str,'\\')) != NULL) {
271 *p = 0;
272 } else {
273 *str = 0;
275 str = talloc_asprintf(ctx,
276 "%s%s",
277 str,
278 s1);
279 if (!str) {
280 return NULL;
284 trim_string(str,NULL,"\\..");
285 return talloc_all_string_sub(ctx, str, "\\.\\", "\\");
288 /*******************************************************************
289 Reduce a file name, removing .. elements.
290 ********************************************************************/
292 char *unix_clean_name(TALLOC_CTX *ctx, const char *s)
294 char *p = NULL;
295 char *str = NULL;
297 DEBUG(3,("unix_clean_name [%s]\n",s));
299 /* remove any double slashes */
300 str = talloc_all_string_sub(ctx, s, "//","/");
301 if (!str) {
302 return NULL;
305 /* Remove leading ./ characters */
306 if(strncmp(str, "./", 2) == 0) {
307 trim_string(str, "./", NULL);
308 if(*str == 0) {
309 str = talloc_strdup(ctx, "./");
310 if (!str) {
311 return NULL;
316 while ((p = strstr_m(str,"/../")) != NULL) {
317 char *s1;
319 *p = 0;
320 s1 = p+3;
322 if ((p=strrchr_m(str,'/')) != NULL) {
323 *p = 0;
324 } else {
325 *str = 0;
327 str = talloc_asprintf(ctx,
328 "%s%s",
329 str,
330 s1);
331 if (!str) {
332 return NULL;
336 trim_string(str,NULL,"/..");
337 return talloc_all_string_sub(ctx, str, "/./", "/");
340 char *clean_name(TALLOC_CTX *ctx, const char *s)
342 char *str = dos_clean_name(ctx, s);
343 if (!str) {
344 return NULL;
346 return unix_clean_name(ctx, str);
349 /*******************************************************************
350 Write data into an fd at a given offset. Ignore seek errors.
351 ********************************************************************/
353 ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, off_t pos)
355 size_t total=0;
356 ssize_t ret;
358 if (pos == (off_t)-1) {
359 return write_data(fd, buffer, N);
361 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
362 while (total < N) {
363 ret = sys_pwrite(fd,buffer + total,N - total, pos);
364 if (ret == -1 && errno == ESPIPE) {
365 return write_data(fd, buffer + total,N - total);
367 if (ret == -1) {
368 DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
369 return -1;
371 if (ret == 0) {
372 return total;
374 total += ret;
375 pos += ret;
377 return (ssize_t)total;
378 #else
379 /* Use lseek and write_data. */
380 if (lseek(fd, pos, SEEK_SET) == -1) {
381 if (errno != ESPIPE) {
382 return -1;
385 return write_data(fd, buffer, N);
386 #endif
389 static int reinit_after_fork_pipe[2] = { -1, -1 };
391 NTSTATUS init_before_fork(void)
393 int ret;
395 ret = pipe(reinit_after_fork_pipe);
396 if (ret == -1) {
397 NTSTATUS status;
399 status = map_nt_error_from_unix_common(errno);
401 DEBUG(0, ("Error creating child_pipe: %s\n",
402 nt_errstr(status)));
404 return status;
407 return NT_STATUS_OK;
411 * Detect died parent by detecting EOF on the pipe
413 static void reinit_after_fork_pipe_handler(struct tevent_context *ev,
414 struct tevent_fd *fde,
415 uint16_t flags,
416 void *private_data)
418 char c;
420 if (sys_read(reinit_after_fork_pipe[0], &c, 1) != 1) {
422 * we have reached EOF on stdin, which means the
423 * parent has exited. Shutdown the server
425 (void)kill(getpid(), SIGTERM);
430 NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
431 struct tevent_context *ev_ctx,
432 bool parent_longlived)
434 NTSTATUS status = NT_STATUS_OK;
436 if (reinit_after_fork_pipe[1] != -1) {
437 close(reinit_after_fork_pipe[1]);
438 reinit_after_fork_pipe[1] = -1;
441 /* Reset the state of the random
442 * number generation system, so
443 * children do not get the same random
444 * numbers as each other */
445 set_need_random_reseed();
447 /* tdb needs special fork handling */
448 if (tdb_reopen_all(parent_longlived ? 1 : 0) != 0) {
449 DEBUG(0,("tdb_reopen_all failed.\n"));
450 status = NT_STATUS_OPEN_FAILED;
451 goto done;
454 if (ev_ctx != NULL) {
455 tevent_set_trace_callback(ev_ctx, NULL, NULL);
456 if (tevent_re_initialise(ev_ctx) != 0) {
457 smb_panic(__location__ ": Failed to re-initialise event context");
461 if (reinit_after_fork_pipe[0] != -1) {
462 struct tevent_fd *fde;
464 fde = tevent_add_fd(ev_ctx, ev_ctx /* TALLOC_CTX */,
465 reinit_after_fork_pipe[0], TEVENT_FD_READ,
466 reinit_after_fork_pipe_handler, NULL);
467 if (fde == NULL) {
468 smb_panic(__location__ ": Failed to add reinit_after_fork pipe event");
472 if (msg_ctx) {
474 * For clustering, we need to re-init our ctdbd connection after the
475 * fork
477 status = messaging_reinit(msg_ctx);
478 if (!NT_STATUS_IS_OK(status)) {
479 DEBUG(0,("messaging_reinit() failed: %s\n",
480 nt_errstr(status)));
483 done:
484 return status;
487 /****************************************************************************
488 (Hopefully) efficient array append.
489 ****************************************************************************/
491 void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
492 void *element, void *_array, uint32 *num_elements,
493 ssize_t *array_size)
495 void **array = (void **)_array;
497 if (*array_size < 0) {
498 return;
501 if (*array == NULL) {
502 if (*array_size == 0) {
503 *array_size = 128;
506 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
507 goto error;
510 *array = TALLOC(mem_ctx, element_size * (*array_size));
511 if (*array == NULL) {
512 goto error;
516 if (*num_elements == *array_size) {
517 *array_size *= 2;
519 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
520 goto error;
523 *array = TALLOC_REALLOC(mem_ctx, *array,
524 element_size * (*array_size));
526 if (*array == NULL) {
527 goto error;
531 memcpy((char *)(*array) + element_size*(*num_elements),
532 element, element_size);
533 *num_elements += 1;
535 return;
537 error:
538 *num_elements = 0;
539 *array_size = -1;
542 /****************************************************************************
543 Get my own domain name, or "" if we have none.
544 ****************************************************************************/
546 char *get_mydnsdomname(TALLOC_CTX *ctx)
548 const char *domname;
549 char *p;
551 domname = get_mydnsfullname();
552 if (!domname) {
553 return NULL;
556 p = strchr_m(domname, '.');
557 if (p) {
558 p++;
559 return talloc_strdup(ctx, p);
560 } else {
561 return talloc_strdup(ctx, "");
565 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
566 /******************************************************************
567 Remove any mount options such as -rsize=2048,wsize=2048 etc.
568 Based on a fix from <Thomas.Hepper@icem.de>.
569 Returns a malloc'ed string.
570 *******************************************************************/
572 static char *strip_mount_options(TALLOC_CTX *ctx, const char *str)
574 if (*str == '-') {
575 const char *p = str;
576 while(*p && !isspace(*p))
577 p++;
578 while(*p && isspace(*p))
579 p++;
580 if(*p) {
581 return talloc_strdup(ctx, p);
584 return NULL;
587 /*******************************************************************
588 Patch from jkf@soton.ac.uk
589 Split Luke's automount_server into YP lookup and string splitter
590 so can easily implement automount_path().
591 Returns a malloc'ed string.
592 *******************************************************************/
594 #ifdef WITH_NISPLUS_HOME
595 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
597 char *value = NULL;
599 char *nis_map = (char *)lp_homedir_map();
601 char buffer[NIS_MAXATTRVAL + 1];
602 nis_result *result;
603 nis_object *object;
604 entry_obj *entry;
606 snprintf(buffer, sizeof(buffer), "[key=%s],%s", user_name, nis_map);
607 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
609 if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
610 if (result->status != NIS_SUCCESS) {
611 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
612 } else {
613 object = result->objects.objects_val;
614 if (object->zo_data.zo_type == ENTRY_OBJ) {
615 entry = &object->zo_data.objdata_u.en_data;
616 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
617 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
619 value = talloc_strdup(ctx,
620 entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
621 if (!value) {
622 nis_freeresult(result);
623 return NULL;
625 value = talloc_string_sub(ctx,
626 value,
627 "&",
628 user_name);
632 nis_freeresult(result);
634 if (value) {
635 value = strip_mount_options(ctx, value);
636 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n",
637 user_name, value));
639 return value;
641 #else /* WITH_NISPLUS_HOME */
643 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
645 char *value = NULL;
647 int nis_error; /* returned by yp all functions */
648 char *nis_result; /* yp_match inits this */
649 int nis_result_len; /* and set this */
650 char *nis_domain; /* yp_get_default_domain inits this */
651 char *nis_map = lp_homedir_map(talloc_tos());
653 if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
654 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
655 return NULL;
658 DEBUG(5, ("NIS Domain: %s\n", nis_domain));
660 if ((nis_error = yp_match(nis_domain, nis_map, user_name,
661 strlen(user_name), &nis_result,
662 &nis_result_len)) == 0) {
663 if (nis_result_len > 0 && nis_result[nis_result_len] == '\n') {
664 nis_result[nis_result_len] = '\0';
666 value = talloc_strdup(ctx, nis_result);
667 if (!value) {
668 return NULL;
670 value = strip_mount_options(ctx, value);
671 } else if(nis_error == YPERR_KEY) {
672 DEBUG(3, ("YP Key not found: while looking up \"%s\" in map \"%s\"\n",
673 user_name, nis_map));
674 DEBUG(3, ("using defaults for server and home directory\n"));
675 } else {
676 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
677 yperr_string(nis_error), user_name, nis_map));
680 if (value) {
681 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, value));
683 return value;
685 #endif /* WITH_NISPLUS_HOME */
686 #endif
688 bool process_exists(const struct server_id pid)
690 return serverid_exists(&pid);
693 /*******************************************************************
694 Convert a uid into a user name.
695 ********************************************************************/
697 const char *uidtoname(uid_t uid)
699 TALLOC_CTX *ctx = talloc_tos();
700 char *name = NULL;
701 struct passwd *pass = NULL;
703 pass = getpwuid_alloc(ctx,uid);
704 if (pass) {
705 name = talloc_strdup(ctx,pass->pw_name);
706 TALLOC_FREE(pass);
707 } else {
708 name = talloc_asprintf(ctx,
709 "%ld",
710 (long int)uid);
712 return name;
715 /*******************************************************************
716 Convert a gid into a group name.
717 ********************************************************************/
719 char *gidtoname(gid_t gid)
721 struct group *grp;
723 grp = getgrgid(gid);
724 if (grp) {
725 return talloc_strdup(talloc_tos(), grp->gr_name);
727 else {
728 return talloc_asprintf(talloc_tos(),
729 "%d",
730 (int)gid);
734 /*******************************************************************
735 Convert a user name into a uid.
736 ********************************************************************/
738 uid_t nametouid(const char *name)
740 struct passwd *pass;
741 char *p;
742 uid_t u;
744 pass = Get_Pwnam_alloc(talloc_tos(), name);
745 if (pass) {
746 u = pass->pw_uid;
747 TALLOC_FREE(pass);
748 return u;
751 u = (uid_t)strtol(name, &p, 0);
752 if ((p != name) && (*p == '\0'))
753 return u;
755 return (uid_t)-1;
758 /*******************************************************************
759 Convert a name to a gid_t if possible. Return -1 if not a group.
760 ********************************************************************/
762 gid_t nametogid(const char *name)
764 struct group *grp;
765 char *p;
766 gid_t g;
768 g = (gid_t)strtol(name, &p, 0);
769 if ((p != name) && (*p == '\0'))
770 return g;
772 grp = getgrnam(name);
773 if (grp)
774 return(grp->gr_gid);
775 return (gid_t)-1;
778 /*******************************************************************
779 Something really nasty happened - panic !
780 ********************************************************************/
782 void smb_panic_s3(const char *why)
784 char *cmd;
785 int result;
787 DEBUG(0,("PANIC (pid %llu): %s\n",
788 (unsigned long long)getpid(), why));
789 log_stack_trace();
791 #if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER)
793 * Make sure all children can attach a debugger.
795 prctl(PR_SET_PTRACER, getpid(), 0, 0, 0);
796 #endif
798 cmd = lp_panic_action(talloc_tos());
799 if (cmd && *cmd) {
800 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
801 result = system(cmd);
803 if (result == -1)
804 DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
805 strerror(errno)));
806 else
807 DEBUG(0, ("smb_panic(): action returned status %d\n",
808 WEXITSTATUS(result)));
811 dump_core();
814 /*******************************************************************
815 Print a backtrace of the stack to the debug log. This function
816 DELIBERATELY LEAKS MEMORY. The expectation is that you should
817 exit shortly after calling it.
818 ********************************************************************/
820 #ifdef HAVE_LIBUNWIND_H
821 #include <libunwind.h>
822 #endif
824 #ifdef HAVE_EXECINFO_H
825 #include <execinfo.h>
826 #endif
828 #ifdef HAVE_LIBEXC_H
829 #include <libexc.h>
830 #endif
832 void log_stack_trace(void)
834 #ifdef HAVE_LIBUNWIND
835 /* Try to use libunwind before any other technique since on ia64
836 * libunwind correctly walks the stack in more circumstances than
837 * backtrace.
839 unw_cursor_t cursor;
840 unw_context_t uc;
841 unsigned i = 0;
843 char procname[256];
844 unw_word_t ip, sp, off;
846 procname[sizeof(procname) - 1] = '\0';
848 if (unw_getcontext(&uc) != 0) {
849 goto libunwind_failed;
852 if (unw_init_local(&cursor, &uc) != 0) {
853 goto libunwind_failed;
856 DEBUG(0, ("BACKTRACE:\n"));
858 do {
859 ip = sp = 0;
860 unw_get_reg(&cursor, UNW_REG_IP, &ip);
861 unw_get_reg(&cursor, UNW_REG_SP, &sp);
863 switch (unw_get_proc_name(&cursor,
864 procname, sizeof(procname) - 1, &off) ) {
865 case 0:
866 /* Name found. */
867 case -UNW_ENOMEM:
868 /* Name truncated. */
869 DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
870 i, procname, (long long)off,
871 (long long)ip, (long long) sp));
872 break;
873 default:
874 /* case -UNW_ENOINFO: */
875 /* case -UNW_EUNSPEC: */
876 /* No symbol name found. */
877 DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
878 i, "<unknown symbol>",
879 (long long)ip, (long long) sp));
881 ++i;
882 } while (unw_step(&cursor) > 0);
884 return;
886 libunwind_failed:
887 DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
889 #elif HAVE_BACKTRACE_SYMBOLS
890 void *backtrace_stack[BACKTRACE_STACK_SIZE];
891 size_t backtrace_size;
892 char **backtrace_strings;
894 /* get the backtrace (stack frames) */
895 backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
896 backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
898 DEBUG(0, ("BACKTRACE: %lu stack frames:\n",
899 (unsigned long)backtrace_size));
901 if (backtrace_strings) {
902 int i;
904 for (i = 0; i < backtrace_size; i++)
905 DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
907 /* Leak the backtrace_strings, rather than risk what free() might do */
910 #elif HAVE_LIBEXC
912 /* The IRIX libexc library provides an API for unwinding the stack. See
913 * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
914 * since we are about to abort anyway, it hardly matters.
917 #define NAMESIZE 32 /* Arbitrary */
919 __uint64_t addrs[BACKTRACE_STACK_SIZE];
920 char * names[BACKTRACE_STACK_SIZE];
921 char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
923 int i;
924 int levels;
926 ZERO_ARRAY(addrs);
927 ZERO_ARRAY(names);
928 ZERO_ARRAY(namebuf);
930 /* We need to be root so we can open our /proc entry to walk
931 * our stack. It also helps when we want to dump core.
933 become_root();
935 for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
936 names[i] = namebuf + (i * NAMESIZE);
939 levels = trace_back_stack(0, addrs, names,
940 BACKTRACE_STACK_SIZE, NAMESIZE - 1);
942 DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
943 for (i = 0; i < levels; i++) {
944 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
946 #undef NAMESIZE
948 #else
949 DEBUG(0, ("unable to produce a stack trace on this platform\n"));
950 #endif
953 /*******************************************************************
954 A readdir wrapper which just returns the file name.
955 ********************************************************************/
957 const char *readdirname(DIR *p)
959 struct dirent *ptr;
960 char *dname;
962 if (!p)
963 return(NULL);
965 ptr = (struct dirent *)readdir(p);
966 if (!ptr)
967 return(NULL);
969 dname = ptr->d_name;
971 #ifdef NEXT2
972 if (telldir(p) < 0)
973 return(NULL);
974 #endif
976 #ifdef HAVE_BROKEN_READDIR_NAME
977 /* using /usr/ucb/cc is BAD */
978 dname = dname - 2;
979 #endif
981 return talloc_strdup(talloc_tos(), dname);
984 /*******************************************************************
985 Utility function used to decide if the last component
986 of a path matches a (possibly wildcarded) entry in a namelist.
987 ********************************************************************/
989 bool is_in_path(const char *name, name_compare_entry *namelist, bool case_sensitive)
991 const char *last_component;
993 /* if we have no list it's obviously not in the path */
994 if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
995 return False;
998 DEBUG(8, ("is_in_path: %s\n", name));
1000 /* Get the last component of the unix name. */
1001 last_component = strrchr_m(name, '/');
1002 if (!last_component) {
1003 last_component = name;
1004 } else {
1005 last_component++; /* Go past '/' */
1008 for(; namelist->name != NULL; namelist++) {
1009 if(namelist->is_wild) {
1010 if (mask_match(last_component, namelist->name, case_sensitive)) {
1011 DEBUG(8,("is_in_path: mask match succeeded\n"));
1012 return True;
1014 } else {
1015 if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
1016 (!case_sensitive && (strcasecmp_m(last_component, namelist->name) == 0))) {
1017 DEBUG(8,("is_in_path: match succeeded\n"));
1018 return True;
1022 DEBUG(8,("is_in_path: match not found\n"));
1023 return False;
1026 /*******************************************************************
1027 Strip a '/' separated list into an array of
1028 name_compare_enties structures suitable for
1029 passing to is_in_path(). We do this for
1030 speed so we can pre-parse all the names in the list
1031 and don't do it for each call to is_in_path().
1032 We also check if the entry contains a wildcard to
1033 remove a potentially expensive call to mask_match
1034 if possible.
1035 ********************************************************************/
1037 void set_namearray(name_compare_entry **ppname_array, const char *namelist_in)
1039 char *name_end;
1040 char *namelist;
1041 char *namelist_end;
1042 char *nameptr;
1043 int num_entries = 0;
1044 int i;
1046 (*ppname_array) = NULL;
1048 if((namelist_in == NULL ) || ((namelist_in != NULL) && (*namelist_in == '\0')))
1049 return;
1051 namelist = talloc_strdup(talloc_tos(), namelist_in);
1052 if (namelist == NULL) {
1053 DEBUG(0,("set_namearray: talloc fail\n"));
1054 return;
1056 nameptr = namelist;
1058 namelist_end = &namelist[strlen(namelist)];
1060 /* We need to make two passes over the string. The
1061 first to count the number of elements, the second
1062 to split it.
1065 while(nameptr <= namelist_end) {
1066 if ( *nameptr == '/' ) {
1067 /* cope with multiple (useless) /s) */
1068 nameptr++;
1069 continue;
1071 /* anything left? */
1072 if ( *nameptr == '\0' )
1073 break;
1075 /* find the next '/' or consume remaining */
1076 name_end = strchr_m(nameptr, '/');
1077 if (name_end == NULL) {
1078 /* Point nameptr at the terminating '\0' */
1079 nameptr += strlen(nameptr);
1080 } else {
1081 /* next segment please */
1082 nameptr = name_end + 1;
1084 num_entries++;
1087 if(num_entries == 0) {
1088 talloc_free(namelist);
1089 return;
1092 if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1093 DEBUG(0,("set_namearray: malloc fail\n"));
1094 talloc_free(namelist);
1095 return;
1098 /* Now copy out the names */
1099 nameptr = namelist;
1100 i = 0;
1101 while(nameptr <= namelist_end) {
1102 if ( *nameptr == '/' ) {
1103 /* cope with multiple (useless) /s) */
1104 nameptr++;
1105 continue;
1107 /* anything left? */
1108 if ( *nameptr == '\0' )
1109 break;
1111 /* find the next '/' or consume remaining */
1112 name_end = strchr_m(nameptr, '/');
1113 if (name_end != NULL) {
1114 *name_end = '\0';
1117 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1118 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1119 DEBUG(0,("set_namearray: malloc fail (1)\n"));
1120 talloc_free(namelist);
1121 return;
1124 if (name_end == NULL) {
1125 /* Point nameptr at the terminating '\0' */
1126 nameptr += strlen(nameptr);
1127 } else {
1128 /* next segment please */
1129 nameptr = name_end + 1;
1131 i++;
1134 (*ppname_array)[i].name = NULL;
1136 talloc_free(namelist);
1137 return;
1140 #undef DBGC_CLASS
1141 #define DBGC_CLASS DBGC_LOCKING
1143 /****************************************************************************
1144 Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
1145 is dealt with in posix.c
1146 Returns True if we have information regarding this lock region (and returns
1147 F_UNLCK in *ptype if the region is unlocked). False if the call failed.
1148 ****************************************************************************/
1150 bool fcntl_getlock(int fd, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1152 struct flock lock;
1153 int ret;
1155 DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
1156 fd,(double)*poffset,(double)*pcount,*ptype));
1158 lock.l_type = *ptype;
1159 lock.l_whence = SEEK_SET;
1160 lock.l_start = *poffset;
1161 lock.l_len = *pcount;
1162 lock.l_pid = 0;
1164 ret = sys_fcntl_ptr(fd,F_GETLK,&lock);
1166 if (ret == -1) {
1167 int sav = errno;
1168 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
1169 (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
1170 errno = sav;
1171 return False;
1174 *ptype = lock.l_type;
1175 *poffset = lock.l_start;
1176 *pcount = lock.l_len;
1177 *ppid = lock.l_pid;
1179 DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
1180 fd, (int)lock.l_type, (unsigned int)lock.l_pid));
1181 return True;
1184 #undef DBGC_CLASS
1185 #define DBGC_CLASS DBGC_ALL
1187 /*******************************************************************
1188 Is the name specified one of my netbios names.
1189 Returns true if it is equal, false otherwise.
1190 ********************************************************************/
1192 bool is_myname(const char *s)
1194 int n;
1195 bool ret = False;
1197 for (n=0; my_netbios_names(n); n++) {
1198 if (strequal(my_netbios_names(n), s)) {
1199 ret=True;
1200 break;
1203 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1204 return(ret);
1207 /*******************************************************************
1208 we distinguish between 2K and XP by the "Native Lan Manager" string
1209 WinXP => "Windows 2002 5.1"
1210 WinXP 64bit => "Windows XP 5.2"
1211 Win2k => "Windows 2000 5.0"
1212 NT4 => "Windows NT 4.0"
1213 Win9x => "Windows 4.0"
1214 Windows 2003 doesn't set the native lan manager string but
1215 they do set the domain to "Windows 2003 5.2" (probably a bug).
1216 ********************************************************************/
1218 void ra_lanman_string( const char *native_lanman )
1220 if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1221 set_remote_arch( RA_WINXP );
1222 else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1223 set_remote_arch( RA_WINXP64 );
1224 else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1225 set_remote_arch( RA_WIN2K3 );
1228 static const char *remote_arch_str;
1230 const char *get_remote_arch_str(void)
1232 if (!remote_arch_str) {
1233 return "UNKNOWN";
1235 return remote_arch_str;
1238 /*******************************************************************
1239 Set the horrid remote_arch string based on an enum.
1240 ********************************************************************/
1242 void set_remote_arch(enum remote_arch_types type)
1244 ra_type = type;
1245 switch( type ) {
1246 case RA_WFWG:
1247 remote_arch_str = "WfWg";
1248 break;
1249 case RA_OS2:
1250 remote_arch_str = "OS2";
1251 break;
1252 case RA_WIN95:
1253 remote_arch_str = "Win95";
1254 break;
1255 case RA_WINNT:
1256 remote_arch_str = "WinNT";
1257 break;
1258 case RA_WIN2K:
1259 remote_arch_str = "Win2K";
1260 break;
1261 case RA_WINXP:
1262 remote_arch_str = "WinXP";
1263 break;
1264 case RA_WINXP64:
1265 remote_arch_str = "WinXP64";
1266 break;
1267 case RA_WIN2K3:
1268 remote_arch_str = "Win2K3";
1269 break;
1270 case RA_VISTA:
1271 remote_arch_str = "Vista";
1272 break;
1273 case RA_SAMBA:
1274 remote_arch_str = "Samba";
1275 break;
1276 case RA_CIFSFS:
1277 remote_arch_str = "CIFSFS";
1278 break;
1279 case RA_OSX:
1280 remote_arch_str = "OSX";
1281 break;
1282 default:
1283 ra_type = RA_UNKNOWN;
1284 remote_arch_str = "UNKNOWN";
1285 break;
1288 DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1289 remote_arch_str));
1292 /*******************************************************************
1293 Get the remote_arch type.
1294 ********************************************************************/
1296 enum remote_arch_types get_remote_arch(void)
1298 return ra_type;
1301 const char *tab_depth(int level, int depth)
1303 if( CHECK_DEBUGLVL(level) ) {
1304 dbgtext("%*s", depth*4, "");
1306 return "";
1309 /*****************************************************************************
1310 Provide a checksum on a string
1312 Input: s - the null-terminated character string for which the checksum
1313 will be calculated.
1315 Output: The checksum value calculated for s.
1316 *****************************************************************************/
1318 int str_checksum(const char *s)
1320 if (s == NULL)
1321 return 0;
1322 return hash(s, strlen(s), 0);
1325 /*****************************************************************
1326 Zero a memory area then free it. Used to catch bugs faster.
1327 *****************************************************************/
1329 void zero_free(void *p, size_t size)
1331 memset(p, 0, size);
1332 SAFE_FREE(p);
1335 /*****************************************************************
1336 Set our open file limit to a requested max and return the limit.
1337 *****************************************************************/
1339 int set_maxfiles(int requested_max)
1341 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1342 struct rlimit rlp;
1343 int saved_current_limit;
1345 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1346 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1347 strerror(errno) ));
1348 /* just guess... */
1349 return requested_max;
1353 * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1354 * account for the extra fd we need
1355 * as well as the log files and standard
1356 * handles etc. Save the limit we want to set in case
1357 * we are running on an OS that doesn't support this limit (AIX)
1358 * which always returns RLIM_INFINITY for rlp.rlim_max.
1361 /* Try raising the hard (max) limit to the requested amount. */
1363 #if defined(RLIM_INFINITY)
1364 if (rlp.rlim_max != RLIM_INFINITY) {
1365 int orig_max = rlp.rlim_max;
1367 if ( rlp.rlim_max < requested_max )
1368 rlp.rlim_max = requested_max;
1370 /* This failing is not an error - many systems (Linux) don't
1371 support our default request of 10,000 open files. JRA. */
1373 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1374 DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n",
1375 (int)rlp.rlim_max, strerror(errno) ));
1377 /* Set failed - restore original value from get. */
1378 rlp.rlim_max = orig_max;
1381 #endif
1383 /* Now try setting the soft (current) limit. */
1385 saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1387 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1388 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
1389 (int)rlp.rlim_cur, strerror(errno) ));
1390 /* just guess... */
1391 return saved_current_limit;
1394 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1395 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1396 strerror(errno) ));
1397 /* just guess... */
1398 return saved_current_limit;
1401 #if defined(RLIM_INFINITY)
1402 if(rlp.rlim_cur == RLIM_INFINITY)
1403 return saved_current_limit;
1404 #endif
1406 if((int)rlp.rlim_cur > saved_current_limit)
1407 return saved_current_limit;
1409 return rlp.rlim_cur;
1410 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1412 * No way to know - just guess...
1414 return requested_max;
1415 #endif
1418 /*****************************************************************
1419 malloc that aborts with smb_panic on fail or zero size.
1420 *****************************************************************/
1422 void *smb_xmalloc_array(size_t size, unsigned int count)
1424 void *p;
1425 if (size == 0) {
1426 smb_panic("smb_xmalloc_array: called with zero size");
1428 if (count >= MAX_ALLOC_SIZE/size) {
1429 smb_panic("smb_xmalloc_array: alloc size too large");
1431 if ((p = SMB_MALLOC(size*count)) == NULL) {
1432 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1433 (unsigned long)size, (unsigned long)count));
1434 smb_panic("smb_xmalloc_array: malloc failed");
1436 return p;
1440 vasprintf that aborts on malloc fail
1443 int smb_xvasprintf(char **ptr, const char *format, va_list ap)
1445 int n;
1446 va_list ap2;
1448 va_copy(ap2, ap);
1450 n = vasprintf(ptr, format, ap2);
1451 va_end(ap2);
1452 if (n == -1 || ! *ptr) {
1453 smb_panic("smb_xvasprintf: out of memory");
1455 return n;
1458 /*****************************************************************
1459 Get local hostname and cache result.
1460 *****************************************************************/
1462 char *myhostname(void)
1464 static char *ret;
1465 if (ret == NULL) {
1466 ret = get_myname(NULL);
1468 return ret;
1471 /*****************************************************************
1472 Get local hostname and cache result.
1473 *****************************************************************/
1475 char *myhostname_upper(void)
1477 static char *ret;
1478 if (ret == NULL) {
1479 char *name = get_myname(NULL);
1480 if (name == NULL) {
1481 return NULL;
1483 ret = strupper_talloc(NULL, name);
1484 talloc_free(name);
1486 return ret;
1490 * @brief Returns an absolute path to a file concatenating the provided
1491 * @a rootpath and @a basename
1493 * @param name Filename, relative to @a rootpath
1495 * @retval Pointer to a string containing the full path.
1498 static char *xx_path(const char *name, const char *rootpath)
1500 char *fname = NULL;
1502 fname = talloc_strdup(talloc_tos(), rootpath);
1503 if (!fname) {
1504 return NULL;
1506 trim_string(fname,"","/");
1508 if (!directory_exist(fname)) {
1509 if (mkdir(fname,0755) == -1) {
1510 /* Did someone else win the race ? */
1511 if (errno != EEXIST) {
1512 DEBUG(1, ("Unable to create directory %s for file %s. "
1513 "Error was %s\n", fname, name, strerror(errno)));
1514 return NULL;
1519 return talloc_asprintf_append(fname, "/%s", name);
1523 * @brief Returns an absolute path to a file in the Samba lock directory.
1525 * @param name File to find, relative to LOCKDIR.
1527 * @retval Pointer to a talloc'ed string containing the full path.
1530 char *lock_path(const char *name)
1532 return xx_path(name, lp_lock_directory());
1536 * @brief Returns an absolute path to a file in the Samba state directory.
1538 * @param name File to find, relative to STATEDIR.
1540 * @retval Pointer to a talloc'ed string containing the full path.
1543 char *state_path(const char *name)
1545 return xx_path(name, lp_state_directory());
1549 * @brief Returns an absolute path to a file in the Samba cache directory.
1551 * @param name File to find, relative to CACHEDIR.
1553 * @retval Pointer to a talloc'ed string containing the full path.
1556 char *cache_path(const char *name)
1558 return xx_path(name, lp_cache_directory());
1561 /*******************************************************************
1562 Given a filename - get its directory name
1563 ********************************************************************/
1565 bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
1566 const char **name)
1568 char *p;
1569 ptrdiff_t len;
1571 p = strrchr_m(dir, '/'); /* Find final '/', if any */
1573 if (p == NULL) {
1574 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
1575 return False;
1577 if (name) {
1578 *name = dir;
1580 return True;
1583 len = p-dir;
1585 if (!(*parent = (char *)talloc_memdup(mem_ctx, dir, len+1))) {
1586 return False;
1588 (*parent)[len] = '\0';
1590 if (name) {
1591 *name = p+1;
1593 return True;
1596 /*******************************************************************
1597 Determine if a pattern contains any Microsoft wildcard characters.
1598 *******************************************************************/
1600 bool ms_has_wild(const char *s)
1602 char c;
1604 if (lp_posix_pathnames()) {
1605 /* With posix pathnames no characters are wild. */
1606 return False;
1609 while ((c = *s++)) {
1610 switch (c) {
1611 case '*':
1612 case '?':
1613 case '<':
1614 case '>':
1615 case '"':
1616 return True;
1619 return False;
1622 bool ms_has_wild_w(const smb_ucs2_t *s)
1624 smb_ucs2_t c;
1625 if (!s) return False;
1626 while ((c = *s++)) {
1627 switch (c) {
1628 case UCS2_CHAR('*'):
1629 case UCS2_CHAR('?'):
1630 case UCS2_CHAR('<'):
1631 case UCS2_CHAR('>'):
1632 case UCS2_CHAR('"'):
1633 return True;
1636 return False;
1639 /*******************************************************************
1640 A wrapper that handles case sensitivity and the special handling
1641 of the ".." name.
1642 *******************************************************************/
1644 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
1646 if (ISDOTDOT(string))
1647 string = ".";
1648 if (ISDOT(pattern))
1649 return False;
1651 return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
1654 /*******************************************************************
1655 A wrapper that handles case sensitivity and the special handling
1656 of the ".." name. Varient that is only called by old search code which requires
1657 pattern translation.
1658 *******************************************************************/
1660 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
1662 if (ISDOTDOT(string))
1663 string = ".";
1664 if (ISDOT(pattern))
1665 return False;
1667 return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
1670 /*******************************************************************
1671 A wrapper that handles a list of patters and calls mask_match()
1672 on each. Returns True if any of the patterns match.
1673 *******************************************************************/
1675 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
1677 while (listLen-- > 0) {
1678 if (mask_match(string, *list++, is_case_sensitive))
1679 return True;
1681 return False;
1684 /*********************************************************
1685 Recursive routine that is called by unix_wild_match.
1686 *********************************************************/
1688 static bool unix_do_match(const char *regexp, const char *str)
1690 const char *p;
1692 for( p = regexp; *p && *str; ) {
1694 switch(*p) {
1695 case '?':
1696 str++;
1697 p++;
1698 break;
1700 case '*':
1703 * Look for a character matching
1704 * the one after the '*'.
1706 p++;
1707 if(!*p)
1708 return true; /* Automatic match */
1709 while(*str) {
1711 while(*str && (*p != *str))
1712 str++;
1715 * Patch from weidel@multichart.de. In the case of the regexp
1716 * '*XX*' we want to ensure there are at least 2 'X' characters
1717 * in the string after the '*' for a match to be made.
1721 int matchcount=0;
1724 * Eat all the characters that match, but count how many there were.
1727 while(*str && (*p == *str)) {
1728 str++;
1729 matchcount++;
1733 * Now check that if the regexp had n identical characters that
1734 * matchcount had at least that many matches.
1737 while ( *(p+1) && (*(p+1) == *p)) {
1738 p++;
1739 matchcount--;
1742 if ( matchcount <= 0 )
1743 return false;
1746 str--; /* We've eaten the match char after the '*' */
1748 if(unix_do_match(p, str))
1749 return true;
1751 if(!*str)
1752 return false;
1753 else
1754 str++;
1756 return false;
1758 default:
1759 if(*str != *p)
1760 return false;
1761 str++;
1762 p++;
1763 break;
1767 if(!*p && !*str)
1768 return true;
1770 if (!*p && str[0] == '.' && str[1] == 0)
1771 return true;
1773 if (!*str && *p == '?') {
1774 while (*p == '?')
1775 p++;
1776 return(!*p);
1779 if(!*str && (*p == '*' && p[1] == '\0'))
1780 return true;
1782 return false;
1785 /*******************************************************************
1786 Simple case insensitive interface to a UNIX wildcard matcher.
1787 Returns True if match, False if not.
1788 *******************************************************************/
1790 bool unix_wild_match(const char *pattern, const char *string)
1792 TALLOC_CTX *ctx = talloc_stackframe();
1793 char *p2;
1794 char *s2;
1795 char *p;
1796 bool ret = false;
1798 p2 = talloc_strdup(ctx,pattern);
1799 s2 = talloc_strdup(ctx,string);
1800 if (!p2 || !s2) {
1801 TALLOC_FREE(ctx);
1802 return false;
1804 if (!strlower_m(p2)) {
1805 TALLOC_FREE(ctx);
1806 return false;
1808 if (!strlower_m(s2)) {
1809 TALLOC_FREE(ctx);
1810 return false;
1813 /* Remove any *? and ** from the pattern as they are meaningless */
1814 for(p = p2; *p; p++) {
1815 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
1816 memmove(&p[1], &p[2], strlen(&p[2])+1);
1820 if (strequal(p2,"*")) {
1821 TALLOC_FREE(ctx);
1822 return true;
1825 ret = unix_do_match(p2, s2);
1826 TALLOC_FREE(ctx);
1827 return ret;
1830 /**********************************************************************
1831 Converts a name to a fully qualified domain name.
1832 Returns true if lookup succeeded, false if not (then fqdn is set to name)
1833 Note we deliberately use gethostbyname here, not getaddrinfo as we want
1834 to examine the h_aliases and I don't know how to do that with getaddrinfo.
1835 ***********************************************************************/
1837 bool name_to_fqdn(fstring fqdn, const char *name)
1839 char *full = NULL;
1840 struct hostent *hp = gethostbyname(name);
1842 if (!hp || !hp->h_name || !*hp->h_name) {
1843 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
1844 fstrcpy(fqdn, name);
1845 return false;
1848 /* Find out if the fqdn is returned as an alias
1849 * to cope with /etc/hosts files where the first
1850 * name is not the fqdn but the short name */
1851 if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
1852 int i;
1853 for (i = 0; hp->h_aliases[i]; i++) {
1854 if (strchr_m(hp->h_aliases[i], '.')) {
1855 full = hp->h_aliases[i];
1856 break;
1860 if (full && (strcasecmp_m(full, "localhost.localdomain") == 0)) {
1861 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
1862 DEBUGADD(1, (" Specifying the machine hostname for address 127.0.0.1 may lead\n"));
1863 DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n"));
1864 DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n"));
1865 full = hp->h_name;
1867 if (!full) {
1868 full = hp->h_name;
1871 DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
1872 fstrcpy(fqdn, full);
1873 return true;
1876 /**********************************************************************
1877 Append a DATA_BLOB to a talloc'ed object
1878 ***********************************************************************/
1880 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
1882 size_t old_size = 0;
1883 char *result;
1885 if (blob.length == 0) {
1886 return buf;
1889 if (buf != NULL) {
1890 old_size = talloc_get_size(buf);
1893 result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
1894 if (result == NULL) {
1895 return NULL;
1898 memcpy(result + old_size, blob.data, blob.length);
1899 return result;
1902 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
1904 switch (share_access & ~FILE_SHARE_DELETE) {
1905 case FILE_SHARE_NONE:
1906 return DENY_ALL;
1907 case FILE_SHARE_READ:
1908 return DENY_WRITE;
1909 case FILE_SHARE_WRITE:
1910 return DENY_READ;
1911 case FILE_SHARE_READ|FILE_SHARE_WRITE:
1912 return DENY_NONE;
1914 if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
1915 return DENY_DOS;
1916 } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
1917 return DENY_FCB;
1920 return (uint32)-1;
1923 pid_t procid_to_pid(const struct server_id *proc)
1925 return proc->pid;
1928 static uint32 my_vnn = NONCLUSTER_VNN;
1930 void set_my_vnn(uint32 vnn)
1932 DEBUG(10, ("vnn pid %d = %u\n", (int)getpid(), (unsigned int)vnn));
1933 my_vnn = vnn;
1936 uint32 get_my_vnn(void)
1938 return my_vnn;
1941 static uint64_t my_unique_id = 0;
1943 void set_my_unique_id(uint64_t unique_id)
1945 my_unique_id = unique_id;
1948 struct server_id pid_to_procid(pid_t pid)
1950 struct server_id result;
1951 result.pid = pid;
1952 result.task_id = 0;
1953 result.unique_id = my_unique_id;
1954 result.vnn = my_vnn;
1955 return result;
1958 struct server_id procid_self(void)
1960 return pid_to_procid(getpid());
1963 bool procid_is_me(const struct server_id *pid)
1965 if (pid->pid != getpid())
1966 return False;
1967 if (pid->task_id != 0)
1968 return False;
1969 if (pid->vnn != my_vnn)
1970 return False;
1971 return True;
1974 struct server_id interpret_pid(const char *pid_string)
1976 return server_id_from_string(get_my_vnn(), pid_string);
1979 char *procid_str_static(const struct server_id *pid)
1981 return server_id_str(talloc_tos(), pid);
1984 bool procid_valid(const struct server_id *pid)
1986 return (pid->pid != (uint64_t)-1);
1989 bool procid_is_local(const struct server_id *pid)
1991 return pid->vnn == my_vnn;
1994 /****************************************************************
1995 Check if an offset into a buffer is safe.
1996 If this returns True it's safe to indirect into the byte at
1997 pointer ptr+off.
1998 ****************************************************************/
2000 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2002 const char *end_base = buf_base + buf_len;
2003 char *end_ptr = ptr + off;
2005 if (!buf_base || !ptr) {
2006 return False;
2009 if (end_base < buf_base || end_ptr < ptr) {
2010 return False; /* wrap. */
2013 if (end_ptr < end_base) {
2014 return True;
2016 return False;
2019 /****************************************************************
2020 Return a safe pointer into a buffer, or NULL.
2021 ****************************************************************/
2023 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2025 return is_offset_safe(buf_base, buf_len, ptr, off) ?
2026 ptr + off : NULL;
2029 /****************************************************************
2030 Return a safe pointer into a string within a buffer, or NULL.
2031 ****************************************************************/
2033 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2035 if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2036 return NULL;
2038 /* Check if a valid string exists at this offset. */
2039 if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2040 return NULL;
2042 return ptr + off;
2045 /****************************************************************
2046 Return an SVAL at a pointer, or failval if beyond the end.
2047 ****************************************************************/
2049 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2052 * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2053 * NOT ptr[2].
2055 if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2056 return failval;
2058 return SVAL(ptr,off);
2061 /****************************************************************
2062 Return an IVAL at a pointer, or failval if beyond the end.
2063 ****************************************************************/
2065 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2068 * Note we use off+3 here, not off+4 as IVAL accesses
2069 * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2071 if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2072 return failval;
2074 return IVAL(ptr,off);
2077 /****************************************************************
2078 Split DOM\user into DOM and user. Do not mix with winbind variants of that
2079 call (they take care of winbind separator and other winbind specific settings).
2080 ****************************************************************/
2082 void split_domain_user(TALLOC_CTX *mem_ctx,
2083 const char *full_name,
2084 char **domain,
2085 char **user)
2087 const char *p = NULL;
2089 p = strchr_m(full_name, '\\');
2091 if (p != NULL) {
2092 *domain = talloc_strndup(mem_ctx, full_name,
2093 PTR_DIFF(p, full_name));
2094 *user = talloc_strdup(mem_ctx, p+1);
2095 } else {
2096 *domain = talloc_strdup(mem_ctx, "");
2097 *user = talloc_strdup(mem_ctx, full_name);
2101 /****************************************************************
2102 strip off leading '\\' from a hostname
2103 ****************************************************************/
2105 const char *strip_hostname(const char *s)
2107 if (!s) {
2108 return NULL;
2111 if (strlen_m(s) < 3) {
2112 return s;
2115 if (s[0] == '\\') s++;
2116 if (s[0] == '\\') s++;
2118 return s;
2121 bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result)
2123 if (!NT_STATUS_IS_OK(err1)) {
2124 *result = err1;
2125 return true;
2127 if (!NT_STATUS_IS_OK(err2)) {
2128 *result = err2;
2129 return true;
2131 return false;
2134 int timeval_to_msec(struct timeval t)
2136 return t.tv_sec * 1000 + (t.tv_usec+999) / 1000;
2139 /*******************************************************************
2140 Check a given DOS pathname is valid for a share.
2141 ********************************************************************/
2143 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
2145 char *ptr = NULL;
2147 if (!dos_pathname) {
2148 return NULL;
2151 ptr = talloc_strdup(ctx, dos_pathname);
2152 if (!ptr) {
2153 return NULL;
2155 /* Convert any '\' paths to '/' */
2156 unix_format(ptr);
2157 ptr = unix_clean_name(ctx, ptr);
2158 if (!ptr) {
2159 return NULL;
2162 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
2163 if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
2164 ptr += 2;
2166 /* Only absolute paths allowed. */
2167 if (*ptr != '/')
2168 return NULL;
2170 return ptr;
2173 /*******************************************************************
2174 Return True if the filename is one of the special executable types.
2175 ********************************************************************/
2177 bool is_executable(const char *fname)
2179 if ((fname = strrchr_m(fname,'.'))) {
2180 if (strequal(fname,".com") ||
2181 strequal(fname,".dll") ||
2182 strequal(fname,".exe") ||
2183 strequal(fname,".sym")) {
2184 return True;
2187 return False;
2190 /****************************************************************************
2191 Open a file with a share mode - old openX method - map into NTCreate.
2192 ****************************************************************************/
2194 bool map_open_params_to_ntcreate(const char *smb_base_fname,
2195 int deny_mode, int open_func,
2196 uint32 *paccess_mask,
2197 uint32 *pshare_mode,
2198 uint32 *pcreate_disposition,
2199 uint32 *pcreate_options,
2200 uint32_t *pprivate_flags)
2202 uint32 access_mask;
2203 uint32 share_mode;
2204 uint32 create_disposition;
2205 uint32 create_options = FILE_NON_DIRECTORY_FILE;
2206 uint32_t private_flags = 0;
2208 DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
2209 "open_func = 0x%x\n",
2210 smb_base_fname, (unsigned int)deny_mode,
2211 (unsigned int)open_func ));
2213 /* Create the NT compatible access_mask. */
2214 switch (GET_OPENX_MODE(deny_mode)) {
2215 case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
2216 case DOS_OPEN_RDONLY:
2217 access_mask = FILE_GENERIC_READ;
2218 break;
2219 case DOS_OPEN_WRONLY:
2220 access_mask = FILE_GENERIC_WRITE;
2221 break;
2222 case DOS_OPEN_RDWR:
2223 case DOS_OPEN_FCB:
2224 access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
2225 break;
2226 default:
2227 DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
2228 (unsigned int)GET_OPENX_MODE(deny_mode)));
2229 return False;
2232 /* Create the NT compatible create_disposition. */
2233 switch (open_func) {
2234 case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
2235 create_disposition = FILE_CREATE;
2236 break;
2238 case OPENX_FILE_EXISTS_OPEN:
2239 create_disposition = FILE_OPEN;
2240 break;
2242 case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
2243 create_disposition = FILE_OPEN_IF;
2244 break;
2246 case OPENX_FILE_EXISTS_TRUNCATE:
2247 create_disposition = FILE_OVERWRITE;
2248 break;
2250 case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
2251 create_disposition = FILE_OVERWRITE_IF;
2252 break;
2254 default:
2255 /* From samba4 - to be confirmed. */
2256 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
2257 create_disposition = FILE_CREATE;
2258 break;
2260 DEBUG(10,("map_open_params_to_ntcreate: bad "
2261 "open_func 0x%x\n", (unsigned int)open_func));
2262 return False;
2265 /* Create the NT compatible share modes. */
2266 switch (GET_DENY_MODE(deny_mode)) {
2267 case DENY_ALL:
2268 share_mode = FILE_SHARE_NONE;
2269 break;
2271 case DENY_WRITE:
2272 share_mode = FILE_SHARE_READ;
2273 break;
2275 case DENY_READ:
2276 share_mode = FILE_SHARE_WRITE;
2277 break;
2279 case DENY_NONE:
2280 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2281 break;
2283 case DENY_DOS:
2284 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
2285 if (is_executable(smb_base_fname)) {
2286 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2287 } else {
2288 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
2289 share_mode = FILE_SHARE_READ;
2290 } else {
2291 share_mode = FILE_SHARE_NONE;
2294 break;
2296 case DENY_FCB:
2297 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
2298 share_mode = FILE_SHARE_NONE;
2299 break;
2301 default:
2302 DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
2303 (unsigned int)GET_DENY_MODE(deny_mode) ));
2304 return False;
2307 DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
2308 "share_mode = 0x%x, create_disposition = 0x%x, "
2309 "create_options = 0x%x private_flags = 0x%x\n",
2310 smb_base_fname,
2311 (unsigned int)access_mask,
2312 (unsigned int)share_mode,
2313 (unsigned int)create_disposition,
2314 (unsigned int)create_options,
2315 (unsigned int)private_flags));
2317 if (paccess_mask) {
2318 *paccess_mask = access_mask;
2320 if (pshare_mode) {
2321 *pshare_mode = share_mode;
2323 if (pcreate_disposition) {
2324 *pcreate_disposition = create_disposition;
2326 if (pcreate_options) {
2327 *pcreate_options = create_options;
2329 if (pprivate_flags) {
2330 *pprivate_flags = private_flags;
2333 return True;
2337 /*************************************************************************
2338 Return a talloced copy of a struct security_unix_token. NULL on fail.
2339 *************************************************************************/
2341 struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct security_unix_token *tok)
2343 struct security_unix_token *cpy;
2345 cpy = talloc(ctx, struct security_unix_token);
2346 if (!cpy) {
2347 return NULL;
2350 cpy->uid = tok->uid;
2351 cpy->gid = tok->gid;
2352 cpy->ngroups = tok->ngroups;
2353 if (tok->ngroups) {
2354 /* Make this a talloc child of cpy. */
2355 cpy->groups = (gid_t *)talloc_memdup(
2356 cpy, tok->groups, tok->ngroups * sizeof(gid_t));
2357 if (!cpy->groups) {
2358 TALLOC_FREE(cpy);
2359 return NULL;
2361 } else {
2362 cpy->groups = NULL;
2364 return cpy;
2367 /****************************************************************************
2368 Check that a file matches a particular file type.
2369 ****************************************************************************/
2371 bool dir_check_ftype(uint32_t mode, uint32_t dirtype)
2373 uint32_t mask;
2375 /* Check the "may have" search bits. */
2376 if (((mode & ~dirtype) &
2377 (FILE_ATTRIBUTE_HIDDEN |
2378 FILE_ATTRIBUTE_SYSTEM |
2379 FILE_ATTRIBUTE_DIRECTORY)) != 0) {
2380 return false;
2383 /* Check the "must have" bits,
2384 which are the may have bits shifted eight */
2385 /* If must have bit is set, the file/dir can
2386 not be returned in search unless the matching
2387 file attribute is set */
2388 mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|
2389 FILE_ATTRIBUTE_ARCHIVE|
2390 FILE_ATTRIBUTE_READONLY|
2391 FILE_ATTRIBUTE_HIDDEN|
2392 FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
2393 if(mask) {
2394 if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|
2395 FILE_ATTRIBUTE_ARCHIVE|
2396 FILE_ATTRIBUTE_READONLY|
2397 FILE_ATTRIBUTE_HIDDEN|
2398 FILE_ATTRIBUTE_SYSTEM))) == mask) {
2399 /* check if matching attribute present */
2400 return true;
2401 } else {
2402 return false;
2406 return true;