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