s4-dsdb/reanimate: Swap rename->modify operations to modify->rename sequence
[Samba.git] / source3 / lib / util.c
blobe53953b085f0388438c5c79b38a9eeae21d39e32
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"
34 #include "lib/sys_rw.h"
35 #include "lib/sys_rw_data.h"
37 #ifdef HAVE_SYS_PRCTL_H
38 #include <sys/prctl.h>
39 #endif
41 /* Max allowable allococation - 256mb - 0x10000000 */
42 #define MAX_ALLOC_SIZE (1024*1024*256)
44 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
45 #ifdef WITH_NISPLUS_HOME
46 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
48 * The following lines are needed due to buggy include files
49 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
50 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
51 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
52 * an enum in /usr/include/rpcsvc/nis.h.
55 #if defined(GROUP)
56 #undef GROUP
57 #endif
59 #if defined(GROUP_OBJ)
60 #undef GROUP_OBJ
61 #endif
63 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
65 #include <rpcsvc/nis.h>
67 #endif /* WITH_NISPLUS_HOME */
68 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
70 static enum protocol_types Protocol = PROTOCOL_COREPLUS;
72 enum protocol_types get_Protocol(void)
74 return Protocol;
77 void set_Protocol(enum protocol_types p)
79 Protocol = p;
82 static enum remote_arch_types ra_type = RA_UNKNOWN;
84 void gfree_all( void )
86 gfree_names();
87 gfree_loadparm();
88 gfree_charcnv();
89 gfree_interfaces();
90 gfree_debugsyms();
93 /*******************************************************************
94 Check if a file exists - call vfs_file_exist for samba files.
95 ********************************************************************/
97 bool file_exist_stat(const char *fname,SMB_STRUCT_STAT *sbuf,
98 bool fake_dir_create_times)
100 SMB_STRUCT_STAT st;
101 if (!sbuf)
102 sbuf = &st;
104 if (sys_stat(fname, sbuf, fake_dir_create_times) != 0)
105 return(False);
107 return((S_ISREG(sbuf->st_ex_mode)) || (S_ISFIFO(sbuf->st_ex_mode)));
110 /*******************************************************************
111 Check if a unix domain socket exists - call vfs_file_exist for samba files.
112 ********************************************************************/
114 bool socket_exist(const char *fname)
116 SMB_STRUCT_STAT st;
117 if (sys_stat(fname, &st, false) != 0)
118 return(False);
120 return S_ISSOCK(st.st_ex_mode);
123 /*******************************************************************
124 Returns the size in bytes of the named given the stat struct.
125 ********************************************************************/
127 uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf)
129 return sbuf->st_ex_size;
132 /****************************************************************************
133 Check two stats have identical dev and ino fields.
134 ****************************************************************************/
136 bool check_same_dev_ino(const SMB_STRUCT_STAT *sbuf1,
137 const SMB_STRUCT_STAT *sbuf2)
139 if (sbuf1->st_ex_dev != sbuf2->st_ex_dev ||
140 sbuf1->st_ex_ino != sbuf2->st_ex_ino) {
141 return false;
143 return true;
146 /****************************************************************************
147 Check if a stat struct is identical for use.
148 ****************************************************************************/
150 bool check_same_stat(const SMB_STRUCT_STAT *sbuf1,
151 const SMB_STRUCT_STAT *sbuf2)
153 if (sbuf1->st_ex_uid != sbuf2->st_ex_uid ||
154 sbuf1->st_ex_gid != sbuf2->st_ex_gid ||
155 !check_same_dev_ino(sbuf1, sbuf2)) {
156 return false;
158 return true;
161 /*******************************************************************
162 Show a smb message structure.
163 ********************************************************************/
165 void show_msg(const char *buf)
167 int i;
168 int bcc=0;
170 if (!DEBUGLVL(5))
171 return;
173 DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
174 smb_len(buf),
175 (int)CVAL(buf,smb_com),
176 (int)CVAL(buf,smb_rcls),
177 (int)CVAL(buf,smb_reh),
178 (int)SVAL(buf,smb_err),
179 (int)CVAL(buf,smb_flg),
180 (int)SVAL(buf,smb_flg2)));
181 DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
182 (int)SVAL(buf,smb_tid),
183 (int)SVAL(buf,smb_pid),
184 (int)SVAL(buf,smb_uid),
185 (int)SVAL(buf,smb_mid)));
186 DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
188 for (i=0;i<(int)CVAL(buf,smb_wct);i++)
189 DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
190 SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
192 bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
194 DEBUGADD(5,("smb_bcc=%d\n",bcc));
196 if (DEBUGLEVEL < 10)
197 return;
199 if (DEBUGLEVEL < 50)
200 bcc = MIN(bcc, 512);
202 dump_data(10, (const uint8 *)smb_buf_const(buf), bcc);
205 /*******************************************************************
206 Setup only the byte count for a smb message.
207 ********************************************************************/
209 int set_message_bcc(char *buf,int num_bytes)
211 int num_words = CVAL(buf,smb_wct);
212 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
213 _smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
214 return (smb_size + num_words*2 + num_bytes);
217 /*******************************************************************
218 Add a data blob to the end of a smb_buf, adjusting bcc and smb_len.
219 Return the bytes added
220 ********************************************************************/
222 ssize_t message_push_blob(uint8 **outbuf, DATA_BLOB blob)
224 size_t newlen = smb_len(*outbuf) + 4 + blob.length;
225 uint8 *tmp;
227 if (!(tmp = talloc_realloc(NULL, *outbuf, uint8, newlen))) {
228 DEBUG(0, ("talloc failed\n"));
229 return -1;
231 *outbuf = tmp;
233 memcpy(tmp + smb_len(tmp) + 4, blob.data, blob.length);
234 set_message_bcc((char *)tmp, smb_buflen(tmp) + blob.length);
235 return blob.length;
238 /*******************************************************************
239 Reduce a file name, removing .. elements.
240 ********************************************************************/
242 static char *dos_clean_name(TALLOC_CTX *ctx, const char *s)
244 char *p = NULL;
245 char *str = NULL;
247 DEBUG(3,("dos_clean_name [%s]\n",s));
249 /* remove any double slashes */
250 str = talloc_all_string_sub(ctx, s, "\\\\", "\\");
251 if (!str) {
252 return NULL;
255 /* Remove leading .\\ characters */
256 if(strncmp(str, ".\\", 2) == 0) {
257 trim_string(str, ".\\", NULL);
258 if(*str == 0) {
259 str = talloc_strdup(ctx, ".\\");
260 if (!str) {
261 return NULL;
266 while ((p = strstr_m(str,"\\..\\")) != NULL) {
267 char *s1;
269 *p = 0;
270 s1 = p+3;
272 if ((p=strrchr_m(str,'\\')) != NULL) {
273 *p = 0;
274 } else {
275 *str = 0;
277 str = talloc_asprintf(ctx,
278 "%s%s",
279 str,
280 s1);
281 if (!str) {
282 return NULL;
286 trim_string(str,NULL,"\\..");
287 return talloc_all_string_sub(ctx, str, "\\.\\", "\\");
290 /*******************************************************************
291 Reduce a file name, removing .. elements.
292 ********************************************************************/
294 char *unix_clean_name(TALLOC_CTX *ctx, const char *s)
296 char *p = NULL;
297 char *str = NULL;
299 DEBUG(3,("unix_clean_name [%s]\n",s));
301 /* remove any double slashes */
302 str = talloc_all_string_sub(ctx, s, "//","/");
303 if (!str) {
304 return NULL;
307 /* Remove leading ./ characters */
308 if(strncmp(str, "./", 2) == 0) {
309 trim_string(str, "./", NULL);
310 if(*str == 0) {
311 str = talloc_strdup(ctx, "./");
312 if (!str) {
313 return NULL;
318 while ((p = strstr_m(str,"/../")) != NULL) {
319 char *s1;
321 *p = 0;
322 s1 = p+3;
324 if ((p=strrchr_m(str,'/')) != NULL) {
325 *p = 0;
326 } else {
327 *str = 0;
329 str = talloc_asprintf(ctx,
330 "%s%s",
331 str,
332 s1);
333 if (!str) {
334 return NULL;
338 trim_string(str,NULL,"/..");
339 return talloc_all_string_sub(ctx, str, "/./", "/");
342 char *clean_name(TALLOC_CTX *ctx, const char *s)
344 char *str = dos_clean_name(ctx, s);
345 if (!str) {
346 return NULL;
348 return unix_clean_name(ctx, str);
351 /*******************************************************************
352 Write data into an fd at a given offset. Ignore seek errors.
353 ********************************************************************/
355 ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, off_t pos)
357 size_t total=0;
358 ssize_t ret;
360 if (pos == (off_t)-1) {
361 return write_data(fd, buffer, N);
363 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
364 while (total < N) {
365 ret = sys_pwrite(fd,buffer + total,N - total, pos);
366 if (ret == -1 && errno == ESPIPE) {
367 return write_data(fd, buffer + total,N - total);
369 if (ret == -1) {
370 DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
371 return -1;
373 if (ret == 0) {
374 return total;
376 total += ret;
377 pos += ret;
379 return (ssize_t)total;
380 #else
381 /* Use lseek and write_data. */
382 if (lseek(fd, pos, SEEK_SET) == -1) {
383 if (errno != ESPIPE) {
384 return -1;
387 return write_data(fd, buffer, N);
388 #endif
391 static int reinit_after_fork_pipe[2] = { -1, -1 };
393 NTSTATUS init_before_fork(void)
395 int ret;
397 ret = pipe(reinit_after_fork_pipe);
398 if (ret == -1) {
399 NTSTATUS status;
401 status = map_nt_error_from_unix_common(errno);
403 DEBUG(0, ("Error creating child_pipe: %s\n",
404 nt_errstr(status)));
406 return status;
409 return NT_STATUS_OK;
413 * Detect died parent by detecting EOF on the pipe
415 static void reinit_after_fork_pipe_handler(struct tevent_context *ev,
416 struct tevent_fd *fde,
417 uint16_t flags,
418 void *private_data)
420 char c;
422 if (sys_read(reinit_after_fork_pipe[0], &c, 1) != 1) {
424 * we have reached EOF on stdin, which means the
425 * parent has exited. Shutdown the server
427 (void)kill(getpid(), SIGTERM);
432 NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
433 struct tevent_context *ev_ctx,
434 bool parent_longlived)
436 NTSTATUS status = NT_STATUS_OK;
438 if (reinit_after_fork_pipe[1] != -1) {
439 close(reinit_after_fork_pipe[1]);
440 reinit_after_fork_pipe[1] = -1;
443 /* Reset the state of the random
444 * number generation system, so
445 * children do not get the same random
446 * numbers as each other */
447 set_need_random_reseed();
449 /* tdb needs special fork handling */
450 if (tdb_reopen_all(parent_longlived ? 1 : 0) != 0) {
451 DEBUG(0,("tdb_reopen_all failed.\n"));
452 status = NT_STATUS_OPEN_FAILED;
453 goto done;
456 if (ev_ctx != NULL) {
457 tevent_set_trace_callback(ev_ctx, NULL, NULL);
458 if (tevent_re_initialise(ev_ctx) != 0) {
459 smb_panic(__location__ ": Failed to re-initialise event context");
463 if (reinit_after_fork_pipe[0] != -1) {
464 struct tevent_fd *fde;
466 fde = tevent_add_fd(ev_ctx, ev_ctx /* TALLOC_CTX */,
467 reinit_after_fork_pipe[0], TEVENT_FD_READ,
468 reinit_after_fork_pipe_handler, NULL);
469 if (fde == NULL) {
470 smb_panic(__location__ ": Failed to add reinit_after_fork pipe event");
474 if (msg_ctx) {
476 * For clustering, we need to re-init our ctdbd connection after the
477 * fork
479 status = messaging_reinit(msg_ctx);
480 if (!NT_STATUS_IS_OK(status)) {
481 DEBUG(0,("messaging_reinit() failed: %s\n",
482 nt_errstr(status)));
485 done:
486 return status;
489 /****************************************************************************
490 (Hopefully) efficient array append.
491 ****************************************************************************/
493 void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
494 void *element, void *_array, uint32 *num_elements,
495 ssize_t *array_size)
497 void **array = (void **)_array;
499 if (*array_size < 0) {
500 return;
503 if (*array == NULL) {
504 if (*array_size == 0) {
505 *array_size = 128;
508 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
509 goto error;
512 *array = TALLOC(mem_ctx, element_size * (*array_size));
513 if (*array == NULL) {
514 goto error;
518 if (*num_elements == *array_size) {
519 *array_size *= 2;
521 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
522 goto error;
525 *array = TALLOC_REALLOC(mem_ctx, *array,
526 element_size * (*array_size));
528 if (*array == NULL) {
529 goto error;
533 memcpy((char *)(*array) + element_size*(*num_elements),
534 element, element_size);
535 *num_elements += 1;
537 return;
539 error:
540 *num_elements = 0;
541 *array_size = -1;
544 /****************************************************************************
545 Get my own domain name, or "" if we have none.
546 ****************************************************************************/
548 char *get_mydnsdomname(TALLOC_CTX *ctx)
550 const char *domname;
551 char *p;
553 domname = get_mydnsfullname();
554 if (!domname) {
555 return NULL;
558 p = strchr_m(domname, '.');
559 if (p) {
560 p++;
561 return talloc_strdup(ctx, p);
562 } else {
563 return talloc_strdup(ctx, "");
567 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
568 /******************************************************************
569 Remove any mount options such as -rsize=2048,wsize=2048 etc.
570 Based on a fix from <Thomas.Hepper@icem.de>.
571 Returns a malloc'ed string.
572 *******************************************************************/
574 static char *strip_mount_options(TALLOC_CTX *ctx, const char *str)
576 if (*str == '-') {
577 const char *p = str;
578 while(*p && !isspace(*p))
579 p++;
580 while(*p && isspace(*p))
581 p++;
582 if(*p) {
583 return talloc_strdup(ctx, p);
586 return NULL;
589 /*******************************************************************
590 Patch from jkf@soton.ac.uk
591 Split Luke's automount_server into YP lookup and string splitter
592 so can easily implement automount_path().
593 Returns a malloc'ed string.
594 *******************************************************************/
596 #ifdef WITH_NISPLUS_HOME
597 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
599 char *value = NULL;
601 char *nis_map = (char *)lp_homedir_map();
603 char buffer[NIS_MAXATTRVAL + 1];
604 nis_result *result;
605 nis_object *object;
606 entry_obj *entry;
608 snprintf(buffer, sizeof(buffer), "[key=%s],%s", user_name, nis_map);
609 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
611 if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
612 if (result->status != NIS_SUCCESS) {
613 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
614 } else {
615 object = result->objects.objects_val;
616 if (object->zo_data.zo_type == ENTRY_OBJ) {
617 entry = &object->zo_data.objdata_u.en_data;
618 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
619 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
621 value = talloc_strdup(ctx,
622 entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
623 if (!value) {
624 nis_freeresult(result);
625 return NULL;
627 value = talloc_string_sub(ctx,
628 value,
629 "&",
630 user_name);
634 nis_freeresult(result);
636 if (value) {
637 value = strip_mount_options(ctx, value);
638 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n",
639 user_name, value));
641 return value;
643 #else /* WITH_NISPLUS_HOME */
645 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
647 char *value = NULL;
649 int nis_error; /* returned by yp all functions */
650 char *nis_result; /* yp_match inits this */
651 int nis_result_len; /* and set this */
652 char *nis_domain; /* yp_get_default_domain inits this */
653 char *nis_map = lp_homedir_map(talloc_tos());
655 if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
656 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
657 return NULL;
660 DEBUG(5, ("NIS Domain: %s\n", nis_domain));
662 if ((nis_error = yp_match(nis_domain, nis_map, user_name,
663 strlen(user_name), &nis_result,
664 &nis_result_len)) == 0) {
665 if (nis_result_len > 0 && nis_result[nis_result_len] == '\n') {
666 nis_result[nis_result_len] = '\0';
668 value = talloc_strdup(ctx, nis_result);
669 if (!value) {
670 return NULL;
672 value = strip_mount_options(ctx, value);
673 } else if(nis_error == YPERR_KEY) {
674 DEBUG(3, ("YP Key not found: while looking up \"%s\" in map \"%s\"\n",
675 user_name, nis_map));
676 DEBUG(3, ("using defaults for server and home directory\n"));
677 } else {
678 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
679 yperr_string(nis_error), user_name, nis_map));
682 if (value) {
683 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, value));
685 return value;
687 #endif /* WITH_NISPLUS_HOME */
688 #endif
690 bool process_exists(const struct server_id pid)
692 return serverid_exists(&pid);
695 /*******************************************************************
696 Convert a uid into a user name.
697 ********************************************************************/
699 const char *uidtoname(uid_t uid)
701 TALLOC_CTX *ctx = talloc_tos();
702 char *name = NULL;
703 struct passwd *pass = NULL;
705 pass = getpwuid_alloc(ctx,uid);
706 if (pass) {
707 name = talloc_strdup(ctx,pass->pw_name);
708 TALLOC_FREE(pass);
709 } else {
710 name = talloc_asprintf(ctx,
711 "%ld",
712 (long int)uid);
714 return name;
717 /*******************************************************************
718 Convert a gid into a group name.
719 ********************************************************************/
721 char *gidtoname(gid_t gid)
723 struct group *grp;
725 grp = getgrgid(gid);
726 if (grp) {
727 return talloc_strdup(talloc_tos(), grp->gr_name);
729 else {
730 return talloc_asprintf(talloc_tos(),
731 "%d",
732 (int)gid);
736 /*******************************************************************
737 Convert a user name into a uid.
738 ********************************************************************/
740 uid_t nametouid(const char *name)
742 struct passwd *pass;
743 char *p;
744 uid_t u;
746 pass = Get_Pwnam_alloc(talloc_tos(), name);
747 if (pass) {
748 u = pass->pw_uid;
749 TALLOC_FREE(pass);
750 return u;
753 u = (uid_t)strtol(name, &p, 0);
754 if ((p != name) && (*p == '\0'))
755 return u;
757 return (uid_t)-1;
760 /*******************************************************************
761 Convert a name to a gid_t if possible. Return -1 if not a group.
762 ********************************************************************/
764 gid_t nametogid(const char *name)
766 struct group *grp;
767 char *p;
768 gid_t g;
770 g = (gid_t)strtol(name, &p, 0);
771 if ((p != name) && (*p == '\0'))
772 return g;
774 grp = getgrnam(name);
775 if (grp)
776 return(grp->gr_gid);
777 return (gid_t)-1;
780 /*******************************************************************
781 Something really nasty happened - panic !
782 ********************************************************************/
784 void smb_panic_s3(const char *why)
786 char *cmd;
787 int result;
789 DEBUG(0,("PANIC (pid %llu): %s\n",
790 (unsigned long long)getpid(), why));
791 log_stack_trace();
793 #if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER)
795 * Make sure all children can attach a debugger.
797 prctl(PR_SET_PTRACER, getpid(), 0, 0, 0);
798 #endif
800 cmd = lp_panic_action(talloc_tos());
801 if (cmd && *cmd) {
802 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
803 result = system(cmd);
805 if (result == -1)
806 DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
807 strerror(errno)));
808 else
809 DEBUG(0, ("smb_panic(): action returned status %d\n",
810 WEXITSTATUS(result)));
813 dump_core();
816 /*******************************************************************
817 Print a backtrace of the stack to the debug log. This function
818 DELIBERATELY LEAKS MEMORY. The expectation is that you should
819 exit shortly after calling it.
820 ********************************************************************/
822 #ifdef HAVE_LIBUNWIND_H
823 #include <libunwind.h>
824 #endif
826 #ifdef HAVE_EXECINFO_H
827 #include <execinfo.h>
828 #endif
830 #ifdef HAVE_LIBEXC_H
831 #include <libexc.h>
832 #endif
834 void log_stack_trace(void)
836 #ifdef HAVE_LIBUNWIND
837 /* Try to use libunwind before any other technique since on ia64
838 * libunwind correctly walks the stack in more circumstances than
839 * backtrace.
841 unw_cursor_t cursor;
842 unw_context_t uc;
843 unsigned i = 0;
845 char procname[256];
846 unw_word_t ip, sp, off;
848 procname[sizeof(procname) - 1] = '\0';
850 if (unw_getcontext(&uc) != 0) {
851 goto libunwind_failed;
854 if (unw_init_local(&cursor, &uc) != 0) {
855 goto libunwind_failed;
858 DEBUG(0, ("BACKTRACE:\n"));
860 do {
861 ip = sp = 0;
862 unw_get_reg(&cursor, UNW_REG_IP, &ip);
863 unw_get_reg(&cursor, UNW_REG_SP, &sp);
865 switch (unw_get_proc_name(&cursor,
866 procname, sizeof(procname) - 1, &off) ) {
867 case 0:
868 /* Name found. */
869 case -UNW_ENOMEM:
870 /* Name truncated. */
871 DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
872 i, procname, (long long)off,
873 (long long)ip, (long long) sp));
874 break;
875 default:
876 /* case -UNW_ENOINFO: */
877 /* case -UNW_EUNSPEC: */
878 /* No symbol name found. */
879 DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
880 i, "<unknown symbol>",
881 (long long)ip, (long long) sp));
883 ++i;
884 } while (unw_step(&cursor) > 0);
886 return;
888 libunwind_failed:
889 DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
891 #elif HAVE_BACKTRACE_SYMBOLS
892 void *backtrace_stack[BACKTRACE_STACK_SIZE];
893 size_t backtrace_size;
894 char **backtrace_strings;
896 /* get the backtrace (stack frames) */
897 backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
898 backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
900 DEBUG(0, ("BACKTRACE: %lu stack frames:\n",
901 (unsigned long)backtrace_size));
903 if (backtrace_strings) {
904 int i;
906 for (i = 0; i < backtrace_size; i++)
907 DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
909 /* Leak the backtrace_strings, rather than risk what free() might do */
912 #elif HAVE_LIBEXC
914 /* The IRIX libexc library provides an API for unwinding the stack. See
915 * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
916 * since we are about to abort anyway, it hardly matters.
919 #define NAMESIZE 32 /* Arbitrary */
921 __uint64_t addrs[BACKTRACE_STACK_SIZE];
922 char * names[BACKTRACE_STACK_SIZE];
923 char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
925 int i;
926 int levels;
928 ZERO_ARRAY(addrs);
929 ZERO_ARRAY(names);
930 ZERO_ARRAY(namebuf);
932 /* We need to be root so we can open our /proc entry to walk
933 * our stack. It also helps when we want to dump core.
935 become_root();
937 for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
938 names[i] = namebuf + (i * NAMESIZE);
941 levels = trace_back_stack(0, addrs, names,
942 BACKTRACE_STACK_SIZE, NAMESIZE - 1);
944 DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
945 for (i = 0; i < levels; i++) {
946 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
948 #undef NAMESIZE
950 #else
951 DEBUG(0, ("unable to produce a stack trace on this platform\n"));
952 #endif
955 /*******************************************************************
956 A readdir wrapper which just returns the file name.
957 ********************************************************************/
959 const char *readdirname(DIR *p)
961 struct dirent *ptr;
962 char *dname;
964 if (!p)
965 return(NULL);
967 ptr = (struct dirent *)readdir(p);
968 if (!ptr)
969 return(NULL);
971 dname = ptr->d_name;
973 #ifdef NEXT2
974 if (telldir(p) < 0)
975 return(NULL);
976 #endif
978 #ifdef HAVE_BROKEN_READDIR_NAME
979 /* using /usr/ucb/cc is BAD */
980 dname = dname - 2;
981 #endif
983 return talloc_strdup(talloc_tos(), dname);
986 /*******************************************************************
987 Utility function used to decide if the last component
988 of a path matches a (possibly wildcarded) entry in a namelist.
989 ********************************************************************/
991 bool is_in_path(const char *name, name_compare_entry *namelist, bool case_sensitive)
993 const char *last_component;
995 /* if we have no list it's obviously not in the path */
996 if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
997 return False;
1000 DEBUG(8, ("is_in_path: %s\n", name));
1002 /* Get the last component of the unix name. */
1003 last_component = strrchr_m(name, '/');
1004 if (!last_component) {
1005 last_component = name;
1006 } else {
1007 last_component++; /* Go past '/' */
1010 for(; namelist->name != NULL; namelist++) {
1011 if(namelist->is_wild) {
1012 if (mask_match(last_component, namelist->name, case_sensitive)) {
1013 DEBUG(8,("is_in_path: mask match succeeded\n"));
1014 return True;
1016 } else {
1017 if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
1018 (!case_sensitive && (strcasecmp_m(last_component, namelist->name) == 0))) {
1019 DEBUG(8,("is_in_path: match succeeded\n"));
1020 return True;
1024 DEBUG(8,("is_in_path: match not found\n"));
1025 return False;
1028 /*******************************************************************
1029 Strip a '/' separated list into an array of
1030 name_compare_enties structures suitable for
1031 passing to is_in_path(). We do this for
1032 speed so we can pre-parse all the names in the list
1033 and don't do it for each call to is_in_path().
1034 We also check if the entry contains a wildcard to
1035 remove a potentially expensive call to mask_match
1036 if possible.
1037 ********************************************************************/
1039 void set_namearray(name_compare_entry **ppname_array, const char *namelist_in)
1041 char *name_end;
1042 char *namelist;
1043 char *namelist_end;
1044 char *nameptr;
1045 int num_entries = 0;
1046 int i;
1048 (*ppname_array) = NULL;
1050 if((namelist_in == NULL ) || ((namelist_in != NULL) && (*namelist_in == '\0')))
1051 return;
1053 namelist = talloc_strdup(talloc_tos(), namelist_in);
1054 if (namelist == NULL) {
1055 DEBUG(0,("set_namearray: talloc fail\n"));
1056 return;
1058 nameptr = namelist;
1060 namelist_end = &namelist[strlen(namelist)];
1062 /* We need to make two passes over the string. The
1063 first to count the number of elements, the second
1064 to split it.
1067 while(nameptr <= namelist_end) {
1068 if ( *nameptr == '/' ) {
1069 /* cope with multiple (useless) /s) */
1070 nameptr++;
1071 continue;
1073 /* anything left? */
1074 if ( *nameptr == '\0' )
1075 break;
1077 /* find the next '/' or consume remaining */
1078 name_end = strchr_m(nameptr, '/');
1079 if (name_end == NULL) {
1080 /* Point nameptr at the terminating '\0' */
1081 nameptr += strlen(nameptr);
1082 } else {
1083 /* next segment please */
1084 nameptr = name_end + 1;
1086 num_entries++;
1089 if(num_entries == 0) {
1090 talloc_free(namelist);
1091 return;
1094 if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1095 DEBUG(0,("set_namearray: malloc fail\n"));
1096 talloc_free(namelist);
1097 return;
1100 /* Now copy out the names */
1101 nameptr = namelist;
1102 i = 0;
1103 while(nameptr <= namelist_end) {
1104 if ( *nameptr == '/' ) {
1105 /* cope with multiple (useless) /s) */
1106 nameptr++;
1107 continue;
1109 /* anything left? */
1110 if ( *nameptr == '\0' )
1111 break;
1113 /* find the next '/' or consume remaining */
1114 name_end = strchr_m(nameptr, '/');
1115 if (name_end != NULL) {
1116 *name_end = '\0';
1119 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1120 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1121 DEBUG(0,("set_namearray: malloc fail (1)\n"));
1122 talloc_free(namelist);
1123 return;
1126 if (name_end == NULL) {
1127 /* Point nameptr at the terminating '\0' */
1128 nameptr += strlen(nameptr);
1129 } else {
1130 /* next segment please */
1131 nameptr = name_end + 1;
1133 i++;
1136 (*ppname_array)[i].name = NULL;
1138 talloc_free(namelist);
1139 return;
1142 #undef DBGC_CLASS
1143 #define DBGC_CLASS DBGC_LOCKING
1145 /****************************************************************************
1146 Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
1147 is dealt with in posix.c
1148 Returns True if we have information regarding this lock region (and returns
1149 F_UNLCK in *ptype if the region is unlocked). False if the call failed.
1150 ****************************************************************************/
1152 bool fcntl_getlock(int fd, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1154 struct flock lock;
1155 int ret;
1157 DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
1158 fd,(double)*poffset,(double)*pcount,*ptype));
1160 lock.l_type = *ptype;
1161 lock.l_whence = SEEK_SET;
1162 lock.l_start = *poffset;
1163 lock.l_len = *pcount;
1164 lock.l_pid = 0;
1166 ret = sys_fcntl_ptr(fd,F_GETLK,&lock);
1168 if (ret == -1) {
1169 int sav = errno;
1170 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
1171 (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
1172 errno = sav;
1173 return False;
1176 *ptype = lock.l_type;
1177 *poffset = lock.l_start;
1178 *pcount = lock.l_len;
1179 *ppid = lock.l_pid;
1181 DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
1182 fd, (int)lock.l_type, (unsigned int)lock.l_pid));
1183 return True;
1186 #undef DBGC_CLASS
1187 #define DBGC_CLASS DBGC_ALL
1189 /*******************************************************************
1190 Is the name specified one of my netbios names.
1191 Returns true if it is equal, false otherwise.
1192 ********************************************************************/
1194 bool is_myname(const char *s)
1196 int n;
1197 bool ret = False;
1199 for (n=0; my_netbios_names(n); n++) {
1200 const char *nbt_name = my_netbios_names(n);
1202 if (strncasecmp_m(nbt_name, s, strlen(nbt_name)) == 0) {
1203 ret=True;
1204 break;
1207 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1208 return(ret);
1211 /*******************************************************************
1212 we distinguish between 2K and XP by the "Native Lan Manager" string
1213 WinXP => "Windows 2002 5.1"
1214 WinXP 64bit => "Windows XP 5.2"
1215 Win2k => "Windows 2000 5.0"
1216 NT4 => "Windows NT 4.0"
1217 Win9x => "Windows 4.0"
1218 Windows 2003 doesn't set the native lan manager string but
1219 they do set the domain to "Windows 2003 5.2" (probably a bug).
1220 ********************************************************************/
1222 void ra_lanman_string( const char *native_lanman )
1224 if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1225 set_remote_arch( RA_WINXP );
1226 else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1227 set_remote_arch( RA_WINXP64 );
1228 else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1229 set_remote_arch( RA_WIN2K3 );
1232 static const char *remote_arch_str;
1234 const char *get_remote_arch_str(void)
1236 if (!remote_arch_str) {
1237 return "UNKNOWN";
1239 return remote_arch_str;
1242 /*******************************************************************
1243 Set the horrid remote_arch string based on an enum.
1244 ********************************************************************/
1246 void set_remote_arch(enum remote_arch_types type)
1248 ra_type = type;
1249 switch( type ) {
1250 case RA_WFWG:
1251 remote_arch_str = "WfWg";
1252 break;
1253 case RA_OS2:
1254 remote_arch_str = "OS2";
1255 break;
1256 case RA_WIN95:
1257 remote_arch_str = "Win95";
1258 break;
1259 case RA_WINNT:
1260 remote_arch_str = "WinNT";
1261 break;
1262 case RA_WIN2K:
1263 remote_arch_str = "Win2K";
1264 break;
1265 case RA_WINXP:
1266 remote_arch_str = "WinXP";
1267 break;
1268 case RA_WINXP64:
1269 remote_arch_str = "WinXP64";
1270 break;
1271 case RA_WIN2K3:
1272 remote_arch_str = "Win2K3";
1273 break;
1274 case RA_VISTA:
1275 remote_arch_str = "Vista";
1276 break;
1277 case RA_SAMBA:
1278 remote_arch_str = "Samba";
1279 break;
1280 case RA_CIFSFS:
1281 remote_arch_str = "CIFSFS";
1282 break;
1283 case RA_OSX:
1284 remote_arch_str = "OSX";
1285 break;
1286 default:
1287 ra_type = RA_UNKNOWN;
1288 remote_arch_str = "UNKNOWN";
1289 break;
1292 DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1293 remote_arch_str));
1296 /*******************************************************************
1297 Get the remote_arch type.
1298 ********************************************************************/
1300 enum remote_arch_types get_remote_arch(void)
1302 return ra_type;
1305 const char *tab_depth(int level, int depth)
1307 if( CHECK_DEBUGLVL(level) ) {
1308 dbgtext("%*s", depth*4, "");
1310 return "";
1313 /*****************************************************************************
1314 Provide a checksum on a string
1316 Input: s - the null-terminated character string for which the checksum
1317 will be calculated.
1319 Output: The checksum value calculated for s.
1320 *****************************************************************************/
1322 int str_checksum(const char *s)
1324 if (s == NULL)
1325 return 0;
1326 return hash(s, strlen(s), 0);
1329 /*****************************************************************
1330 Zero a memory area then free it. Used to catch bugs faster.
1331 *****************************************************************/
1333 void zero_free(void *p, size_t size)
1335 memset(p, 0, size);
1336 SAFE_FREE(p);
1339 /*****************************************************************
1340 Set our open file limit to a requested max and return the limit.
1341 *****************************************************************/
1343 int set_maxfiles(int requested_max)
1345 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1346 struct rlimit rlp;
1347 int saved_current_limit;
1349 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1350 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1351 strerror(errno) ));
1352 /* just guess... */
1353 return requested_max;
1357 * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1358 * account for the extra fd we need
1359 * as well as the log files and standard
1360 * handles etc. Save the limit we want to set in case
1361 * we are running on an OS that doesn't support this limit (AIX)
1362 * which always returns RLIM_INFINITY for rlp.rlim_max.
1365 /* Try raising the hard (max) limit to the requested amount. */
1367 #if defined(RLIM_INFINITY)
1368 if (rlp.rlim_max != RLIM_INFINITY) {
1369 int orig_max = rlp.rlim_max;
1371 if ( rlp.rlim_max < requested_max )
1372 rlp.rlim_max = requested_max;
1374 /* This failing is not an error - many systems (Linux) don't
1375 support our default request of 10,000 open files. JRA. */
1377 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1378 DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n",
1379 (int)rlp.rlim_max, strerror(errno) ));
1381 /* Set failed - restore original value from get. */
1382 rlp.rlim_max = orig_max;
1385 #endif
1387 /* Now try setting the soft (current) limit. */
1389 saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1391 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1392 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
1393 (int)rlp.rlim_cur, strerror(errno) ));
1394 /* just guess... */
1395 return saved_current_limit;
1398 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1399 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1400 strerror(errno) ));
1401 /* just guess... */
1402 return saved_current_limit;
1405 #if defined(RLIM_INFINITY)
1406 if(rlp.rlim_cur == RLIM_INFINITY)
1407 return saved_current_limit;
1408 #endif
1410 if((int)rlp.rlim_cur > saved_current_limit)
1411 return saved_current_limit;
1413 return rlp.rlim_cur;
1414 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1416 * No way to know - just guess...
1418 return requested_max;
1419 #endif
1422 /*****************************************************************
1423 malloc that aborts with smb_panic on fail or zero size.
1424 *****************************************************************/
1426 void *smb_xmalloc_array(size_t size, unsigned int count)
1428 void *p;
1429 if (size == 0) {
1430 smb_panic("smb_xmalloc_array: called with zero size");
1432 if (count >= MAX_ALLOC_SIZE/size) {
1433 smb_panic("smb_xmalloc_array: alloc size too large");
1435 if ((p = SMB_MALLOC(size*count)) == NULL) {
1436 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1437 (unsigned long)size, (unsigned long)count));
1438 smb_panic("smb_xmalloc_array: malloc failed");
1440 return p;
1444 vasprintf that aborts on malloc fail
1447 int smb_xvasprintf(char **ptr, const char *format, va_list ap)
1449 int n;
1450 va_list ap2;
1452 va_copy(ap2, ap);
1454 n = vasprintf(ptr, format, ap2);
1455 va_end(ap2);
1456 if (n == -1 || ! *ptr) {
1457 smb_panic("smb_xvasprintf: out of memory");
1459 return n;
1462 /*****************************************************************
1463 Get local hostname and cache result.
1464 *****************************************************************/
1466 char *myhostname(void)
1468 static char *ret;
1469 if (ret == NULL) {
1470 ret = get_myname(NULL);
1472 return ret;
1475 /*****************************************************************
1476 Get local hostname and cache result.
1477 *****************************************************************/
1479 char *myhostname_upper(void)
1481 static char *ret;
1482 if (ret == NULL) {
1483 char *name = get_myname(NULL);
1484 if (name == NULL) {
1485 return NULL;
1487 ret = strupper_talloc(NULL, name);
1488 talloc_free(name);
1490 return ret;
1494 * @brief Returns an absolute path to a file concatenating the provided
1495 * @a rootpath and @a basename
1497 * @param name Filename, relative to @a rootpath
1499 * @retval Pointer to a string containing the full path.
1502 static char *xx_path(const char *name, const char *rootpath)
1504 char *fname = NULL;
1506 fname = talloc_strdup(talloc_tos(), rootpath);
1507 if (!fname) {
1508 return NULL;
1510 trim_string(fname,"","/");
1512 if (!directory_exist(fname)) {
1513 if (mkdir(fname,0755) == -1) {
1514 /* Did someone else win the race ? */
1515 if (errno != EEXIST) {
1516 DEBUG(1, ("Unable to create directory %s for file %s. "
1517 "Error was %s\n", fname, name, strerror(errno)));
1518 return NULL;
1523 return talloc_asprintf_append(fname, "/%s", name);
1527 * @brief Returns an absolute path to a file in the Samba lock directory.
1529 * @param name File to find, relative to LOCKDIR.
1531 * @retval Pointer to a talloc'ed string containing the full path.
1534 char *lock_path(const char *name)
1536 return xx_path(name, lp_lock_directory());
1540 * @brief Returns an absolute path to a file in the Samba state directory.
1542 * @param name File to find, relative to STATEDIR.
1544 * @retval Pointer to a talloc'ed string containing the full path.
1547 char *state_path(const char *name)
1549 return xx_path(name, lp_state_directory());
1553 * @brief Returns an absolute path to a file in the Samba cache directory.
1555 * @param name File to find, relative to CACHEDIR.
1557 * @retval Pointer to a talloc'ed string containing the full path.
1560 char *cache_path(const char *name)
1562 return xx_path(name, lp_cache_directory());
1565 /*******************************************************************
1566 Given a filename - get its directory name
1567 ********************************************************************/
1569 bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
1570 const char **name)
1572 char *p;
1573 ptrdiff_t len;
1575 p = strrchr_m(dir, '/'); /* Find final '/', if any */
1577 if (p == NULL) {
1578 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
1579 return False;
1581 if (name) {
1582 *name = dir;
1584 return True;
1587 len = p-dir;
1589 if (!(*parent = (char *)talloc_memdup(mem_ctx, dir, len+1))) {
1590 return False;
1592 (*parent)[len] = '\0';
1594 if (name) {
1595 *name = p+1;
1597 return True;
1600 /*******************************************************************
1601 Determine if a pattern contains any Microsoft wildcard characters.
1602 *******************************************************************/
1604 bool ms_has_wild(const char *s)
1606 char c;
1608 if (lp_posix_pathnames()) {
1609 /* With posix pathnames no characters are wild. */
1610 return False;
1613 while ((c = *s++)) {
1614 switch (c) {
1615 case '*':
1616 case '?':
1617 case '<':
1618 case '>':
1619 case '"':
1620 return True;
1623 return False;
1626 bool ms_has_wild_w(const smb_ucs2_t *s)
1628 smb_ucs2_t c;
1629 if (!s) return False;
1630 while ((c = *s++)) {
1631 switch (c) {
1632 case UCS2_CHAR('*'):
1633 case UCS2_CHAR('?'):
1634 case UCS2_CHAR('<'):
1635 case UCS2_CHAR('>'):
1636 case UCS2_CHAR('"'):
1637 return True;
1640 return False;
1643 /*******************************************************************
1644 A wrapper that handles case sensitivity and the special handling
1645 of the ".." name.
1646 *******************************************************************/
1648 bool mask_match(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, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
1658 /*******************************************************************
1659 A wrapper that handles case sensitivity and the special handling
1660 of the ".." name. Varient that is only called by old search code which requires
1661 pattern translation.
1662 *******************************************************************/
1664 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
1666 if (ISDOTDOT(string))
1667 string = ".";
1668 if (ISDOT(pattern))
1669 return False;
1671 return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
1674 /*******************************************************************
1675 A wrapper that handles a list of patters and calls mask_match()
1676 on each. Returns True if any of the patterns match.
1677 *******************************************************************/
1679 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
1681 while (listLen-- > 0) {
1682 if (mask_match(string, *list++, is_case_sensitive))
1683 return True;
1685 return False;
1688 /*********************************************************
1689 Recursive routine that is called by unix_wild_match.
1690 *********************************************************/
1692 static bool unix_do_match(const char *regexp, const char *str)
1694 const char *p;
1696 for( p = regexp; *p && *str; ) {
1698 switch(*p) {
1699 case '?':
1700 str++;
1701 p++;
1702 break;
1704 case '*':
1707 * Look for a character matching
1708 * the one after the '*'.
1710 p++;
1711 if(!*p)
1712 return true; /* Automatic match */
1713 while(*str) {
1715 while(*str && (*p != *str))
1716 str++;
1719 * Patch from weidel@multichart.de. In the case of the regexp
1720 * '*XX*' we want to ensure there are at least 2 'X' characters
1721 * in the string after the '*' for a match to be made.
1725 int matchcount=0;
1728 * Eat all the characters that match, but count how many there were.
1731 while(*str && (*p == *str)) {
1732 str++;
1733 matchcount++;
1737 * Now check that if the regexp had n identical characters that
1738 * matchcount had at least that many matches.
1741 while ( *(p+1) && (*(p+1) == *p)) {
1742 p++;
1743 matchcount--;
1746 if ( matchcount <= 0 )
1747 return false;
1750 str--; /* We've eaten the match char after the '*' */
1752 if(unix_do_match(p, str))
1753 return true;
1755 if(!*str)
1756 return false;
1757 else
1758 str++;
1760 return false;
1762 default:
1763 if(*str != *p)
1764 return false;
1765 str++;
1766 p++;
1767 break;
1771 if(!*p && !*str)
1772 return true;
1774 if (!*p && str[0] == '.' && str[1] == 0)
1775 return true;
1777 if (!*str && *p == '?') {
1778 while (*p == '?')
1779 p++;
1780 return(!*p);
1783 if(!*str && (*p == '*' && p[1] == '\0'))
1784 return true;
1786 return false;
1789 /*******************************************************************
1790 Simple case insensitive interface to a UNIX wildcard matcher.
1791 Returns True if match, False if not.
1792 *******************************************************************/
1794 bool unix_wild_match(const char *pattern, const char *string)
1796 TALLOC_CTX *ctx = talloc_stackframe();
1797 char *p2;
1798 char *s2;
1799 char *p;
1800 bool ret = false;
1802 p2 = talloc_strdup(ctx,pattern);
1803 s2 = talloc_strdup(ctx,string);
1804 if (!p2 || !s2) {
1805 TALLOC_FREE(ctx);
1806 return false;
1808 if (!strlower_m(p2)) {
1809 TALLOC_FREE(ctx);
1810 return false;
1812 if (!strlower_m(s2)) {
1813 TALLOC_FREE(ctx);
1814 return false;
1817 /* Remove any *? and ** from the pattern as they are meaningless */
1818 for(p = p2; *p; p++) {
1819 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
1820 memmove(&p[1], &p[2], strlen(&p[2])+1);
1824 if (strequal(p2,"*")) {
1825 TALLOC_FREE(ctx);
1826 return true;
1829 ret = unix_do_match(p2, s2);
1830 TALLOC_FREE(ctx);
1831 return ret;
1834 /**********************************************************************
1835 Converts a name to a fully qualified domain name.
1836 Returns true if lookup succeeded, false if not (then fqdn is set to name)
1837 Note we deliberately use gethostbyname here, not getaddrinfo as we want
1838 to examine the h_aliases and I don't know how to do that with getaddrinfo.
1839 ***********************************************************************/
1841 bool name_to_fqdn(fstring fqdn, const char *name)
1843 char *full = NULL;
1844 struct hostent *hp = gethostbyname(name);
1846 if (!hp || !hp->h_name || !*hp->h_name) {
1847 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
1848 fstrcpy(fqdn, name);
1849 return false;
1852 /* Find out if the fqdn is returned as an alias
1853 * to cope with /etc/hosts files where the first
1854 * name is not the fqdn but the short name */
1855 if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
1856 int i;
1857 for (i = 0; hp->h_aliases[i]; i++) {
1858 if (strchr_m(hp->h_aliases[i], '.')) {
1859 full = hp->h_aliases[i];
1860 break;
1864 if (full && (strcasecmp_m(full, "localhost.localdomain") == 0)) {
1865 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
1866 DEBUGADD(1, (" Specifying the machine hostname for address 127.0.0.1 may lead\n"));
1867 DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n"));
1868 DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n"));
1869 full = hp->h_name;
1871 if (!full) {
1872 full = hp->h_name;
1875 DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
1876 fstrcpy(fqdn, full);
1877 return true;
1880 /**********************************************************************
1881 Append a DATA_BLOB to a talloc'ed object
1882 ***********************************************************************/
1884 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
1886 size_t old_size = 0;
1887 char *result;
1889 if (blob.length == 0) {
1890 return buf;
1893 if (buf != NULL) {
1894 old_size = talloc_get_size(buf);
1897 result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
1898 if (result == NULL) {
1899 return NULL;
1902 memcpy(result + old_size, blob.data, blob.length);
1903 return result;
1906 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
1908 switch (share_access & ~FILE_SHARE_DELETE) {
1909 case FILE_SHARE_NONE:
1910 return DENY_ALL;
1911 case FILE_SHARE_READ:
1912 return DENY_WRITE;
1913 case FILE_SHARE_WRITE:
1914 return DENY_READ;
1915 case FILE_SHARE_READ|FILE_SHARE_WRITE:
1916 return DENY_NONE;
1918 if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
1919 return DENY_DOS;
1920 } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
1921 return DENY_FCB;
1924 return (uint32)-1;
1927 pid_t procid_to_pid(const struct server_id *proc)
1929 return proc->pid;
1932 static uint32 my_vnn = NONCLUSTER_VNN;
1934 void set_my_vnn(uint32 vnn)
1936 DEBUG(10, ("vnn pid %d = %u\n", (int)getpid(), (unsigned int)vnn));
1937 my_vnn = vnn;
1940 uint32 get_my_vnn(void)
1942 return my_vnn;
1945 static uint64_t my_unique_id = 0;
1947 void set_my_unique_id(uint64_t unique_id)
1949 my_unique_id = unique_id;
1952 struct server_id pid_to_procid(pid_t pid)
1954 struct server_id result;
1955 result.pid = pid;
1956 result.task_id = 0;
1957 result.unique_id = my_unique_id;
1958 result.vnn = my_vnn;
1959 return result;
1962 struct server_id procid_self(void)
1964 return pid_to_procid(getpid());
1967 bool procid_is_me(const struct server_id *pid)
1969 if (pid->pid != getpid())
1970 return False;
1971 if (pid->task_id != 0)
1972 return False;
1973 if (pid->vnn != my_vnn)
1974 return False;
1975 return True;
1978 struct server_id interpret_pid(const char *pid_string)
1980 return server_id_from_string(get_my_vnn(), pid_string);
1983 char *procid_str_static(const struct server_id *pid)
1985 return server_id_str(talloc_tos(), pid);
1988 bool procid_valid(const struct server_id *pid)
1990 return (pid->pid != (uint64_t)-1);
1993 bool procid_is_local(const struct server_id *pid)
1995 return pid->vnn == my_vnn;
1998 /****************************************************************
1999 Check if an offset into a buffer is safe.
2000 If this returns True it's safe to indirect into the byte at
2001 pointer ptr+off.
2002 ****************************************************************/
2004 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2006 const char *end_base = buf_base + buf_len;
2007 char *end_ptr = ptr + off;
2009 if (!buf_base || !ptr) {
2010 return False;
2013 if (end_base < buf_base || end_ptr < ptr) {
2014 return False; /* wrap. */
2017 if (end_ptr < end_base) {
2018 return True;
2020 return False;
2023 /****************************************************************
2024 Return a safe pointer into a buffer, or NULL.
2025 ****************************************************************/
2027 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2029 return is_offset_safe(buf_base, buf_len, ptr, off) ?
2030 ptr + off : NULL;
2033 /****************************************************************
2034 Return a safe pointer into a string within a buffer, or NULL.
2035 ****************************************************************/
2037 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2039 if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2040 return NULL;
2042 /* Check if a valid string exists at this offset. */
2043 if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2044 return NULL;
2046 return ptr + off;
2049 /****************************************************************
2050 Return an SVAL at a pointer, or failval if beyond the end.
2051 ****************************************************************/
2053 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2056 * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2057 * NOT ptr[2].
2059 if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2060 return failval;
2062 return SVAL(ptr,off);
2065 /****************************************************************
2066 Return an IVAL at a pointer, or failval if beyond the end.
2067 ****************************************************************/
2069 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2072 * Note we use off+3 here, not off+4 as IVAL accesses
2073 * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2075 if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2076 return failval;
2078 return IVAL(ptr,off);
2081 /****************************************************************
2082 Split DOM\user into DOM and user. Do not mix with winbind variants of that
2083 call (they take care of winbind separator and other winbind specific settings).
2084 ****************************************************************/
2086 void split_domain_user(TALLOC_CTX *mem_ctx,
2087 const char *full_name,
2088 char **domain,
2089 char **user)
2091 const char *p = NULL;
2093 p = strchr_m(full_name, '\\');
2095 if (p != NULL) {
2096 *domain = talloc_strndup(mem_ctx, full_name,
2097 PTR_DIFF(p, full_name));
2098 *user = talloc_strdup(mem_ctx, p+1);
2099 } else {
2100 *domain = talloc_strdup(mem_ctx, "");
2101 *user = talloc_strdup(mem_ctx, full_name);
2105 /****************************************************************
2106 strip off leading '\\' from a hostname
2107 ****************************************************************/
2109 const char *strip_hostname(const char *s)
2111 if (!s) {
2112 return NULL;
2115 if (strlen_m(s) < 3) {
2116 return s;
2119 if (s[0] == '\\') s++;
2120 if (s[0] == '\\') s++;
2122 return s;
2125 bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result)
2127 if (!NT_STATUS_IS_OK(err1)) {
2128 *result = err1;
2129 return true;
2131 if (!NT_STATUS_IS_OK(err2)) {
2132 *result = err2;
2133 return true;
2135 return false;
2138 int timeval_to_msec(struct timeval t)
2140 return t.tv_sec * 1000 + (t.tv_usec+999) / 1000;
2143 /*******************************************************************
2144 Check a given DOS pathname is valid for a share.
2145 ********************************************************************/
2147 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
2149 char *ptr = NULL;
2151 if (!dos_pathname) {
2152 return NULL;
2155 ptr = talloc_strdup(ctx, dos_pathname);
2156 if (!ptr) {
2157 return NULL;
2159 /* Convert any '\' paths to '/' */
2160 unix_format(ptr);
2161 ptr = unix_clean_name(ctx, ptr);
2162 if (!ptr) {
2163 return NULL;
2166 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
2167 if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
2168 ptr += 2;
2170 /* Only absolute paths allowed. */
2171 if (*ptr != '/')
2172 return NULL;
2174 return ptr;
2177 /*******************************************************************
2178 Return True if the filename is one of the special executable types.
2179 ********************************************************************/
2181 bool is_executable(const char *fname)
2183 if ((fname = strrchr_m(fname,'.'))) {
2184 if (strequal(fname,".com") ||
2185 strequal(fname,".dll") ||
2186 strequal(fname,".exe") ||
2187 strequal(fname,".sym")) {
2188 return True;
2191 return False;
2194 /****************************************************************************
2195 Open a file with a share mode - old openX method - map into NTCreate.
2196 ****************************************************************************/
2198 bool map_open_params_to_ntcreate(const char *smb_base_fname,
2199 int deny_mode, int open_func,
2200 uint32 *paccess_mask,
2201 uint32 *pshare_mode,
2202 uint32 *pcreate_disposition,
2203 uint32 *pcreate_options,
2204 uint32_t *pprivate_flags)
2206 uint32 access_mask;
2207 uint32 share_mode;
2208 uint32 create_disposition;
2209 uint32 create_options = FILE_NON_DIRECTORY_FILE;
2210 uint32_t private_flags = 0;
2212 DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
2213 "open_func = 0x%x\n",
2214 smb_base_fname, (unsigned int)deny_mode,
2215 (unsigned int)open_func ));
2217 /* Create the NT compatible access_mask. */
2218 switch (GET_OPENX_MODE(deny_mode)) {
2219 case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
2220 case DOS_OPEN_RDONLY:
2221 access_mask = FILE_GENERIC_READ;
2222 break;
2223 case DOS_OPEN_WRONLY:
2224 access_mask = FILE_GENERIC_WRITE;
2225 break;
2226 case DOS_OPEN_RDWR:
2227 case DOS_OPEN_FCB:
2228 access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
2229 break;
2230 default:
2231 DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
2232 (unsigned int)GET_OPENX_MODE(deny_mode)));
2233 return False;
2236 /* Create the NT compatible create_disposition. */
2237 switch (open_func) {
2238 case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
2239 create_disposition = FILE_CREATE;
2240 break;
2242 case OPENX_FILE_EXISTS_OPEN:
2243 create_disposition = FILE_OPEN;
2244 break;
2246 case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
2247 create_disposition = FILE_OPEN_IF;
2248 break;
2250 case OPENX_FILE_EXISTS_TRUNCATE:
2251 create_disposition = FILE_OVERWRITE;
2252 break;
2254 case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
2255 create_disposition = FILE_OVERWRITE_IF;
2256 break;
2258 default:
2259 /* From samba4 - to be confirmed. */
2260 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
2261 create_disposition = FILE_CREATE;
2262 break;
2264 DEBUG(10,("map_open_params_to_ntcreate: bad "
2265 "open_func 0x%x\n", (unsigned int)open_func));
2266 return False;
2269 /* Create the NT compatible share modes. */
2270 switch (GET_DENY_MODE(deny_mode)) {
2271 case DENY_ALL:
2272 share_mode = FILE_SHARE_NONE;
2273 break;
2275 case DENY_WRITE:
2276 share_mode = FILE_SHARE_READ;
2277 break;
2279 case DENY_READ:
2280 share_mode = FILE_SHARE_WRITE;
2281 break;
2283 case DENY_NONE:
2284 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2285 break;
2287 case DENY_DOS:
2288 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
2289 if (is_executable(smb_base_fname)) {
2290 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2291 } else {
2292 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
2293 share_mode = FILE_SHARE_READ;
2294 } else {
2295 share_mode = FILE_SHARE_NONE;
2298 break;
2300 case DENY_FCB:
2301 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
2302 share_mode = FILE_SHARE_NONE;
2303 break;
2305 default:
2306 DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
2307 (unsigned int)GET_DENY_MODE(deny_mode) ));
2308 return False;
2311 DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
2312 "share_mode = 0x%x, create_disposition = 0x%x, "
2313 "create_options = 0x%x private_flags = 0x%x\n",
2314 smb_base_fname,
2315 (unsigned int)access_mask,
2316 (unsigned int)share_mode,
2317 (unsigned int)create_disposition,
2318 (unsigned int)create_options,
2319 (unsigned int)private_flags));
2321 if (paccess_mask) {
2322 *paccess_mask = access_mask;
2324 if (pshare_mode) {
2325 *pshare_mode = share_mode;
2327 if (pcreate_disposition) {
2328 *pcreate_disposition = create_disposition;
2330 if (pcreate_options) {
2331 *pcreate_options = create_options;
2333 if (pprivate_flags) {
2334 *pprivate_flags = private_flags;
2337 return True;
2341 /*************************************************************************
2342 Return a talloced copy of a struct security_unix_token. NULL on fail.
2343 *************************************************************************/
2345 struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct security_unix_token *tok)
2347 struct security_unix_token *cpy;
2349 cpy = talloc(ctx, struct security_unix_token);
2350 if (!cpy) {
2351 return NULL;
2354 cpy->uid = tok->uid;
2355 cpy->gid = tok->gid;
2356 cpy->ngroups = tok->ngroups;
2357 if (tok->ngroups) {
2358 /* Make this a talloc child of cpy. */
2359 cpy->groups = (gid_t *)talloc_memdup(
2360 cpy, tok->groups, tok->ngroups * sizeof(gid_t));
2361 if (!cpy->groups) {
2362 TALLOC_FREE(cpy);
2363 return NULL;
2365 } else {
2366 cpy->groups = NULL;
2368 return cpy;
2371 /****************************************************************************
2372 Check that a file matches a particular file type.
2373 ****************************************************************************/
2375 bool dir_check_ftype(uint32_t mode, uint32_t dirtype)
2377 uint32_t mask;
2379 /* Check the "may have" search bits. */
2380 if (((mode & ~dirtype) &
2381 (FILE_ATTRIBUTE_HIDDEN |
2382 FILE_ATTRIBUTE_SYSTEM |
2383 FILE_ATTRIBUTE_DIRECTORY)) != 0) {
2384 return false;
2387 /* Check the "must have" bits,
2388 which are the may have bits shifted eight */
2389 /* If must have bit is set, the file/dir can
2390 not be returned in search unless the matching
2391 file attribute is set */
2392 mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|
2393 FILE_ATTRIBUTE_ARCHIVE|
2394 FILE_ATTRIBUTE_READONLY|
2395 FILE_ATTRIBUTE_HIDDEN|
2396 FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
2397 if(mask) {
2398 if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|
2399 FILE_ATTRIBUTE_ARCHIVE|
2400 FILE_ATTRIBUTE_READONLY|
2401 FILE_ATTRIBUTE_HIDDEN|
2402 FILE_ATTRIBUTE_SYSTEM))) == mask) {
2403 /* check if matching attribute present */
2404 return true;
2405 } else {
2406 return false;
2410 return true;