buildtools: Rename perl vendorarch configure option.
[Samba.git] / source3 / lib / util.c
blob07daad2894b6bd0bf41015b5b7b95b2d8b9613ac
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 && tevent_re_initialise(ev_ctx) != 0) {
455 smb_panic(__location__ ": Failed to re-initialise event context");
458 if (reinit_after_fork_pipe[0] != -1) {
459 struct tevent_fd *fde;
461 fde = tevent_add_fd(ev_ctx, ev_ctx /* TALLOC_CTX */,
462 reinit_after_fork_pipe[0], TEVENT_FD_READ,
463 reinit_after_fork_pipe_handler, NULL);
464 if (fde == NULL) {
465 smb_panic(__location__ ": Failed to add reinit_after_fork pipe event");
469 if (msg_ctx) {
471 * For clustering, we need to re-init our ctdbd connection after the
472 * fork
474 status = messaging_reinit(msg_ctx);
475 if (!NT_STATUS_IS_OK(status)) {
476 DEBUG(0,("messaging_reinit() failed: %s\n",
477 nt_errstr(status)));
480 done:
481 return status;
484 /****************************************************************************
485 (Hopefully) efficient array append.
486 ****************************************************************************/
488 void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
489 void *element, void *_array, uint32 *num_elements,
490 ssize_t *array_size)
492 void **array = (void **)_array;
494 if (*array_size < 0) {
495 return;
498 if (*array == NULL) {
499 if (*array_size == 0) {
500 *array_size = 128;
503 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
504 goto error;
507 *array = TALLOC(mem_ctx, element_size * (*array_size));
508 if (*array == NULL) {
509 goto error;
513 if (*num_elements == *array_size) {
514 *array_size *= 2;
516 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
517 goto error;
520 *array = TALLOC_REALLOC(mem_ctx, *array,
521 element_size * (*array_size));
523 if (*array == NULL) {
524 goto error;
528 memcpy((char *)(*array) + element_size*(*num_elements),
529 element, element_size);
530 *num_elements += 1;
532 return;
534 error:
535 *num_elements = 0;
536 *array_size = -1;
539 /****************************************************************************
540 Get my own domain name, or "" if we have none.
541 ****************************************************************************/
543 char *get_mydnsdomname(TALLOC_CTX *ctx)
545 const char *domname;
546 char *p;
548 domname = get_mydnsfullname();
549 if (!domname) {
550 return NULL;
553 p = strchr_m(domname, '.');
554 if (p) {
555 p++;
556 return talloc_strdup(ctx, p);
557 } else {
558 return talloc_strdup(ctx, "");
562 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
563 /******************************************************************
564 Remove any mount options such as -rsize=2048,wsize=2048 etc.
565 Based on a fix from <Thomas.Hepper@icem.de>.
566 Returns a malloc'ed string.
567 *******************************************************************/
569 static char *strip_mount_options(TALLOC_CTX *ctx, const char *str)
571 if (*str == '-') {
572 const char *p = str;
573 while(*p && !isspace(*p))
574 p++;
575 while(*p && isspace(*p))
576 p++;
577 if(*p) {
578 return talloc_strdup(ctx, p);
581 return NULL;
584 /*******************************************************************
585 Patch from jkf@soton.ac.uk
586 Split Luke's automount_server into YP lookup and string splitter
587 so can easily implement automount_path().
588 Returns a malloc'ed string.
589 *******************************************************************/
591 #ifdef WITH_NISPLUS_HOME
592 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
594 char *value = NULL;
596 char *nis_map = (char *)lp_homedir_map();
598 char buffer[NIS_MAXATTRVAL + 1];
599 nis_result *result;
600 nis_object *object;
601 entry_obj *entry;
603 snprintf(buffer, sizeof(buffer), "[key=%s],%s", user_name, nis_map);
604 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
606 if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
607 if (result->status != NIS_SUCCESS) {
608 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
609 } else {
610 object = result->objects.objects_val;
611 if (object->zo_data.zo_type == ENTRY_OBJ) {
612 entry = &object->zo_data.objdata_u.en_data;
613 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
614 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
616 value = talloc_strdup(ctx,
617 entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
618 if (!value) {
619 nis_freeresult(result);
620 return NULL;
622 value = talloc_string_sub(ctx,
623 value,
624 "&",
625 user_name);
629 nis_freeresult(result);
631 if (value) {
632 value = strip_mount_options(ctx, value);
633 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n",
634 user_name, value));
636 return value;
638 #else /* WITH_NISPLUS_HOME */
640 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
642 char *value = NULL;
644 int nis_error; /* returned by yp all functions */
645 char *nis_result; /* yp_match inits this */
646 int nis_result_len; /* and set this */
647 char *nis_domain; /* yp_get_default_domain inits this */
648 char *nis_map = lp_homedir_map(talloc_tos());
650 if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
651 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
652 return NULL;
655 DEBUG(5, ("NIS Domain: %s\n", nis_domain));
657 if ((nis_error = yp_match(nis_domain, nis_map, user_name,
658 strlen(user_name), &nis_result,
659 &nis_result_len)) == 0) {
660 if (nis_result_len > 0 && nis_result[nis_result_len] == '\n') {
661 nis_result[nis_result_len] = '\0';
663 value = talloc_strdup(ctx, nis_result);
664 if (!value) {
665 return NULL;
667 value = strip_mount_options(ctx, value);
668 } else if(nis_error == YPERR_KEY) {
669 DEBUG(3, ("YP Key not found: while looking up \"%s\" in map \"%s\"\n",
670 user_name, nis_map));
671 DEBUG(3, ("using defaults for server and home directory\n"));
672 } else {
673 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
674 yperr_string(nis_error), user_name, nis_map));
677 if (value) {
678 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, value));
680 return value;
682 #endif /* WITH_NISPLUS_HOME */
683 #endif
685 bool process_exists(const struct server_id pid)
687 return serverid_exists(&pid);
690 /*******************************************************************
691 Convert a uid into a user name.
692 ********************************************************************/
694 const char *uidtoname(uid_t uid)
696 TALLOC_CTX *ctx = talloc_tos();
697 char *name = NULL;
698 struct passwd *pass = NULL;
700 pass = getpwuid_alloc(ctx,uid);
701 if (pass) {
702 name = talloc_strdup(ctx,pass->pw_name);
703 TALLOC_FREE(pass);
704 } else {
705 name = talloc_asprintf(ctx,
706 "%ld",
707 (long int)uid);
709 return name;
712 /*******************************************************************
713 Convert a gid into a group name.
714 ********************************************************************/
716 char *gidtoname(gid_t gid)
718 struct group *grp;
720 grp = getgrgid(gid);
721 if (grp) {
722 return talloc_strdup(talloc_tos(), grp->gr_name);
724 else {
725 return talloc_asprintf(talloc_tos(),
726 "%d",
727 (int)gid);
731 /*******************************************************************
732 Convert a user name into a uid.
733 ********************************************************************/
735 uid_t nametouid(const char *name)
737 struct passwd *pass;
738 char *p;
739 uid_t u;
741 pass = Get_Pwnam_alloc(talloc_tos(), name);
742 if (pass) {
743 u = pass->pw_uid;
744 TALLOC_FREE(pass);
745 return u;
748 u = (uid_t)strtol(name, &p, 0);
749 if ((p != name) && (*p == '\0'))
750 return u;
752 return (uid_t)-1;
755 /*******************************************************************
756 Convert a name to a gid_t if possible. Return -1 if not a group.
757 ********************************************************************/
759 gid_t nametogid(const char *name)
761 struct group *grp;
762 char *p;
763 gid_t g;
765 g = (gid_t)strtol(name, &p, 0);
766 if ((p != name) && (*p == '\0'))
767 return g;
769 grp = getgrnam(name);
770 if (grp)
771 return(grp->gr_gid);
772 return (gid_t)-1;
775 /*******************************************************************
776 Something really nasty happened - panic !
777 ********************************************************************/
779 void smb_panic_s3(const char *why)
781 char *cmd;
782 int result;
784 DEBUG(0,("PANIC (pid %llu): %s\n",
785 (unsigned long long)getpid(), why));
786 log_stack_trace();
788 #if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER)
790 * Make sure all children can attach a debugger.
792 prctl(PR_SET_PTRACER, getpid(), 0, 0, 0);
793 #endif
795 cmd = lp_panic_action(talloc_tos());
796 if (cmd && *cmd) {
797 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
798 result = system(cmd);
800 if (result == -1)
801 DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
802 strerror(errno)));
803 else
804 DEBUG(0, ("smb_panic(): action returned status %d\n",
805 WEXITSTATUS(result)));
808 dump_core();
811 /*******************************************************************
812 Print a backtrace of the stack to the debug log. This function
813 DELIBERATELY LEAKS MEMORY. The expectation is that you should
814 exit shortly after calling it.
815 ********************************************************************/
817 #ifdef HAVE_LIBUNWIND_H
818 #include <libunwind.h>
819 #endif
821 #ifdef HAVE_EXECINFO_H
822 #include <execinfo.h>
823 #endif
825 #ifdef HAVE_LIBEXC_H
826 #include <libexc.h>
827 #endif
829 void log_stack_trace(void)
831 #ifdef HAVE_LIBUNWIND
832 /* Try to use libunwind before any other technique since on ia64
833 * libunwind correctly walks the stack in more circumstances than
834 * backtrace.
836 unw_cursor_t cursor;
837 unw_context_t uc;
838 unsigned i = 0;
840 char procname[256];
841 unw_word_t ip, sp, off;
843 procname[sizeof(procname) - 1] = '\0';
845 if (unw_getcontext(&uc) != 0) {
846 goto libunwind_failed;
849 if (unw_init_local(&cursor, &uc) != 0) {
850 goto libunwind_failed;
853 DEBUG(0, ("BACKTRACE:\n"));
855 do {
856 ip = sp = 0;
857 unw_get_reg(&cursor, UNW_REG_IP, &ip);
858 unw_get_reg(&cursor, UNW_REG_SP, &sp);
860 switch (unw_get_proc_name(&cursor,
861 procname, sizeof(procname) - 1, &off) ) {
862 case 0:
863 /* Name found. */
864 case -UNW_ENOMEM:
865 /* Name truncated. */
866 DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
867 i, procname, (long long)off,
868 (long long)ip, (long long) sp));
869 break;
870 default:
871 /* case -UNW_ENOINFO: */
872 /* case -UNW_EUNSPEC: */
873 /* No symbol name found. */
874 DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
875 i, "<unknown symbol>",
876 (long long)ip, (long long) sp));
878 ++i;
879 } while (unw_step(&cursor) > 0);
881 return;
883 libunwind_failed:
884 DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
886 #elif HAVE_BACKTRACE_SYMBOLS
887 void *backtrace_stack[BACKTRACE_STACK_SIZE];
888 size_t backtrace_size;
889 char **backtrace_strings;
891 /* get the backtrace (stack frames) */
892 backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
893 backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
895 DEBUG(0, ("BACKTRACE: %lu stack frames:\n",
896 (unsigned long)backtrace_size));
898 if (backtrace_strings) {
899 int i;
901 for (i = 0; i < backtrace_size; i++)
902 DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
904 /* Leak the backtrace_strings, rather than risk what free() might do */
907 #elif HAVE_LIBEXC
909 /* The IRIX libexc library provides an API for unwinding the stack. See
910 * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
911 * since we are about to abort anyway, it hardly matters.
914 #define NAMESIZE 32 /* Arbitrary */
916 __uint64_t addrs[BACKTRACE_STACK_SIZE];
917 char * names[BACKTRACE_STACK_SIZE];
918 char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
920 int i;
921 int levels;
923 ZERO_ARRAY(addrs);
924 ZERO_ARRAY(names);
925 ZERO_ARRAY(namebuf);
927 /* We need to be root so we can open our /proc entry to walk
928 * our stack. It also helps when we want to dump core.
930 become_root();
932 for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
933 names[i] = namebuf + (i * NAMESIZE);
936 levels = trace_back_stack(0, addrs, names,
937 BACKTRACE_STACK_SIZE, NAMESIZE - 1);
939 DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
940 for (i = 0; i < levels; i++) {
941 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
943 #undef NAMESIZE
945 #else
946 DEBUG(0, ("unable to produce a stack trace on this platform\n"));
947 #endif
950 /*******************************************************************
951 A readdir wrapper which just returns the file name.
952 ********************************************************************/
954 const char *readdirname(DIR *p)
956 struct dirent *ptr;
957 char *dname;
959 if (!p)
960 return(NULL);
962 ptr = (struct dirent *)readdir(p);
963 if (!ptr)
964 return(NULL);
966 dname = ptr->d_name;
968 #ifdef NEXT2
969 if (telldir(p) < 0)
970 return(NULL);
971 #endif
973 #ifdef HAVE_BROKEN_READDIR_NAME
974 /* using /usr/ucb/cc is BAD */
975 dname = dname - 2;
976 #endif
978 return talloc_strdup(talloc_tos(), dname);
981 /*******************************************************************
982 Utility function used to decide if the last component
983 of a path matches a (possibly wildcarded) entry in a namelist.
984 ********************************************************************/
986 bool is_in_path(const char *name, name_compare_entry *namelist, bool case_sensitive)
988 const char *last_component;
990 /* if we have no list it's obviously not in the path */
991 if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
992 return False;
995 DEBUG(8, ("is_in_path: %s\n", name));
997 /* Get the last component of the unix name. */
998 last_component = strrchr_m(name, '/');
999 if (!last_component) {
1000 last_component = name;
1001 } else {
1002 last_component++; /* Go past '/' */
1005 for(; namelist->name != NULL; namelist++) {
1006 if(namelist->is_wild) {
1007 if (mask_match(last_component, namelist->name, case_sensitive)) {
1008 DEBUG(8,("is_in_path: mask match succeeded\n"));
1009 return True;
1011 } else {
1012 if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
1013 (!case_sensitive && (strcasecmp_m(last_component, namelist->name) == 0))) {
1014 DEBUG(8,("is_in_path: match succeeded\n"));
1015 return True;
1019 DEBUG(8,("is_in_path: match not found\n"));
1020 return False;
1023 /*******************************************************************
1024 Strip a '/' separated list into an array of
1025 name_compare_enties structures suitable for
1026 passing to is_in_path(). We do this for
1027 speed so we can pre-parse all the names in the list
1028 and don't do it for each call to is_in_path().
1029 We also check if the entry contains a wildcard to
1030 remove a potentially expensive call to mask_match
1031 if possible.
1032 ********************************************************************/
1034 void set_namearray(name_compare_entry **ppname_array, const char *namelist_in)
1036 char *name_end;
1037 char *namelist;
1038 char *nameptr;
1039 int num_entries = 0;
1040 int i;
1042 (*ppname_array) = NULL;
1044 if((namelist_in == NULL ) || ((namelist_in != NULL) && (*namelist_in == '\0')))
1045 return;
1047 namelist = talloc_strdup(talloc_tos(), namelist_in);
1048 if (namelist == NULL) {
1049 DEBUG(0,("set_namearray: talloc fail\n"));
1050 return;
1052 nameptr = namelist;
1054 /* We need to make two passes over the string. The
1055 first to count the number of elements, the second
1056 to split it.
1059 while(*nameptr) {
1060 if ( *nameptr == '/' ) {
1061 /* cope with multiple (useless) /s) */
1062 nameptr++;
1063 continue;
1065 /* anything left? */
1066 if ( *nameptr == '\0' )
1067 break;
1069 /* find the next '/' or consume remaining */
1070 name_end = strchr_m(nameptr, '/');
1071 if (name_end == NULL)
1072 name_end = (char *)nameptr + strlen(nameptr);
1074 /* next segment please */
1075 nameptr = name_end + 1;
1076 num_entries++;
1079 if(num_entries == 0) {
1080 talloc_free(namelist);
1081 return;
1084 if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1085 DEBUG(0,("set_namearray: malloc fail\n"));
1086 talloc_free(namelist);
1087 return;
1090 /* Now copy out the names */
1091 nameptr = namelist;
1092 i = 0;
1093 while(*nameptr) {
1094 if ( *nameptr == '/' ) {
1095 /* cope with multiple (useless) /s) */
1096 nameptr++;
1097 continue;
1099 /* anything left? */
1100 if ( *nameptr == '\0' )
1101 break;
1103 /* find the next '/' or consume remaining */
1104 name_end = strchr_m(nameptr, '/');
1105 if (name_end)
1106 *name_end = '\0';
1107 else
1108 name_end = nameptr + strlen(nameptr);
1110 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1111 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1112 DEBUG(0,("set_namearray: malloc fail (1)\n"));
1113 talloc_free(namelist);
1114 return;
1117 /* next segment please */
1118 nameptr = name_end + 1;
1119 i++;
1122 (*ppname_array)[i].name = NULL;
1124 talloc_free(namelist);
1125 return;
1128 #undef DBGC_CLASS
1129 #define DBGC_CLASS DBGC_LOCKING
1131 /****************************************************************************
1132 Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
1133 is dealt with in posix.c
1134 Returns True if we have information regarding this lock region (and returns
1135 F_UNLCK in *ptype if the region is unlocked). False if the call failed.
1136 ****************************************************************************/
1138 bool fcntl_getlock(int fd, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1140 struct flock lock;
1141 int ret;
1143 DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
1144 fd,(double)*poffset,(double)*pcount,*ptype));
1146 lock.l_type = *ptype;
1147 lock.l_whence = SEEK_SET;
1148 lock.l_start = *poffset;
1149 lock.l_len = *pcount;
1150 lock.l_pid = 0;
1152 ret = sys_fcntl_ptr(fd,F_GETLK,&lock);
1154 if (ret == -1) {
1155 int sav = errno;
1156 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
1157 (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
1158 errno = sav;
1159 return False;
1162 *ptype = lock.l_type;
1163 *poffset = lock.l_start;
1164 *pcount = lock.l_len;
1165 *ppid = lock.l_pid;
1167 DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
1168 fd, (int)lock.l_type, (unsigned int)lock.l_pid));
1169 return True;
1172 #undef DBGC_CLASS
1173 #define DBGC_CLASS DBGC_ALL
1175 /*******************************************************************
1176 Is the name specified one of my netbios names.
1177 Returns true if it is equal, false otherwise.
1178 ********************************************************************/
1180 bool is_myname(const char *s)
1182 int n;
1183 bool ret = False;
1185 for (n=0; my_netbios_names(n); n++) {
1186 if (strequal(my_netbios_names(n), s)) {
1187 ret=True;
1188 break;
1191 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1192 return(ret);
1195 /*******************************************************************
1196 we distinguish between 2K and XP by the "Native Lan Manager" string
1197 WinXP => "Windows 2002 5.1"
1198 WinXP 64bit => "Windows XP 5.2"
1199 Win2k => "Windows 2000 5.0"
1200 NT4 => "Windows NT 4.0"
1201 Win9x => "Windows 4.0"
1202 Windows 2003 doesn't set the native lan manager string but
1203 they do set the domain to "Windows 2003 5.2" (probably a bug).
1204 ********************************************************************/
1206 void ra_lanman_string( const char *native_lanman )
1208 if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1209 set_remote_arch( RA_WINXP );
1210 else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1211 set_remote_arch( RA_WINXP64 );
1212 else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1213 set_remote_arch( RA_WIN2K3 );
1216 static const char *remote_arch_str;
1218 const char *get_remote_arch_str(void)
1220 if (!remote_arch_str) {
1221 return "UNKNOWN";
1223 return remote_arch_str;
1226 /*******************************************************************
1227 Set the horrid remote_arch string based on an enum.
1228 ********************************************************************/
1230 void set_remote_arch(enum remote_arch_types type)
1232 ra_type = type;
1233 switch( type ) {
1234 case RA_WFWG:
1235 remote_arch_str = "WfWg";
1236 break;
1237 case RA_OS2:
1238 remote_arch_str = "OS2";
1239 break;
1240 case RA_WIN95:
1241 remote_arch_str = "Win95";
1242 break;
1243 case RA_WINNT:
1244 remote_arch_str = "WinNT";
1245 break;
1246 case RA_WIN2K:
1247 remote_arch_str = "Win2K";
1248 break;
1249 case RA_WINXP:
1250 remote_arch_str = "WinXP";
1251 break;
1252 case RA_WINXP64:
1253 remote_arch_str = "WinXP64";
1254 break;
1255 case RA_WIN2K3:
1256 remote_arch_str = "Win2K3";
1257 break;
1258 case RA_VISTA:
1259 remote_arch_str = "Vista";
1260 break;
1261 case RA_SAMBA:
1262 remote_arch_str = "Samba";
1263 break;
1264 case RA_CIFSFS:
1265 remote_arch_str = "CIFSFS";
1266 break;
1267 case RA_OSX:
1268 remote_arch_str = "OSX";
1269 break;
1270 default:
1271 ra_type = RA_UNKNOWN;
1272 remote_arch_str = "UNKNOWN";
1273 break;
1276 DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1277 remote_arch_str));
1280 /*******************************************************************
1281 Get the remote_arch type.
1282 ********************************************************************/
1284 enum remote_arch_types get_remote_arch(void)
1286 return ra_type;
1289 const char *tab_depth(int level, int depth)
1291 if( CHECK_DEBUGLVL(level) ) {
1292 dbgtext("%*s", depth*4, "");
1294 return "";
1297 /*****************************************************************************
1298 Provide a checksum on a string
1300 Input: s - the null-terminated character string for which the checksum
1301 will be calculated.
1303 Output: The checksum value calculated for s.
1304 *****************************************************************************/
1306 int str_checksum(const char *s)
1308 if (s == NULL)
1309 return 0;
1310 return hash(s, strlen(s), 0);
1313 /*****************************************************************
1314 Zero a memory area then free it. Used to catch bugs faster.
1315 *****************************************************************/
1317 void zero_free(void *p, size_t size)
1319 memset(p, 0, size);
1320 SAFE_FREE(p);
1323 /*****************************************************************
1324 Set our open file limit to a requested max and return the limit.
1325 *****************************************************************/
1327 int set_maxfiles(int requested_max)
1329 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1330 struct rlimit rlp;
1331 int saved_current_limit;
1333 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1334 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1335 strerror(errno) ));
1336 /* just guess... */
1337 return requested_max;
1341 * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1342 * account for the extra fd we need
1343 * as well as the log files and standard
1344 * handles etc. Save the limit we want to set in case
1345 * we are running on an OS that doesn't support this limit (AIX)
1346 * which always returns RLIM_INFINITY for rlp.rlim_max.
1349 /* Try raising the hard (max) limit to the requested amount. */
1351 #if defined(RLIM_INFINITY)
1352 if (rlp.rlim_max != RLIM_INFINITY) {
1353 int orig_max = rlp.rlim_max;
1355 if ( rlp.rlim_max < requested_max )
1356 rlp.rlim_max = requested_max;
1358 /* This failing is not an error - many systems (Linux) don't
1359 support our default request of 10,000 open files. JRA. */
1361 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1362 DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n",
1363 (int)rlp.rlim_max, strerror(errno) ));
1365 /* Set failed - restore original value from get. */
1366 rlp.rlim_max = orig_max;
1369 #endif
1371 /* Now try setting the soft (current) limit. */
1373 saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1375 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1376 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
1377 (int)rlp.rlim_cur, strerror(errno) ));
1378 /* just guess... */
1379 return saved_current_limit;
1382 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1383 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1384 strerror(errno) ));
1385 /* just guess... */
1386 return saved_current_limit;
1389 #if defined(RLIM_INFINITY)
1390 if(rlp.rlim_cur == RLIM_INFINITY)
1391 return saved_current_limit;
1392 #endif
1394 if((int)rlp.rlim_cur > saved_current_limit)
1395 return saved_current_limit;
1397 return rlp.rlim_cur;
1398 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1400 * No way to know - just guess...
1402 return requested_max;
1403 #endif
1406 /*****************************************************************
1407 malloc that aborts with smb_panic on fail or zero size.
1408 *****************************************************************/
1410 void *smb_xmalloc_array(size_t size, unsigned int count)
1412 void *p;
1413 if (size == 0) {
1414 smb_panic("smb_xmalloc_array: called with zero size");
1416 if (count >= MAX_ALLOC_SIZE/size) {
1417 smb_panic("smb_xmalloc_array: alloc size too large");
1419 if ((p = SMB_MALLOC(size*count)) == NULL) {
1420 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1421 (unsigned long)size, (unsigned long)count));
1422 smb_panic("smb_xmalloc_array: malloc failed");
1424 return p;
1428 vasprintf that aborts on malloc fail
1431 int smb_xvasprintf(char **ptr, const char *format, va_list ap)
1433 int n;
1434 va_list ap2;
1436 va_copy(ap2, ap);
1438 n = vasprintf(ptr, format, ap2);
1439 va_end(ap2);
1440 if (n == -1 || ! *ptr) {
1441 smb_panic("smb_xvasprintf: out of memory");
1443 return n;
1446 /*****************************************************************
1447 Get local hostname and cache result.
1448 *****************************************************************/
1450 char *myhostname(void)
1452 static char *ret;
1453 if (ret == NULL) {
1454 ret = get_myname(NULL);
1456 return ret;
1459 /*****************************************************************
1460 Get local hostname and cache result.
1461 *****************************************************************/
1463 char *myhostname_upper(void)
1465 static char *ret;
1466 if (ret == NULL) {
1467 char *name = get_myname(NULL);
1468 if (name == NULL) {
1469 return NULL;
1471 ret = strupper_talloc(NULL, name);
1472 talloc_free(name);
1474 return ret;
1478 * @brief Returns an absolute path to a file concatenating the provided
1479 * @a rootpath and @a basename
1481 * @param name Filename, relative to @a rootpath
1483 * @retval Pointer to a string containing the full path.
1486 static char *xx_path(const char *name, const char *rootpath)
1488 char *fname = NULL;
1490 fname = talloc_strdup(talloc_tos(), rootpath);
1491 if (!fname) {
1492 return NULL;
1494 trim_string(fname,"","/");
1496 if (!directory_exist(fname)) {
1497 if (mkdir(fname,0755) == -1) {
1498 /* Did someone else win the race ? */
1499 if (errno != EEXIST) {
1500 DEBUG(1, ("Unable to create directory %s for file %s. "
1501 "Error was %s\n", fname, name, strerror(errno)));
1502 return NULL;
1507 return talloc_asprintf_append_buffer(fname, "/%s", name);
1511 * @brief Returns an absolute path to a file in the Samba lock directory.
1513 * @param name File to find, relative to LOCKDIR.
1515 * @retval Pointer to a talloc'ed string containing the full path.
1518 char *lock_path(const char *name)
1520 return xx_path(name, lp_lock_directory());
1524 * @brief Returns an absolute path to a file in the Samba state directory.
1526 * @param name File to find, relative to STATEDIR.
1528 * @retval Pointer to a talloc'ed string containing the full path.
1531 char *state_path(const char *name)
1533 return xx_path(name, lp_state_directory());
1537 * @brief Returns an absolute path to a file in the Samba cache directory.
1539 * @param name File to find, relative to CACHEDIR.
1541 * @retval Pointer to a talloc'ed string containing the full path.
1544 char *cache_path(const char *name)
1546 return xx_path(name, lp_cache_directory());
1549 /*******************************************************************
1550 Given a filename - get its directory name
1551 ********************************************************************/
1553 bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
1554 const char **name)
1556 char *p;
1557 ptrdiff_t len;
1559 p = strrchr_m(dir, '/'); /* Find final '/', if any */
1561 if (p == NULL) {
1562 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
1563 return False;
1565 if (name) {
1566 *name = dir;
1568 return True;
1571 len = p-dir;
1573 if (!(*parent = (char *)talloc_memdup(mem_ctx, dir, len+1))) {
1574 return False;
1576 (*parent)[len] = '\0';
1578 if (name) {
1579 *name = p+1;
1581 return True;
1584 /*******************************************************************
1585 Determine if a pattern contains any Microsoft wildcard characters.
1586 *******************************************************************/
1588 bool ms_has_wild(const char *s)
1590 char c;
1592 if (lp_posix_pathnames()) {
1593 /* With posix pathnames no characters are wild. */
1594 return False;
1597 while ((c = *s++)) {
1598 switch (c) {
1599 case '*':
1600 case '?':
1601 case '<':
1602 case '>':
1603 case '"':
1604 return True;
1607 return False;
1610 bool ms_has_wild_w(const smb_ucs2_t *s)
1612 smb_ucs2_t c;
1613 if (!s) return False;
1614 while ((c = *s++)) {
1615 switch (c) {
1616 case UCS2_CHAR('*'):
1617 case UCS2_CHAR('?'):
1618 case UCS2_CHAR('<'):
1619 case UCS2_CHAR('>'):
1620 case UCS2_CHAR('"'):
1621 return True;
1624 return False;
1627 /*******************************************************************
1628 A wrapper that handles case sensitivity and the special handling
1629 of the ".." name.
1630 *******************************************************************/
1632 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
1634 if (ISDOTDOT(string))
1635 string = ".";
1636 if (ISDOT(pattern))
1637 return False;
1639 return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
1642 /*******************************************************************
1643 A wrapper that handles case sensitivity and the special handling
1644 of the ".." name. Varient that is only called by old search code which requires
1645 pattern translation.
1646 *******************************************************************/
1648 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
1650 if (ISDOTDOT(string))
1651 string = ".";
1652 if (ISDOT(pattern))
1653 return False;
1655 return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
1658 /*******************************************************************
1659 A wrapper that handles a list of patters and calls mask_match()
1660 on each. Returns True if any of the patterns match.
1661 *******************************************************************/
1663 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
1665 while (listLen-- > 0) {
1666 if (mask_match(string, *list++, is_case_sensitive))
1667 return True;
1669 return False;
1672 /*********************************************************
1673 Recursive routine that is called by unix_wild_match.
1674 *********************************************************/
1676 static bool unix_do_match(const char *regexp, const char *str)
1678 const char *p;
1680 for( p = regexp; *p && *str; ) {
1682 switch(*p) {
1683 case '?':
1684 str++;
1685 p++;
1686 break;
1688 case '*':
1691 * Look for a character matching
1692 * the one after the '*'.
1694 p++;
1695 if(!*p)
1696 return true; /* Automatic match */
1697 while(*str) {
1699 while(*str && (*p != *str))
1700 str++;
1703 * Patch from weidel@multichart.de. In the case of the regexp
1704 * '*XX*' we want to ensure there are at least 2 'X' characters
1705 * in the string after the '*' for a match to be made.
1709 int matchcount=0;
1712 * Eat all the characters that match, but count how many there were.
1715 while(*str && (*p == *str)) {
1716 str++;
1717 matchcount++;
1721 * Now check that if the regexp had n identical characters that
1722 * matchcount had at least that many matches.
1725 while ( *(p+1) && (*(p+1) == *p)) {
1726 p++;
1727 matchcount--;
1730 if ( matchcount <= 0 )
1731 return false;
1734 str--; /* We've eaten the match char after the '*' */
1736 if(unix_do_match(p, str))
1737 return true;
1739 if(!*str)
1740 return false;
1741 else
1742 str++;
1744 return false;
1746 default:
1747 if(*str != *p)
1748 return false;
1749 str++;
1750 p++;
1751 break;
1755 if(!*p && !*str)
1756 return true;
1758 if (!*p && str[0] == '.' && str[1] == 0)
1759 return true;
1761 if (!*str && *p == '?') {
1762 while (*p == '?')
1763 p++;
1764 return(!*p);
1767 if(!*str && (*p == '*' && p[1] == '\0'))
1768 return true;
1770 return false;
1773 /*******************************************************************
1774 Simple case insensitive interface to a UNIX wildcard matcher.
1775 Returns True if match, False if not.
1776 *******************************************************************/
1778 bool unix_wild_match(const char *pattern, const char *string)
1780 TALLOC_CTX *ctx = talloc_stackframe();
1781 char *p2;
1782 char *s2;
1783 char *p;
1784 bool ret = false;
1786 p2 = talloc_strdup(ctx,pattern);
1787 s2 = talloc_strdup(ctx,string);
1788 if (!p2 || !s2) {
1789 TALLOC_FREE(ctx);
1790 return false;
1792 if (!strlower_m(p2)) {
1793 TALLOC_FREE(ctx);
1794 return false;
1796 if (!strlower_m(s2)) {
1797 TALLOC_FREE(ctx);
1798 return false;
1801 /* Remove any *? and ** from the pattern as they are meaningless */
1802 for(p = p2; *p; p++) {
1803 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
1804 memmove(&p[1], &p[2], strlen(&p[2])+1);
1808 if (strequal(p2,"*")) {
1809 TALLOC_FREE(ctx);
1810 return true;
1813 ret = unix_do_match(p2, s2);
1814 TALLOC_FREE(ctx);
1815 return ret;
1818 /**********************************************************************
1819 Converts a name to a fully qualified domain name.
1820 Returns true if lookup succeeded, false if not (then fqdn is set to name)
1821 Note we deliberately use gethostbyname here, not getaddrinfo as we want
1822 to examine the h_aliases and I don't know how to do that with getaddrinfo.
1823 ***********************************************************************/
1825 bool name_to_fqdn(fstring fqdn, const char *name)
1827 char *full = NULL;
1828 struct hostent *hp = gethostbyname(name);
1830 if (!hp || !hp->h_name || !*hp->h_name) {
1831 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
1832 fstrcpy(fqdn, name);
1833 return false;
1836 /* Find out if the fqdn is returned as an alias
1837 * to cope with /etc/hosts files where the first
1838 * name is not the fqdn but the short name */
1839 if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
1840 int i;
1841 for (i = 0; hp->h_aliases[i]; i++) {
1842 if (strchr_m(hp->h_aliases[i], '.')) {
1843 full = hp->h_aliases[i];
1844 break;
1848 if (full && (strcasecmp_m(full, "localhost.localdomain") == 0)) {
1849 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
1850 DEBUGADD(1, (" Specifing the machine hostname for address 127.0.0.1 may lead\n"));
1851 DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n"));
1852 DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n"));
1853 full = hp->h_name;
1855 if (!full) {
1856 full = hp->h_name;
1859 DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
1860 fstrcpy(fqdn, full);
1861 return true;
1864 /**********************************************************************
1865 Append a DATA_BLOB to a talloc'ed object
1866 ***********************************************************************/
1868 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
1870 size_t old_size = 0;
1871 char *result;
1873 if (blob.length == 0) {
1874 return buf;
1877 if (buf != NULL) {
1878 old_size = talloc_get_size(buf);
1881 result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
1882 if (result == NULL) {
1883 return NULL;
1886 memcpy(result + old_size, blob.data, blob.length);
1887 return result;
1890 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
1892 switch (share_access & ~FILE_SHARE_DELETE) {
1893 case FILE_SHARE_NONE:
1894 return DENY_ALL;
1895 case FILE_SHARE_READ:
1896 return DENY_WRITE;
1897 case FILE_SHARE_WRITE:
1898 return DENY_READ;
1899 case FILE_SHARE_READ|FILE_SHARE_WRITE:
1900 return DENY_NONE;
1902 if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
1903 return DENY_DOS;
1904 } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
1905 return DENY_FCB;
1908 return (uint32)-1;
1911 pid_t procid_to_pid(const struct server_id *proc)
1913 return proc->pid;
1916 static uint32 my_vnn = NONCLUSTER_VNN;
1918 void set_my_vnn(uint32 vnn)
1920 DEBUG(10, ("vnn pid %d = %u\n", (int)getpid(), (unsigned int)vnn));
1921 my_vnn = vnn;
1924 uint32 get_my_vnn(void)
1926 return my_vnn;
1929 static uint64_t my_unique_id = 0;
1931 void set_my_unique_id(uint64_t unique_id)
1933 my_unique_id = unique_id;
1936 struct server_id pid_to_procid(pid_t pid)
1938 struct server_id result;
1939 result.pid = pid;
1940 result.task_id = 0;
1941 result.unique_id = my_unique_id;
1942 result.vnn = my_vnn;
1943 return result;
1946 struct server_id procid_self(void)
1948 return pid_to_procid(getpid());
1951 bool procid_is_me(const struct server_id *pid)
1953 if (pid->pid != getpid())
1954 return False;
1955 if (pid->task_id != 0)
1956 return False;
1957 if (pid->vnn != my_vnn)
1958 return False;
1959 return True;
1962 struct server_id interpret_pid(const char *pid_string)
1964 return server_id_from_string(get_my_vnn(), pid_string);
1967 char *procid_str_static(const struct server_id *pid)
1969 return server_id_str(talloc_tos(), pid);
1972 bool procid_valid(const struct server_id *pid)
1974 return (pid->pid != (uint64_t)-1);
1977 bool procid_is_local(const struct server_id *pid)
1979 return pid->vnn == my_vnn;
1982 /****************************************************************
1983 Check if an offset into a buffer is safe.
1984 If this returns True it's safe to indirect into the byte at
1985 pointer ptr+off.
1986 ****************************************************************/
1988 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
1990 const char *end_base = buf_base + buf_len;
1991 char *end_ptr = ptr + off;
1993 if (!buf_base || !ptr) {
1994 return False;
1997 if (end_base < buf_base || end_ptr < ptr) {
1998 return False; /* wrap. */
2001 if (end_ptr < end_base) {
2002 return True;
2004 return False;
2007 /****************************************************************
2008 Return a safe pointer into a buffer, or NULL.
2009 ****************************************************************/
2011 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2013 return is_offset_safe(buf_base, buf_len, ptr, off) ?
2014 ptr + off : NULL;
2017 /****************************************************************
2018 Return a safe pointer into a string within a buffer, or NULL.
2019 ****************************************************************/
2021 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2023 if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2024 return NULL;
2026 /* Check if a valid string exists at this offset. */
2027 if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2028 return NULL;
2030 return ptr + off;
2033 /****************************************************************
2034 Return an SVAL at a pointer, or failval if beyond the end.
2035 ****************************************************************/
2037 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2040 * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2041 * NOT ptr[2].
2043 if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2044 return failval;
2046 return SVAL(ptr,off);
2049 /****************************************************************
2050 Return an IVAL at a pointer, or failval if beyond the end.
2051 ****************************************************************/
2053 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2056 * Note we use off+3 here, not off+4 as IVAL accesses
2057 * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2059 if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2060 return failval;
2062 return IVAL(ptr,off);
2065 /****************************************************************
2066 Split DOM\user into DOM and user. Do not mix with winbind variants of that
2067 call (they take care of winbind separator and other winbind specific settings).
2068 ****************************************************************/
2070 void split_domain_user(TALLOC_CTX *mem_ctx,
2071 const char *full_name,
2072 char **domain,
2073 char **user)
2075 const char *p = NULL;
2077 p = strchr_m(full_name, '\\');
2079 if (p != NULL) {
2080 *domain = talloc_strndup(mem_ctx, full_name,
2081 PTR_DIFF(p, full_name));
2082 *user = talloc_strdup(mem_ctx, p+1);
2083 } else {
2084 *domain = talloc_strdup(mem_ctx, "");
2085 *user = talloc_strdup(mem_ctx, full_name);
2089 /****************************************************************
2090 strip off leading '\\' from a hostname
2091 ****************************************************************/
2093 const char *strip_hostname(const char *s)
2095 if (!s) {
2096 return NULL;
2099 if (strlen_m(s) < 3) {
2100 return s;
2103 if (s[0] == '\\') s++;
2104 if (s[0] == '\\') s++;
2106 return s;
2109 bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result)
2111 if (!NT_STATUS_IS_OK(err1)) {
2112 *result = err1;
2113 return true;
2115 if (!NT_STATUS_IS_OK(err2)) {
2116 *result = err2;
2117 return true;
2119 return false;
2122 int timeval_to_msec(struct timeval t)
2124 return t.tv_sec * 1000 + (t.tv_usec+999) / 1000;
2127 /*******************************************************************
2128 Check a given DOS pathname is valid for a share.
2129 ********************************************************************/
2131 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
2133 char *ptr = NULL;
2135 if (!dos_pathname) {
2136 return NULL;
2139 ptr = talloc_strdup(ctx, dos_pathname);
2140 if (!ptr) {
2141 return NULL;
2143 /* Convert any '\' paths to '/' */
2144 unix_format(ptr);
2145 ptr = unix_clean_name(ctx, ptr);
2146 if (!ptr) {
2147 return NULL;
2150 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
2151 if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
2152 ptr += 2;
2154 /* Only absolute paths allowed. */
2155 if (*ptr != '/')
2156 return NULL;
2158 return ptr;
2161 /*******************************************************************
2162 Return True if the filename is one of the special executable types.
2163 ********************************************************************/
2165 bool is_executable(const char *fname)
2167 if ((fname = strrchr_m(fname,'.'))) {
2168 if (strequal(fname,".com") ||
2169 strequal(fname,".dll") ||
2170 strequal(fname,".exe") ||
2171 strequal(fname,".sym")) {
2172 return True;
2175 return False;
2178 /****************************************************************************
2179 Open a file with a share mode - old openX method - map into NTCreate.
2180 ****************************************************************************/
2182 bool map_open_params_to_ntcreate(const char *smb_base_fname,
2183 int deny_mode, int open_func,
2184 uint32 *paccess_mask,
2185 uint32 *pshare_mode,
2186 uint32 *pcreate_disposition,
2187 uint32 *pcreate_options,
2188 uint32_t *pprivate_flags)
2190 uint32 access_mask;
2191 uint32 share_mode;
2192 uint32 create_disposition;
2193 uint32 create_options = FILE_NON_DIRECTORY_FILE;
2194 uint32_t private_flags = 0;
2196 DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
2197 "open_func = 0x%x\n",
2198 smb_base_fname, (unsigned int)deny_mode,
2199 (unsigned int)open_func ));
2201 /* Create the NT compatible access_mask. */
2202 switch (GET_OPENX_MODE(deny_mode)) {
2203 case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
2204 case DOS_OPEN_RDONLY:
2205 access_mask = FILE_GENERIC_READ;
2206 break;
2207 case DOS_OPEN_WRONLY:
2208 access_mask = FILE_GENERIC_WRITE;
2209 break;
2210 case DOS_OPEN_RDWR:
2211 case DOS_OPEN_FCB:
2212 access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
2213 break;
2214 default:
2215 DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
2216 (unsigned int)GET_OPENX_MODE(deny_mode)));
2217 return False;
2220 /* Create the NT compatible create_disposition. */
2221 switch (open_func) {
2222 case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
2223 create_disposition = FILE_CREATE;
2224 break;
2226 case OPENX_FILE_EXISTS_OPEN:
2227 create_disposition = FILE_OPEN;
2228 break;
2230 case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
2231 create_disposition = FILE_OPEN_IF;
2232 break;
2234 case OPENX_FILE_EXISTS_TRUNCATE:
2235 create_disposition = FILE_OVERWRITE;
2236 break;
2238 case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
2239 create_disposition = FILE_OVERWRITE_IF;
2240 break;
2242 default:
2243 /* From samba4 - to be confirmed. */
2244 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
2245 create_disposition = FILE_CREATE;
2246 break;
2248 DEBUG(10,("map_open_params_to_ntcreate: bad "
2249 "open_func 0x%x\n", (unsigned int)open_func));
2250 return False;
2253 /* Create the NT compatible share modes. */
2254 switch (GET_DENY_MODE(deny_mode)) {
2255 case DENY_ALL:
2256 share_mode = FILE_SHARE_NONE;
2257 break;
2259 case DENY_WRITE:
2260 share_mode = FILE_SHARE_READ;
2261 break;
2263 case DENY_READ:
2264 share_mode = FILE_SHARE_WRITE;
2265 break;
2267 case DENY_NONE:
2268 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2269 break;
2271 case DENY_DOS:
2272 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
2273 if (is_executable(smb_base_fname)) {
2274 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2275 } else {
2276 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
2277 share_mode = FILE_SHARE_READ;
2278 } else {
2279 share_mode = FILE_SHARE_NONE;
2282 break;
2284 case DENY_FCB:
2285 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
2286 share_mode = FILE_SHARE_NONE;
2287 break;
2289 default:
2290 DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
2291 (unsigned int)GET_DENY_MODE(deny_mode) ));
2292 return False;
2295 DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
2296 "share_mode = 0x%x, create_disposition = 0x%x, "
2297 "create_options = 0x%x private_flags = 0x%x\n",
2298 smb_base_fname,
2299 (unsigned int)access_mask,
2300 (unsigned int)share_mode,
2301 (unsigned int)create_disposition,
2302 (unsigned int)create_options,
2303 (unsigned int)private_flags));
2305 if (paccess_mask) {
2306 *paccess_mask = access_mask;
2308 if (pshare_mode) {
2309 *pshare_mode = share_mode;
2311 if (pcreate_disposition) {
2312 *pcreate_disposition = create_disposition;
2314 if (pcreate_options) {
2315 *pcreate_options = create_options;
2317 if (pprivate_flags) {
2318 *pprivate_flags = private_flags;
2321 return True;
2325 /*************************************************************************
2326 Return a talloced copy of a struct security_unix_token. NULL on fail.
2327 *************************************************************************/
2329 struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct security_unix_token *tok)
2331 struct security_unix_token *cpy;
2333 cpy = talloc(ctx, struct security_unix_token);
2334 if (!cpy) {
2335 return NULL;
2338 cpy->uid = tok->uid;
2339 cpy->gid = tok->gid;
2340 cpy->ngroups = tok->ngroups;
2341 if (tok->ngroups) {
2342 /* Make this a talloc child of cpy. */
2343 cpy->groups = (gid_t *)talloc_memdup(
2344 cpy, tok->groups, tok->ngroups * sizeof(gid_t));
2345 if (!cpy->groups) {
2346 TALLOC_FREE(cpy);
2347 return NULL;
2349 } else {
2350 cpy->groups = NULL;
2352 return cpy;
2355 /****************************************************************************
2356 Check that a file matches a particular file type.
2357 ****************************************************************************/
2359 bool dir_check_ftype(uint32_t mode, uint32_t dirtype)
2361 uint32_t mask;
2363 /* Check the "may have" search bits. */
2364 if (((mode & ~dirtype) &
2365 (FILE_ATTRIBUTE_HIDDEN |
2366 FILE_ATTRIBUTE_SYSTEM |
2367 FILE_ATTRIBUTE_DIRECTORY)) != 0) {
2368 return false;
2371 /* Check the "must have" bits,
2372 which are the may have bits shifted eight */
2373 /* If must have bit is set, the file/dir can
2374 not be returned in search unless the matching
2375 file attribute is set */
2376 mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|
2377 FILE_ATTRIBUTE_ARCHIVE|
2378 FILE_ATTRIBUTE_READONLY|
2379 FILE_ATTRIBUTE_HIDDEN|
2380 FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
2381 if(mask) {
2382 if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|
2383 FILE_ATTRIBUTE_ARCHIVE|
2384 FILE_ATTRIBUTE_READONLY|
2385 FILE_ATTRIBUTE_HIDDEN|
2386 FILE_ATTRIBUTE_SYSTEM))) == mask) {
2387 /* check if matching attribute present */
2388 return true;
2389 } else {
2390 return false;
2394 return true;