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/>.
25 #include "system/passwd.h"
26 #include "system/filesys.h"
28 #include "ctdbd_conn.h"
29 #include "../lib/util/util_pw.h"
31 #include "libcli/security/security.h"
33 #include "lib/sys_rw.h"
34 #include "lib/sys_rw_data.h"
36 #ifdef HAVE_SYS_PRCTL_H
37 #include <sys/prctl.h>
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.
58 #if defined(GROUP_OBJ)
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)
76 void set_Protocol(enum protocol_types p)
81 static enum remote_arch_types ra_type = RA_UNKNOWN;
83 void gfree_all( void )
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)
103 if (sys_stat(fname, sbuf, fake_dir_create_times) != 0)
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)
116 if (sys_stat(fname, &st, false) != 0)
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) {
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)) {
160 /*******************************************************************
161 Show a smb message structure.
162 ********************************************************************/
164 void show_msg(const char *buf)
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",
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));
201 dump_data(10, (const uint8_t *)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_t **outbuf, DATA_BLOB blob)
223 size_t newlen = smb_len(*outbuf) + 4 + blob.length;
226 if (!(tmp = talloc_realloc(NULL, *outbuf, uint8, newlen))) {
227 DEBUG(0, ("talloc failed\n"));
232 memcpy(tmp + smb_len(tmp) + 4, blob.data, blob.length);
233 set_message_bcc((char *)tmp, smb_buflen(tmp) + blob.length);
237 /*******************************************************************
238 Reduce a file name, removing .. elements.
239 ********************************************************************/
241 static char *dos_clean_name(TALLOC_CTX *ctx, const char *s)
246 DEBUG(3,("dos_clean_name [%s]\n",s));
248 /* remove any double slashes */
249 str = talloc_all_string_sub(ctx, s, "\\\\", "\\");
254 /* Remove leading .\\ characters */
255 if(strncmp(str, ".\\", 2) == 0) {
256 trim_string(str, ".\\", NULL);
258 str = talloc_strdup(ctx, ".\\");
265 while ((p = strstr_m(str,"\\..\\")) != NULL) {
271 if ((p=strrchr_m(str,'\\')) != NULL) {
276 str = talloc_asprintf(ctx,
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)
298 DEBUG(3,("unix_clean_name [%s]\n",s));
300 /* remove any double slashes */
301 str = talloc_all_string_sub(ctx, s, "//","/");
306 /* Remove leading ./ characters */
307 if(strncmp(str, "./", 2) == 0) {
308 trim_string(str, "./", NULL);
310 str = talloc_strdup(ctx, "./");
317 while ((p = strstr_m(str,"/../")) != NULL) {
323 if ((p=strrchr_m(str,'/')) != NULL) {
328 str = talloc_asprintf(ctx,
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);
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)
359 if (pos == (off_t)-1) {
360 return write_data(fd, buffer, N);
362 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
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);
369 DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
378 return (ssize_t)total;
380 /* Use lseek and write_data. */
381 if (lseek(fd, pos, SEEK_SET) == -1) {
382 if (errno != ESPIPE) {
386 return write_data(fd, buffer, N);
390 static int reinit_after_fork_pipe[2] = { -1, -1 };
392 NTSTATUS init_before_fork(void)
396 ret = pipe(reinit_after_fork_pipe);
400 status = map_nt_error_from_unix_common(errno);
402 DEBUG(0, ("Error creating child_pipe: %s\n",
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,
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;
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);
469 smb_panic(__location__ ": Failed to add reinit_after_fork pipe event");
475 * For clustering, we need to re-init our ctdbd connection after the
478 status = messaging_reinit(msg_ctx);
479 if (!NT_STATUS_IS_OK(status)) {
480 DEBUG(0,("messaging_reinit() failed: %s\n",
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_t *num_elements,
496 void **array = (void **)_array;
498 if (*array_size < 0) {
502 if (*array == NULL) {
503 if (*array_size == 0) {
507 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
511 *array = TALLOC(mem_ctx, element_size * (*array_size));
512 if (*array == NULL) {
517 if (*num_elements == *array_size) {
520 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
524 *array = TALLOC_REALLOC(mem_ctx, *array,
525 element_size * (*array_size));
527 if (*array == NULL) {
532 memcpy((char *)(*array) + element_size*(*num_elements),
533 element, element_size);
543 /****************************************************************************
544 Get my own domain name, or "" if we have none.
545 ****************************************************************************/
547 char *get_mydnsdomname(TALLOC_CTX *ctx)
552 domname = get_mydnsfullname();
557 p = strchr_m(domname, '.');
560 return talloc_strdup(ctx, p);
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)
577 while(*p && !isspace(*p))
579 while(*p && isspace(*p))
582 return talloc_strdup(ctx, p);
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)
600 char *nis_map = (char *)lp_homedir_map();
602 char buffer[NIS_MAXATTRVAL + 1];
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)));
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);
623 nis_freeresult(result);
626 value = talloc_string_sub(ctx,
633 nis_freeresult(result);
636 value = strip_mount_options(ctx, value);
637 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n",
642 #else /* WITH_NISPLUS_HOME */
644 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
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)));
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);
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"));
677 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
678 yperr_string(nis_error), user_name, nis_map));
682 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, value));
686 #endif /* WITH_NISPLUS_HOME */
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();
702 struct passwd *pass = NULL;
704 pass = getpwuid_alloc(ctx,uid);
706 name = talloc_strdup(ctx,pass->pw_name);
709 name = talloc_asprintf(ctx,
716 /*******************************************************************
717 Convert a gid into a group name.
718 ********************************************************************/
720 char *gidtoname(gid_t gid)
726 return talloc_strdup(talloc_tos(), grp->gr_name);
729 return talloc_asprintf(talloc_tos(),
735 /*******************************************************************
736 Convert a user name into a uid.
737 ********************************************************************/
739 uid_t nametouid(const char *name)
745 pass = Get_Pwnam_alloc(talloc_tos(), name);
752 u = (uid_t)strtol(name, &p, 0);
753 if ((p != name) && (*p == '\0'))
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)
769 g = (gid_t)strtol(name, &p, 0);
770 if ((p != name) && (*p == '\0'))
773 grp = getgrnam(name);
779 /*******************************************************************
780 Something really nasty happened - panic !
781 ********************************************************************/
783 void smb_panic_s3(const char *why)
788 DEBUG(0,("PANIC (pid %llu): %s\n",
789 (unsigned long long)getpid(), why));
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);
799 cmd = lp_panic_action(talloc_tos());
801 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
802 result = system(cmd);
805 DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
808 DEBUG(0, ("smb_panic(): action returned status %d\n",
809 WEXITSTATUS(result)));
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>
825 #ifdef HAVE_EXECINFO_H
826 #include <execinfo.h>
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
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"));
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) ) {
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));
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));
883 } while (unw_step(&cursor) > 0);
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) {
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 */
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];
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.
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]));
950 DEBUG(0, ("unable to produce a stack trace on this platform\n"));
954 /*******************************************************************
955 A readdir wrapper which just returns the file name.
956 ********************************************************************/
958 const char *readdirname(DIR *p)
966 ptr = (struct dirent *)readdir(p);
977 #ifdef HAVE_BROKEN_READDIR_NAME
978 /* using /usr/ucb/cc is BAD */
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))) {
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;
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"));
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"));
1023 DEBUG(8,("is_in_path: match not found\n"));
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
1036 ********************************************************************/
1038 void set_namearray(name_compare_entry **ppname_array, const char *namelist_in)
1044 int num_entries = 0;
1047 (*ppname_array) = NULL;
1049 if((namelist_in == NULL ) || ((namelist_in != NULL) && (*namelist_in == '\0')))
1052 namelist = talloc_strdup(talloc_tos(), namelist_in);
1053 if (namelist == NULL) {
1054 DEBUG(0,("set_namearray: talloc fail\n"));
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
1066 while(nameptr <= namelist_end) {
1067 if ( *nameptr == '/' ) {
1068 /* cope with multiple (useless) /s) */
1072 /* anything left? */
1073 if ( *nameptr == '\0' )
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);
1082 /* next segment please */
1083 nameptr = name_end + 1;
1088 if(num_entries == 0) {
1089 talloc_free(namelist);
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);
1099 /* Now copy out the names */
1102 while(nameptr <= namelist_end) {
1103 if ( *nameptr == '/' ) {
1104 /* cope with multiple (useless) /s) */
1108 /* anything left? */
1109 if ( *nameptr == '\0' )
1112 /* find the next '/' or consume remaining */
1113 name_end = strchr_m(nameptr, '/');
1114 if (name_end != NULL) {
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);
1125 if (name_end == NULL) {
1126 /* Point nameptr at the terminating '\0' */
1127 nameptr += strlen(nameptr);
1129 /* next segment please */
1130 nameptr = name_end + 1;
1135 (*ppname_array)[i].name = NULL;
1137 talloc_free(namelist);
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)
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;
1165 ret = sys_fcntl_ptr(fd,F_GETLK,&lock);
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)));
1175 *ptype = lock.l_type;
1176 *poffset = lock.l_start;
1177 *pcount = lock.l_len;
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));
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)
1198 for (n=0; my_netbios_names(n); n++) {
1199 const char *nbt_name = my_netbios_names(n);
1201 if (strncasecmp_m(nbt_name, s, strlen(nbt_name)) == 0) {
1206 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1210 /*******************************************************************
1211 we distinguish between 2K and XP by the "Native Lan Manager" string
1212 WinXP => "Windows 2002 5.1"
1213 WinXP 64bit => "Windows XP 5.2"
1214 Win2k => "Windows 2000 5.0"
1215 NT4 => "Windows NT 4.0"
1216 Win9x => "Windows 4.0"
1217 Windows 2003 doesn't set the native lan manager string but
1218 they do set the domain to "Windows 2003 5.2" (probably a bug).
1219 ********************************************************************/
1221 void ra_lanman_string( const char *native_lanman )
1223 if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1224 set_remote_arch( RA_WINXP );
1225 else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1226 set_remote_arch( RA_WINXP64 );
1227 else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1228 set_remote_arch( RA_WIN2K3 );
1231 static const char *remote_arch_str;
1233 const char *get_remote_arch_str(void)
1235 if (!remote_arch_str) {
1238 return remote_arch_str;
1241 /*******************************************************************
1242 Set the horrid remote_arch string based on an enum.
1243 ********************************************************************/
1245 void set_remote_arch(enum remote_arch_types type)
1250 remote_arch_str = "WfWg";
1253 remote_arch_str = "OS2";
1256 remote_arch_str = "Win95";
1259 remote_arch_str = "WinNT";
1262 remote_arch_str = "Win2K";
1265 remote_arch_str = "WinXP";
1268 remote_arch_str = "WinXP64";
1271 remote_arch_str = "Win2K3";
1274 remote_arch_str = "Vista";
1277 remote_arch_str = "Samba";
1280 remote_arch_str = "CIFSFS";
1283 remote_arch_str = "OSX";
1286 ra_type = RA_UNKNOWN;
1287 remote_arch_str = "UNKNOWN";
1291 DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1295 /*******************************************************************
1296 Get the remote_arch type.
1297 ********************************************************************/
1299 enum remote_arch_types get_remote_arch(void)
1304 const char *tab_depth(int level, int depth)
1306 if( CHECK_DEBUGLVL(level) ) {
1307 dbgtext("%*s", depth*4, "");
1312 /*****************************************************************************
1313 Provide a checksum on a string
1315 Input: s - the null-terminated character string for which the checksum
1318 Output: The checksum value calculated for s.
1319 *****************************************************************************/
1321 int str_checksum(const char *s)
1327 key = (TDB_DATA) { .dptr = discard_const_p(uint8_t, s),
1328 .dsize = strlen(s) };
1330 return tdb_jenkins_hash(&key);
1333 /*****************************************************************
1334 Zero a memory area then free it. Used to catch bugs faster.
1335 *****************************************************************/
1337 void zero_free(void *p, size_t size)
1343 /*****************************************************************
1344 Set our open file limit to a requested max and return the limit.
1345 *****************************************************************/
1347 int set_maxfiles(int requested_max)
1349 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1351 int saved_current_limit;
1353 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1354 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1357 return requested_max;
1361 * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1362 * account for the extra fd we need
1363 * as well as the log files and standard
1364 * handles etc. Save the limit we want to set in case
1365 * we are running on an OS that doesn't support this limit (AIX)
1366 * which always returns RLIM_INFINITY for rlp.rlim_max.
1369 /* Try raising the hard (max) limit to the requested amount. */
1371 #if defined(RLIM_INFINITY)
1372 if (rlp.rlim_max != RLIM_INFINITY) {
1373 int orig_max = rlp.rlim_max;
1375 if ( rlp.rlim_max < requested_max )
1376 rlp.rlim_max = requested_max;
1378 /* This failing is not an error - many systems (Linux) don't
1379 support our default request of 10,000 open files. JRA. */
1381 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1382 DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n",
1383 (int)rlp.rlim_max, strerror(errno) ));
1385 /* Set failed - restore original value from get. */
1386 rlp.rlim_max = orig_max;
1391 /* Now try setting the soft (current) limit. */
1393 saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1395 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1396 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
1397 (int)rlp.rlim_cur, strerror(errno) ));
1399 return saved_current_limit;
1402 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1403 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1406 return saved_current_limit;
1409 #if defined(RLIM_INFINITY)
1410 if(rlp.rlim_cur == RLIM_INFINITY)
1411 return saved_current_limit;
1414 if((int)rlp.rlim_cur > saved_current_limit)
1415 return saved_current_limit;
1417 return rlp.rlim_cur;
1418 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1420 * No way to know - just guess...
1422 return requested_max;
1426 /*****************************************************************
1427 malloc that aborts with smb_panic on fail or zero size.
1428 *****************************************************************/
1430 void *smb_xmalloc_array(size_t size, unsigned int count)
1434 smb_panic("smb_xmalloc_array: called with zero size");
1436 if (count >= MAX_ALLOC_SIZE/size) {
1437 smb_panic("smb_xmalloc_array: alloc size too large");
1439 if ((p = SMB_MALLOC(size*count)) == NULL) {
1440 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1441 (unsigned long)size, (unsigned long)count));
1442 smb_panic("smb_xmalloc_array: malloc failed");
1448 vasprintf that aborts on malloc fail
1451 int smb_xvasprintf(char **ptr, const char *format, va_list ap)
1458 n = vasprintf(ptr, format, ap2);
1460 if (n == -1 || ! *ptr) {
1461 smb_panic("smb_xvasprintf: out of memory");
1466 /*****************************************************************
1467 Get local hostname and cache result.
1468 *****************************************************************/
1470 char *myhostname(void)
1474 ret = get_myname(NULL);
1479 /*****************************************************************
1480 Get local hostname and cache result.
1481 *****************************************************************/
1483 char *myhostname_upper(void)
1487 char *name = get_myname(NULL);
1491 ret = strupper_talloc(NULL, name);
1498 * @brief Returns an absolute path to a file concatenating the provided
1499 * @a rootpath and @a basename
1501 * @param name Filename, relative to @a rootpath
1503 * @retval Pointer to a string containing the full path.
1506 static char *xx_path(const char *name, const char *rootpath)
1510 fname = talloc_strdup(talloc_tos(), rootpath);
1514 trim_string(fname,"","/");
1516 if (!directory_exist(fname)) {
1517 if (mkdir(fname,0755) == -1) {
1518 /* Did someone else win the race ? */
1519 if (errno != EEXIST) {
1520 DEBUG(1, ("Unable to create directory %s for file %s. "
1521 "Error was %s\n", fname, name, strerror(errno)));
1527 return talloc_asprintf_append(fname, "/%s", name);
1531 * @brief Returns an absolute path to a file in the Samba lock directory.
1533 * @param name File to find, relative to LOCKDIR.
1535 * @retval Pointer to a talloc'ed string containing the full path.
1538 char *lock_path(const char *name)
1540 return xx_path(name, lp_lock_directory());
1544 * @brief Returns an absolute path to a file in the Samba state directory.
1546 * @param name File to find, relative to STATEDIR.
1548 * @retval Pointer to a talloc'ed string containing the full path.
1551 char *state_path(const char *name)
1553 return xx_path(name, lp_state_directory());
1557 * @brief Returns an absolute path to a file in the Samba cache directory.
1559 * @param name File to find, relative to CACHEDIR.
1561 * @retval Pointer to a talloc'ed string containing the full path.
1564 char *cache_path(const char *name)
1566 return xx_path(name, lp_cache_directory());
1569 /*******************************************************************
1570 Given a filename - get its directory name
1571 ********************************************************************/
1573 bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
1579 p = strrchr_m(dir, '/'); /* Find final '/', if any */
1582 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
1593 if (!(*parent = (char *)talloc_memdup(mem_ctx, dir, len+1))) {
1596 (*parent)[len] = '\0';
1604 /*******************************************************************
1605 Determine if a pattern contains any Microsoft wildcard characters.
1606 *******************************************************************/
1608 bool ms_has_wild(const char *s)
1612 if (lp_posix_pathnames()) {
1613 /* With posix pathnames no characters are wild. */
1617 while ((c = *s++)) {
1630 bool ms_has_wild_w(const smb_ucs2_t *s)
1633 if (!s) return False;
1634 while ((c = *s++)) {
1636 case UCS2_CHAR('*'):
1637 case UCS2_CHAR('?'):
1638 case UCS2_CHAR('<'):
1639 case UCS2_CHAR('>'):
1640 case UCS2_CHAR('"'):
1647 /*******************************************************************
1648 A wrapper that handles case sensitivity and the special handling
1650 *******************************************************************/
1652 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
1654 if (ISDOTDOT(string))
1659 return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
1662 /*******************************************************************
1663 A wrapper that handles case sensitivity and the special handling
1664 of the ".." name. Varient that is only called by old search code which requires
1665 pattern translation.
1666 *******************************************************************/
1668 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
1670 if (ISDOTDOT(string))
1675 return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
1678 /*******************************************************************
1679 A wrapper that handles a list of patters and calls mask_match()
1680 on each. Returns True if any of the patterns match.
1681 *******************************************************************/
1683 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
1685 while (listLen-- > 0) {
1686 if (mask_match(string, *list++, is_case_sensitive))
1692 /*********************************************************
1693 Recursive routine that is called by unix_wild_match.
1694 *********************************************************/
1696 static bool unix_do_match(const char *regexp, const char *str)
1700 for( p = regexp; *p && *str; ) {
1711 * Look for a character matching
1712 * the one after the '*'.
1716 return true; /* Automatic match */
1719 while(*str && (*p != *str))
1723 * Patch from weidel@multichart.de. In the case of the regexp
1724 * '*XX*' we want to ensure there are at least 2 'X' characters
1725 * in the string after the '*' for a match to be made.
1732 * Eat all the characters that match, but count how many there were.
1735 while(*str && (*p == *str)) {
1741 * Now check that if the regexp had n identical characters that
1742 * matchcount had at least that many matches.
1745 while ( *(p+1) && (*(p+1) == *p)) {
1750 if ( matchcount <= 0 )
1754 str--; /* We've eaten the match char after the '*' */
1756 if(unix_do_match(p, str))
1778 if (!*p && str[0] == '.' && str[1] == 0)
1781 if (!*str && *p == '?') {
1787 if(!*str && (*p == '*' && p[1] == '\0'))
1793 /*******************************************************************
1794 Simple case insensitive interface to a UNIX wildcard matcher.
1795 Returns True if match, False if not.
1796 *******************************************************************/
1798 bool unix_wild_match(const char *pattern, const char *string)
1800 TALLOC_CTX *ctx = talloc_stackframe();
1806 p2 = talloc_strdup(ctx,pattern);
1807 s2 = talloc_strdup(ctx,string);
1812 if (!strlower_m(p2)) {
1816 if (!strlower_m(s2)) {
1821 /* Remove any *? and ** from the pattern as they are meaningless */
1822 for(p = p2; *p; p++) {
1823 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
1824 memmove(&p[1], &p[2], strlen(&p[2])+1);
1828 if (strequal(p2,"*")) {
1833 ret = unix_do_match(p2, s2);
1838 /**********************************************************************
1839 Converts a name to a fully qualified domain name.
1840 Returns true if lookup succeeded, false if not (then fqdn is set to name)
1841 Note we deliberately use gethostbyname here, not getaddrinfo as we want
1842 to examine the h_aliases and I don't know how to do that with getaddrinfo.
1843 ***********************************************************************/
1845 bool name_to_fqdn(fstring fqdn, const char *name)
1848 struct hostent *hp = gethostbyname(name);
1850 if (!hp || !hp->h_name || !*hp->h_name) {
1851 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
1852 fstrcpy(fqdn, name);
1856 /* Find out if the fqdn is returned as an alias
1857 * to cope with /etc/hosts files where the first
1858 * name is not the fqdn but the short name */
1859 if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
1861 for (i = 0; hp->h_aliases[i]; i++) {
1862 if (strchr_m(hp->h_aliases[i], '.')) {
1863 full = hp->h_aliases[i];
1868 if (full && (strcasecmp_m(full, "localhost.localdomain") == 0)) {
1869 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
1870 DEBUGADD(1, (" Specifying the machine hostname for address 127.0.0.1 may lead\n"));
1871 DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n"));
1872 DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n"));
1879 DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
1880 fstrcpy(fqdn, full);
1884 /**********************************************************************
1885 Append a DATA_BLOB to a talloc'ed object
1886 ***********************************************************************/
1888 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
1890 size_t old_size = 0;
1893 if (blob.length == 0) {
1898 old_size = talloc_get_size(buf);
1901 result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
1902 if (result == NULL) {
1906 memcpy(result + old_size, blob.data, blob.length);
1910 uint32_t map_share_mode_to_deny_mode(uint32_t share_access, uint32_t private_options)
1912 switch (share_access & ~FILE_SHARE_DELETE) {
1913 case FILE_SHARE_NONE:
1915 case FILE_SHARE_READ:
1917 case FILE_SHARE_WRITE:
1919 case FILE_SHARE_READ|FILE_SHARE_WRITE:
1922 if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
1924 } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
1931 pid_t procid_to_pid(const struct server_id *proc)
1936 static uint32_t my_vnn = NONCLUSTER_VNN;
1938 void set_my_vnn(uint32_t vnn)
1940 DEBUG(10, ("vnn pid %d = %u\n", (int)getpid(), (unsigned int)vnn));
1944 uint32_t get_my_vnn(void)
1949 static uint64_t my_unique_id = 0;
1951 void set_my_unique_id(uint64_t unique_id)
1953 my_unique_id = unique_id;
1956 struct server_id pid_to_procid(pid_t pid)
1958 struct server_id result;
1961 result.unique_id = my_unique_id;
1962 result.vnn = my_vnn;
1966 struct server_id procid_self(void)
1968 return pid_to_procid(getpid());
1971 bool procid_is_me(const struct server_id *pid)
1973 if (pid->pid != getpid())
1975 if (pid->task_id != 0)
1977 if (pid->vnn != my_vnn)
1982 struct server_id interpret_pid(const char *pid_string)
1984 return server_id_from_string(get_my_vnn(), pid_string);
1987 bool procid_valid(const struct server_id *pid)
1989 return (pid->pid != (uint64_t)-1);
1992 bool procid_is_local(const struct server_id *pid)
1994 return pid->vnn == my_vnn;
1997 /****************************************************************
1998 Check if an offset into a buffer is safe.
1999 If this returns True it's safe to indirect into the byte at
2001 ****************************************************************/
2003 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2005 const char *end_base = buf_base + buf_len;
2006 char *end_ptr = ptr + off;
2008 if (!buf_base || !ptr) {
2012 if (end_base < buf_base || end_ptr < ptr) {
2013 return False; /* wrap. */
2016 if (end_ptr < end_base) {
2022 /****************************************************************
2023 Return a safe pointer into a buffer, or NULL.
2024 ****************************************************************/
2026 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2028 return is_offset_safe(buf_base, buf_len, ptr, off) ?
2032 /****************************************************************
2033 Return a safe pointer into a string within a buffer, or NULL.
2034 ****************************************************************/
2036 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2038 if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2041 /* Check if a valid string exists at this offset. */
2042 if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2048 /****************************************************************
2049 Return an SVAL at a pointer, or failval if beyond the end.
2050 ****************************************************************/
2052 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2055 * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2058 if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2061 return SVAL(ptr,off);
2064 /****************************************************************
2065 Return an IVAL at a pointer, or failval if beyond the end.
2066 ****************************************************************/
2068 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2071 * Note we use off+3 here, not off+4 as IVAL accesses
2072 * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2074 if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2077 return IVAL(ptr,off);
2080 /****************************************************************
2081 Split DOM\user into DOM and user. Do not mix with winbind variants of that
2082 call (they take care of winbind separator and other winbind specific settings).
2083 ****************************************************************/
2085 void split_domain_user(TALLOC_CTX *mem_ctx,
2086 const char *full_name,
2090 const char *p = NULL;
2092 p = strchr_m(full_name, '\\');
2095 *domain = talloc_strndup(mem_ctx, full_name,
2096 PTR_DIFF(p, full_name));
2097 *user = talloc_strdup(mem_ctx, p+1);
2099 *domain = talloc_strdup(mem_ctx, "");
2100 *user = talloc_strdup(mem_ctx, full_name);
2104 /****************************************************************
2105 strip off leading '\\' from a hostname
2106 ****************************************************************/
2108 const char *strip_hostname(const char *s)
2114 if (strlen_m(s) < 3) {
2118 if (s[0] == '\\') s++;
2119 if (s[0] == '\\') s++;
2124 bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result)
2126 if (!NT_STATUS_IS_OK(err1)) {
2130 if (!NT_STATUS_IS_OK(err2)) {
2137 int timeval_to_msec(struct timeval t)
2139 return t.tv_sec * 1000 + (t.tv_usec+999) / 1000;
2142 /*******************************************************************
2143 Check a given DOS pathname is valid for a share.
2144 ********************************************************************/
2146 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
2150 if (!dos_pathname) {
2154 ptr = talloc_strdup(ctx, dos_pathname);
2158 /* Convert any '\' paths to '/' */
2160 ptr = unix_clean_name(ctx, ptr);
2165 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
2166 if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
2169 /* Only absolute paths allowed. */
2176 /*******************************************************************
2177 Return True if the filename is one of the special executable types.
2178 ********************************************************************/
2180 bool is_executable(const char *fname)
2182 if ((fname = strrchr_m(fname,'.'))) {
2183 if (strequal(fname,".com") ||
2184 strequal(fname,".dll") ||
2185 strequal(fname,".exe") ||
2186 strequal(fname,".sym")) {
2193 /****************************************************************************
2194 Open a file with a share mode - old openX method - map into NTCreate.
2195 ****************************************************************************/
2197 bool map_open_params_to_ntcreate(const char *smb_base_fname,
2198 int deny_mode, int open_func,
2199 uint32_t *paccess_mask,
2200 uint32_t *pshare_mode,
2201 uint32_t *pcreate_disposition,
2202 uint32_t *pcreate_options,
2203 uint32_t *pprivate_flags)
2205 uint32_t access_mask;
2206 uint32_t share_mode;
2207 uint32_t create_disposition;
2208 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
2209 uint32_t private_flags = 0;
2211 DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
2212 "open_func = 0x%x\n",
2213 smb_base_fname, (unsigned int)deny_mode,
2214 (unsigned int)open_func ));
2216 /* Create the NT compatible access_mask. */
2217 switch (GET_OPENX_MODE(deny_mode)) {
2218 case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
2219 case DOS_OPEN_RDONLY:
2220 access_mask = FILE_GENERIC_READ;
2222 case DOS_OPEN_WRONLY:
2223 access_mask = FILE_GENERIC_WRITE;
2227 access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
2230 DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
2231 (unsigned int)GET_OPENX_MODE(deny_mode)));
2235 /* Create the NT compatible create_disposition. */
2236 switch (open_func) {
2237 case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
2238 create_disposition = FILE_CREATE;
2241 case OPENX_FILE_EXISTS_OPEN:
2242 create_disposition = FILE_OPEN;
2245 case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
2246 create_disposition = FILE_OPEN_IF;
2249 case OPENX_FILE_EXISTS_TRUNCATE:
2250 create_disposition = FILE_OVERWRITE;
2253 case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
2254 create_disposition = FILE_OVERWRITE_IF;
2258 /* From samba4 - to be confirmed. */
2259 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
2260 create_disposition = FILE_CREATE;
2263 DEBUG(10,("map_open_params_to_ntcreate: bad "
2264 "open_func 0x%x\n", (unsigned int)open_func));
2268 /* Create the NT compatible share modes. */
2269 switch (GET_DENY_MODE(deny_mode)) {
2271 share_mode = FILE_SHARE_NONE;
2275 share_mode = FILE_SHARE_READ;
2279 share_mode = FILE_SHARE_WRITE;
2283 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2287 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
2288 if (is_executable(smb_base_fname)) {
2289 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2291 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
2292 share_mode = FILE_SHARE_READ;
2294 share_mode = FILE_SHARE_NONE;
2300 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
2301 share_mode = FILE_SHARE_NONE;
2305 DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
2306 (unsigned int)GET_DENY_MODE(deny_mode) ));
2310 DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
2311 "share_mode = 0x%x, create_disposition = 0x%x, "
2312 "create_options = 0x%x private_flags = 0x%x\n",
2314 (unsigned int)access_mask,
2315 (unsigned int)share_mode,
2316 (unsigned int)create_disposition,
2317 (unsigned int)create_options,
2318 (unsigned int)private_flags));
2321 *paccess_mask = access_mask;
2324 *pshare_mode = share_mode;
2326 if (pcreate_disposition) {
2327 *pcreate_disposition = create_disposition;
2329 if (pcreate_options) {
2330 *pcreate_options = create_options;
2332 if (pprivate_flags) {
2333 *pprivate_flags = private_flags;
2340 /*************************************************************************
2341 Return a talloced copy of a struct security_unix_token. NULL on fail.
2342 *************************************************************************/
2344 struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct security_unix_token *tok)
2346 struct security_unix_token *cpy;
2348 cpy = talloc(ctx, struct security_unix_token);
2353 cpy->uid = tok->uid;
2354 cpy->gid = tok->gid;
2355 cpy->ngroups = tok->ngroups;
2357 /* Make this a talloc child of cpy. */
2358 cpy->groups = (gid_t *)talloc_memdup(
2359 cpy, tok->groups, tok->ngroups * sizeof(gid_t));
2370 /****************************************************************************
2371 Check that a file matches a particular file type.
2372 ****************************************************************************/
2374 bool dir_check_ftype(uint32_t mode, uint32_t dirtype)
2378 /* Check the "may have" search bits. */
2379 if (((mode & ~dirtype) &
2380 (FILE_ATTRIBUTE_HIDDEN |
2381 FILE_ATTRIBUTE_SYSTEM |
2382 FILE_ATTRIBUTE_DIRECTORY)) != 0) {
2386 /* Check the "must have" bits,
2387 which are the may have bits shifted eight */
2388 /* If must have bit is set, the file/dir can
2389 not be returned in search unless the matching
2390 file attribute is set */
2391 mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|
2392 FILE_ATTRIBUTE_ARCHIVE|
2393 FILE_ATTRIBUTE_READONLY|
2394 FILE_ATTRIBUTE_HIDDEN|
2395 FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
2397 if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|
2398 FILE_ATTRIBUTE_ARCHIVE|
2399 FILE_ATTRIBUTE_READONLY|
2400 FILE_ATTRIBUTE_HIDDEN|
2401 FILE_ATTRIBUTE_SYSTEM))) == mask) {
2402 /* check if matching attribute present */