s4:torture/rpc: avoid compiler warnings
[Samba.git] / source3 / lib / util.c
blobe296fd5e0f9f87585237094a630b80b37080df27
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"
32 #include "serverid.h"
33 #include "lib/sys_rw.h"
34 #include "lib/sys_rw_data.h"
36 #ifdef HAVE_SYS_PRCTL_H
37 #include <sys/prctl.h>
38 #endif
40 /* Max allowable allococation - 256mb - 0x10000000 */
41 #define MAX_ALLOC_SIZE (1024*1024*256)
43 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
44 #ifdef WITH_NISPLUS_HOME
45 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
47 * The following lines are needed due to buggy include files
48 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
49 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
50 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
51 * an enum in /usr/include/rpcsvc/nis.h.
54 #if defined(GROUP)
55 #undef GROUP
56 #endif
58 #if defined(GROUP_OBJ)
59 #undef GROUP_OBJ
60 #endif
62 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
64 #include <rpcsvc/nis.h>
66 #endif /* WITH_NISPLUS_HOME */
67 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
69 static enum protocol_types Protocol = PROTOCOL_COREPLUS;
71 enum protocol_types get_Protocol(void)
73 return Protocol;
76 void set_Protocol(enum protocol_types p)
78 Protocol = p;
81 static enum remote_arch_types ra_type = RA_UNKNOWN;
83 void gfree_all( void )
85 gfree_names();
86 gfree_loadparm();
87 gfree_charcnv();
88 gfree_interfaces();
89 gfree_debugsyms();
92 /*******************************************************************
93 Check if a file exists - call vfs_file_exist for samba files.
94 ********************************************************************/
96 bool file_exist_stat(const char *fname,SMB_STRUCT_STAT *sbuf,
97 bool fake_dir_create_times)
99 SMB_STRUCT_STAT st;
100 if (!sbuf)
101 sbuf = &st;
103 if (sys_stat(fname, sbuf, fake_dir_create_times) != 0)
104 return(False);
106 return((S_ISREG(sbuf->st_ex_mode)) || (S_ISFIFO(sbuf->st_ex_mode)));
109 /*******************************************************************
110 Check if a unix domain socket exists - call vfs_file_exist for samba files.
111 ********************************************************************/
113 bool socket_exist(const char *fname)
115 SMB_STRUCT_STAT st;
116 if (sys_stat(fname, &st, false) != 0)
117 return(False);
119 return S_ISSOCK(st.st_ex_mode);
122 /*******************************************************************
123 Returns the size in bytes of the named given the stat struct.
124 ********************************************************************/
126 uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf)
128 return sbuf->st_ex_size;
131 /****************************************************************************
132 Check two stats have identical dev and ino fields.
133 ****************************************************************************/
135 bool check_same_dev_ino(const SMB_STRUCT_STAT *sbuf1,
136 const SMB_STRUCT_STAT *sbuf2)
138 if (sbuf1->st_ex_dev != sbuf2->st_ex_dev ||
139 sbuf1->st_ex_ino != sbuf2->st_ex_ino) {
140 return false;
142 return true;
145 /****************************************************************************
146 Check if a stat struct is identical for use.
147 ****************************************************************************/
149 bool check_same_stat(const SMB_STRUCT_STAT *sbuf1,
150 const SMB_STRUCT_STAT *sbuf2)
152 if (sbuf1->st_ex_uid != sbuf2->st_ex_uid ||
153 sbuf1->st_ex_gid != sbuf2->st_ex_gid ||
154 !check_same_dev_ino(sbuf1, sbuf2)) {
155 return false;
157 return true;
160 /*******************************************************************
161 Show a smb message structure.
162 ********************************************************************/
164 void show_msg(const char *buf)
166 int i;
167 int bcc=0;
169 if (!DEBUGLVL(5))
170 return;
172 DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
173 smb_len(buf),
174 (int)CVAL(buf,smb_com),
175 (int)CVAL(buf,smb_rcls),
176 (int)CVAL(buf,smb_reh),
177 (int)SVAL(buf,smb_err),
178 (int)CVAL(buf,smb_flg),
179 (int)SVAL(buf,smb_flg2)));
180 DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
181 (int)SVAL(buf,smb_tid),
182 (int)SVAL(buf,smb_pid),
183 (int)SVAL(buf,smb_uid),
184 (int)SVAL(buf,smb_mid)));
185 DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
187 for (i=0;i<(int)CVAL(buf,smb_wct);i++)
188 DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
189 SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
191 bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
193 DEBUGADD(5,("smb_bcc=%d\n",bcc));
195 if (DEBUGLEVEL < 10)
196 return;
198 if (DEBUGLEVEL < 50)
199 bcc = MIN(bcc, 512);
201 dump_data(10, (const uint8 *)smb_buf_const(buf), bcc);
204 /*******************************************************************
205 Setup only the byte count for a smb message.
206 ********************************************************************/
208 int set_message_bcc(char *buf,int num_bytes)
210 int num_words = CVAL(buf,smb_wct);
211 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
212 _smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
213 return (smb_size + num_words*2 + num_bytes);
216 /*******************************************************************
217 Add a data blob to the end of a smb_buf, adjusting bcc and smb_len.
218 Return the bytes added
219 ********************************************************************/
221 ssize_t message_push_blob(uint8 **outbuf, DATA_BLOB blob)
223 size_t newlen = smb_len(*outbuf) + 4 + blob.length;
224 uint8 *tmp;
226 if (!(tmp = talloc_realloc(NULL, *outbuf, uint8, newlen))) {
227 DEBUG(0, ("talloc failed\n"));
228 return -1;
230 *outbuf = tmp;
232 memcpy(tmp + smb_len(tmp) + 4, blob.data, blob.length);
233 set_message_bcc((char *)tmp, smb_buflen(tmp) + blob.length);
234 return blob.length;
237 /*******************************************************************
238 Reduce a file name, removing .. elements.
239 ********************************************************************/
241 static char *dos_clean_name(TALLOC_CTX *ctx, const char *s)
243 char *p = NULL;
244 char *str = NULL;
246 DEBUG(3,("dos_clean_name [%s]\n",s));
248 /* remove any double slashes */
249 str = talloc_all_string_sub(ctx, s, "\\\\", "\\");
250 if (!str) {
251 return NULL;
254 /* Remove leading .\\ characters */
255 if(strncmp(str, ".\\", 2) == 0) {
256 trim_string(str, ".\\", NULL);
257 if(*str == 0) {
258 str = talloc_strdup(ctx, ".\\");
259 if (!str) {
260 return NULL;
265 while ((p = strstr_m(str,"\\..\\")) != NULL) {
266 char *s1;
268 *p = 0;
269 s1 = p+3;
271 if ((p=strrchr_m(str,'\\')) != NULL) {
272 *p = 0;
273 } else {
274 *str = 0;
276 str = talloc_asprintf(ctx,
277 "%s%s",
278 str,
279 s1);
280 if (!str) {
281 return NULL;
285 trim_string(str,NULL,"\\..");
286 return talloc_all_string_sub(ctx, str, "\\.\\", "\\");
289 /*******************************************************************
290 Reduce a file name, removing .. elements.
291 ********************************************************************/
293 char *unix_clean_name(TALLOC_CTX *ctx, const char *s)
295 char *p = NULL;
296 char *str = NULL;
298 DEBUG(3,("unix_clean_name [%s]\n",s));
300 /* remove any double slashes */
301 str = talloc_all_string_sub(ctx, s, "//","/");
302 if (!str) {
303 return NULL;
306 /* Remove leading ./ characters */
307 if(strncmp(str, "./", 2) == 0) {
308 trim_string(str, "./", NULL);
309 if(*str == 0) {
310 str = talloc_strdup(ctx, "./");
311 if (!str) {
312 return NULL;
317 while ((p = strstr_m(str,"/../")) != NULL) {
318 char *s1;
320 *p = 0;
321 s1 = p+3;
323 if ((p=strrchr_m(str,'/')) != NULL) {
324 *p = 0;
325 } else {
326 *str = 0;
328 str = talloc_asprintf(ctx,
329 "%s%s",
330 str,
331 s1);
332 if (!str) {
333 return NULL;
337 trim_string(str,NULL,"/..");
338 return talloc_all_string_sub(ctx, str, "/./", "/");
341 char *clean_name(TALLOC_CTX *ctx, const char *s)
343 char *str = dos_clean_name(ctx, s);
344 if (!str) {
345 return NULL;
347 return unix_clean_name(ctx, str);
350 /*******************************************************************
351 Write data into an fd at a given offset. Ignore seek errors.
352 ********************************************************************/
354 ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, off_t pos)
356 size_t total=0;
357 ssize_t ret;
359 if (pos == (off_t)-1) {
360 return write_data(fd, buffer, N);
362 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
363 while (total < N) {
364 ret = sys_pwrite(fd,buffer + total,N - total, pos);
365 if (ret == -1 && errno == ESPIPE) {
366 return write_data(fd, buffer + total,N - total);
368 if (ret == -1) {
369 DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
370 return -1;
372 if (ret == 0) {
373 return total;
375 total += ret;
376 pos += ret;
378 return (ssize_t)total;
379 #else
380 /* Use lseek and write_data. */
381 if (lseek(fd, pos, SEEK_SET) == -1) {
382 if (errno != ESPIPE) {
383 return -1;
386 return write_data(fd, buffer, N);
387 #endif
390 static int reinit_after_fork_pipe[2] = { -1, -1 };
392 NTSTATUS init_before_fork(void)
394 int ret;
396 ret = pipe(reinit_after_fork_pipe);
397 if (ret == -1) {
398 NTSTATUS status;
400 status = map_nt_error_from_unix_common(errno);
402 DEBUG(0, ("Error creating child_pipe: %s\n",
403 nt_errstr(status)));
405 return status;
408 return NT_STATUS_OK;
412 * Detect died parent by detecting EOF on the pipe
414 static void reinit_after_fork_pipe_handler(struct tevent_context *ev,
415 struct tevent_fd *fde,
416 uint16_t flags,
417 void *private_data)
419 char c;
421 if (sys_read(reinit_after_fork_pipe[0], &c, 1) != 1) {
423 * we have reached EOF on stdin, which means the
424 * parent has exited. Shutdown the server
426 (void)kill(getpid(), SIGTERM);
431 NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
432 struct tevent_context *ev_ctx,
433 bool parent_longlived)
435 NTSTATUS status = NT_STATUS_OK;
437 if (reinit_after_fork_pipe[1] != -1) {
438 close(reinit_after_fork_pipe[1]);
439 reinit_after_fork_pipe[1] = -1;
442 /* Reset the state of the random
443 * number generation system, so
444 * children do not get the same random
445 * numbers as each other */
446 set_need_random_reseed();
448 /* tdb needs special fork handling */
449 if (tdb_reopen_all(parent_longlived ? 1 : 0) != 0) {
450 DEBUG(0,("tdb_reopen_all failed.\n"));
451 status = NT_STATUS_OPEN_FAILED;
452 goto done;
455 if (ev_ctx != NULL) {
456 tevent_set_trace_callback(ev_ctx, NULL, NULL);
457 if (tevent_re_initialise(ev_ctx) != 0) {
458 smb_panic(__location__ ": Failed to re-initialise event context");
462 if (reinit_after_fork_pipe[0] != -1) {
463 struct tevent_fd *fde;
465 fde = tevent_add_fd(ev_ctx, ev_ctx /* TALLOC_CTX */,
466 reinit_after_fork_pipe[0], TEVENT_FD_READ,
467 reinit_after_fork_pipe_handler, NULL);
468 if (fde == NULL) {
469 smb_panic(__location__ ": Failed to add reinit_after_fork pipe event");
473 if (msg_ctx) {
475 * For clustering, we need to re-init our ctdbd connection after the
476 * fork
478 status = messaging_reinit(msg_ctx);
479 if (!NT_STATUS_IS_OK(status)) {
480 DEBUG(0,("messaging_reinit() failed: %s\n",
481 nt_errstr(status)));
484 done:
485 return status;
488 /****************************************************************************
489 (Hopefully) efficient array append.
490 ****************************************************************************/
492 void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
493 void *element, void *_array, uint32 *num_elements,
494 ssize_t *array_size)
496 void **array = (void **)_array;
498 if (*array_size < 0) {
499 return;
502 if (*array == NULL) {
503 if (*array_size == 0) {
504 *array_size = 128;
507 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
508 goto error;
511 *array = TALLOC(mem_ctx, element_size * (*array_size));
512 if (*array == NULL) {
513 goto error;
517 if (*num_elements == *array_size) {
518 *array_size *= 2;
520 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
521 goto error;
524 *array = TALLOC_REALLOC(mem_ctx, *array,
525 element_size * (*array_size));
527 if (*array == NULL) {
528 goto error;
532 memcpy((char *)(*array) + element_size*(*num_elements),
533 element, element_size);
534 *num_elements += 1;
536 return;
538 error:
539 *num_elements = 0;
540 *array_size = -1;
543 /****************************************************************************
544 Get my own domain name, or "" if we have none.
545 ****************************************************************************/
547 char *get_mydnsdomname(TALLOC_CTX *ctx)
549 const char *domname;
550 char *p;
552 domname = get_mydnsfullname();
553 if (!domname) {
554 return NULL;
557 p = strchr_m(domname, '.');
558 if (p) {
559 p++;
560 return talloc_strdup(ctx, p);
561 } else {
562 return talloc_strdup(ctx, "");
566 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
567 /******************************************************************
568 Remove any mount options such as -rsize=2048,wsize=2048 etc.
569 Based on a fix from <Thomas.Hepper@icem.de>.
570 Returns a malloc'ed string.
571 *******************************************************************/
573 static char *strip_mount_options(TALLOC_CTX *ctx, const char *str)
575 if (*str == '-') {
576 const char *p = str;
577 while(*p && !isspace(*p))
578 p++;
579 while(*p && isspace(*p))
580 p++;
581 if(*p) {
582 return talloc_strdup(ctx, p);
585 return NULL;
588 /*******************************************************************
589 Patch from jkf@soton.ac.uk
590 Split Luke's automount_server into YP lookup and string splitter
591 so can easily implement automount_path().
592 Returns a malloc'ed string.
593 *******************************************************************/
595 #ifdef WITH_NISPLUS_HOME
596 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
598 char *value = NULL;
600 char *nis_map = (char *)lp_homedir_map();
602 char buffer[NIS_MAXATTRVAL + 1];
603 nis_result *result;
604 nis_object *object;
605 entry_obj *entry;
607 snprintf(buffer, sizeof(buffer), "[key=%s],%s", user_name, nis_map);
608 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
610 if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
611 if (result->status != NIS_SUCCESS) {
612 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
613 } else {
614 object = result->objects.objects_val;
615 if (object->zo_data.zo_type == ENTRY_OBJ) {
616 entry = &object->zo_data.objdata_u.en_data;
617 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
618 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
620 value = talloc_strdup(ctx,
621 entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
622 if (!value) {
623 nis_freeresult(result);
624 return NULL;
626 value = talloc_string_sub(ctx,
627 value,
628 "&",
629 user_name);
633 nis_freeresult(result);
635 if (value) {
636 value = strip_mount_options(ctx, value);
637 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n",
638 user_name, value));
640 return value;
642 #else /* WITH_NISPLUS_HOME */
644 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
646 char *value = NULL;
648 int nis_error; /* returned by yp all functions */
649 char *nis_result; /* yp_match inits this */
650 int nis_result_len; /* and set this */
651 char *nis_domain; /* yp_get_default_domain inits this */
652 char *nis_map = lp_homedir_map(talloc_tos());
654 if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
655 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
656 return NULL;
659 DEBUG(5, ("NIS Domain: %s\n", nis_domain));
661 if ((nis_error = yp_match(nis_domain, nis_map, user_name,
662 strlen(user_name), &nis_result,
663 &nis_result_len)) == 0) {
664 if (nis_result_len > 0 && nis_result[nis_result_len] == '\n') {
665 nis_result[nis_result_len] = '\0';
667 value = talloc_strdup(ctx, nis_result);
668 if (!value) {
669 return NULL;
671 value = strip_mount_options(ctx, value);
672 } else if(nis_error == YPERR_KEY) {
673 DEBUG(3, ("YP Key not found: while looking up \"%s\" in map \"%s\"\n",
674 user_name, nis_map));
675 DEBUG(3, ("using defaults for server and home directory\n"));
676 } else {
677 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
678 yperr_string(nis_error), user_name, nis_map));
681 if (value) {
682 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, value));
684 return value;
686 #endif /* WITH_NISPLUS_HOME */
687 #endif
689 bool process_exists(const struct server_id pid)
691 return serverid_exists(&pid);
694 /*******************************************************************
695 Convert a uid into a user name.
696 ********************************************************************/
698 const char *uidtoname(uid_t uid)
700 TALLOC_CTX *ctx = talloc_tos();
701 char *name = NULL;
702 struct passwd *pass = NULL;
704 pass = getpwuid_alloc(ctx,uid);
705 if (pass) {
706 name = talloc_strdup(ctx,pass->pw_name);
707 TALLOC_FREE(pass);
708 } else {
709 name = talloc_asprintf(ctx,
710 "%ld",
711 (long int)uid);
713 return name;
716 /*******************************************************************
717 Convert a gid into a group name.
718 ********************************************************************/
720 char *gidtoname(gid_t gid)
722 struct group *grp;
724 grp = getgrgid(gid);
725 if (grp) {
726 return talloc_strdup(talloc_tos(), grp->gr_name);
728 else {
729 return talloc_asprintf(talloc_tos(),
730 "%d",
731 (int)gid);
735 /*******************************************************************
736 Convert a user name into a uid.
737 ********************************************************************/
739 uid_t nametouid(const char *name)
741 struct passwd *pass;
742 char *p;
743 uid_t u;
745 pass = Get_Pwnam_alloc(talloc_tos(), name);
746 if (pass) {
747 u = pass->pw_uid;
748 TALLOC_FREE(pass);
749 return u;
752 u = (uid_t)strtol(name, &p, 0);
753 if ((p != name) && (*p == '\0'))
754 return u;
756 return (uid_t)-1;
759 /*******************************************************************
760 Convert a name to a gid_t if possible. Return -1 if not a group.
761 ********************************************************************/
763 gid_t nametogid(const char *name)
765 struct group *grp;
766 char *p;
767 gid_t g;
769 g = (gid_t)strtol(name, &p, 0);
770 if ((p != name) && (*p == '\0'))
771 return g;
773 grp = getgrnam(name);
774 if (grp)
775 return(grp->gr_gid);
776 return (gid_t)-1;
779 /*******************************************************************
780 Something really nasty happened - panic !
781 ********************************************************************/
783 void smb_panic_s3(const char *why)
785 char *cmd;
786 int result;
788 DEBUG(0,("PANIC (pid %llu): %s\n",
789 (unsigned long long)getpid(), why));
790 log_stack_trace();
792 #if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER)
794 * Make sure all children can attach a debugger.
796 prctl(PR_SET_PTRACER, getpid(), 0, 0, 0);
797 #endif
799 cmd = lp_panic_action(talloc_tos());
800 if (cmd && *cmd) {
801 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
802 result = system(cmd);
804 if (result == -1)
805 DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
806 strerror(errno)));
807 else
808 DEBUG(0, ("smb_panic(): action returned status %d\n",
809 WEXITSTATUS(result)));
812 dump_core();
815 /*******************************************************************
816 Print a backtrace of the stack to the debug log. This function
817 DELIBERATELY LEAKS MEMORY. The expectation is that you should
818 exit shortly after calling it.
819 ********************************************************************/
821 #ifdef HAVE_LIBUNWIND_H
822 #include <libunwind.h>
823 #endif
825 #ifdef HAVE_EXECINFO_H
826 #include <execinfo.h>
827 #endif
829 #ifdef HAVE_LIBEXC_H
830 #include <libexc.h>
831 #endif
833 void log_stack_trace(void)
835 #ifdef HAVE_LIBUNWIND
836 /* Try to use libunwind before any other technique since on ia64
837 * libunwind correctly walks the stack in more circumstances than
838 * backtrace.
840 unw_cursor_t cursor;
841 unw_context_t uc;
842 unsigned i = 0;
844 char procname[256];
845 unw_word_t ip, sp, off;
847 procname[sizeof(procname) - 1] = '\0';
849 if (unw_getcontext(&uc) != 0) {
850 goto libunwind_failed;
853 if (unw_init_local(&cursor, &uc) != 0) {
854 goto libunwind_failed;
857 DEBUG(0, ("BACKTRACE:\n"));
859 do {
860 ip = sp = 0;
861 unw_get_reg(&cursor, UNW_REG_IP, &ip);
862 unw_get_reg(&cursor, UNW_REG_SP, &sp);
864 switch (unw_get_proc_name(&cursor,
865 procname, sizeof(procname) - 1, &off) ) {
866 case 0:
867 /* Name found. */
868 case -UNW_ENOMEM:
869 /* Name truncated. */
870 DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
871 i, procname, (long long)off,
872 (long long)ip, (long long) sp));
873 break;
874 default:
875 /* case -UNW_ENOINFO: */
876 /* case -UNW_EUNSPEC: */
877 /* No symbol name found. */
878 DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
879 i, "<unknown symbol>",
880 (long long)ip, (long long) sp));
882 ++i;
883 } while (unw_step(&cursor) > 0);
885 return;
887 libunwind_failed:
888 DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
890 #elif HAVE_BACKTRACE_SYMBOLS
891 void *backtrace_stack[BACKTRACE_STACK_SIZE];
892 size_t backtrace_size;
893 char **backtrace_strings;
895 /* get the backtrace (stack frames) */
896 backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
897 backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
899 DEBUG(0, ("BACKTRACE: %lu stack frames:\n",
900 (unsigned long)backtrace_size));
902 if (backtrace_strings) {
903 int i;
905 for (i = 0; i < backtrace_size; i++)
906 DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
908 /* Leak the backtrace_strings, rather than risk what free() might do */
911 #elif HAVE_LIBEXC
913 /* The IRIX libexc library provides an API for unwinding the stack. See
914 * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
915 * since we are about to abort anyway, it hardly matters.
918 #define NAMESIZE 32 /* Arbitrary */
920 __uint64_t addrs[BACKTRACE_STACK_SIZE];
921 char * names[BACKTRACE_STACK_SIZE];
922 char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
924 int i;
925 int levels;
927 ZERO_ARRAY(addrs);
928 ZERO_ARRAY(names);
929 ZERO_ARRAY(namebuf);
931 /* We need to be root so we can open our /proc entry to walk
932 * our stack. It also helps when we want to dump core.
934 become_root();
936 for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
937 names[i] = namebuf + (i * NAMESIZE);
940 levels = trace_back_stack(0, addrs, names,
941 BACKTRACE_STACK_SIZE, NAMESIZE - 1);
943 DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
944 for (i = 0; i < levels; i++) {
945 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
947 #undef NAMESIZE
949 #else
950 DEBUG(0, ("unable to produce a stack trace on this platform\n"));
951 #endif
954 /*******************************************************************
955 A readdir wrapper which just returns the file name.
956 ********************************************************************/
958 const char *readdirname(DIR *p)
960 struct dirent *ptr;
961 char *dname;
963 if (!p)
964 return(NULL);
966 ptr = (struct dirent *)readdir(p);
967 if (!ptr)
968 return(NULL);
970 dname = ptr->d_name;
972 #ifdef NEXT2
973 if (telldir(p) < 0)
974 return(NULL);
975 #endif
977 #ifdef HAVE_BROKEN_READDIR_NAME
978 /* using /usr/ucb/cc is BAD */
979 dname = dname - 2;
980 #endif
982 return talloc_strdup(talloc_tos(), dname);
985 /*******************************************************************
986 Utility function used to decide if the last component
987 of a path matches a (possibly wildcarded) entry in a namelist.
988 ********************************************************************/
990 bool is_in_path(const char *name, name_compare_entry *namelist, bool case_sensitive)
992 const char *last_component;
994 /* if we have no list it's obviously not in the path */
995 if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
996 return False;
999 DEBUG(8, ("is_in_path: %s\n", name));
1001 /* Get the last component of the unix name. */
1002 last_component = strrchr_m(name, '/');
1003 if (!last_component) {
1004 last_component = name;
1005 } else {
1006 last_component++; /* Go past '/' */
1009 for(; namelist->name != NULL; namelist++) {
1010 if(namelist->is_wild) {
1011 if (mask_match(last_component, namelist->name, case_sensitive)) {
1012 DEBUG(8,("is_in_path: mask match succeeded\n"));
1013 return True;
1015 } else {
1016 if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
1017 (!case_sensitive && (strcasecmp_m(last_component, namelist->name) == 0))) {
1018 DEBUG(8,("is_in_path: match succeeded\n"));
1019 return True;
1023 DEBUG(8,("is_in_path: match not found\n"));
1024 return False;
1027 /*******************************************************************
1028 Strip a '/' separated list into an array of
1029 name_compare_enties structures suitable for
1030 passing to is_in_path(). We do this for
1031 speed so we can pre-parse all the names in the list
1032 and don't do it for each call to is_in_path().
1033 We also check if the entry contains a wildcard to
1034 remove a potentially expensive call to mask_match
1035 if possible.
1036 ********************************************************************/
1038 void set_namearray(name_compare_entry **ppname_array, const char *namelist_in)
1040 char *name_end;
1041 char *namelist;
1042 char *namelist_end;
1043 char *nameptr;
1044 int num_entries = 0;
1045 int i;
1047 (*ppname_array) = NULL;
1049 if((namelist_in == NULL ) || ((namelist_in != NULL) && (*namelist_in == '\0')))
1050 return;
1052 namelist = talloc_strdup(talloc_tos(), namelist_in);
1053 if (namelist == NULL) {
1054 DEBUG(0,("set_namearray: talloc fail\n"));
1055 return;
1057 nameptr = namelist;
1059 namelist_end = &namelist[strlen(namelist)];
1061 /* We need to make two passes over the string. The
1062 first to count the number of elements, the second
1063 to split it.
1066 while(nameptr <= namelist_end) {
1067 if ( *nameptr == '/' ) {
1068 /* cope with multiple (useless) /s) */
1069 nameptr++;
1070 continue;
1072 /* anything left? */
1073 if ( *nameptr == '\0' )
1074 break;
1076 /* find the next '/' or consume remaining */
1077 name_end = strchr_m(nameptr, '/');
1078 if (name_end == NULL) {
1079 /* Point nameptr at the terminating '\0' */
1080 nameptr += strlen(nameptr);
1081 } else {
1082 /* next segment please */
1083 nameptr = name_end + 1;
1085 num_entries++;
1088 if(num_entries == 0) {
1089 talloc_free(namelist);
1090 return;
1093 if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1094 DEBUG(0,("set_namearray: malloc fail\n"));
1095 talloc_free(namelist);
1096 return;
1099 /* Now copy out the names */
1100 nameptr = namelist;
1101 i = 0;
1102 while(nameptr <= namelist_end) {
1103 if ( *nameptr == '/' ) {
1104 /* cope with multiple (useless) /s) */
1105 nameptr++;
1106 continue;
1108 /* anything left? */
1109 if ( *nameptr == '\0' )
1110 break;
1112 /* find the next '/' or consume remaining */
1113 name_end = strchr_m(nameptr, '/');
1114 if (name_end != NULL) {
1115 *name_end = '\0';
1118 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1119 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1120 DEBUG(0,("set_namearray: malloc fail (1)\n"));
1121 talloc_free(namelist);
1122 return;
1125 if (name_end == NULL) {
1126 /* Point nameptr at the terminating '\0' */
1127 nameptr += strlen(nameptr);
1128 } else {
1129 /* next segment please */
1130 nameptr = name_end + 1;
1132 i++;
1135 (*ppname_array)[i].name = NULL;
1137 talloc_free(namelist);
1138 return;
1141 #undef DBGC_CLASS
1142 #define DBGC_CLASS DBGC_LOCKING
1144 /****************************************************************************
1145 Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
1146 is dealt with in posix.c
1147 Returns True if we have information regarding this lock region (and returns
1148 F_UNLCK in *ptype if the region is unlocked). False if the call failed.
1149 ****************************************************************************/
1151 bool fcntl_getlock(int fd, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1153 struct flock lock;
1154 int ret;
1156 DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
1157 fd,(double)*poffset,(double)*pcount,*ptype));
1159 lock.l_type = *ptype;
1160 lock.l_whence = SEEK_SET;
1161 lock.l_start = *poffset;
1162 lock.l_len = *pcount;
1163 lock.l_pid = 0;
1165 ret = sys_fcntl_ptr(fd,F_GETLK,&lock);
1167 if (ret == -1) {
1168 int sav = errno;
1169 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
1170 (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
1171 errno = sav;
1172 return False;
1175 *ptype = lock.l_type;
1176 *poffset = lock.l_start;
1177 *pcount = lock.l_len;
1178 *ppid = lock.l_pid;
1180 DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
1181 fd, (int)lock.l_type, (unsigned int)lock.l_pid));
1182 return True;
1185 #undef DBGC_CLASS
1186 #define DBGC_CLASS DBGC_ALL
1188 /*******************************************************************
1189 Is the name specified one of my netbios names.
1190 Returns true if it is equal, false otherwise.
1191 ********************************************************************/
1193 bool is_myname(const char *s)
1195 int n;
1196 bool ret = False;
1198 for (n=0; my_netbios_names(n); n++) {
1199 const char *nbt_name = my_netbios_names(n);
1201 if (strncasecmp_m(nbt_name, s, strlen(nbt_name)) == 0) {
1202 ret=True;
1203 break;
1206 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1207 return(ret);
1210 /*******************************************************************
1211 we distinguish between 2K and XP by the "Native Lan Manager" string
1212 WinXP => "Windows 2002 5.1"
1213 WinXP 64bit => "Windows XP 5.2"
1214 Win2k => "Windows 2000 5.0"
1215 NT4 => "Windows NT 4.0"
1216 Win9x => "Windows 4.0"
1217 Windows 2003 doesn't set the native lan manager string but
1218 they do set the domain to "Windows 2003 5.2" (probably a bug).
1219 ********************************************************************/
1221 void ra_lanman_string( const char *native_lanman )
1223 if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1224 set_remote_arch( RA_WINXP );
1225 else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1226 set_remote_arch( RA_WINXP64 );
1227 else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1228 set_remote_arch( RA_WIN2K3 );
1231 static const char *remote_arch_str;
1233 const char *get_remote_arch_str(void)
1235 if (!remote_arch_str) {
1236 return "UNKNOWN";
1238 return remote_arch_str;
1241 /*******************************************************************
1242 Set the horrid remote_arch string based on an enum.
1243 ********************************************************************/
1245 void set_remote_arch(enum remote_arch_types type)
1247 ra_type = type;
1248 switch( type ) {
1249 case RA_WFWG:
1250 remote_arch_str = "WfWg";
1251 break;
1252 case RA_OS2:
1253 remote_arch_str = "OS2";
1254 break;
1255 case RA_WIN95:
1256 remote_arch_str = "Win95";
1257 break;
1258 case RA_WINNT:
1259 remote_arch_str = "WinNT";
1260 break;
1261 case RA_WIN2K:
1262 remote_arch_str = "Win2K";
1263 break;
1264 case RA_WINXP:
1265 remote_arch_str = "WinXP";
1266 break;
1267 case RA_WINXP64:
1268 remote_arch_str = "WinXP64";
1269 break;
1270 case RA_WIN2K3:
1271 remote_arch_str = "Win2K3";
1272 break;
1273 case RA_VISTA:
1274 remote_arch_str = "Vista";
1275 break;
1276 case RA_SAMBA:
1277 remote_arch_str = "Samba";
1278 break;
1279 case RA_CIFSFS:
1280 remote_arch_str = "CIFSFS";
1281 break;
1282 case RA_OSX:
1283 remote_arch_str = "OSX";
1284 break;
1285 default:
1286 ra_type = RA_UNKNOWN;
1287 remote_arch_str = "UNKNOWN";
1288 break;
1291 DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1292 remote_arch_str));
1295 /*******************************************************************
1296 Get the remote_arch type.
1297 ********************************************************************/
1299 enum remote_arch_types get_remote_arch(void)
1301 return ra_type;
1304 const char *tab_depth(int level, int depth)
1306 if( CHECK_DEBUGLVL(level) ) {
1307 dbgtext("%*s", depth*4, "");
1309 return "";
1312 /*****************************************************************************
1313 Provide a checksum on a string
1315 Input: s - the null-terminated character string for which the checksum
1316 will be calculated.
1318 Output: The checksum value calculated for s.
1319 *****************************************************************************/
1321 int str_checksum(const char *s)
1323 TDB_DATA key;
1324 if (s == NULL)
1325 return 0;
1327 key = (TDB_DATA) { .dptr = discard_const_p(uint8_t, s),
1328 .dsize = strlen(s) };
1330 return tdb_jenkins_hash(&key);
1333 /*****************************************************************
1334 Zero a memory area then free it. Used to catch bugs faster.
1335 *****************************************************************/
1337 void zero_free(void *p, size_t size)
1339 memset(p, 0, size);
1340 SAFE_FREE(p);
1343 /*****************************************************************
1344 Set our open file limit to a requested max and return the limit.
1345 *****************************************************************/
1347 int set_maxfiles(int requested_max)
1349 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1350 struct rlimit rlp;
1351 int saved_current_limit;
1353 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1354 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1355 strerror(errno) ));
1356 /* just guess... */
1357 return requested_max;
1361 * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1362 * account for the extra fd we need
1363 * as well as the log files and standard
1364 * handles etc. Save the limit we want to set in case
1365 * we are running on an OS that doesn't support this limit (AIX)
1366 * which always returns RLIM_INFINITY for rlp.rlim_max.
1369 /* Try raising the hard (max) limit to the requested amount. */
1371 #if defined(RLIM_INFINITY)
1372 if (rlp.rlim_max != RLIM_INFINITY) {
1373 int orig_max = rlp.rlim_max;
1375 if ( rlp.rlim_max < requested_max )
1376 rlp.rlim_max = requested_max;
1378 /* This failing is not an error - many systems (Linux) don't
1379 support our default request of 10,000 open files. JRA. */
1381 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1382 DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n",
1383 (int)rlp.rlim_max, strerror(errno) ));
1385 /* Set failed - restore original value from get. */
1386 rlp.rlim_max = orig_max;
1389 #endif
1391 /* Now try setting the soft (current) limit. */
1393 saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1395 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1396 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
1397 (int)rlp.rlim_cur, strerror(errno) ));
1398 /* just guess... */
1399 return saved_current_limit;
1402 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1403 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1404 strerror(errno) ));
1405 /* just guess... */
1406 return saved_current_limit;
1409 #if defined(RLIM_INFINITY)
1410 if(rlp.rlim_cur == RLIM_INFINITY)
1411 return saved_current_limit;
1412 #endif
1414 if((int)rlp.rlim_cur > saved_current_limit)
1415 return saved_current_limit;
1417 return rlp.rlim_cur;
1418 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1420 * No way to know - just guess...
1422 return requested_max;
1423 #endif
1426 /*****************************************************************
1427 malloc that aborts with smb_panic on fail or zero size.
1428 *****************************************************************/
1430 void *smb_xmalloc_array(size_t size, unsigned int count)
1432 void *p;
1433 if (size == 0) {
1434 smb_panic("smb_xmalloc_array: called with zero size");
1436 if (count >= MAX_ALLOC_SIZE/size) {
1437 smb_panic("smb_xmalloc_array: alloc size too large");
1439 if ((p = SMB_MALLOC(size*count)) == NULL) {
1440 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1441 (unsigned long)size, (unsigned long)count));
1442 smb_panic("smb_xmalloc_array: malloc failed");
1444 return p;
1448 vasprintf that aborts on malloc fail
1451 int smb_xvasprintf(char **ptr, const char *format, va_list ap)
1453 int n;
1454 va_list ap2;
1456 va_copy(ap2, ap);
1458 n = vasprintf(ptr, format, ap2);
1459 va_end(ap2);
1460 if (n == -1 || ! *ptr) {
1461 smb_panic("smb_xvasprintf: out of memory");
1463 return n;
1466 /*****************************************************************
1467 Get local hostname and cache result.
1468 *****************************************************************/
1470 char *myhostname(void)
1472 static char *ret;
1473 if (ret == NULL) {
1474 ret = get_myname(NULL);
1476 return ret;
1479 /*****************************************************************
1480 Get local hostname and cache result.
1481 *****************************************************************/
1483 char *myhostname_upper(void)
1485 static char *ret;
1486 if (ret == NULL) {
1487 char *name = get_myname(NULL);
1488 if (name == NULL) {
1489 return NULL;
1491 ret = strupper_talloc(NULL, name);
1492 talloc_free(name);
1494 return ret;
1498 * @brief Returns an absolute path to a file concatenating the provided
1499 * @a rootpath and @a basename
1501 * @param name Filename, relative to @a rootpath
1503 * @retval Pointer to a string containing the full path.
1506 static char *xx_path(const char *name, const char *rootpath)
1508 char *fname = NULL;
1510 fname = talloc_strdup(talloc_tos(), rootpath);
1511 if (!fname) {
1512 return NULL;
1514 trim_string(fname,"","/");
1516 if (!directory_exist(fname)) {
1517 if (mkdir(fname,0755) == -1) {
1518 /* Did someone else win the race ? */
1519 if (errno != EEXIST) {
1520 DEBUG(1, ("Unable to create directory %s for file %s. "
1521 "Error was %s\n", fname, name, strerror(errno)));
1522 return NULL;
1527 return talloc_asprintf_append(fname, "/%s", name);
1531 * @brief Returns an absolute path to a file in the Samba lock directory.
1533 * @param name File to find, relative to LOCKDIR.
1535 * @retval Pointer to a talloc'ed string containing the full path.
1538 char *lock_path(const char *name)
1540 return xx_path(name, lp_lock_directory());
1544 * @brief Returns an absolute path to a file in the Samba state directory.
1546 * @param name File to find, relative to STATEDIR.
1548 * @retval Pointer to a talloc'ed string containing the full path.
1551 char *state_path(const char *name)
1553 return xx_path(name, lp_state_directory());
1557 * @brief Returns an absolute path to a file in the Samba cache directory.
1559 * @param name File to find, relative to CACHEDIR.
1561 * @retval Pointer to a talloc'ed string containing the full path.
1564 char *cache_path(const char *name)
1566 return xx_path(name, lp_cache_directory());
1569 /*******************************************************************
1570 Given a filename - get its directory name
1571 ********************************************************************/
1573 bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
1574 const char **name)
1576 char *p;
1577 ptrdiff_t len;
1579 p = strrchr_m(dir, '/'); /* Find final '/', if any */
1581 if (p == NULL) {
1582 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
1583 return False;
1585 if (name) {
1586 *name = dir;
1588 return True;
1591 len = p-dir;
1593 if (!(*parent = (char *)talloc_memdup(mem_ctx, dir, len+1))) {
1594 return False;
1596 (*parent)[len] = '\0';
1598 if (name) {
1599 *name = p+1;
1601 return True;
1604 /*******************************************************************
1605 Determine if a pattern contains any Microsoft wildcard characters.
1606 *******************************************************************/
1608 bool ms_has_wild(const char *s)
1610 char c;
1612 if (lp_posix_pathnames()) {
1613 /* With posix pathnames no characters are wild. */
1614 return False;
1617 while ((c = *s++)) {
1618 switch (c) {
1619 case '*':
1620 case '?':
1621 case '<':
1622 case '>':
1623 case '"':
1624 return True;
1627 return False;
1630 bool ms_has_wild_w(const smb_ucs2_t *s)
1632 smb_ucs2_t c;
1633 if (!s) return False;
1634 while ((c = *s++)) {
1635 switch (c) {
1636 case UCS2_CHAR('*'):
1637 case UCS2_CHAR('?'):
1638 case UCS2_CHAR('<'):
1639 case UCS2_CHAR('>'):
1640 case UCS2_CHAR('"'):
1641 return True;
1644 return False;
1647 /*******************************************************************
1648 A wrapper that handles case sensitivity and the special handling
1649 of the ".." name.
1650 *******************************************************************/
1652 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
1654 if (ISDOTDOT(string))
1655 string = ".";
1656 if (ISDOT(pattern))
1657 return False;
1659 return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
1662 /*******************************************************************
1663 A wrapper that handles case sensitivity and the special handling
1664 of the ".." name. Varient that is only called by old search code which requires
1665 pattern translation.
1666 *******************************************************************/
1668 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
1670 if (ISDOTDOT(string))
1671 string = ".";
1672 if (ISDOT(pattern))
1673 return False;
1675 return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
1678 /*******************************************************************
1679 A wrapper that handles a list of patters and calls mask_match()
1680 on each. Returns True if any of the patterns match.
1681 *******************************************************************/
1683 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
1685 while (listLen-- > 0) {
1686 if (mask_match(string, *list++, is_case_sensitive))
1687 return True;
1689 return False;
1692 /*********************************************************
1693 Recursive routine that is called by unix_wild_match.
1694 *********************************************************/
1696 static bool unix_do_match(const char *regexp, const char *str)
1698 const char *p;
1700 for( p = regexp; *p && *str; ) {
1702 switch(*p) {
1703 case '?':
1704 str++;
1705 p++;
1706 break;
1708 case '*':
1711 * Look for a character matching
1712 * the one after the '*'.
1714 p++;
1715 if(!*p)
1716 return true; /* Automatic match */
1717 while(*str) {
1719 while(*str && (*p != *str))
1720 str++;
1723 * Patch from weidel@multichart.de. In the case of the regexp
1724 * '*XX*' we want to ensure there are at least 2 'X' characters
1725 * in the string after the '*' for a match to be made.
1729 int matchcount=0;
1732 * Eat all the characters that match, but count how many there were.
1735 while(*str && (*p == *str)) {
1736 str++;
1737 matchcount++;
1741 * Now check that if the regexp had n identical characters that
1742 * matchcount had at least that many matches.
1745 while ( *(p+1) && (*(p+1) == *p)) {
1746 p++;
1747 matchcount--;
1750 if ( matchcount <= 0 )
1751 return false;
1754 str--; /* We've eaten the match char after the '*' */
1756 if(unix_do_match(p, str))
1757 return true;
1759 if(!*str)
1760 return false;
1761 else
1762 str++;
1764 return false;
1766 default:
1767 if(*str != *p)
1768 return false;
1769 str++;
1770 p++;
1771 break;
1775 if(!*p && !*str)
1776 return true;
1778 if (!*p && str[0] == '.' && str[1] == 0)
1779 return true;
1781 if (!*str && *p == '?') {
1782 while (*p == '?')
1783 p++;
1784 return(!*p);
1787 if(!*str && (*p == '*' && p[1] == '\0'))
1788 return true;
1790 return false;
1793 /*******************************************************************
1794 Simple case insensitive interface to a UNIX wildcard matcher.
1795 Returns True if match, False if not.
1796 *******************************************************************/
1798 bool unix_wild_match(const char *pattern, const char *string)
1800 TALLOC_CTX *ctx = talloc_stackframe();
1801 char *p2;
1802 char *s2;
1803 char *p;
1804 bool ret = false;
1806 p2 = talloc_strdup(ctx,pattern);
1807 s2 = talloc_strdup(ctx,string);
1808 if (!p2 || !s2) {
1809 TALLOC_FREE(ctx);
1810 return false;
1812 if (!strlower_m(p2)) {
1813 TALLOC_FREE(ctx);
1814 return false;
1816 if (!strlower_m(s2)) {
1817 TALLOC_FREE(ctx);
1818 return false;
1821 /* Remove any *? and ** from the pattern as they are meaningless */
1822 for(p = p2; *p; p++) {
1823 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
1824 memmove(&p[1], &p[2], strlen(&p[2])+1);
1828 if (strequal(p2,"*")) {
1829 TALLOC_FREE(ctx);
1830 return true;
1833 ret = unix_do_match(p2, s2);
1834 TALLOC_FREE(ctx);
1835 return ret;
1838 /**********************************************************************
1839 Converts a name to a fully qualified domain name.
1840 Returns true if lookup succeeded, false if not (then fqdn is set to name)
1841 Note we deliberately use gethostbyname here, not getaddrinfo as we want
1842 to examine the h_aliases and I don't know how to do that with getaddrinfo.
1843 ***********************************************************************/
1845 bool name_to_fqdn(fstring fqdn, const char *name)
1847 char *full = NULL;
1848 struct hostent *hp = gethostbyname(name);
1850 if (!hp || !hp->h_name || !*hp->h_name) {
1851 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
1852 fstrcpy(fqdn, name);
1853 return false;
1856 /* Find out if the fqdn is returned as an alias
1857 * to cope with /etc/hosts files where the first
1858 * name is not the fqdn but the short name */
1859 if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
1860 int i;
1861 for (i = 0; hp->h_aliases[i]; i++) {
1862 if (strchr_m(hp->h_aliases[i], '.')) {
1863 full = hp->h_aliases[i];
1864 break;
1868 if (full && (strcasecmp_m(full, "localhost.localdomain") == 0)) {
1869 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
1870 DEBUGADD(1, (" Specifying the machine hostname for address 127.0.0.1 may lead\n"));
1871 DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n"));
1872 DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n"));
1873 full = hp->h_name;
1875 if (!full) {
1876 full = hp->h_name;
1879 DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
1880 fstrcpy(fqdn, full);
1881 return true;
1884 /**********************************************************************
1885 Append a DATA_BLOB to a talloc'ed object
1886 ***********************************************************************/
1888 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
1890 size_t old_size = 0;
1891 char *result;
1893 if (blob.length == 0) {
1894 return buf;
1897 if (buf != NULL) {
1898 old_size = talloc_get_size(buf);
1901 result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
1902 if (result == NULL) {
1903 return NULL;
1906 memcpy(result + old_size, blob.data, blob.length);
1907 return result;
1910 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
1912 switch (share_access & ~FILE_SHARE_DELETE) {
1913 case FILE_SHARE_NONE:
1914 return DENY_ALL;
1915 case FILE_SHARE_READ:
1916 return DENY_WRITE;
1917 case FILE_SHARE_WRITE:
1918 return DENY_READ;
1919 case FILE_SHARE_READ|FILE_SHARE_WRITE:
1920 return DENY_NONE;
1922 if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
1923 return DENY_DOS;
1924 } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
1925 return DENY_FCB;
1928 return (uint32)-1;
1931 pid_t procid_to_pid(const struct server_id *proc)
1933 return proc->pid;
1936 static uint32 my_vnn = NONCLUSTER_VNN;
1938 void set_my_vnn(uint32 vnn)
1940 DEBUG(10, ("vnn pid %d = %u\n", (int)getpid(), (unsigned int)vnn));
1941 my_vnn = vnn;
1944 uint32 get_my_vnn(void)
1946 return my_vnn;
1949 static uint64_t my_unique_id = 0;
1951 void set_my_unique_id(uint64_t unique_id)
1953 my_unique_id = unique_id;
1956 struct server_id pid_to_procid(pid_t pid)
1958 struct server_id result;
1959 result.pid = pid;
1960 result.task_id = 0;
1961 result.unique_id = my_unique_id;
1962 result.vnn = my_vnn;
1963 return result;
1966 struct server_id procid_self(void)
1968 return pid_to_procid(getpid());
1971 bool procid_is_me(const struct server_id *pid)
1973 if (pid->pid != getpid())
1974 return False;
1975 if (pid->task_id != 0)
1976 return False;
1977 if (pid->vnn != my_vnn)
1978 return False;
1979 return True;
1982 struct server_id interpret_pid(const char *pid_string)
1984 return server_id_from_string(get_my_vnn(), pid_string);
1987 char *procid_str_static(const struct server_id *pid)
1989 return server_id_str(talloc_tos(), pid);
1992 bool procid_valid(const struct server_id *pid)
1994 return (pid->pid != (uint64_t)-1);
1997 bool procid_is_local(const struct server_id *pid)
1999 return pid->vnn == my_vnn;
2002 /****************************************************************
2003 Check if an offset into a buffer is safe.
2004 If this returns True it's safe to indirect into the byte at
2005 pointer ptr+off.
2006 ****************************************************************/
2008 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2010 const char *end_base = buf_base + buf_len;
2011 char *end_ptr = ptr + off;
2013 if (!buf_base || !ptr) {
2014 return False;
2017 if (end_base < buf_base || end_ptr < ptr) {
2018 return False; /* wrap. */
2021 if (end_ptr < end_base) {
2022 return True;
2024 return False;
2027 /****************************************************************
2028 Return a safe pointer into a buffer, or NULL.
2029 ****************************************************************/
2031 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2033 return is_offset_safe(buf_base, buf_len, ptr, off) ?
2034 ptr + off : NULL;
2037 /****************************************************************
2038 Return a safe pointer into a string within a buffer, or NULL.
2039 ****************************************************************/
2041 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2043 if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2044 return NULL;
2046 /* Check if a valid string exists at this offset. */
2047 if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2048 return NULL;
2050 return ptr + off;
2053 /****************************************************************
2054 Return an SVAL at a pointer, or failval if beyond the end.
2055 ****************************************************************/
2057 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2060 * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2061 * NOT ptr[2].
2063 if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2064 return failval;
2066 return SVAL(ptr,off);
2069 /****************************************************************
2070 Return an IVAL at a pointer, or failval if beyond the end.
2071 ****************************************************************/
2073 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2076 * Note we use off+3 here, not off+4 as IVAL accesses
2077 * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2079 if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2080 return failval;
2082 return IVAL(ptr,off);
2085 /****************************************************************
2086 Split DOM\user into DOM and user. Do not mix with winbind variants of that
2087 call (they take care of winbind separator and other winbind specific settings).
2088 ****************************************************************/
2090 void split_domain_user(TALLOC_CTX *mem_ctx,
2091 const char *full_name,
2092 char **domain,
2093 char **user)
2095 const char *p = NULL;
2097 p = strchr_m(full_name, '\\');
2099 if (p != NULL) {
2100 *domain = talloc_strndup(mem_ctx, full_name,
2101 PTR_DIFF(p, full_name));
2102 *user = talloc_strdup(mem_ctx, p+1);
2103 } else {
2104 *domain = talloc_strdup(mem_ctx, "");
2105 *user = talloc_strdup(mem_ctx, full_name);
2109 /****************************************************************
2110 strip off leading '\\' from a hostname
2111 ****************************************************************/
2113 const char *strip_hostname(const char *s)
2115 if (!s) {
2116 return NULL;
2119 if (strlen_m(s) < 3) {
2120 return s;
2123 if (s[0] == '\\') s++;
2124 if (s[0] == '\\') s++;
2126 return s;
2129 bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result)
2131 if (!NT_STATUS_IS_OK(err1)) {
2132 *result = err1;
2133 return true;
2135 if (!NT_STATUS_IS_OK(err2)) {
2136 *result = err2;
2137 return true;
2139 return false;
2142 int timeval_to_msec(struct timeval t)
2144 return t.tv_sec * 1000 + (t.tv_usec+999) / 1000;
2147 /*******************************************************************
2148 Check a given DOS pathname is valid for a share.
2149 ********************************************************************/
2151 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
2153 char *ptr = NULL;
2155 if (!dos_pathname) {
2156 return NULL;
2159 ptr = talloc_strdup(ctx, dos_pathname);
2160 if (!ptr) {
2161 return NULL;
2163 /* Convert any '\' paths to '/' */
2164 unix_format(ptr);
2165 ptr = unix_clean_name(ctx, ptr);
2166 if (!ptr) {
2167 return NULL;
2170 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
2171 if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
2172 ptr += 2;
2174 /* Only absolute paths allowed. */
2175 if (*ptr != '/')
2176 return NULL;
2178 return ptr;
2181 /*******************************************************************
2182 Return True if the filename is one of the special executable types.
2183 ********************************************************************/
2185 bool is_executable(const char *fname)
2187 if ((fname = strrchr_m(fname,'.'))) {
2188 if (strequal(fname,".com") ||
2189 strequal(fname,".dll") ||
2190 strequal(fname,".exe") ||
2191 strequal(fname,".sym")) {
2192 return True;
2195 return False;
2198 /****************************************************************************
2199 Open a file with a share mode - old openX method - map into NTCreate.
2200 ****************************************************************************/
2202 bool map_open_params_to_ntcreate(const char *smb_base_fname,
2203 int deny_mode, int open_func,
2204 uint32 *paccess_mask,
2205 uint32 *pshare_mode,
2206 uint32 *pcreate_disposition,
2207 uint32 *pcreate_options,
2208 uint32_t *pprivate_flags)
2210 uint32 access_mask;
2211 uint32 share_mode;
2212 uint32 create_disposition;
2213 uint32 create_options = FILE_NON_DIRECTORY_FILE;
2214 uint32_t private_flags = 0;
2216 DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
2217 "open_func = 0x%x\n",
2218 smb_base_fname, (unsigned int)deny_mode,
2219 (unsigned int)open_func ));
2221 /* Create the NT compatible access_mask. */
2222 switch (GET_OPENX_MODE(deny_mode)) {
2223 case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
2224 case DOS_OPEN_RDONLY:
2225 access_mask = FILE_GENERIC_READ;
2226 break;
2227 case DOS_OPEN_WRONLY:
2228 access_mask = FILE_GENERIC_WRITE;
2229 break;
2230 case DOS_OPEN_RDWR:
2231 case DOS_OPEN_FCB:
2232 access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
2233 break;
2234 default:
2235 DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
2236 (unsigned int)GET_OPENX_MODE(deny_mode)));
2237 return False;
2240 /* Create the NT compatible create_disposition. */
2241 switch (open_func) {
2242 case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
2243 create_disposition = FILE_CREATE;
2244 break;
2246 case OPENX_FILE_EXISTS_OPEN:
2247 create_disposition = FILE_OPEN;
2248 break;
2250 case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
2251 create_disposition = FILE_OPEN_IF;
2252 break;
2254 case OPENX_FILE_EXISTS_TRUNCATE:
2255 create_disposition = FILE_OVERWRITE;
2256 break;
2258 case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
2259 create_disposition = FILE_OVERWRITE_IF;
2260 break;
2262 default:
2263 /* From samba4 - to be confirmed. */
2264 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
2265 create_disposition = FILE_CREATE;
2266 break;
2268 DEBUG(10,("map_open_params_to_ntcreate: bad "
2269 "open_func 0x%x\n", (unsigned int)open_func));
2270 return False;
2273 /* Create the NT compatible share modes. */
2274 switch (GET_DENY_MODE(deny_mode)) {
2275 case DENY_ALL:
2276 share_mode = FILE_SHARE_NONE;
2277 break;
2279 case DENY_WRITE:
2280 share_mode = FILE_SHARE_READ;
2281 break;
2283 case DENY_READ:
2284 share_mode = FILE_SHARE_WRITE;
2285 break;
2287 case DENY_NONE:
2288 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2289 break;
2291 case DENY_DOS:
2292 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
2293 if (is_executable(smb_base_fname)) {
2294 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2295 } else {
2296 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
2297 share_mode = FILE_SHARE_READ;
2298 } else {
2299 share_mode = FILE_SHARE_NONE;
2302 break;
2304 case DENY_FCB:
2305 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
2306 share_mode = FILE_SHARE_NONE;
2307 break;
2309 default:
2310 DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
2311 (unsigned int)GET_DENY_MODE(deny_mode) ));
2312 return False;
2315 DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
2316 "share_mode = 0x%x, create_disposition = 0x%x, "
2317 "create_options = 0x%x private_flags = 0x%x\n",
2318 smb_base_fname,
2319 (unsigned int)access_mask,
2320 (unsigned int)share_mode,
2321 (unsigned int)create_disposition,
2322 (unsigned int)create_options,
2323 (unsigned int)private_flags));
2325 if (paccess_mask) {
2326 *paccess_mask = access_mask;
2328 if (pshare_mode) {
2329 *pshare_mode = share_mode;
2331 if (pcreate_disposition) {
2332 *pcreate_disposition = create_disposition;
2334 if (pcreate_options) {
2335 *pcreate_options = create_options;
2337 if (pprivate_flags) {
2338 *pprivate_flags = private_flags;
2341 return True;
2345 /*************************************************************************
2346 Return a talloced copy of a struct security_unix_token. NULL on fail.
2347 *************************************************************************/
2349 struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct security_unix_token *tok)
2351 struct security_unix_token *cpy;
2353 cpy = talloc(ctx, struct security_unix_token);
2354 if (!cpy) {
2355 return NULL;
2358 cpy->uid = tok->uid;
2359 cpy->gid = tok->gid;
2360 cpy->ngroups = tok->ngroups;
2361 if (tok->ngroups) {
2362 /* Make this a talloc child of cpy. */
2363 cpy->groups = (gid_t *)talloc_memdup(
2364 cpy, tok->groups, tok->ngroups * sizeof(gid_t));
2365 if (!cpy->groups) {
2366 TALLOC_FREE(cpy);
2367 return NULL;
2369 } else {
2370 cpy->groups = NULL;
2372 return cpy;
2375 /****************************************************************************
2376 Check that a file matches a particular file type.
2377 ****************************************************************************/
2379 bool dir_check_ftype(uint32_t mode, uint32_t dirtype)
2381 uint32_t mask;
2383 /* Check the "may have" search bits. */
2384 if (((mode & ~dirtype) &
2385 (FILE_ATTRIBUTE_HIDDEN |
2386 FILE_ATTRIBUTE_SYSTEM |
2387 FILE_ATTRIBUTE_DIRECTORY)) != 0) {
2388 return false;
2391 /* Check the "must have" bits,
2392 which are the may have bits shifted eight */
2393 /* If must have bit is set, the file/dir can
2394 not be returned in search unless the matching
2395 file attribute is set */
2396 mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|
2397 FILE_ATTRIBUTE_ARCHIVE|
2398 FILE_ATTRIBUTE_READONLY|
2399 FILE_ATTRIBUTE_HIDDEN|
2400 FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
2401 if(mask) {
2402 if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|
2403 FILE_ATTRIBUTE_ARCHIVE|
2404 FILE_ATTRIBUTE_READONLY|
2405 FILE_ATTRIBUTE_HIDDEN|
2406 FILE_ATTRIBUTE_SYSTEM))) == mask) {
2407 /* check if matching attribute present */
2408 return true;
2409 } else {
2410 return false;
2414 return true;