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 <ccan/hash/hash.h>
32 #include "libcli/security/security.h"
34 #ifdef HAVE_SYS_PRCTL_H
35 #include <sys/prctl.h>
38 /* Max allowable allococation - 256mb - 0x10000000 */
39 #define MAX_ALLOC_SIZE (1024*1024*256)
41 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
42 #ifdef WITH_NISPLUS_HOME
43 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
45 * The following lines are needed due to buggy include files
46 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
47 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
48 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
49 * an enum in /usr/include/rpcsvc/nis.h.
56 #if defined(GROUP_OBJ)
60 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
62 #include <rpcsvc/nis.h>
64 #endif /* WITH_NISPLUS_HOME */
65 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
67 static enum protocol_types Protocol
= PROTOCOL_COREPLUS
;
69 enum protocol_types
get_Protocol(void)
74 void set_Protocol(enum protocol_types p
)
79 static enum remote_arch_types ra_type
= RA_UNKNOWN
;
81 void gfree_all( void )
90 /*******************************************************************
91 Check if a file exists - call vfs_file_exist for samba files.
92 ********************************************************************/
94 bool file_exist_stat(const char *fname
,SMB_STRUCT_STAT
*sbuf
,
95 bool fake_dir_create_times
)
101 if (sys_stat(fname
, sbuf
, fake_dir_create_times
) != 0)
104 return((S_ISREG(sbuf
->st_ex_mode
)) || (S_ISFIFO(sbuf
->st_ex_mode
)));
107 /*******************************************************************
108 Check if a unix domain socket exists - call vfs_file_exist for samba files.
109 ********************************************************************/
111 bool socket_exist(const char *fname
)
114 if (sys_stat(fname
, &st
, false) != 0)
117 return S_ISSOCK(st
.st_ex_mode
);
120 /*******************************************************************
121 Returns the size in bytes of the named given the stat struct.
122 ********************************************************************/
124 uint64_t get_file_size_stat(const SMB_STRUCT_STAT
*sbuf
)
126 return sbuf
->st_ex_size
;
129 /****************************************************************************
130 Check two stats have identical dev and ino fields.
131 ****************************************************************************/
133 bool check_same_dev_ino(const SMB_STRUCT_STAT
*sbuf1
,
134 const SMB_STRUCT_STAT
*sbuf2
)
136 if (sbuf1
->st_ex_dev
!= sbuf2
->st_ex_dev
||
137 sbuf1
->st_ex_ino
!= sbuf2
->st_ex_ino
) {
143 /****************************************************************************
144 Check if a stat struct is identical for use.
145 ****************************************************************************/
147 bool check_same_stat(const SMB_STRUCT_STAT
*sbuf1
,
148 const SMB_STRUCT_STAT
*sbuf2
)
150 if (sbuf1
->st_ex_uid
!= sbuf2
->st_ex_uid
||
151 sbuf1
->st_ex_gid
!= sbuf2
->st_ex_gid
||
152 !check_same_dev_ino(sbuf1
, sbuf2
)) {
158 /*******************************************************************
159 Show a smb message structure.
160 ********************************************************************/
162 void show_msg(const char *buf
)
170 DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
172 (int)CVAL(buf
,smb_com
),
173 (int)CVAL(buf
,smb_rcls
),
174 (int)CVAL(buf
,smb_reh
),
175 (int)SVAL(buf
,smb_err
),
176 (int)CVAL(buf
,smb_flg
),
177 (int)SVAL(buf
,smb_flg2
)));
178 DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
179 (int)SVAL(buf
,smb_tid
),
180 (int)SVAL(buf
,smb_pid
),
181 (int)SVAL(buf
,smb_uid
),
182 (int)SVAL(buf
,smb_mid
)));
183 DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf
,smb_wct
)));
185 for (i
=0;i
<(int)CVAL(buf
,smb_wct
);i
++)
186 DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i
,
187 SVAL(buf
,smb_vwv
+2*i
),SVAL(buf
,smb_vwv
+2*i
)));
189 bcc
= (int)SVAL(buf
,smb_vwv
+2*(CVAL(buf
,smb_wct
)));
191 DEBUGADD(5,("smb_bcc=%d\n",bcc
));
199 dump_data(10, (const uint8
*)smb_buf_const(buf
), bcc
);
202 /*******************************************************************
203 Setup only the byte count for a smb message.
204 ********************************************************************/
206 int set_message_bcc(char *buf
,int num_bytes
)
208 int num_words
= CVAL(buf
,smb_wct
);
209 SSVAL(buf
,smb_vwv
+ num_words
*SIZEOFWORD
,num_bytes
);
210 _smb_setlen(buf
,smb_size
+ num_words
*2 + num_bytes
- 4);
211 return (smb_size
+ num_words
*2 + num_bytes
);
214 /*******************************************************************
215 Add a data blob to the end of a smb_buf, adjusting bcc and smb_len.
216 Return the bytes added
217 ********************************************************************/
219 ssize_t
message_push_blob(uint8
**outbuf
, DATA_BLOB blob
)
221 size_t newlen
= smb_len(*outbuf
) + 4 + blob
.length
;
224 if (!(tmp
= talloc_realloc(NULL
, *outbuf
, uint8
, newlen
))) {
225 DEBUG(0, ("talloc failed\n"));
230 memcpy(tmp
+ smb_len(tmp
) + 4, blob
.data
, blob
.length
);
231 set_message_bcc((char *)tmp
, smb_buflen(tmp
) + blob
.length
);
235 /*******************************************************************
236 Reduce a file name, removing .. elements.
237 ********************************************************************/
239 static char *dos_clean_name(TALLOC_CTX
*ctx
, const char *s
)
244 DEBUG(3,("dos_clean_name [%s]\n",s
));
246 /* remove any double slashes */
247 str
= talloc_all_string_sub(ctx
, s
, "\\\\", "\\");
252 /* Remove leading .\\ characters */
253 if(strncmp(str
, ".\\", 2) == 0) {
254 trim_string(str
, ".\\", NULL
);
256 str
= talloc_strdup(ctx
, ".\\");
263 while ((p
= strstr_m(str
,"\\..\\")) != NULL
) {
269 if ((p
=strrchr_m(str
,'\\')) != NULL
) {
274 str
= talloc_asprintf(ctx
,
283 trim_string(str
,NULL
,"\\..");
284 return talloc_all_string_sub(ctx
, str
, "\\.\\", "\\");
287 /*******************************************************************
288 Reduce a file name, removing .. elements.
289 ********************************************************************/
291 char *unix_clean_name(TALLOC_CTX
*ctx
, const char *s
)
296 DEBUG(3,("unix_clean_name [%s]\n",s
));
298 /* remove any double slashes */
299 str
= talloc_all_string_sub(ctx
, s
, "//","/");
304 /* Remove leading ./ characters */
305 if(strncmp(str
, "./", 2) == 0) {
306 trim_string(str
, "./", NULL
);
308 str
= talloc_strdup(ctx
, "./");
315 while ((p
= strstr_m(str
,"/../")) != NULL
) {
321 if ((p
=strrchr_m(str
,'/')) != NULL
) {
326 str
= talloc_asprintf(ctx
,
335 trim_string(str
,NULL
,"/..");
336 return talloc_all_string_sub(ctx
, str
, "/./", "/");
339 char *clean_name(TALLOC_CTX
*ctx
, const char *s
)
341 char *str
= dos_clean_name(ctx
, s
);
345 return unix_clean_name(ctx
, str
);
348 /*******************************************************************
349 Write data into an fd at a given offset. Ignore seek errors.
350 ********************************************************************/
352 ssize_t
write_data_at_offset(int fd
, const char *buffer
, size_t N
, off_t pos
)
357 if (pos
== (off_t
)-1) {
358 return write_data(fd
, buffer
, N
);
360 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
362 ret
= sys_pwrite(fd
,buffer
+ total
,N
- total
, pos
);
363 if (ret
== -1 && errno
== ESPIPE
) {
364 return write_data(fd
, buffer
+ total
,N
- total
);
367 DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno
) ));
376 return (ssize_t
)total
;
378 /* Use lseek and write_data. */
379 if (lseek(fd
, pos
, SEEK_SET
) == -1) {
380 if (errno
!= ESPIPE
) {
384 return write_data(fd
, buffer
, N
);
388 static int reinit_after_fork_pipe
[2] = { -1, -1 };
390 NTSTATUS
init_before_fork(void)
394 ret
= pipe(reinit_after_fork_pipe
);
398 status
= map_nt_error_from_unix_common(errno
);
400 DEBUG(0, ("Error creating child_pipe: %s\n",
410 * Detect died parent by detecting EOF on the pipe
412 static void reinit_after_fork_pipe_handler(struct tevent_context
*ev
,
413 struct tevent_fd
*fde
,
419 if (sys_read(reinit_after_fork_pipe
[0], &c
, 1) != 1) {
421 * we have reached EOF on stdin, which means the
422 * parent has exited. Shutdown the server
424 (void)kill(getpid(), SIGTERM
);
429 NTSTATUS
reinit_after_fork(struct messaging_context
*msg_ctx
,
430 struct event_context
*ev_ctx
,
431 bool parent_longlived
)
433 NTSTATUS status
= NT_STATUS_OK
;
435 if (reinit_after_fork_pipe
[1] != -1) {
436 close(reinit_after_fork_pipe
[1]);
437 reinit_after_fork_pipe
[1] = -1;
440 /* Reset the state of the random
441 * number generation system, so
442 * children do not get the same random
443 * numbers as each other */
444 set_need_random_reseed();
446 /* tdb needs special fork handling */
447 if (tdb_reopen_all(parent_longlived
? 1 : 0) != 0) {
448 DEBUG(0,("tdb_reopen_all failed.\n"));
449 status
= NT_STATUS_OPEN_FAILED
;
453 if (ev_ctx
&& tevent_re_initialise(ev_ctx
) != 0) {
454 smb_panic(__location__
": Failed to re-initialise event context");
457 if (reinit_after_fork_pipe
[0] != -1) {
458 struct tevent_fd
*fde
;
460 fde
= tevent_add_fd(ev_ctx
, ev_ctx
/* TALLOC_CTX */,
461 reinit_after_fork_pipe
[0], TEVENT_FD_READ
,
462 reinit_after_fork_pipe_handler
, NULL
);
464 smb_panic(__location__
": Failed to add reinit_after_fork pipe event");
470 * For clustering, we need to re-init our ctdbd connection after the
473 status
= messaging_reinit(msg_ctx
);
474 if (!NT_STATUS_IS_OK(status
)) {
475 DEBUG(0,("messaging_reinit() failed: %s\n",
483 /****************************************************************************
484 (Hopefully) efficient array append.
485 ****************************************************************************/
487 void add_to_large_array(TALLOC_CTX
*mem_ctx
, size_t element_size
,
488 void *element
, void *_array
, uint32
*num_elements
,
491 void **array
= (void **)_array
;
493 if (*array_size
< 0) {
497 if (*array
== NULL
) {
498 if (*array_size
== 0) {
502 if (*array_size
>= MAX_ALLOC_SIZE
/element_size
) {
506 *array
= TALLOC(mem_ctx
, element_size
* (*array_size
));
507 if (*array
== NULL
) {
512 if (*num_elements
== *array_size
) {
515 if (*array_size
>= MAX_ALLOC_SIZE
/element_size
) {
519 *array
= TALLOC_REALLOC(mem_ctx
, *array
,
520 element_size
* (*array_size
));
522 if (*array
== NULL
) {
527 memcpy((char *)(*array
) + element_size
*(*num_elements
),
528 element
, element_size
);
538 /****************************************************************************
539 Get my own domain name, or "" if we have none.
540 ****************************************************************************/
542 char *get_mydnsdomname(TALLOC_CTX
*ctx
)
547 domname
= get_mydnsfullname();
552 p
= strchr_m(domname
, '.');
555 return talloc_strdup(ctx
, p
);
557 return talloc_strdup(ctx
, "");
561 /****************************************************************************
562 Interpret a protocol description string, with a default.
563 ****************************************************************************/
565 int interpret_protocol(const char *str
,int def
)
567 if (strequal(str
,"NT1"))
568 return(PROTOCOL_NT1
);
569 if (strequal(str
,"LANMAN2"))
570 return(PROTOCOL_LANMAN2
);
571 if (strequal(str
,"LANMAN1"))
572 return(PROTOCOL_LANMAN1
);
573 if (strequal(str
,"CORE"))
574 return(PROTOCOL_CORE
);
575 if (strequal(str
,"COREPLUS"))
576 return(PROTOCOL_COREPLUS
);
577 if (strequal(str
,"CORE+"))
578 return(PROTOCOL_COREPLUS
);
580 DEBUG(0,("Unrecognised protocol level %s\n",str
));
586 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
587 /******************************************************************
588 Remove any mount options such as -rsize=2048,wsize=2048 etc.
589 Based on a fix from <Thomas.Hepper@icem.de>.
590 Returns a malloc'ed string.
591 *******************************************************************/
593 static char *strip_mount_options(TALLOC_CTX
*ctx
, const char *str
)
597 while(*p
&& !isspace(*p
))
599 while(*p
&& isspace(*p
))
602 return talloc_strdup(ctx
, p
);
608 /*******************************************************************
609 Patch from jkf@soton.ac.uk
610 Split Luke's automount_server into YP lookup and string splitter
611 so can easily implement automount_path().
612 Returns a malloc'ed string.
613 *******************************************************************/
615 #ifdef WITH_NISPLUS_HOME
616 char *automount_lookup(TALLOC_CTX
*ctx
, const char *user_name
)
620 char *nis_map
= (char *)lp_nis_home_map_name();
622 char buffer
[NIS_MAXATTRVAL
+ 1];
627 snprintf(buffer
, sizeof(buffer
), "[key=%s],%s", user_name
, nis_map
);
628 DEBUG(5, ("NIS+ querystring: %s\n", buffer
));
630 if (result
= nis_list(buffer
, FOLLOW_PATH
|EXPAND_NAME
|HARD_LOOKUP
, NULL
, NULL
)) {
631 if (result
->status
!= NIS_SUCCESS
) {
632 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result
->status
)));
634 object
= result
->objects
.objects_val
;
635 if (object
->zo_data
.zo_type
== ENTRY_OBJ
) {
636 entry
= &object
->zo_data
.objdata_u
.en_data
;
637 DEBUG(5, ("NIS+ entry type: %s\n", entry
->en_type
));
638 DEBUG(3, ("NIS+ result: %s\n", entry
->en_cols
.en_cols_val
[1].ec_value
.ec_value_val
));
640 value
= talloc_strdup(ctx
,
641 entry
->en_cols
.en_cols_val
[1].ec_value
.ec_value_val
);
643 nis_freeresult(result
);
646 value
= talloc_string_sub(ctx
,
653 nis_freeresult(result
);
656 value
= strip_mount_options(ctx
, value
);
657 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n",
662 #else /* WITH_NISPLUS_HOME */
664 char *automount_lookup(TALLOC_CTX
*ctx
, const char *user_name
)
668 int nis_error
; /* returned by yp all functions */
669 char *nis_result
; /* yp_match inits this */
670 int nis_result_len
; /* and set this */
671 char *nis_domain
; /* yp_get_default_domain inits this */
672 char *nis_map
= lp_nis_home_map_name(talloc_tos());
674 if ((nis_error
= yp_get_default_domain(&nis_domain
)) != 0) {
675 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error
)));
679 DEBUG(5, ("NIS Domain: %s\n", nis_domain
));
681 if ((nis_error
= yp_match(nis_domain
, nis_map
, user_name
,
682 strlen(user_name
), &nis_result
,
683 &nis_result_len
)) == 0) {
684 if (nis_result_len
> 0 && nis_result
[nis_result_len
] == '\n') {
685 nis_result
[nis_result_len
] = '\0';
687 value
= talloc_strdup(ctx
, nis_result
);
691 value
= strip_mount_options(ctx
, value
);
692 } else if(nis_error
== YPERR_KEY
) {
693 DEBUG(3, ("YP Key not found: while looking up \"%s\" in map \"%s\"\n",
694 user_name
, nis_map
));
695 DEBUG(3, ("using defaults for server and home directory\n"));
697 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
698 yperr_string(nis_error
), user_name
, nis_map
));
702 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name
, value
));
706 #endif /* WITH_NISPLUS_HOME */
709 /****************************************************************************
710 Check if a process exists. Does this work on all unixes?
711 ****************************************************************************/
713 bool process_exists(const struct server_id pid
)
715 if (procid_is_me(&pid
)) {
719 if (procid_is_local(&pid
)) {
720 return (kill(pid
.pid
,0) == 0 || errno
!= ESRCH
);
723 #ifdef CLUSTER_SUPPORT
724 return ctdbd_process_exists(messaging_ctdbd_connection(),
731 bool processes_exist(const struct server_id
*pids
, int num_pids
,
734 struct server_id
*remote_pids
= NULL
;
735 int *remote_idx
= NULL
;
736 bool *remote_results
= NULL
;
737 int i
, num_remote_pids
;
740 remote_pids
= talloc_array(talloc_tos(), struct server_id
, num_pids
);
741 if (remote_pids
== NULL
) {
744 remote_idx
= talloc_array(talloc_tos(), int, num_pids
);
745 if (remote_idx
== NULL
) {
748 remote_results
= talloc_array(talloc_tos(), bool, num_pids
);
749 if (remote_results
== NULL
) {
755 for (i
=0; i
<num_pids
; i
++) {
756 if (procid_is_me(&pids
[i
])) {
760 if (procid_is_local(&pids
[i
])) {
761 results
[i
] = ((kill(pids
[i
].pid
,0) == 0) ||
766 remote_pids
[num_remote_pids
] = pids
[i
];
767 remote_idx
[num_remote_pids
] = i
;
768 num_remote_pids
+= 1;
771 if (num_remote_pids
!= 0) {
772 #ifdef CLUSTER_SUPPORT
773 if (!ctdb_processes_exist(messaging_ctdbd_connection(),
774 remote_pids
, num_remote_pids
,
779 for (i
=0; i
<num_remote_pids
; i
++) {
780 remote_results
[i
] = false;
784 for (i
=0; i
<num_remote_pids
; i
++) {
785 results
[remote_idx
[i
]] = remote_results
[i
];
791 TALLOC_FREE(remote_results
);
792 TALLOC_FREE(remote_idx
);
793 TALLOC_FREE(remote_pids
);
797 /*******************************************************************
798 Convert a uid into a user name.
799 ********************************************************************/
801 const char *uidtoname(uid_t uid
)
803 TALLOC_CTX
*ctx
= talloc_tos();
805 struct passwd
*pass
= NULL
;
807 pass
= getpwuid_alloc(ctx
,uid
);
809 name
= talloc_strdup(ctx
,pass
->pw_name
);
812 name
= talloc_asprintf(ctx
,
819 /*******************************************************************
820 Convert a gid into a group name.
821 ********************************************************************/
823 char *gidtoname(gid_t gid
)
829 return talloc_strdup(talloc_tos(), grp
->gr_name
);
832 return talloc_asprintf(talloc_tos(),
838 /*******************************************************************
839 Convert a user name into a uid.
840 ********************************************************************/
842 uid_t
nametouid(const char *name
)
848 pass
= Get_Pwnam_alloc(talloc_tos(), name
);
855 u
= (uid_t
)strtol(name
, &p
, 0);
856 if ((p
!= name
) && (*p
== '\0'))
862 /*******************************************************************
863 Convert a name to a gid_t if possible. Return -1 if not a group.
864 ********************************************************************/
866 gid_t
nametogid(const char *name
)
872 g
= (gid_t
)strtol(name
, &p
, 0);
873 if ((p
!= name
) && (*p
== '\0'))
876 grp
= getgrnam(name
);
882 /*******************************************************************
883 Something really nasty happened - panic !
884 ********************************************************************/
886 void smb_panic_s3(const char *why
)
891 DEBUG(0,("PANIC (pid %llu): %s\n",
892 (unsigned long long)getpid(), why
));
895 #if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER)
897 * Make sure all children can attach a debugger.
899 prctl(PR_SET_PTRACER
, getpid(), 0, 0, 0);
902 cmd
= lp_panic_action(talloc_tos());
904 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd
));
905 result
= system(cmd
);
908 DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
911 DEBUG(0, ("smb_panic(): action returned status %d\n",
912 WEXITSTATUS(result
)));
918 /*******************************************************************
919 Print a backtrace of the stack to the debug log. This function
920 DELIBERATELY LEAKS MEMORY. The expectation is that you should
921 exit shortly after calling it.
922 ********************************************************************/
924 #ifdef HAVE_LIBUNWIND_H
925 #include <libunwind.h>
928 #ifdef HAVE_EXECINFO_H
929 #include <execinfo.h>
936 void log_stack_trace(void)
938 #ifdef HAVE_LIBUNWIND
939 /* Try to use libunwind before any other technique since on ia64
940 * libunwind correctly walks the stack in more circumstances than
948 unw_word_t ip
, sp
, off
;
950 procname
[sizeof(procname
) - 1] = '\0';
952 if (unw_getcontext(&uc
) != 0) {
953 goto libunwind_failed
;
956 if (unw_init_local(&cursor
, &uc
) != 0) {
957 goto libunwind_failed
;
960 DEBUG(0, ("BACKTRACE:\n"));
964 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
965 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
967 switch (unw_get_proc_name(&cursor
,
968 procname
, sizeof(procname
) - 1, &off
) ) {
972 /* Name truncated. */
973 DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
974 i
, procname
, (long long)off
,
975 (long long)ip
, (long long) sp
));
978 /* case -UNW_ENOINFO: */
979 /* case -UNW_EUNSPEC: */
980 /* No symbol name found. */
981 DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
982 i
, "<unknown symbol>",
983 (long long)ip
, (long long) sp
));
986 } while (unw_step(&cursor
) > 0);
991 DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
993 #elif HAVE_BACKTRACE_SYMBOLS
994 void *backtrace_stack
[BACKTRACE_STACK_SIZE
];
995 size_t backtrace_size
;
996 char **backtrace_strings
;
998 /* get the backtrace (stack frames) */
999 backtrace_size
= backtrace(backtrace_stack
,BACKTRACE_STACK_SIZE
);
1000 backtrace_strings
= backtrace_symbols(backtrace_stack
, backtrace_size
);
1002 DEBUG(0, ("BACKTRACE: %lu stack frames:\n",
1003 (unsigned long)backtrace_size
));
1005 if (backtrace_strings
) {
1008 for (i
= 0; i
< backtrace_size
; i
++)
1009 DEBUGADD(0, (" #%u %s\n", i
, backtrace_strings
[i
]));
1011 /* Leak the backtrace_strings, rather than risk what free() might do */
1016 /* The IRIX libexc library provides an API for unwinding the stack. See
1017 * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
1018 * since we are about to abort anyway, it hardly matters.
1021 #define NAMESIZE 32 /* Arbitrary */
1023 __uint64_t addrs
[BACKTRACE_STACK_SIZE
];
1024 char * names
[BACKTRACE_STACK_SIZE
];
1025 char namebuf
[BACKTRACE_STACK_SIZE
* NAMESIZE
];
1032 ZERO_ARRAY(namebuf
);
1034 /* We need to be root so we can open our /proc entry to walk
1035 * our stack. It also helps when we want to dump core.
1039 for (i
= 0; i
< BACKTRACE_STACK_SIZE
; i
++) {
1040 names
[i
] = namebuf
+ (i
* NAMESIZE
);
1043 levels
= trace_back_stack(0, addrs
, names
,
1044 BACKTRACE_STACK_SIZE
, NAMESIZE
- 1);
1046 DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels
));
1047 for (i
= 0; i
< levels
; i
++) {
1048 DEBUGADD(0, (" #%d 0x%llx %s\n", i
, addrs
[i
], names
[i
]));
1053 DEBUG(0, ("unable to produce a stack trace on this platform\n"));
1057 /*******************************************************************
1058 A readdir wrapper which just returns the file name.
1059 ********************************************************************/
1061 const char *readdirname(DIR *p
)
1069 ptr
= (struct dirent
*)readdir(p
);
1073 dname
= ptr
->d_name
;
1080 #ifdef HAVE_BROKEN_READDIR_NAME
1081 /* using /usr/ucb/cc is BAD */
1085 return talloc_strdup(talloc_tos(), dname
);
1088 /*******************************************************************
1089 Utility function used to decide if the last component
1090 of a path matches a (possibly wildcarded) entry in a namelist.
1091 ********************************************************************/
1093 bool is_in_path(const char *name
, name_compare_entry
*namelist
, bool case_sensitive
)
1095 const char *last_component
;
1097 /* if we have no list it's obviously not in the path */
1098 if((namelist
== NULL
) || ((namelist
!= NULL
) && (namelist
[0].name
== NULL
))) {
1102 DEBUG(8, ("is_in_path: %s\n", name
));
1104 /* Get the last component of the unix name. */
1105 last_component
= strrchr_m(name
, '/');
1106 if (!last_component
) {
1107 last_component
= name
;
1109 last_component
++; /* Go past '/' */
1112 for(; namelist
->name
!= NULL
; namelist
++) {
1113 if(namelist
->is_wild
) {
1114 if (mask_match(last_component
, namelist
->name
, case_sensitive
)) {
1115 DEBUG(8,("is_in_path: mask match succeeded\n"));
1119 if((case_sensitive
&& (strcmp(last_component
, namelist
->name
) == 0))||
1120 (!case_sensitive
&& (strcasecmp_m(last_component
, namelist
->name
) == 0))) {
1121 DEBUG(8,("is_in_path: match succeeded\n"));
1126 DEBUG(8,("is_in_path: match not found\n"));
1130 /*******************************************************************
1131 Strip a '/' separated list into an array of
1132 name_compare_enties structures suitable for
1133 passing to is_in_path(). We do this for
1134 speed so we can pre-parse all the names in the list
1135 and don't do it for each call to is_in_path().
1136 We also check if the entry contains a wildcard to
1137 remove a potentially expensive call to mask_match
1139 ********************************************************************/
1141 void set_namearray(name_compare_entry
**ppname_array
, const char *namelist_in
)
1146 int num_entries
= 0;
1149 (*ppname_array
) = NULL
;
1151 if((namelist_in
== NULL
) || ((namelist_in
!= NULL
) && (*namelist_in
== '\0')))
1154 namelist
= talloc_strdup(talloc_tos(), namelist_in
);
1155 if (namelist
== NULL
) {
1156 DEBUG(0,("set_namearray: talloc fail\n"));
1161 /* We need to make two passes over the string. The
1162 first to count the number of elements, the second
1167 if ( *nameptr
== '/' ) {
1168 /* cope with multiple (useless) /s) */
1172 /* anything left? */
1173 if ( *nameptr
== '\0' )
1176 /* find the next '/' or consume remaining */
1177 name_end
= strchr_m(nameptr
, '/');
1178 if (name_end
== NULL
)
1179 name_end
= (char *)nameptr
+ strlen(nameptr
);
1181 /* next segment please */
1182 nameptr
= name_end
+ 1;
1186 if(num_entries
== 0) {
1187 talloc_free(namelist
);
1191 if(( (*ppname_array
) = SMB_MALLOC_ARRAY(name_compare_entry
, num_entries
+ 1)) == NULL
) {
1192 DEBUG(0,("set_namearray: malloc fail\n"));
1193 talloc_free(namelist
);
1197 /* Now copy out the names */
1201 if ( *nameptr
== '/' ) {
1202 /* cope with multiple (useless) /s) */
1206 /* anything left? */
1207 if ( *nameptr
== '\0' )
1210 /* find the next '/' or consume remaining */
1211 name_end
= strchr_m(nameptr
, '/');
1215 name_end
= nameptr
+ strlen(nameptr
);
1217 (*ppname_array
)[i
].is_wild
= ms_has_wild(nameptr
);
1218 if(((*ppname_array
)[i
].name
= SMB_STRDUP(nameptr
)) == NULL
) {
1219 DEBUG(0,("set_namearray: malloc fail (1)\n"));
1220 talloc_free(namelist
);
1224 /* next segment please */
1225 nameptr
= name_end
+ 1;
1229 (*ppname_array
)[i
].name
= NULL
;
1231 talloc_free(namelist
);
1236 #define DBGC_CLASS DBGC_LOCKING
1238 /****************************************************************************
1239 Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
1240 is dealt with in posix.c
1241 Returns True if we have information regarding this lock region (and returns
1242 F_UNLCK in *ptype if the region is unlocked). False if the call failed.
1243 ****************************************************************************/
1245 bool fcntl_getlock(int fd
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
1250 DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
1251 fd
,(double)*poffset
,(double)*pcount
,*ptype
));
1253 lock
.l_type
= *ptype
;
1254 lock
.l_whence
= SEEK_SET
;
1255 lock
.l_start
= *poffset
;
1256 lock
.l_len
= *pcount
;
1259 ret
= sys_fcntl_ptr(fd
,F_GETLK
,&lock
);
1263 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
1264 (double)*poffset
,(double)*pcount
,*ptype
,strerror(errno
)));
1269 *ptype
= lock
.l_type
;
1270 *poffset
= lock
.l_start
;
1271 *pcount
= lock
.l_len
;
1274 DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
1275 fd
, (int)lock
.l_type
, (unsigned int)lock
.l_pid
));
1280 #define DBGC_CLASS DBGC_ALL
1282 /*******************************************************************
1283 Is the name specified one of my netbios names.
1284 Returns true if it is equal, false otherwise.
1285 ********************************************************************/
1287 bool is_myname(const char *s
)
1292 for (n
=0; my_netbios_names(n
); n
++) {
1293 if (strequal(my_netbios_names(n
), s
)) {
1298 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s
, ret
));
1302 /*******************************************************************
1303 we distinguish between 2K and XP by the "Native Lan Manager" string
1304 WinXP => "Windows 2002 5.1"
1305 WinXP 64bit => "Windows XP 5.2"
1306 Win2k => "Windows 2000 5.0"
1307 NT4 => "Windows NT 4.0"
1308 Win9x => "Windows 4.0"
1309 Windows 2003 doesn't set the native lan manager string but
1310 they do set the domain to "Windows 2003 5.2" (probably a bug).
1311 ********************************************************************/
1313 void ra_lanman_string( const char *native_lanman
)
1315 if ( strcmp( native_lanman
, "Windows 2002 5.1" ) == 0 )
1316 set_remote_arch( RA_WINXP
);
1317 else if ( strcmp( native_lanman
, "Windows XP 5.2" ) == 0 )
1318 set_remote_arch( RA_WINXP64
);
1319 else if ( strcmp( native_lanman
, "Windows Server 2003 5.2" ) == 0 )
1320 set_remote_arch( RA_WIN2K3
);
1323 static const char *remote_arch_str
;
1325 const char *get_remote_arch_str(void)
1327 if (!remote_arch_str
) {
1330 return remote_arch_str
;
1333 /*******************************************************************
1334 Set the horrid remote_arch string based on an enum.
1335 ********************************************************************/
1337 void set_remote_arch(enum remote_arch_types type
)
1342 remote_arch_str
= "WfWg";
1345 remote_arch_str
= "OS2";
1348 remote_arch_str
= "Win95";
1351 remote_arch_str
= "WinNT";
1354 remote_arch_str
= "Win2K";
1357 remote_arch_str
= "WinXP";
1360 remote_arch_str
= "WinXP64";
1363 remote_arch_str
= "Win2K3";
1366 remote_arch_str
= "Vista";
1369 remote_arch_str
= "Samba";
1372 remote_arch_str
= "CIFSFS";
1375 remote_arch_str
= "OSX";
1378 ra_type
= RA_UNKNOWN
;
1379 remote_arch_str
= "UNKNOWN";
1383 DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1387 /*******************************************************************
1388 Get the remote_arch type.
1389 ********************************************************************/
1391 enum remote_arch_types
get_remote_arch(void)
1396 const char *tab_depth(int level
, int depth
)
1398 if( CHECK_DEBUGLVL(level
) ) {
1399 dbgtext("%*s", depth
*4, "");
1404 /*****************************************************************************
1405 Provide a checksum on a string
1407 Input: s - the null-terminated character string for which the checksum
1410 Output: The checksum value calculated for s.
1411 *****************************************************************************/
1413 int str_checksum(const char *s
)
1417 return hash(s
, strlen(s
), 0);
1420 /*****************************************************************
1421 Zero a memory area then free it. Used to catch bugs faster.
1422 *****************************************************************/
1424 void zero_free(void *p
, size_t size
)
1430 /*****************************************************************
1431 Set our open file limit to a requested max and return the limit.
1432 *****************************************************************/
1434 int set_maxfiles(int requested_max
)
1436 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1438 int saved_current_limit
;
1440 if(getrlimit(RLIMIT_NOFILE
, &rlp
)) {
1441 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1444 return requested_max
;
1448 * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1449 * account for the extra fd we need
1450 * as well as the log files and standard
1451 * handles etc. Save the limit we want to set in case
1452 * we are running on an OS that doesn't support this limit (AIX)
1453 * which always returns RLIM_INFINITY for rlp.rlim_max.
1456 /* Try raising the hard (max) limit to the requested amount. */
1458 #if defined(RLIM_INFINITY)
1459 if (rlp
.rlim_max
!= RLIM_INFINITY
) {
1460 int orig_max
= rlp
.rlim_max
;
1462 if ( rlp
.rlim_max
< requested_max
)
1463 rlp
.rlim_max
= requested_max
;
1465 /* This failing is not an error - many systems (Linux) don't
1466 support our default request of 10,000 open files. JRA. */
1468 if(setrlimit(RLIMIT_NOFILE
, &rlp
)) {
1469 DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n",
1470 (int)rlp
.rlim_max
, strerror(errno
) ));
1472 /* Set failed - restore original value from get. */
1473 rlp
.rlim_max
= orig_max
;
1478 /* Now try setting the soft (current) limit. */
1480 saved_current_limit
= rlp
.rlim_cur
= MIN(requested_max
,rlp
.rlim_max
);
1482 if(setrlimit(RLIMIT_NOFILE
, &rlp
)) {
1483 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
1484 (int)rlp
.rlim_cur
, strerror(errno
) ));
1486 return saved_current_limit
;
1489 if(getrlimit(RLIMIT_NOFILE
, &rlp
)) {
1490 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1493 return saved_current_limit
;
1496 #if defined(RLIM_INFINITY)
1497 if(rlp
.rlim_cur
== RLIM_INFINITY
)
1498 return saved_current_limit
;
1501 if((int)rlp
.rlim_cur
> saved_current_limit
)
1502 return saved_current_limit
;
1504 return rlp
.rlim_cur
;
1505 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1507 * No way to know - just guess...
1509 return requested_max
;
1513 /*****************************************************************
1514 malloc that aborts with smb_panic on fail or zero size.
1515 *****************************************************************/
1517 void *smb_xmalloc_array(size_t size
, unsigned int count
)
1521 smb_panic("smb_xmalloc_array: called with zero size");
1523 if (count
>= MAX_ALLOC_SIZE
/size
) {
1524 smb_panic("smb_xmalloc_array: alloc size too large");
1526 if ((p
= SMB_MALLOC(size
*count
)) == NULL
) {
1527 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1528 (unsigned long)size
, (unsigned long)count
));
1529 smb_panic("smb_xmalloc_array: malloc failed");
1535 vasprintf that aborts on malloc fail
1538 int smb_xvasprintf(char **ptr
, const char *format
, va_list ap
)
1545 n
= vasprintf(ptr
, format
, ap2
);
1547 if (n
== -1 || ! *ptr
) {
1548 smb_panic("smb_xvasprintf: out of memory");
1553 /*****************************************************************
1554 Get local hostname and cache result.
1555 *****************************************************************/
1557 char *myhostname(void)
1561 ret
= get_myname(NULL
);
1566 /*****************************************************************
1567 Get local hostname and cache result.
1568 *****************************************************************/
1570 char *myhostname_upper(void)
1575 name
= get_myname(talloc_tos());
1576 ret
= strupper_talloc(NULL
, name
);
1583 * @brief Returns an absolute path to a file concatenating the provided
1584 * @a rootpath and @a basename
1586 * @param name Filename, relative to @a rootpath
1588 * @retval Pointer to a string containing the full path.
1591 static char *xx_path(const char *name
, const char *rootpath
)
1595 fname
= talloc_strdup(talloc_tos(), rootpath
);
1599 trim_string(fname
,"","/");
1601 if (!directory_exist(fname
)) {
1602 if (!mkdir(fname
,0755))
1603 DEBUG(1, ("Unable to create directory %s for file %s. "
1604 "Error was %s\n", fname
, name
, strerror(errno
)));
1607 return talloc_asprintf(talloc_tos(),
1614 * @brief Returns an absolute path to a file in the Samba lock directory.
1616 * @param name File to find, relative to LOCKDIR.
1618 * @retval Pointer to a talloc'ed string containing the full path.
1621 char *lock_path(const char *name
)
1623 return xx_path(name
, lp_lockdir());
1627 * @brief Returns an absolute path to a file in the Samba state directory.
1629 * @param name File to find, relative to STATEDIR.
1631 * @retval Pointer to a talloc'ed string containing the full path.
1634 char *state_path(const char *name
)
1636 return xx_path(name
, lp_statedir());
1640 * @brief Returns an absolute path to a file in the Samba cache directory.
1642 * @param name File to find, relative to CACHEDIR.
1644 * @retval Pointer to a talloc'ed string containing the full path.
1647 char *cache_path(const char *name
)
1649 return xx_path(name
, lp_cachedir());
1652 /*******************************************************************
1653 Given a filename - get its directory name
1654 ********************************************************************/
1656 bool parent_dirname(TALLOC_CTX
*mem_ctx
, const char *dir
, char **parent
,
1662 p
= strrchr_m(dir
, '/'); /* Find final '/', if any */
1665 if (!(*parent
= talloc_strdup(mem_ctx
, "."))) {
1676 if (!(*parent
= (char *)talloc_memdup(mem_ctx
, dir
, len
+1))) {
1679 (*parent
)[len
] = '\0';
1687 /*******************************************************************
1688 Determine if a pattern contains any Microsoft wildcard characters.
1689 *******************************************************************/
1691 bool ms_has_wild(const char *s
)
1695 if (lp_posix_pathnames()) {
1696 /* With posix pathnames no characters are wild. */
1700 while ((c
= *s
++)) {
1713 bool ms_has_wild_w(const smb_ucs2_t
*s
)
1716 if (!s
) return False
;
1717 while ((c
= *s
++)) {
1719 case UCS2_CHAR('*'):
1720 case UCS2_CHAR('?'):
1721 case UCS2_CHAR('<'):
1722 case UCS2_CHAR('>'):
1723 case UCS2_CHAR('"'):
1730 /*******************************************************************
1731 A wrapper that handles case sensitivity and the special handling
1733 *******************************************************************/
1735 bool mask_match(const char *string
, const char *pattern
, bool is_case_sensitive
)
1737 if (ISDOTDOT(string
))
1742 return ms_fnmatch(pattern
, string
, Protocol
<= PROTOCOL_LANMAN2
, is_case_sensitive
) == 0;
1745 /*******************************************************************
1746 A wrapper that handles case sensitivity and the special handling
1747 of the ".." name. Varient that is only called by old search code which requires
1748 pattern translation.
1749 *******************************************************************/
1751 bool mask_match_search(const char *string
, const char *pattern
, bool is_case_sensitive
)
1753 if (ISDOTDOT(string
))
1758 return ms_fnmatch(pattern
, string
, True
, is_case_sensitive
) == 0;
1761 /*******************************************************************
1762 A wrapper that handles a list of patters and calls mask_match()
1763 on each. Returns True if any of the patterns match.
1764 *******************************************************************/
1766 bool mask_match_list(const char *string
, char **list
, int listLen
, bool is_case_sensitive
)
1768 while (listLen
-- > 0) {
1769 if (mask_match(string
, *list
++, is_case_sensitive
))
1775 /*********************************************************
1776 Recursive routine that is called by unix_wild_match.
1777 *********************************************************/
1779 static bool unix_do_match(const char *regexp
, const char *str
)
1783 for( p
= regexp
; *p
&& *str
; ) {
1794 * Look for a character matching
1795 * the one after the '*'.
1799 return true; /* Automatic match */
1802 while(*str
&& (*p
!= *str
))
1806 * Patch from weidel@multichart.de. In the case of the regexp
1807 * '*XX*' we want to ensure there are at least 2 'X' characters
1808 * in the string after the '*' for a match to be made.
1815 * Eat all the characters that match, but count how many there were.
1818 while(*str
&& (*p
== *str
)) {
1824 * Now check that if the regexp had n identical characters that
1825 * matchcount had at least that many matches.
1828 while ( *(p
+1) && (*(p
+1) == *p
)) {
1833 if ( matchcount
<= 0 )
1837 str
--; /* We've eaten the match char after the '*' */
1839 if(unix_do_match(p
, str
))
1861 if (!*p
&& str
[0] == '.' && str
[1] == 0)
1864 if (!*str
&& *p
== '?') {
1870 if(!*str
&& (*p
== '*' && p
[1] == '\0'))
1876 /*******************************************************************
1877 Simple case insensitive interface to a UNIX wildcard matcher.
1878 Returns True if match, False if not.
1879 *******************************************************************/
1881 bool unix_wild_match(const char *pattern
, const char *string
)
1883 TALLOC_CTX
*ctx
= talloc_stackframe();
1889 p2
= talloc_strdup(ctx
,pattern
);
1890 s2
= talloc_strdup(ctx
,string
);
1895 if (!strlower_m(p2
)) {
1899 if (!strlower_m(s2
)) {
1904 /* Remove any *? and ** from the pattern as they are meaningless */
1905 for(p
= p2
; *p
; p
++) {
1906 while( *p
== '*' && (p
[1] == '?' ||p
[1] == '*')) {
1907 memmove(&p
[1], &p
[2], strlen(&p
[2])+1);
1911 if (strequal(p2
,"*")) {
1916 ret
= unix_do_match(p2
, s2
);
1921 /**********************************************************************
1922 Converts a name to a fully qualified domain name.
1923 Returns true if lookup succeeded, false if not (then fqdn is set to name)
1924 Note we deliberately use gethostbyname here, not getaddrinfo as we want
1925 to examine the h_aliases and I don't know how to do that with getaddrinfo.
1926 ***********************************************************************/
1928 bool name_to_fqdn(fstring fqdn
, const char *name
)
1931 struct hostent
*hp
= gethostbyname(name
);
1933 if (!hp
|| !hp
->h_name
|| !*hp
->h_name
) {
1934 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name
));
1935 fstrcpy(fqdn
, name
);
1939 /* Find out if the fqdn is returned as an alias
1940 * to cope with /etc/hosts files where the first
1941 * name is not the fqdn but the short name */
1942 if (hp
->h_aliases
&& (! strchr_m(hp
->h_name
, '.'))) {
1944 for (i
= 0; hp
->h_aliases
[i
]; i
++) {
1945 if (strchr_m(hp
->h_aliases
[i
], '.')) {
1946 full
= hp
->h_aliases
[i
];
1951 if (full
&& (strcasecmp_m(full
, "localhost.localdomain") == 0)) {
1952 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
1953 DEBUGADD(1, (" Specifing the machine hostname for address 127.0.0.1 may lead\n"));
1954 DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n"));
1955 DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n"));
1962 DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name
, full
));
1963 fstrcpy(fqdn
, full
);
1967 /**********************************************************************
1968 Append a DATA_BLOB to a talloc'ed object
1969 ***********************************************************************/
1971 void *talloc_append_blob(TALLOC_CTX
*mem_ctx
, void *buf
, DATA_BLOB blob
)
1973 size_t old_size
= 0;
1976 if (blob
.length
== 0) {
1981 old_size
= talloc_get_size(buf
);
1984 result
= (char *)TALLOC_REALLOC(mem_ctx
, buf
, old_size
+ blob
.length
);
1985 if (result
== NULL
) {
1989 memcpy(result
+ old_size
, blob
.data
, blob
.length
);
1993 uint32
map_share_mode_to_deny_mode(uint32 share_access
, uint32 private_options
)
1995 switch (share_access
& ~FILE_SHARE_DELETE
) {
1996 case FILE_SHARE_NONE
:
1998 case FILE_SHARE_READ
:
2000 case FILE_SHARE_WRITE
:
2002 case FILE_SHARE_READ
|FILE_SHARE_WRITE
:
2005 if (private_options
& NTCREATEX_OPTIONS_PRIVATE_DENY_DOS
) {
2007 } else if (private_options
& NTCREATEX_OPTIONS_PRIVATE_DENY_FCB
) {
2014 pid_t
procid_to_pid(const struct server_id
*proc
)
2019 static uint32 my_vnn
= NONCLUSTER_VNN
;
2021 void set_my_vnn(uint32 vnn
)
2023 DEBUG(10, ("vnn pid %d = %u\n", (int)getpid(), (unsigned int)vnn
));
2027 uint32
get_my_vnn(void)
2032 static uint64_t my_unique_id
= 0;
2034 void set_my_unique_id(uint64_t unique_id
)
2036 my_unique_id
= unique_id
;
2039 struct server_id
pid_to_procid(pid_t pid
)
2041 struct server_id result
;
2044 result
.unique_id
= my_unique_id
;
2045 result
.vnn
= my_vnn
;
2049 struct server_id
procid_self(void)
2051 return pid_to_procid(getpid());
2054 static struct idr_context
*task_id_tree
;
2056 static int free_task_id(struct server_id
*server_id
)
2058 idr_remove(task_id_tree
, server_id
->task_id
);
2062 /* Return a server_id with a unique task_id element. Free the
2063 * returned pointer to de-allocate the task_id via a talloc destructor
2064 * (ie, use talloc_free()) */
2065 struct server_id
*new_server_id_task(TALLOC_CTX
*mem_ctx
)
2067 struct server_id
*server_id
;
2069 if (!task_id_tree
) {
2070 task_id_tree
= idr_init(NULL
);
2071 if (!task_id_tree
) {
2076 server_id
= talloc(mem_ctx
, struct server_id
);
2081 *server_id
= procid_self();
2083 /* 0 is the default server_id, so we need to start with 1 */
2084 task_id
= idr_get_new_above(task_id_tree
, server_id
, 1, INT32_MAX
);
2086 if (task_id
== -1) {
2087 talloc_free(server_id
);
2091 talloc_set_destructor(server_id
, free_task_id
);
2092 server_id
->task_id
= task_id
;
2096 bool procid_is_me(const struct server_id
*pid
)
2098 if (pid
->pid
!= getpid())
2100 if (pid
->task_id
!= 0)
2102 if (pid
->vnn
!= my_vnn
)
2107 struct server_id
interpret_pid(const char *pid_string
)
2109 struct server_id result
;
2110 unsigned long long pid
;
2111 unsigned int vnn
, task_id
= 0;
2113 ZERO_STRUCT(result
);
2115 /* We accept various forms with 1, 2 or 3 component forms
2116 * because the server_id_str() can print different forms, and
2117 * we want backwards compatibility for scripts that may call
2119 if (sscanf(pid_string
, "%u:%llu.%u", &vnn
, &pid
, &task_id
) == 3) {
2122 result
.task_id
= task_id
;
2123 } else if (sscanf(pid_string
, "%u:%llu", &vnn
, &pid
) == 2) {
2127 } else if (sscanf(pid_string
, "%llu.%u", &pid
, &task_id
) == 2) {
2128 result
.vnn
= get_my_vnn();
2130 result
.task_id
= task_id
;
2131 } else if (sscanf(pid_string
, "%llu", &pid
) == 1) {
2132 result
.vnn
= get_my_vnn();
2135 result
.vnn
= NONCLUSTER_VNN
;
2136 result
.pid
= (uint64_t)-1;
2141 char *procid_str_static(const struct server_id
*pid
)
2143 return server_id_str(talloc_tos(), pid
);
2146 bool procid_valid(const struct server_id
*pid
)
2148 return (pid
->pid
!= (uint64_t)-1);
2151 bool procid_is_local(const struct server_id
*pid
)
2153 return pid
->vnn
== my_vnn
;
2156 /****************************************************************
2157 Check if an offset into a buffer is safe.
2158 If this returns True it's safe to indirect into the byte at
2160 ****************************************************************/
2162 bool is_offset_safe(const char *buf_base
, size_t buf_len
, char *ptr
, size_t off
)
2164 const char *end_base
= buf_base
+ buf_len
;
2165 char *end_ptr
= ptr
+ off
;
2167 if (!buf_base
|| !ptr
) {
2171 if (end_base
< buf_base
|| end_ptr
< ptr
) {
2172 return False
; /* wrap. */
2175 if (end_ptr
< end_base
) {
2181 /****************************************************************
2182 Return a safe pointer into a buffer, or NULL.
2183 ****************************************************************/
2185 char *get_safe_ptr(const char *buf_base
, size_t buf_len
, char *ptr
, size_t off
)
2187 return is_offset_safe(buf_base
, buf_len
, ptr
, off
) ?
2191 /****************************************************************
2192 Return a safe pointer into a string within a buffer, or NULL.
2193 ****************************************************************/
2195 char *get_safe_str_ptr(const char *buf_base
, size_t buf_len
, char *ptr
, size_t off
)
2197 if (!is_offset_safe(buf_base
, buf_len
, ptr
, off
)) {
2200 /* Check if a valid string exists at this offset. */
2201 if (skip_string(buf_base
,buf_len
, ptr
+ off
) == NULL
) {
2207 /****************************************************************
2208 Return an SVAL at a pointer, or failval if beyond the end.
2209 ****************************************************************/
2211 int get_safe_SVAL(const char *buf_base
, size_t buf_len
, char *ptr
, size_t off
, int failval
)
2214 * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2217 if (!is_offset_safe(buf_base
, buf_len
, ptr
, off
+1)) {
2220 return SVAL(ptr
,off
);
2223 /****************************************************************
2224 Return an IVAL at a pointer, or failval if beyond the end.
2225 ****************************************************************/
2227 int get_safe_IVAL(const char *buf_base
, size_t buf_len
, char *ptr
, size_t off
, int failval
)
2230 * Note we use off+3 here, not off+4 as IVAL accesses
2231 * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2233 if (!is_offset_safe(buf_base
, buf_len
, ptr
, off
+3)) {
2236 return IVAL(ptr
,off
);
2239 /****************************************************************
2240 Split DOM\user into DOM and user. Do not mix with winbind variants of that
2241 call (they take care of winbind separator and other winbind specific settings).
2242 ****************************************************************/
2244 void split_domain_user(TALLOC_CTX
*mem_ctx
,
2245 const char *full_name
,
2249 const char *p
= NULL
;
2251 p
= strchr_m(full_name
, '\\');
2254 *domain
= talloc_strndup(mem_ctx
, full_name
,
2255 PTR_DIFF(p
, full_name
));
2256 *user
= talloc_strdup(mem_ctx
, p
+1);
2258 *domain
= talloc_strdup(mem_ctx
, "");
2259 *user
= talloc_strdup(mem_ctx
, full_name
);
2263 /****************************************************************
2264 strip off leading '\\' from a hostname
2265 ****************************************************************/
2267 const char *strip_hostname(const char *s
)
2273 if (strlen_m(s
) < 3) {
2277 if (s
[0] == '\\') s
++;
2278 if (s
[0] == '\\') s
++;
2283 bool any_nt_status_not_ok(NTSTATUS err1
, NTSTATUS err2
, NTSTATUS
*result
)
2285 if (!NT_STATUS_IS_OK(err1
)) {
2289 if (!NT_STATUS_IS_OK(err2
)) {
2296 int timeval_to_msec(struct timeval t
)
2298 return t
.tv_sec
* 1000 + (t
.tv_usec
+999) / 1000;
2301 /*******************************************************************
2302 Check a given DOS pathname is valid for a share.
2303 ********************************************************************/
2305 char *valid_share_pathname(TALLOC_CTX
*ctx
, const char *dos_pathname
)
2309 if (!dos_pathname
) {
2313 ptr
= talloc_strdup(ctx
, dos_pathname
);
2317 /* Convert any '\' paths to '/' */
2319 ptr
= unix_clean_name(ctx
, ptr
);
2324 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
2325 if (strlen(ptr
) > 2 && ptr
[1] == ':' && ptr
[0] != '/')
2328 /* Only absolute paths allowed. */
2335 /*******************************************************************
2336 Return True if the filename is one of the special executable types.
2337 ********************************************************************/
2339 bool is_executable(const char *fname
)
2341 if ((fname
= strrchr_m(fname
,'.'))) {
2342 if (strequal(fname
,".com") ||
2343 strequal(fname
,".dll") ||
2344 strequal(fname
,".exe") ||
2345 strequal(fname
,".sym")) {
2352 /****************************************************************************
2353 Open a file with a share mode - old openX method - map into NTCreate.
2354 ****************************************************************************/
2356 bool map_open_params_to_ntcreate(const char *smb_base_fname
,
2357 int deny_mode
, int open_func
,
2358 uint32
*paccess_mask
,
2359 uint32
*pshare_mode
,
2360 uint32
*pcreate_disposition
,
2361 uint32
*pcreate_options
,
2362 uint32_t *pprivate_flags
)
2366 uint32 create_disposition
;
2367 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
2368 uint32_t private_flags
= 0;
2370 DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
2371 "open_func = 0x%x\n",
2372 smb_base_fname
, (unsigned int)deny_mode
,
2373 (unsigned int)open_func
));
2375 /* Create the NT compatible access_mask. */
2376 switch (GET_OPENX_MODE(deny_mode
)) {
2377 case DOS_OPEN_EXEC
: /* Implies read-only - used to be FILE_READ_DATA */
2378 case DOS_OPEN_RDONLY
:
2379 access_mask
= FILE_GENERIC_READ
;
2381 case DOS_OPEN_WRONLY
:
2382 access_mask
= FILE_GENERIC_WRITE
;
2386 access_mask
= FILE_GENERIC_READ
|FILE_GENERIC_WRITE
;
2389 DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
2390 (unsigned int)GET_OPENX_MODE(deny_mode
)));
2394 /* Create the NT compatible create_disposition. */
2395 switch (open_func
) {
2396 case OPENX_FILE_EXISTS_FAIL
|OPENX_FILE_CREATE_IF_NOT_EXIST
:
2397 create_disposition
= FILE_CREATE
;
2400 case OPENX_FILE_EXISTS_OPEN
:
2401 create_disposition
= FILE_OPEN
;
2404 case OPENX_FILE_EXISTS_OPEN
|OPENX_FILE_CREATE_IF_NOT_EXIST
:
2405 create_disposition
= FILE_OPEN_IF
;
2408 case OPENX_FILE_EXISTS_TRUNCATE
:
2409 create_disposition
= FILE_OVERWRITE
;
2412 case OPENX_FILE_EXISTS_TRUNCATE
|OPENX_FILE_CREATE_IF_NOT_EXIST
:
2413 create_disposition
= FILE_OVERWRITE_IF
;
2417 /* From samba4 - to be confirmed. */
2418 if (GET_OPENX_MODE(deny_mode
) == DOS_OPEN_EXEC
) {
2419 create_disposition
= FILE_CREATE
;
2422 DEBUG(10,("map_open_params_to_ntcreate: bad "
2423 "open_func 0x%x\n", (unsigned int)open_func
));
2427 /* Create the NT compatible share modes. */
2428 switch (GET_DENY_MODE(deny_mode
)) {
2430 share_mode
= FILE_SHARE_NONE
;
2434 share_mode
= FILE_SHARE_READ
;
2438 share_mode
= FILE_SHARE_WRITE
;
2442 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2446 private_flags
|= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS
;
2447 if (is_executable(smb_base_fname
)) {
2448 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2450 if (GET_OPENX_MODE(deny_mode
) == DOS_OPEN_RDONLY
) {
2451 share_mode
= FILE_SHARE_READ
;
2453 share_mode
= FILE_SHARE_NONE
;
2459 private_flags
|= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB
;
2460 share_mode
= FILE_SHARE_NONE
;
2464 DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
2465 (unsigned int)GET_DENY_MODE(deny_mode
) ));
2469 DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
2470 "share_mode = 0x%x, create_disposition = 0x%x, "
2471 "create_options = 0x%x private_flags = 0x%x\n",
2473 (unsigned int)access_mask
,
2474 (unsigned int)share_mode
,
2475 (unsigned int)create_disposition
,
2476 (unsigned int)create_options
,
2477 (unsigned int)private_flags
));
2480 *paccess_mask
= access_mask
;
2483 *pshare_mode
= share_mode
;
2485 if (pcreate_disposition
) {
2486 *pcreate_disposition
= create_disposition
;
2488 if (pcreate_options
) {
2489 *pcreate_options
= create_options
;
2491 if (pprivate_flags
) {
2492 *pprivate_flags
= private_flags
;
2499 /*************************************************************************
2500 Return a talloced copy of a struct security_unix_token. NULL on fail.
2501 *************************************************************************/
2503 struct security_unix_token
*copy_unix_token(TALLOC_CTX
*ctx
, const struct security_unix_token
*tok
)
2505 struct security_unix_token
*cpy
;
2507 cpy
= talloc(ctx
, struct security_unix_token
);
2512 cpy
->uid
= tok
->uid
;
2513 cpy
->gid
= tok
->gid
;
2514 cpy
->ngroups
= tok
->ngroups
;
2516 /* Make this a talloc child of cpy. */
2517 cpy
->groups
= (gid_t
*)talloc_memdup(
2518 cpy
, tok
->groups
, tok
->ngroups
* sizeof(gid_t
));